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