Java Reference
In-Depth Information
In the j-- compiler, this symbol table is represented as a singly-linked list of Context
objects, that is, objects whose types extend the Context class. Each object in this list
represents some area of scope and contains a mapping from names to definitions. Every
context object maintains three pointers: one to the object representing the surrounding
context, one to the object representing the compilation unit context (at the root), and one
to the enclosing class context.
For example, there is a CompilationUnitContext object for representing the scope
comprising the program, that is, the entire compilation unit. There is a ClassContext
object for representing the scope of a class declaration. The ClassContext has a reference
to the defining class type; this is used to determine where we are (that is, in which class
declaration the compiler is in) for settling issues such as accessibility.
There is a MethodContext (a subclass of LocalContext ) for representing the scopes of
methods and, by extension, constructors. Finally, a LocalContext represents the scope of
a block, including those blocks that enclose method bodies. Here, local variable names are
declared and mapped to LocalVariableDefn s.
1.4.7 preAnalyze() and analyze()
preAnalyze() is a first pass at type checking. Its purpose is to build that part of the symbol
table that is at the top of the AST, to declare both imported types and types introduced
by class declarations, and to declare the members declared in those classes. This first pass
is necessary for declaring names that may be referenced before they are defined. Because
j-- does not support nested classes, this pass need not descend into the method bodies.
analyze() picks up where preAnalyze() left off. It continues to build the symbol table,
decorating the AST with type information and enforcing the j-- type rules. The analyze()
phase performs other important tasks:
Type checking: analyze() computes the type for every expression, and it checks its
type when a particular type is required.
Accessibility: analyze() enforces the accessibility rules (expressed by the modifiers
public , protected , and private ) for both types and members.
Member finding: analyze() finds members (messages in message expressions, based
on signature, and fields in field selections) in types. Of course, only the compile-time
member name is located; polymorphic messages are determined at run-time.
Tree rewriting: analyze() does a certain amount of AST (sub) tree rewriting. Implicit
field selections (denoted by identifiers that are fields in the current class) are made
explicit, and field and variable initializations are rewritten as assignment statements
after the names have been declared.
1.4.8 Stack Frames
analyze() also does a little storage allocation. It allocates positions in the method's current
stack frame for formal parameters and (other) local variables.
The JVM is a stack machine: all computations are carried out atop the run-time stack.
Each time a method is invoked, the JVM allocates a stack frame, a contiguous block of
memory locations on top of the run-time stack. The actual arguments substituted for formal
parameters, the values of local variables, and temporary results are all given positions within
this stack frame. Stack frames for both a static method and for an instance method are
illustrated in Figure 1.10.
 
Search WWH ::




Custom Search