1 // $Id: bytecode.h,v 1.71 2004/03/05 13:10:53 ericb Exp $ -*- c++ -*-
2 //
3 // License Agreement available at the following URL:
4 // http://ibm.com/developerworks/opensource/jikes.
5 // Copyright (C) 1996, 2004 IBM Corporation and others.  All Rights Reserved.
6 // You must accept the terms of that agreement to use this software.
7 //
8 
9 #ifndef bytecode_INCLUDED
10 #define bytecode_INCLUDED
11 
12 #include "platform.h"
13 #include "tuple.h"
14 #include "ast.h"
15 #include "class.h"
16 #include "op.h"
17 #include "segment.h"
18 #include "control.h"
19 
20 #ifdef HAVE_JIKES_NAMESPACE
21 namespace Jikes { // Open namespace Jikes block
22 #endif
23 
24 class TypeSymbol;
25 class Control;
26 class Semantic;
27 
28 class Label
29 {
30 public:
31 
32     class LabelUse
33     {
34     public:
35         int use_length; // length of use (2 or 4 bytes)
36         int op_offset; // length of use from opcode starting instruction
37         int use_offset; // offset in code stream of use
38 
LabelUse()39         LabelUse() : use_length(0), op_offset(0), use_offset(0) {}
40 
LabelUse(int _length,int _op_offset,int _use)41         LabelUse(int _length, int _op_offset, int _use)
42             : use_length(_length),
43               op_offset(_op_offset),
44               use_offset(_use)
45         {}
46     };
47 
48     bool defined; // boolean, set when value is known
49     u2 definition; // offset of definition point of label
50     Tuple<LabelUse> uses;
51 
Label()52     Label() : defined(false), definition(0) {}
53 
54     //
55     // All used labels should have been completed and reset, otherwise a goto
56     // will cause an infinite loop because it was emitted with an offset of 0.
57     //
~Label()58     ~Label() { assert(! uses.Length()); }
59 
Reset()60     void Reset()
61     {
62        uses.Reset();
63        defined = false;
64        definition = 0;
65     }
66 };
67 
68 
69 //
70 //
71 //
72 class MethodStack
73 {
74 public:
75 
Push(AstBlock * block)76     void Push(AstBlock* block)
77     {
78         assert(block -> nesting_level < stack_size &&
79                (top_index == 0 ||
80                 (block -> nesting_level > nesting_level[top_index - 1])));
81 
82         nesting_level[top_index] = block -> nesting_level;
83         break_labels[block -> nesting_level].uses.Reset();
84         continue_labels[block -> nesting_level].uses.Reset();
85         finally_labels[block -> nesting_level].uses.Reset();
86         handler_range_start[block -> nesting_level].Reset();
87         handler_range_end[block -> nesting_level].Reset();
88         blocks[block -> nesting_level] = block;
89         if (size)
90             memset(local_variables_start_pc[block -> nesting_level],
91                    0xFF, size * sizeof(u2));
92         top_index++;
93     }
94 
Pop()95     void Pop()
96     {
97         if (top_index > 0)
98         {
99             top_index--;
100 #ifdef JIKES_DEBUG
101             unsigned level = nesting_level[top_index];
102 
103             nesting_level[top_index] = 0;
104             break_labels[level].Reset();
105             continue_labels[level].Reset();
106             finally_labels[level].Reset();
107             handler_range_start[level].Reset();
108             handler_range_end[level].Reset();
109             blocks[level] = NULL;
110             if (size)
111                 memset(local_variables_start_pc[level], 0xFF,
112                        size * sizeof(u2));
113 #endif // ! JIKES_DEBUG
114         }
115         else assert(false);
116     }
117 
Size()118     unsigned Size() { return top_index; }
119 
120 #ifdef JIKES_DEBUG
AssertIndex(unsigned k)121     void AssertIndex(unsigned k)
122     {
123         for (unsigned i = 0; i < top_index; i++)
124             if (nesting_level[i] == k)
125                 return;
126         assert(false && "missing method stack level");
127     }
128 #else
129 # define AssertIndex(x) /* nop */
130 #endif // ! JIKES_DEBUG
131 
TopNestingLevel()132     unsigned TopNestingLevel()
133     {
134         assert(top_index > 0);
135         return nesting_level[top_index - 1];
136     }
NestingLevel(unsigned i)137     unsigned NestingLevel(unsigned i)
138     {
139         assert(i < top_index);
140         return nesting_level[i];
141     }
142 
TopBreakLabel()143     Label& TopBreakLabel() { return break_labels[TopNestingLevel()]; }
BreakLabel(unsigned i)144     Label& BreakLabel(unsigned i) { AssertIndex(i); return break_labels[i]; }
145 
TopContinueLabel()146     Label& TopContinueLabel() { return continue_labels[TopNestingLevel()]; }
ContinueLabel(unsigned i)147     Label& ContinueLabel(unsigned i)
148     {
149         AssertIndex(i);
150         return continue_labels[i];
151     }
152 
TopFinallyLabel()153     Label& TopFinallyLabel() { return finally_labels[TopNestingLevel()]; }
FinallyLabel(unsigned i)154     Label& FinallyLabel(unsigned i)
155     {
156         AssertIndex(i);
157         return finally_labels[i];
158     }
159 
TopHandlerRangeStart()160     Tuple<u2>& TopHandlerRangeStart()
161     {
162         return handler_range_start[TopNestingLevel()];
163     }
HandlerRangeStart(unsigned i)164     Tuple<u2>& HandlerRangeStart(unsigned i)
165     {
166         AssertIndex(i);
167         return handler_range_start[i];
168     }
169 
TopHandlerRangeEnd()170     Tuple<u2>& TopHandlerRangeEnd()
171     {
172         return handler_range_end[TopNestingLevel()];
173     }
HandlerRangeEnd(unsigned i)174     Tuple<u2>& HandlerRangeEnd(unsigned i)
175     {
176         AssertIndex(i);
177         return handler_range_end[i];
178     }
179 
TopBlock()180     AstBlock* TopBlock() { return blocks[TopNestingLevel()]; }
Block(unsigned i)181     AstBlock* Block(unsigned i) { AssertIndex(i); return blocks[i]; }
182 
TopLocalVariablesStartPc()183     u2* TopLocalVariablesStartPc()
184     {
185         return (u2*) local_variables_start_pc[TopNestingLevel()];
186     }
StartPc(VariableSymbol * variable)187     u2& StartPc(VariableSymbol* variable)
188     {
189         assert(variable -> LocalVariableIndex() >= 0 &&
190                variable -> LocalVariableIndex() < (int) size);
191         return TopLocalVariablesStartPc()[variable -> LocalVariableIndex()];
192     }
193 
MethodStack(unsigned stack_size_,unsigned size_)194     MethodStack(unsigned stack_size_, unsigned size_)
195         : stack_size(stack_size_),
196           size(size_),
197           top_index(0)
198     {
199         nesting_level = new unsigned[stack_size];
200         break_labels = new Label[stack_size];
201         continue_labels = new Label[stack_size];
202         finally_labels = new Label[stack_size];
203         handler_range_start = new Tuple<u2>[stack_size];
204         handler_range_end = new Tuple<u2>[stack_size];
205         blocks = new AstBlock*[stack_size];
206 
207         local_variables_start_pc = new u2*[stack_size];
208         for (unsigned i = 0; i < stack_size; i++)
209             local_variables_start_pc[i] = new u2[size];
210     }
~MethodStack()211     ~MethodStack()
212     {
213         delete [] nesting_level;
214         delete [] break_labels;
215         delete [] continue_labels;
216         delete [] finally_labels;
217         delete [] handler_range_start;
218         delete [] handler_range_end;
219         delete [] blocks;
220 
221         for (unsigned i = 0; i < stack_size; i++)
222             delete [] local_variables_start_pc[i];
223         delete [] local_variables_start_pc;
224     }
225 
226 private:
227     unsigned* nesting_level;
228 
229     Label* break_labels;
230     Label* continue_labels;
231     Label* finally_labels;
232     Tuple<u2>* handler_range_start;
233     Tuple<u2>* handler_range_end;
234 
235     AstBlock** blocks; // block symbols for current block
236 
237     u2** local_variables_start_pc;
238     unsigned stack_size;
239     unsigned size;
240     unsigned top_index;
241 };
242 
243 
244 class ByteCode : public ClassFile, public StringConstant, public Operators
245 {
246     //
247     // A heuristic level for generating code to handle conditional branches
248     // crossing more than 32767 bytes of code. In one test case, 54616 was
249     // required to generate that much code, so 10000 seems like a conservative
250     // value.
251     //
252     enum { TOKEN_WIDTH_REQUIRING_GOTOW = 10000 };
253 
254     Control& control;
255     Semantic& semantic;
256     TypeSymbol* unit_type;
257 
258     int line_number,
259         last_label_pc,        // pc for last (closest to end) label
260         last_op_pc,           // pc of last operation emitted
261         stack_depth,          // current stack depth;
262         max_stack,
263         max_block_depth;
264     MethodStack* method_stack;
265 
266     bool string_overflow,
267          library_method_not_found,
268          last_op_goto;        // set if last operation was GOTO or GOTO_W.
269     //
270     // This variable is non-zero only in constructors of local classes; it
271     // gives the offset where variable shadow parameters begin.
272     //
273     u2 shadow_parameter_offset;
274 
275     CodeAttribute* code_attribute; // code for current method
276     LineNumberTableAttribute* line_number_table_attribute;
277     LocalVariableTableAttribute* local_variable_table_attribute;
278     InnerClassesAttribute* inner_classes_attribute;
279 
MethodInitialization()280     void MethodInitialization()
281     {
282         last_label_pc = 0;
283         last_op_pc = 0;
284         last_op_goto = false;
285         stack_depth = 0;
286         max_stack = 0;
287     }
288 
289     bool ProcessAbruptExit(unsigned, u2, TypeSymbol* = NULL);
290     void CompleteLabel(Label& lab);
291     void DefineLabel(Label& lab);
292     void UseLabel(Label& lab, int length, int op_offset);
293 
IsLabelUsed(Label & lab)294     bool IsLabelUsed(Label& lab)
295     {
296         return lab.uses.Length() > 0;
297     }
298 
299 
300     //
301     // Does p refer to a non-null reference type?
302     //
IsReferenceType(TypeSymbol * p)303     bool IsReferenceType(TypeSymbol* p)
304     {
305         return ! p -> Primitive() && p != control.null_type;
306     }
307     //
308     // Does p refer to an array type that can be assigned arrays?
309     //
IsMultiDimensionalArray(TypeSymbol * p)310     bool IsMultiDimensionalArray(TypeSymbol* p)
311     {
312         return p -> num_dimensions > 1 ||
313             p -> base_type == control.Object() ||
314             p -> base_type == control.Cloneable() ||
315             p -> base_type == control.Serializable();
316     }
317 
318 
319     //
320     // See if operand is constant zero (including -0.0).
321     //
IsZero(AstExpression * p)322     bool IsZero(AstExpression* p)
323     {
324         TypeSymbol* type = p -> Type();
325         if (p -> IsConstant() && type != control.String())
326         {
327             if (control.IsSimpleIntegerValueType(type) ||
328                 type == control.boolean_type)
329             {
330                 return (DYNAMIC_CAST<IntLiteralValue*> (p -> value)) ->
331                     value == 0;
332             }
333             else if (type == control.long_type)
334             {
335                 return (DYNAMIC_CAST<LongLiteralValue*> (p -> value)) ->
336                     value == 0;
337             }
338             else if (type == control.float_type)
339             {
340                 return (DYNAMIC_CAST<FloatLiteralValue*> (p -> value)) ->
341                     value == 0;
342             }
343             else
344             {
345                 assert(type == control.double_type);
346                 return (DYNAMIC_CAST<DoubleLiteralValue*> (p -> value)) ->
347                     value == 0;
348             }
349         }
350         return false;
351     }
352 
353 
354     //
355     // See if operand is constant one.
356     //
IsOne(AstExpression * p)357     bool IsOne(AstExpression* p)
358     {
359         TypeSymbol* type = p -> Type();
360         if (p -> IsConstant() && type != control.String())
361         {
362             if (control.IsSimpleIntegerValueType(type) ||
363                 type == control.boolean_type)
364             {
365                 return (DYNAMIC_CAST<IntLiteralValue*> (p -> value)) ->
366                     value == 1;
367             }
368             else if (type == control.long_type)
369             {
370                 return (DYNAMIC_CAST<LongLiteralValue*> (p -> value)) ->
371                     value == 1;
372             }
373             else if (type == control.float_type)
374             {
375                 return (DYNAMIC_CAST<FloatLiteralValue*> (p -> value)) ->
376                     value == 1;
377             }
378             else
379             {
380                 assert(type == control.double_type);
381                 return (DYNAMIC_CAST<DoubleLiteralValue*> (p -> value)) ->
382                     value == 1;
383             }
384         }
385         return false;
386     }
387 
388 
389     //
390     // memory access: reference either
391     // constant (literal)
392     // name (includes local varable, or class variable, or field access)
393     // array
394     //
395     enum VariableCategory
396     {
397         LOCAL_VAR = 0, // local variable
398         ARRAY_VAR = 1, // array (of any kind)
399         FIELD_VAR = 2, // instance variable
400         STATIC_VAR = 3, // class variable
401         ACCESSED_VAR = 4 // enclosing class field via accessor method
402     };
403 
GetVariableKind(AstExpression * expression)404     VariableCategory GetVariableKind(AstExpression* expression)
405     {
406         AstAssignmentExpression* assignment =
407             expression -> AssignmentExpressionCast();
408         AstPreUnaryExpression* pre = expression -> PreUnaryExpressionCast();
409         AstPostUnaryExpression* post = expression -> PostUnaryExpressionCast();
410 
411         //
412         // Get the expression containing the variable (avoid accessor methods).
413         //
414         AstExpression* lhs = (assignment
415                               ? (assignment -> write_method
416                                  ? (AstExpression*) NULL
417                                  : assignment -> left_hand_side)
418                               : pre
419                               ? (pre -> write_method
420                                  ? (AstExpression*) NULL : pre -> expression)
421                               : post
422                               ? (post -> write_method
423                                  ? (AstExpression*) NULL : post -> expression)
424                               : expression);
425 
426         //
427         // Find symbol that is associated with expression. If the
428         // subexpression has to be referenced via an access method then the
429         // symbol is null.
430         //
431         if (lhs && lhs -> CastExpressionCast())
432             lhs = ((AstCastExpression*) lhs) -> expression;
433         while (lhs && lhs -> ParenthesizedExpressionCast())
434             lhs = ((AstParenthesizedExpression*) lhs) -> expression;
435         Symbol* sym = lhs ? lhs -> symbol : (Symbol*) NULL;
436 
437         //
438         // If the expression associated with the left-hand side is null,
439         // then we have an access method. Otherwise, a left-hand side is
440         // either an array access, a field access or a name. In the case of
441         // a FieldAccess or name, the left-hand side is resolved into a
442         // variable. For an array access, it is resolved into a type.
443         //
444         VariableSymbol* var = (sym ? sym -> VariableCast()
445                                : (VariableSymbol*) NULL);
446         return (! lhs ? ACCESSED_VAR
447                 : ! var ? ARRAY_VAR
448                 : var -> owner -> MethodCast() ? LOCAL_VAR
449                 : var -> ACC_STATIC() ? STATIC_VAR
450                 : FIELD_VAR);
451     }
452 
453 
GetTypeWords(const TypeSymbol * type)454     int GetTypeWords(const TypeSymbol* type)
455     {
456         return control.IsDoubleWordType(type) ? 2 : 1;
457     }
458 
459 
460     //
461     // methods to load and store values
462     //
463     void LoadLocal(int varno, const TypeSymbol*);
464     void StoreLocal(int varno, const TypeSymbol*);
465     void LoadLiteral(LiteralValue*, const TypeSymbol*);
466     void LoadImmediateInteger(i4);
467     int LoadVariable(VariableCategory, AstExpression*, bool = true);
468     int LoadArrayElement(const TypeSymbol*);
469     void StoreArrayElement(const TypeSymbol*);
470     void StoreField(AstExpression*);
471     void StoreVariable(VariableCategory, AstExpression*);
472 
LoadConstantAtIndex(u2 index)473     void LoadConstantAtIndex(u2 index)
474     {
475         if (index <= 255)
476         {
477             PutOp(OP_LDC);
478             PutU1((u1) index);
479         }
480         else
481         {
482             PutOp(OP_LDC_W);
483             PutU2(index);
484         }
485     }
486 
487     //
488     // These pools are sets that keep track of elements that have
489     // already been inserted in the constant pool.
490     //
491     SegmentPool segment_pool;
492 
493     Pair* double_constant_pool_index;
494     Pair* integer_constant_pool_index;
495     Pair* long_constant_pool_index;
496     Pair* float_constant_pool_index;
497     Pair* string_constant_pool_index;
498 
499     Pair utf8_constant_pool_index;
500     Pair class_constant_pool_index;
501 
502     Triplet* name_and_type_constant_pool_index;
503     Triplet* fieldref_constant_pool_index;
504     Triplet* methodref_constant_pool_index;
505 
RegisterNameAndType(Utf8LiteralValue * name,Utf8LiteralValue * type_name)506     u2 RegisterNameAndType(Utf8LiteralValue* name, Utf8LiteralValue* type_name)
507     {
508         assert(name && type_name && "null argument to RegisterNameAndType");
509 
510         if (! name_and_type_constant_pool_index)
511             name_and_type_constant_pool_index =
512                 new Triplet(segment_pool,
513                             control.Utf8_pool.symbol_pool.Length());
514 
515         u2 index = name_and_type_constant_pool_index ->
516             Image(name -> index, type_name -> index);
517         if (index == 0)
518         {
519             //
520             // Either the triplet is not in the constant pool, or the constant
521             // pool overflowed.
522             //
523             u2 name_index = RegisterUtf8(name);
524             u2 type_index = RegisterUtf8(type_name);
525             index = (u2) constant_pool.Length();
526             name_and_type_constant_pool_index ->
527                 Image(name -> index, type_name -> index) = index;
528             constant_pool.SetNext(new CPNameAndTypeInfo(name_index,
529                                                         type_index));
530         }
531         return index;
532     }
533 
534 
535     //
536     // Register a variable, including full control over the qualifying type
537     // emitted (which is not necessarily the variable's owner).
538     //
RegisterFieldref(const TypeSymbol * type,const VariableSymbol * variable)539     u2 RegisterFieldref(const TypeSymbol* type, const VariableSymbol* variable)
540     {
541         Utf8LiteralValue* class_name = type -> fully_qualified_name;
542         Utf8LiteralValue* field_name =
543             variable -> ExternalIdentity() -> Utf8_literal;
544         Utf8LiteralValue* field_type_name = variable -> signature;
545         assert(variable -> owner -> TypeCast());
546         assert(class_name && field_name && field_type_name &&
547                "null argument to RegisterFieldref");
548 
549         if (! fieldref_constant_pool_index)
550             fieldref_constant_pool_index =
551                 new Triplet(segment_pool,
552                             control.Utf8_pool.symbol_pool.Length());
553 
554         u2 name_type_index = RegisterNameAndType(field_name, field_type_name);
555         u2 index = fieldref_constant_pool_index ->
556             Image(class_name -> index, name_type_index);
557         if (index == 0)
558         {
559             //
560             // Either the triplet is not in the constant pool, or the constant
561             // pool overflowed.
562             //
563             u2 class_index = RegisterClass(type);
564             index = (u2) constant_pool.Length();
565             fieldref_constant_pool_index ->
566                 Image(class_name -> index, name_type_index) = index;
567             constant_pool.SetNext(new CPMemberInfo(CPInfo::CONSTANT_Fieldref,
568                                                    class_index,
569                                                    name_type_index));
570         }
571         return index;
572     }
573 
574     //
575     // Shortcut when we want the variable's containing type.
576     //
RegisterFieldref(const VariableSymbol * variable)577     u2 RegisterFieldref(const VariableSymbol* variable)
578     {
579         return RegisterFieldref(variable -> ContainingType(), variable);
580     }
581 
RegisterMethodref(const TypeSymbol * type,const MethodSymbol * method)582     u2 RegisterMethodref(const TypeSymbol* type, const MethodSymbol* method)
583     {
584         CPInfo::ConstantPoolTag kind = type -> ACC_INTERFACE()
585             ? CPInfo::CONSTANT_InterfaceMethodref
586             : CPInfo::CONSTANT_Methodref;
587         Utf8LiteralValue* class_name = type -> fully_qualified_name;
588         Utf8LiteralValue* method_name =
589             method -> ExternalIdentity() -> Utf8_literal;
590         Utf8LiteralValue* method_type = method -> signature;
591         assert(class_name && method_name && method_type &&
592                "null argument to RegisterMethodref");
593 
594         if (! methodref_constant_pool_index)
595             methodref_constant_pool_index =
596                 new Triplet(segment_pool,
597                             control.Utf8_pool.symbol_pool.Length());
598 
599         u2 name_type_index = RegisterNameAndType(method_name, method_type);
600         u2 index = methodref_constant_pool_index ->
601             Image(class_name -> index, name_type_index);
602         if (index == 0)
603         {
604             //
605             // Either the triplet is not in the constant pool, or the constant
606             // pool overflowed.
607             //
608             u2 class_name_index = RegisterClass(type);
609             index = (u2) constant_pool.Length();
610             methodref_constant_pool_index -> Image(class_name -> index,
611                                                    name_type_index) = index;
612             constant_pool.SetNext(new CPMemberInfo(kind, class_name_index,
613                                                    name_type_index));
614         }
615         return index;
616     }
617 
RegisterLibraryMethodref(const MethodSymbol * method)618     u2 RegisterLibraryMethodref(const MethodSymbol* method)
619     {
620         //
621         // The library method must exist. If it does not, flag an error.
622         //
623         if (method)
624             return RegisterMethodref(method -> containing_type, method);
625         library_method_not_found = true;
626         return 0;
627     }
628 
RegisterDouble(DoubleLiteralValue * lit)629     u2 RegisterDouble(DoubleLiteralValue* lit)
630     {
631         assert((lit != NULL) && "null argument to RegisterDouble");
632 
633         if (! double_constant_pool_index)
634             double_constant_pool_index =
635                 new Pair(segment_pool,
636                          control.double_pool.symbol_pool.Length());
637 
638         u2 index = (*double_constant_pool_index)[lit -> index];
639         if (index == 0)
640         {
641             //
642             // Either the pair is not in the constant pool, or the constant
643             // pool overflowed.
644             //
645             index = (u2) constant_pool.Length();
646             (*double_constant_pool_index)[lit -> index] = index;
647             constant_pool.SetNext(new CPDoubleInfo(lit -> value.HighWord(),
648                                                    lit -> value.LowWord()));
649         }
650         return index;
651     }
652 
653 
RegisterInteger(IntLiteralValue * lit)654     u2 RegisterInteger(IntLiteralValue* lit)
655     {
656         assert((lit != NULL) && "null argument to RegisterInteger");
657 
658         if (! integer_constant_pool_index)
659             integer_constant_pool_index =
660                 new Pair(segment_pool, control.int_pool.symbol_pool.Length());
661 
662         u2 index = (*integer_constant_pool_index)[lit -> index];
663         if (index == 0)
664         {
665             //
666             // Either the pair is not in the constant pool, or the constant
667             // pool overflowed.
668             //
669             index = (u2) constant_pool.Length();
670             (*integer_constant_pool_index)[lit -> index] = index;
671             constant_pool.SetNext(new CPIntegerInfo((u4) lit -> value));
672         }
673         return index;
674     }
675 
676 
FindInteger(IntLiteralValue * lit)677     u2 FindInteger(IntLiteralValue* lit)
678     {
679         return (lit && integer_constant_pool_index
680                 ? (*integer_constant_pool_index)[lit -> index] : 0);
681     }
682 
683 
RegisterLong(LongLiteralValue * lit)684     u2 RegisterLong(LongLiteralValue* lit)
685     {
686         assert((lit != NULL) && "null argument to RegisterLong");
687 
688         if (! long_constant_pool_index)
689             long_constant_pool_index =
690                 new Pair(segment_pool, control.long_pool.symbol_pool.Length());
691 
692         u2 index = (*long_constant_pool_index)[lit -> index];
693         if (index == 0)
694         {
695             //
696             // Either the pair is not in the constant pool, or the constant
697             // pool overflowed.
698             //
699             index = (u2) constant_pool.Length();
700             (*long_constant_pool_index)[lit -> index] = index;
701             constant_pool.SetNext(new CPLongInfo(lit -> value.HighWord(),
702                                                  lit -> value.LowWord()));
703         }
704         return index;
705     }
706 
707 
RegisterFloat(FloatLiteralValue * lit)708     u2 RegisterFloat(FloatLiteralValue* lit)
709     {
710         assert((lit != NULL) && "null argument to RegisterFloat");
711 
712         if (! float_constant_pool_index)
713             float_constant_pool_index =
714                 new Pair(segment_pool, control.float_pool.symbol_pool.Length());
715 
716         u2 index = (*float_constant_pool_index)[lit -> index];
717         if (index == 0)
718         {
719             //
720             // Either the pair is not in the constant pool, or the constant
721             // pool overflowed.
722             //
723             index = (u2) constant_pool.Length();
724             (*float_constant_pool_index)[lit -> index] = index;
725             constant_pool.SetNext(new CPFloatInfo(lit -> value.Word()));
726         }
727         return index;
728     }
729 
730 
RegisterUtf8(Utf8LiteralValue * lit)731     u2 RegisterUtf8(Utf8LiteralValue* lit)
732     {
733         assert(lit != NULL && "null argument to RegisterUtf8");
734 
735         u2 index = utf8_constant_pool_index[lit -> index];
736         if (index == 0)
737         {
738             //
739             // Either the pair is not in the constant pool, or the constant
740             // pool overflowed.
741             //
742             index = (u2) constant_pool.Length();
743             utf8_constant_pool_index[lit -> index] = index;
744             constant_pool.SetNext(new CPUtf8Info(lit -> value,
745                                                  lit -> length));
746             if (lit -> length > 0xffff)
747                 string_overflow = true;
748         }
749         return index;
750     }
751 
RegisterName(const NameSymbol * sym)752     u2 RegisterName(const NameSymbol* sym)
753     {
754         return RegisterUtf8(sym -> Utf8_literal);
755     }
756 
RegisterString(Utf8LiteralValue * lit)757     u2 RegisterString(Utf8LiteralValue* lit)
758     {
759         assert(lit && "null argument to RegisterString");
760         if (! string_constant_pool_index)
761             string_constant_pool_index =
762                 new Pair(segment_pool, control.Utf8_pool.symbol_pool.Length());
763 
764         u2 index = (*string_constant_pool_index)[lit -> index];
765         if (index == 0)
766         {
767             //
768             // Either the pair is not in the constant pool, or the constant
769             // pool overflowed.
770             //
771             u2 utf_index = RegisterUtf8(lit);
772             index = (u2) constant_pool.Length();
773             (*string_constant_pool_index)[lit -> index] = index;
774             constant_pool.SetNext(new CPStringInfo(utf_index));
775         }
776         return index;
777     }
778 
RegisterClass(const TypeSymbol * type)779     u2 RegisterClass(const TypeSymbol* type)
780     {
781         Utf8LiteralValue* lit = type -> num_dimensions
782             ? type -> signature : type -> fully_qualified_name;
783         assert(type && lit && "null argument to RegisterClass");
784         u2 index = class_constant_pool_index[lit -> index];
785         if (index == 0)
786         {
787             //
788             // Either the pair is not in the constant pool, or the constant
789             // pool overflowed.
790             //
791             u2 utf_index = RegisterUtf8(lit);
792             index = (u2) constant_pool.Length();
793             class_constant_pool_index[lit -> index] = index;
794             constant_pool.SetNext(new CPClassInfo(utf_index));
795             //
796             // All nested classes must appear in the InnerClasses attribute, as
797             // well.
798             //
799             if (type -> IsNested())
800             {
801                 if (! inner_classes_attribute)
802                 {
803                     inner_classes_attribute = new InnerClassesAttribute
804                         (RegisterUtf8(control.InnerClasses_literal));
805                     AddAttribute(inner_classes_attribute);
806                 }
807                 AccessFlags flags = type -> Flags();
808                 //
809                 // Types are never marked strictfp in .class files. This can be
810                 // reverse engineered from <init> and <clinit> methods; the
811                 // only time when these methods don't exist is in interfaces
812                 // that have no runtime expression evaluations, so no
813                 // information is lost by clearing the flag.
814                 //
815                 flags.ResetACC_STRICTFP();
816                 inner_classes_attribute ->
817                     AddInnerClass(index, type -> IsLocal() ? 0
818                                   : RegisterClass(type -> ContainingType()),
819                                   type -> Anonymous() ? 0
820                                   : RegisterName(type -> name_symbol), flags);
821             }
822         }
823         return index;
824     }
825 
826 
827     //
828     //  Methods to write out the byte code
829     //
CreateDeprecatedAttribute()830     DeprecatedAttribute* CreateDeprecatedAttribute()
831     {
832         return new DeprecatedAttribute(RegisterUtf8
833                                        (control.Deprecated_literal));
834     }
835 
CreateSyntheticAttribute()836     SyntheticAttribute* CreateSyntheticAttribute()
837     {
838         return new SyntheticAttribute(RegisterUtf8(control.Synthetic_literal));
839     }
840 
CreateEnclosingMethodAttribute(MethodSymbol * sym)841     EnclosingMethodAttribute* CreateEnclosingMethodAttribute(MethodSymbol* sym)
842     {
843         u2 attr_name = RegisterUtf8(control.EnclosingMethod_literal);
844         u2 type_index = RegisterClass(sym -> containing_type);
845         u2 name_type_index =
846             (sym -> name_symbol == control.block_init_name_symbol ||
847              sym -> name_symbol == control.clinit_name_symbol) ? 0
848             : RegisterNameAndType(sym -> ExternalIdentity() -> Utf8_literal,
849                                   sym -> signature);
850         return new EnclosingMethodAttribute(attr_name, type_index,
851                                             name_type_index);
852     }
853 
854 
855     //
856     // Methods to generate expressions.
857     //
858     int EmitExpression(AstExpression*, bool = true);
859     int EmitName(AstName*, bool);
860     int EmitArrayCreationExpression(AstArrayCreationExpression*, bool = true);
861     int EmitAssignmentExpression(AstAssignmentExpression*, bool);
862     int EmitBinaryExpression(AstBinaryExpression*, bool);
863     int EmitInstanceofExpression(AstInstanceofExpression*, bool);
864     int EmitCastExpression(AstCastExpression*, bool);
865     void EmitCast(TypeSymbol*, TypeSymbol*);
866     int EmitClassCreationExpression(AstClassCreationExpression*, bool);
867     int EmitConditionalExpression(AstConditionalExpression*, bool);
868     int EmitFieldAccess(AstFieldAccess*, bool = true);
869     AstExpression* VariableExpressionResolution(AstExpression*);
870     TypeSymbol* VariableTypeResolution(AstExpression*, VariableSymbol*);
871     TypeSymbol* MethodTypeResolution(AstExpression*, MethodSymbol*);
872     void EmitFieldAccessLhsBase(AstExpression*);
873     void EmitFieldAccessLhs(AstExpression*);
874     int EmitMethodInvocation(AstMethodInvocation*, bool);
875     void EmitNewArray(unsigned, const TypeSymbol*);
876     int EmitPostUnaryExpression(AstPostUnaryExpression*, bool);
877     void EmitPostUnaryExpressionArray(AstPostUnaryExpression*, bool);
878     void EmitPostUnaryExpressionField(VariableCategory,
879                                       AstPostUnaryExpression*, bool);
880     void EmitPostUnaryExpressionSimple(VariableCategory,
881                                        AstPostUnaryExpression*, bool);
882     int EmitPreUnaryExpression(AstPreUnaryExpression*, bool);
883     void EmitPreUnaryIncrementExpression(AstPreUnaryExpression*, bool);
884     void EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression*, bool);
885     void EmitPreUnaryIncrementExpressionField(VariableCategory,
886                                               AstPreUnaryExpression*, bool);
887     void EmitPreUnaryIncrementExpressionSimple(VariableCategory,
888                                                AstPreUnaryExpression*, bool);
889     void EmitThisInvocation(AstThisCall*);
890     void EmitSuperInvocation(AstSuperCall*);
891     void ConcatenateString(AstBinaryExpression*, bool);
892     void AppendString(AstExpression*, bool);
893     void EmitStringAppendMethod(TypeSymbol*);
894     void ChangeStack(int);
895     void ResolveAccess(AstExpression*);
896     int GenerateClassAccess(AstClassLiteral*, bool);
897     void GenerateClassAccessMethod();
898     void GenerateAssertVariableInitializer(TypeSymbol*, VariableSymbol*);
899     void EmitCheckForNull(AstExpression* expr, bool = true);
900 
901     //
902     // Methods to process statements
903     //
904     void CompileConstructor(AstConstructorDeclaration*,
905                             Tuple<AstVariableDeclarator*>&, bool);
906 
907     void BeginMethod(int, MethodSymbol*);
908     void EndMethod(int, MethodSymbol*);
909     void DeclareField(VariableSymbol*);
910     void InitializeVariable(AstVariableDeclarator*);
911     void InitializeArray(const TypeSymbol*, AstArrayInitializer*, bool = true);
912     void DeclareLocalVariable(AstVariableDeclarator*);
913     bool EmitStatement(AstStatement*);
914     void EmitReturnStatement(AstReturnStatement*);
915     bool EmitSynchronizedStatement(AstSynchronizedStatement*);
916     bool EmitBlockStatement(AstBlock*);
917     void EmitStatementExpression(AstExpression*);
918     bool EmitSwitchStatement(AstSwitchStatement*);
919     bool EmitSwitchBlockStatement(AstSwitchBlockStatement*, bool);
920     void CloseSwitchLocalVariables(AstBlock*, u2 op_start);
921     void EmitTryStatement(AstTryStatement*);
922     void EmitAssertStatement(AstAssertStatement*);
923     void EmitForeachStatement(AstForeachStatement*);
924     void EmitBranchIfExpression(AstExpression*, bool, Label&,
925                                 AstStatement* = NULL);
926     void EmitBranch(Opcode, Label&, AstStatement* = NULL);
927     int CompleteCall(MethodSymbol*, int, bool = true, TypeSymbol* = NULL);
928 
929     AstExpression* StripNops(AstExpression*);
930     bool IsNop(AstBlock*);
931 
932     void EmitArrayAccessLhs(AstArrayAccess* expression);
EmitArrayAccessRhs(AstArrayAccess * expression)933     int EmitArrayAccessRhs(AstArrayAccess* expression)
934     {
935         EmitArrayAccessLhs(expression); // get array address and index
936         return LoadArrayElement(expression -> Type());
937     }
938 
939     // Return the OP_IF... bytecode that has the opposite meaning
InvertIfOpCode(Opcode opc)940     Opcode InvertIfOpCode(Opcode opc)
941     {
942         //
943         // Unfortunately, the JVMS does not nicely specify symmetric opcodes;
944         // we must treat even-odd and odd-even pairs differently.
945         //
946         if (opc >= OP_IFNULL)
947         {
948             assert(opc <= OP_IFNONNULL);
949             return (Opcode) (opc ^ 1);
950         }
951         assert(OP_IFEQ <= opc && opc <= OP_IF_ACMPNE);
952         return (Opcode) (((opc + 1) ^ 1) - 1);
953     }
954 
GenerateReturn(TypeSymbol * type)955     void GenerateReturn(TypeSymbol* type)
956     {
957         PutOp((control.IsSimpleIntegerValueType(type) ||
958                type == control.boolean_type) ? OP_IRETURN
959               : type == control.long_type ? OP_LRETURN
960               : type == control.float_type ? OP_FRETURN
961               : type == control.double_type ? OP_DRETURN
962               : OP_ARETURN);
963     }
964 
965 
966     void PutOp(Opcode);
967 
968     void PutOpWide(Opcode, u2 var);
969 
970     void PutOpIINC(u2 var, int val);
971 
972     //
973     //  Methods to insert values into byte code
974     //
PutI1(i1 i)975     void PutI1(i1 i)
976     {
977         code_attribute -> AddCode(i & 0xff);
978     }
979 
PutI2(i2 i)980     void PutI2(i2 i)
981     {
982         code_attribute -> AddCode((i >> 8) & 0xff);
983         code_attribute -> AddCode(i & 0xff);
984     }
985 
PutU1(u1 u)986     void PutU1(u1 u)
987     {
988         code_attribute -> AddCode(u & 0xff);
989     }
990 
PutU2(u2 u)991     void PutU2(u2 u)
992     {
993         code_attribute -> AddCode((u >> 8) & 0xff);
994         code_attribute -> AddCode(u & 0xff);
995     }
996 
PutU4(u4 u)997     void PutU4(u4 u)
998     {
999         code_attribute -> AddCode((u >> 24));
1000         code_attribute -> AddCode((u >> 16) & 0xff);
1001         code_attribute -> AddCode((u >>  8) & 0xff);
1002         code_attribute -> AddCode(u & 0xff);
1003     }
1004 
1005     void FinishCode();
1006 
Reset()1007     void Reset()
1008     {
1009         constant_pool.Reset();
1010         fields.Reset();
1011         methods.Reset();
1012         attributes.Reset();
1013         this_class = super_class = 0;
1014     }
1015 
1016 public:
1017     ByteCode(TypeSymbol*);
1018 
~ByteCode()1019     ~ByteCode()
1020     {
1021         delete double_constant_pool_index;
1022         delete integer_constant_pool_index;
1023         delete long_constant_pool_index;
1024         delete float_constant_pool_index;
1025         delete string_constant_pool_index;
1026 
1027         delete name_and_type_constant_pool_index;
1028         delete fieldref_constant_pool_index;
1029         delete methodref_constant_pool_index;
1030     }
1031 
1032     void GenerateCode();
1033 };
1034 
1035 #ifdef HAVE_JIKES_NAMESPACE
1036 } // Close namespace Jikes block
1037 #endif
1038 
1039 #endif // bytecode_INCLUDED
1040 
1041