001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.classloader; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.SizeConstants; 017 import org.jikesrvm.runtime.Statics; 018 import org.vmmagic.pragma.Inline; 019 import org.vmmagic.unboxed.Offset; 020 021 /** 022 * Provides minimal abstraction layer to a stream of bytecodes 023 * from the code attribute of a method. 024 */ 025 public class BytecodeStream implements BytecodeConstants, ClassLoaderConstants, SizeConstants { 026 private final NormalMethod method; 027 private final int bcLength; 028 private final byte[] bcodes; 029 private int bcIndex; 030 private int opcode; 031 private boolean wide; 032 033 /** 034 * @param m the method containing the bytecodes 035 * @param bc the array of bytecodes 036 */ 037 public BytecodeStream(NormalMethod m, byte[] bc) { 038 method = m; 039 bcodes = bc; 040 bcLength = bc.length; 041 bcIndex = 0; 042 } 043 044 /** 045 * Returns the method that this bytecode stream is from 046 * @return method 047 */ 048 public final NormalMethod getMethod() { 049 return method; 050 } 051 052 /** 053 * Returns the declaring class that this bytecode stream is from 054 * @return method 055 */ 056 public final RVMClass getDeclaringClass() { 057 return method.getDeclaringClass(); 058 } 059 060 /** 061 * Returns the length of the bytecode stream 062 * Returns 0 if the method doesn't have any bytecodes 063 * (i.e. is abstract or native) 064 * @return bytecode stream length 065 */ 066 public final int length() { 067 return bcLength; 068 } 069 070 /** 071 * Returns the current bytecode index 072 * @return the current bytecode index 073 */ 074 public final int index() { 075 return bcIndex; 076 } 077 078 /** 079 * Resets the stream to the beginning 080 * @see #reset(int) 081 */ 082 public final void reset() { 083 reset(0); 084 } 085 086 /** 087 * Resets the stream to a given position 088 * Use with caution 089 * @param index the position to reset the stream to 090 * @see #reset() 091 */ 092 public final void reset(int index) { 093 bcIndex = index; 094 } 095 096 /** 097 * Does the stream have more bytecodes in it? 098 * @return whether there are more bytecodes 099 */ 100 public final boolean hasMoreBytecodes() { 101 return bcIndex < bcLength; 102 } 103 104 /** 105 * Returns the opcode of the next instruction in the sequence 106 * without advancing to it 107 * @return the opcode of the next instruction 108 * @see #nextInstruction() 109 */ 110 public final int peekNextOpcode() { 111 if (VM.VerifyAssertions) VM._assert(bcIndex < bcLength); 112 return getUnsignedByte(bcIndex); 113 } 114 115 /** 116 * Sets up the next instruction in the sequence 117 * @return the opcode of the next instruction 118 * @see #peekNextOpcode() 119 */ 120 public final int nextInstruction() { 121 if (VM.VerifyAssertions) VM._assert(bcIndex < bcLength); 122 opcode = readUnsignedByte(); 123 wide = (opcode == JBC_wide); 124 return opcode; 125 } 126 127 /** 128 * Returns the opcode of the current instruction in the sequence.<p> 129 * Note: if skipInstruction has been called, but nextInstruction has not, 130 * this method will return the opcode of the skipped instruction! 131 * @return the opcode of the current instruction 132 * @see #nextInstruction() 133 * @see #isWide() 134 */ 135 public final int getOpcode() { 136 return opcode; 137 } 138 139 /** 140 * Are we currently processing a wide instruction? 141 * @return {@code true} if current instruction is wide 142 * @see #nextInstruction() 143 * @see #getOpcode() 144 */ 145 public final boolean isWide() { 146 return wide; 147 } 148 149 /** 150 * Skips the current instruction 151 * @see #skipInstruction(int,boolean) 152 */ 153 public final void skipInstruction() { 154 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 155 int len = JBC_length[opcode] - 1; 156 if (wide) len += len; 157 if (len >= 0) { 158 bcIndex += len; 159 } else { 160 skipSpecialInstruction(opcode); 161 } 162 } 163 164 /** 165 * Skips the current instruction (without using the opcode field) 166 * A slightly optimized version of skipInstruction() 167 * @param opcode current opcode 168 * @param wide whether current instruction follows wide 169 * @see #skipInstruction() 170 */ 171 public final void skipInstruction(int opcode, boolean wide) { 172 if (VM.VerifyAssertions) VM._assert(bcIndex < bcLength); 173 int len = JBC_length[opcode] - 1; 174 if (wide) len += len; 175 if (len >= 0) { 176 bcIndex += len; 177 } else { 178 skipSpecialInstruction(opcode); 179 } 180 } 181 182 /** 183 * Returns a signed byte value 184 * Used for bipush 185 * @return signed byte value 186 */ 187 public final int getByteValue() { 188 if (VM.VerifyAssertions) VM._assert(opcode == JBC_bipush); 189 return readSignedByte(); 190 } 191 192 /** 193 * Returns a signed short value 194 * Used for sipush 195 * @return signed short value 196 */ 197 public final int getShortValue() { 198 if (VM.VerifyAssertions) VM._assert(opcode == JBC_sipush); 199 return readSignedShort(); 200 } 201 202 /** 203 * Returns the number of the local (as an unsigned byte) 204 * Used for iload, lload, fload, dload, aload, 205 * istore, lstore, fstore, dstore, astore, 206 * iinc, ret 207 * @return local number 208 * @see #getWideLocalNumber() 209 */ 210 public final int getLocalNumber() { 211 if (VM.VerifyAssertions) { 212 VM._assert((opcode >= JBC_iload && opcode <= JBC_aload) || 213 (opcode >= JBC_istore && opcode <= JBC_astore) || 214 opcode == JBC_iinc || 215 opcode == JBC_ret); 216 } 217 return readUnsignedByte(); 218 } 219 220 /** 221 * Returns the wide number of the local (as an unsigned short) 222 * Used for iload, lload, fload, dload, aload, 223 * istore, lstore, fstore, dstore, astore, 224 * iinc prefixed by wide 225 * @return wide local number 226 * @see #getLocalNumber() 227 */ 228 public final int getWideLocalNumber() { 229 if (VM.VerifyAssertions) { 230 VM._assert(wide && 231 ((opcode >= JBC_iload && opcode <= JBC_aload) || 232 (opcode >= JBC_istore && opcode <= JBC_astore) || 233 opcode == JBC_iinc)); 234 } 235 return readUnsignedShort(); 236 } 237 238 /** 239 * Returns an increment value (as a signed byte).<p> 240 * Used for iinc 241 * @return increment 242 * @see #getWideIncrement() 243 */ 244 public final int getIncrement() { 245 if (VM.VerifyAssertions) VM._assert(opcode == JBC_iinc); 246 return readSignedByte(); 247 } 248 249 /** 250 * Returns an increment value (as a signed short).<p> 251 * Used for iinc prefixed by wide 252 * @return wide increment 253 * @see #getIncrement() 254 */ 255 public final int getWideIncrement() { 256 if (VM.VerifyAssertions) VM._assert(wide && opcode == JBC_iinc); 257 return readSignedShort(); 258 } 259 260 /** 261 * Returns the offset of the branch (as a signed short).<p> 262 * Used for {@code if<cond>}, {@code ificmp<cond>}, {@code ifacmp<cond>}, 263 * {@code goto}, {@code jsr} 264 * @return branch offset 265 * @see #getWideBranchOffset() 266 */ 267 public final int getBranchOffset() { 268 if (VM.VerifyAssertions) { 269 VM._assert((opcode >= JBC_ifeq && opcode <= JBC_ifle) || 270 (opcode >= JBC_if_icmpeq && opcode <= JBC_if_icmple) || 271 opcode == JBC_if_acmpeq || 272 opcode == JBC_if_acmpne || 273 opcode == JBC_ifnull || 274 opcode == JBC_ifnonnull || 275 opcode == JBC_goto || 276 opcode == JBC_jsr); 277 } 278 return readSignedShort(); 279 } 280 281 /** 282 * Returns the wide offset of the branch (as a signed int).<p> 283 * Used for goto_w, jsr_w 284 * @return wide branch offset 285 * @see #getBranchOffset() 286 */ 287 public final int getWideBranchOffset() { 288 if (VM.VerifyAssertions) { 289 VM._assert(opcode == JBC_goto_w || opcode == JBC_jsr_w); 290 } 291 return readSignedInt(); 292 } 293 294 /** 295 * Skips the padding of a switch instruction.<p> 296 * Used for tableswitch, lookupswitch 297 */ 298 public final void alignSwitch() { 299 if (VM.VerifyAssertions) { 300 VM._assert(opcode == JBC_tableswitch || opcode == JBC_lookupswitch); 301 } 302 int align = bcIndex & 3; 303 if (align != 0) bcIndex += 4 - align; // eat padding 304 } 305 306 /** 307 * Returns the default offset of the switch (as a signed int).<p> 308 * Used for tableswitch, lookupswitch 309 * @return default switch offset 310 */ 311 public final int getDefaultSwitchOffset() { 312 if (VM.VerifyAssertions) { 313 VM._assert(opcode == JBC_tableswitch || opcode == JBC_lookupswitch); 314 } 315 return readSignedInt(); 316 } 317 318 /** 319 * Returns the lowest value of the tableswitch (as a signed int).<p> 320 * Used for tableswitch 321 * @return lowest switch value 322 * @see #getHighSwitchValue() 323 */ 324 public final int getLowSwitchValue() { 325 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch); 326 return readSignedInt(); 327 } 328 329 /** 330 * Returns the highest value of the tableswitch (as a signed int).<p> 331 * Used for tableswitch 332 * @return highest switch value 333 * @see #getLowSwitchValue() 334 */ 335 public final int getHighSwitchValue() { 336 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch); 337 return readSignedInt(); 338 } 339 340 /** 341 * Skips the offsets of a tableswitch instruction.<p> 342 * Used for tableswitch 343 * @param num the number of offsets to skip 344 * @see #getTableSwitchOffset(int) 345 */ 346 public final void skipTableSwitchOffsets(int num) { 347 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch); 348 bcIndex += (num << LOG_BYTES_IN_INT); 349 } 350 351 /** 352 * Returns the numbered offset of the tableswitch (as a signed int).<p> 353 * Used for tableswitch.<p> 354 * The "cursor" has to be positioned at the start of the offset table.<p> 355 * NOTE: Will NOT advance cursor 356 * @param num the number of the offset to retrieve 357 * @return switch offset 358 */ 359 public final int getTableSwitchOffset(int num) { 360 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch); 361 return getSignedInt(bcIndex + (num << LOG_BYTES_IN_INT)); 362 } 363 364 /** 365 * Returns the offset for a given value of the tableswitch (as a signed int) 366 * or 0 if the value is out of range..<p> 367 * Used for tableswitch.<p> 368 * The "cursor" has to be positioned at the start of the offset table.<p> 369 * NOTE: Will NOT advance cursor 370 * @param value the value to retrieve offset for 371 * @param low the lowest value of the tableswitch 372 * @param high the highest value of the tableswitch 373 * @return switch offset 374 */ 375 public final int computeTableSwitchOffset(int value, int low, int high) { 376 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch); 377 if (value < low || value > high) return 0; 378 return getSignedInt(bcIndex + ((value - low) << LOG_BYTES_IN_INT)); 379 } 380 381 /** 382 * Returns the number of match-offset pairs in the lookupswitch 383 * (as a signed int).<p> 384 * Used for lookupswitch 385 * @return number of switch pairs 386 */ 387 public final int getSwitchLength() { 388 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch); 389 return readSignedInt(); 390 } 391 392 /** 393 * Skips the match-offset pairs of a lookupswitch instruction.<p> 394 * Used for lookupswitch 395 * @param num the number of match-offset pairs to skip 396 * @see #getLookupSwitchValue(int) 397 * @see #getLookupSwitchOffset(int) 398 */ 399 public final void skipLookupSwitchPairs(int num) { 400 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch); 401 bcIndex += (num << (LOG_BYTES_IN_INT + 1)); 402 } 403 404 /** 405 * Returns the numbered offset of the lookupswitch (as a signed int).<p> 406 * Used for lookupswitch.<p> 407 * The "cursor" has to be positioned at the start of the pair table.<p> 408 * NOTE: Will NOT advance cursor 409 * @param num the number of the offset to retrieve 410 * @return switch offset 411 * @see #getLookupSwitchValue(int) 412 */ 413 public final int getLookupSwitchOffset(int num) { 414 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch); 415 return getSignedInt(bcIndex + (num << (LOG_BYTES_IN_INT + 1)) + BYTES_IN_INT); 416 } 417 418 /** 419 * Returns the numbered value of the lookupswitch (as a signed int).<p> 420 * Used for lookupswitch.<p> 421 * The "cursor" has to be positioned at the start of the pair table.<p> 422 * NOTE: Will NOT advance cursor 423 * @param num the number of the value to retrieve 424 * @return switch value 425 * @see #getLookupSwitchOffset(int) 426 */ 427 public final int getLookupSwitchValue(int num) { 428 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch); 429 return getSignedInt(bcIndex + (num << (LOG_BYTES_IN_INT + 1))); 430 } 431 432 /** 433 * Returns the offset for a given value of the lookupswitch 434 * (as a signed int) or 0 if the value is not in the table..<p> 435 * Used for lookupswitch.<p> 436 * The "cursor" has to be positioned at the start of the offset table. 437 * <p> 438 * NOTE: Will NOT advance cursor.<p> 439 * WARNING: Uses LINEAR search.<p> 440 * XXX Whoever has time on their hands can 441 * re-implement this as a binary search. 442 * @param value the value to retrieve offset for 443 * @param num the number of match-offset pairs in the lookupswitch 444 * @return switch offset 445 */ 446 public final int computeLookupSwitchOffset(int value, int num) { 447 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch); 448 for (int i = 0; i < num; i++) { 449 if (getSignedInt(bcIndex + (i << (LOG_BYTES_IN_INT + 1))) == value) { 450 return getSignedInt(bcIndex + (i << (LOG_BYTES_IN_INT + 1)) + BYTES_IN_INT); 451 } 452 } 453 return 0; 454 } 455 456 /** 457 * Returns a reference to a field.<p> 458 * Used for getstatic, putstatic, getfield, putfield 459 * @return field reference 460 */ 461 public final FieldReference getFieldReference() { 462 if (VM.VerifyAssertions) { 463 VM._assert(opcode == JBC_getstatic || 464 opcode == JBC_putstatic || 465 opcode == JBC_getfield || 466 opcode == JBC_putfield); 467 } 468 return getDeclaringClass().getFieldRef(readUnsignedShort()); 469 } 470 471 /** 472 * Returns a reference to a field, for use prior to the class being loaded.<p> 473 * Used for getstatic, putstatic, getfield, putfield 474 * @return field reference 475 */ 476 public final FieldReference getFieldReference(int[] constantPool) { 477 if (VM.VerifyAssertions) { 478 VM._assert(opcode == JBC_getstatic || 479 opcode == JBC_putstatic || 480 opcode == JBC_getfield || 481 opcode == JBC_putfield); 482 } 483 return ClassFileReader.getFieldRef(constantPool, readUnsignedShort()); 484 } 485 /** 486 * Returns a reference to a field.<p> 487 * Used for invokevirtual, invokespecial, invokestatic, invokeinterface 488 * @return method reference 489 */ 490 public final MethodReference getMethodReference() { 491 if (VM.VerifyAssertions) { 492 VM._assert(opcode == JBC_invokevirtual || 493 opcode == JBC_invokespecial || 494 opcode == JBC_invokestatic || 495 opcode == JBC_invokeinterface); 496 } 497 return getDeclaringClass().getMethodRef(readUnsignedShort()); 498 } 499 500 /** 501 * Returns a reference to a field, for use prior to the class being loaded.<p> 502 * Used for invokevirtual, invokespecial, invokestatic, invokeinterface 503 * @return method reference 504 */ 505 public final MethodReference getMethodReference(int[] constantPool) { 506 if (VM.VerifyAssertions) { 507 VM._assert(opcode == JBC_invokevirtual || 508 opcode == JBC_invokespecial || 509 opcode == JBC_invokestatic || 510 opcode == JBC_invokeinterface); 511 } 512 return ClassFileReader.getMethodRef(constantPool, readUnsignedShort()); 513 } 514 515 /** 516 * Skips the extra stuff after an invokeinterface instruction.<p> 517 * Used for invokeinterface 518 */ 519 public final void alignInvokeInterface() { 520 if (VM.VerifyAssertions) VM._assert(opcode == JBC_invokeinterface); 521 bcIndex += 2; // eat superfluous stuff 522 } 523 524 /** 525 * Returns the type reference (as a RVMType).<p> 526 * Used for new, anewarray, checkcast, instanceof, multianewarray 527 * @return type reference 528 */ 529 public final TypeReference getTypeReference() { 530 if (VM.VerifyAssertions) { 531 VM._assert(opcode == JBC_new || 532 opcode == JBC_anewarray || 533 opcode == JBC_checkcast || 534 opcode == JBC_instanceof || 535 opcode == JBC_multianewarray); 536 } 537 int index = readUnsignedShort(); 538 return getDeclaringClass().getTypeRef(index); 539 } 540 541 /** 542 * Returns the element type (primitive) of the array (as an unsigned byte).<p> 543 * Used for newarray 544 * @return array element type 545 * @see #getPrimitiveArrayType() 546 * @see #getPrimitiveArrayType(int) 547 */ 548 public final int getArrayElementType() { 549 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray); 550 return readUnsignedByte(); 551 } 552 553 /** 554 * Returns the type of the array of given primitive type (as a RVMType).<p> 555 * Used for newarray 556 * @param etype element type 557 * @return array type 558 * @see #getArrayElementType() 559 * @see #getPrimitiveArrayType() 560 */ 561 public final RVMArray getPrimitiveArrayType(int etype) { 562 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray); 563 return RVMArray.getPrimitiveArrayType(etype); 564 } 565 566 /** 567 * Returns the type of the primitive array (as a RVMType).<p> 568 * Used for newarray 569 * @return array type 570 * @see #getArrayElementType() 571 * @see #getPrimitiveArrayType(int) 572 */ 573 public final RVMType getPrimitiveArrayType() { 574 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray); 575 int etype = readUnsignedByte(); 576 return RVMArray.getPrimitiveArrayType(etype); 577 } 578 579 /** 580 * Returns the type of the array of given object type (as a RVMType).<p> 581 * Used for anewarray 582 * @param klass element type 583 * @return array type 584 * @see #getTypeReference() 585 * @see #getObjectArrayType() 586 */ 587 public final RVMType getObjectArrayType(RVMType klass) { 588 if (VM.VerifyAssertions) VM._assert(opcode == JBC_anewarray); 589 return klass.getArrayTypeForElementType(); 590 } 591 592 /** 593 * Returns the type of the object array (as a RVMType).<p> 594 * Used for anewarray 595 * @return array type 596 * @see #getObjectArrayType(RVMType) 597 */ 598 public final TypeReference getObjectArrayType() { 599 if (VM.VerifyAssertions) VM._assert(opcode == JBC_anewarray); 600 TypeReference klass = getTypeReference(); 601 return klass.getArrayTypeForElementType(); 602 } 603 604 /** 605 * Returns the dimension of the array (as an unsigned byte).<p> 606 * Used for multianewarray 607 * @return array dimension 608 */ 609 public final int getArrayDimension() { 610 if (VM.VerifyAssertions) VM._assert(opcode == JBC_multianewarray); 611 return readUnsignedByte(); 612 } 613 614 /** 615 * Returns the opcode of the wide instruction.<p> 616 * Used for wide.<p> 617 * Can be one of iload, lload, fload, dload, aload, 618 * istore, lstore, fstore, dstore, astore, iinc 619 * @return the opcode of the wide instruction 620 */ 621 public final int getWideOpcode() { 622 if (VM.VerifyAssertions) VM._assert(wide && opcode == JBC_wide); 623 opcode = readUnsignedByte(); 624 if (VM.VerifyAssertions) { 625 VM._assert((opcode >= JBC_iload && opcode <= JBC_aload) || 626 (opcode >= JBC_istore && opcode <= JBC_astore) || 627 opcode == JBC_iinc); 628 } 629 return opcode; 630 } 631 632 /** 633 * Returns the constant pool index of a constant (as an unsigned byte).<p> 634 * Used for ldc 635 * @return constant index 636 * @see #getWideConstantIndex() 637 * @see #getConstantType(int) 638 * @see #getIntConstant(int) 639 * @see #getLongConstant(int) 640 * @see #getFloatConstant(int) 641 * @see #getDoubleConstant(int) 642 * @see #getStringConstant(int) 643 */ 644 public final int getConstantIndex() { 645 if (VM.VerifyAssertions) VM._assert(opcode == JBC_ldc); 646 return readUnsignedByte(); 647 } 648 649 /** 650 * Returns the wide constant pool index of a constant (as an unsigned short).<p> 651 * Used for ldc_w, ldc2_w 652 * @return wide constant index 653 * @see #getConstantIndex() 654 * @see #getConstantType(int) 655 * @see #getIntConstant(int) 656 * @see #getLongConstant(int) 657 * @see #getFloatConstant(int) 658 * @see #getDoubleConstant(int) 659 * @see #getStringConstant(int) 660 */ 661 public final int getWideConstantIndex() { 662 if (VM.VerifyAssertions) { 663 VM._assert(opcode == JBC_ldc_w || opcode == JBC_ldc2_w); 664 } 665 return readUnsignedShort(); 666 } 667 668 /** 669 * Returns the type of a constant at a given constant pool index (as a byte).<p> 670 * Used for ldc, ldc_w, ldc2_w 671 * @return constant type 672 * @see #getConstantIndex() 673 * @see #getWideConstantIndex() 674 * @see #getIntConstant(int) 675 * @see #getLongConstant(int) 676 * @see #getFloatConstant(int) 677 * @see #getDoubleConstant(int) 678 * @see #getStringConstant(int) 679 */ 680 public final byte getConstantType(int index) { 681 if (VM.VerifyAssertions) { 682 VM._assert(opcode == JBC_ldc || opcode == JBC_ldc_w || opcode == JBC_ldc2_w); 683 } 684 byte desc = getDeclaringClass().getLiteralDescription(index); 685 return desc; 686 } 687 688 /** 689 * Returns the constant at a given constant pool index (as an int).<p> 690 * Used for ldc, ldc_w 691 * @return int constant 692 * @see #getConstantIndex() 693 * @see #getWideConstantIndex() 694 * @see #getConstantType(int) 695 * @see #getLongConstant(int) 696 * @see #getFloatConstant(int) 697 * @see #getDoubleConstant(int) 698 * @see #getStringConstant(int) 699 */ 700 public final int getIntConstant(int index) { 701 if (VM.VerifyAssertions) { 702 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && 703 getDeclaringClass().getLiteralDescription(index) == CP_INT); 704 } 705 Offset offset = getDeclaringClass().getLiteralOffset(index); 706 int val = Statics.getSlotContentsAsInt(offset); 707 return val; 708 } 709 710 /** 711 * Returns the constant at a given constant pool index (as a long).<p> 712 * Used for ldc2_w 713 * @return long constant 714 * @see #getConstantIndex() 715 * @see #getWideConstantIndex() 716 * @see #getConstantType(int) 717 * @see #getIntConstant(int) 718 * @see #getFloatConstant(int) 719 * @see #getDoubleConstant(int) 720 * @see #getStringConstant(int) 721 */ 722 public final long getLongConstant(int index) { 723 if (VM.VerifyAssertions) { 724 VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == CP_LONG); 725 } 726 Offset offset = getDeclaringClass().getLiteralOffset(index); 727 long val = Statics.getSlotContentsAsLong(offset); 728 return val; 729 } 730 731 /** 732 * Returns the constant at a given constant pool index (as a float).<p> 733 * Used for ldc, ldc_w 734 * @return float constant 735 * @see #getConstantIndex() 736 * @see #getWideConstantIndex() 737 * @see #getConstantType(int) 738 * @see #getIntConstant(int) 739 * @see #getLongConstant(int) 740 * @see #getDoubleConstant(int) 741 * @see #getStringConstant(int) 742 */ 743 public final float getFloatConstant(int index) { 744 if (VM.VerifyAssertions) { 745 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && 746 getDeclaringClass().getLiteralDescription(index) == CP_FLOAT); 747 } 748 Offset offset = getDeclaringClass().getLiteralOffset(index); 749 int val_raw = Statics.getSlotContentsAsInt(offset); 750 float val = Float.intBitsToFloat(val_raw); 751 return val; 752 } 753 754 /** 755 * Returns the constant at a given constant pool index (as a double).<p> 756 * Used for ldc2_w 757 * @return double constant 758 * @see #getConstantIndex() 759 * @see #getWideConstantIndex() 760 * @see #getConstantType(int) 761 * @see #getIntConstant(int) 762 * @see #getLongConstant(int) 763 * @see #getFloatConstant(int) 764 * @see #getStringConstant(int) 765 */ 766 public final double getDoubleConstant(int index) { 767 if (VM.VerifyAssertions) { 768 VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == CP_DOUBLE); 769 } 770 Offset offset = getDeclaringClass().getLiteralOffset(index); 771 long val_raw = Statics.getSlotContentsAsLong(offset); 772 double val = Double.longBitsToDouble(val_raw); 773 return val; 774 } 775 776 /** 777 * Returns the constant at a given constant pool index (as a String).<p> 778 * Used for ldc, ldc_w 779 * @return String constant 780 * @see #getConstantIndex() 781 * @see #getWideConstantIndex() 782 * @see #getConstantType(int) 783 * @see #getIntConstant(int) 784 * @see #getLongConstant(int) 785 * @see #getFloatConstant(int) 786 * @see #getDoubleConstant(int) 787 */ 788 public final String getStringConstant(int index) { 789 if (VM.VerifyAssertions) { 790 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) && 791 getDeclaringClass().getLiteralDescription(index) == CP_STRING); 792 } 793 Offset offset = getDeclaringClass().getLiteralOffset(index); 794 String val = (String) Statics.getSlotContentsAsObject(offset); 795 return val; 796 } 797 798 //// HELPER FUNCTIONS 799 800 // Skip a tableswitch or a lookupswitch instruction 801 802 private void skipSpecialInstruction(int opcode) { 803 switch (opcode) { 804 case JBC_tableswitch: { 805 alignSwitch(); 806 getDefaultSwitchOffset(); 807 int l = getLowSwitchValue(); 808 int h = getHighSwitchValue(); 809 skipTableSwitchOffsets(h - l + 1); // jump offsets 810 } 811 break; 812 case JBC_lookupswitch: { 813 alignSwitch(); 814 getDefaultSwitchOffset(); 815 int n = getSwitchLength(); 816 skipLookupSwitchPairs(n); // match-offset pairs 817 } 818 break; 819 case JBC_wide: { 820 int oc = getWideOpcode(); 821 int len = JBC_length[oc] - 1; 822 bcIndex += len + len; 823 } 824 break; 825 default: 826 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 827 } 828 } 829 830 public final int nextPseudoInstruction() { 831 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1); 832 return readUnsignedByte(); 833 } 834 835 public final int readIntConst() { 836 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1); 837 return readSignedInt(); 838 } 839 840 public final long readLongConst() { 841 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1); 842 return readLong(); 843 } 844 845 @Inline 846 private long readLong() { 847 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 848 int msb = bcodes[bcIndex++] << (3 * BITS_IN_BYTE); 849 msb |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE); 850 msb |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE; 851 msb |= (bcodes[bcIndex++] & 0xFF); 852 int lsb = bcodes[bcIndex++] << (3 * BITS_IN_BYTE); 853 lsb |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE); 854 lsb |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE; 855 lsb |= (bcodes[bcIndex++] & 0xFF); 856 return (((long)msb) << 32) | (lsb & 0xFFFFFFFFL); 857 } 858 859 //// READ BYTECODES 860 @Inline 861 private byte readSignedByte() { 862 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 863 return bcodes[bcIndex++]; 864 } 865 866 @Inline 867 private int readUnsignedByte() { 868 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 869 return bcodes[bcIndex++] & 0xFF; 870 } 871 872 @Inline 873 private int getUnsignedByte(int index) { 874 if (VM.VerifyAssertions) VM._assert(index <= bcLength); 875 return bcodes[index] & 0xFF; 876 } 877 878 @Inline 879 private int readSignedShort() { 880 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 881 int i = bcodes[bcIndex++] << BITS_IN_BYTE; 882 i |= (bcodes[bcIndex++] & 0xFF); 883 return i; 884 } 885 886 @Inline 887 private int readUnsignedShort() { 888 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 889 int i = (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE; 890 i |= (bcodes[bcIndex++] & 0xFF); 891 return i; 892 } 893 894 @Inline 895 private int readSignedInt() { 896 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength); 897 int i = bcodes[bcIndex++] << (3 * BITS_IN_BYTE); 898 i |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE); 899 i |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE; 900 i |= (bcodes[bcIndex++] & 0xFF); 901 return i; 902 } 903 904 @Inline 905 private int getSignedInt(int index) { 906 if (VM.VerifyAssertions) VM._assert(index <= bcLength); 907 int i = bcodes[index++] << (3 * BITS_IN_BYTE); 908 i |= (bcodes[index++] & 0xFF) << (2 * BITS_IN_BYTE); 909 i |= (bcodes[index++] & 0xFF) << BITS_IN_BYTE; 910 i |= (bcodes[index] & 0xFF); 911 return i; 912 } 913 } 914