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