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
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 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)
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)
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)
262 * Used for if<cond>, ificmp<cond>, ifacmp<cond>, goto, jsr
263 * @return branch offset
264 * @see #getWideBranchOffset()
265 */
266 public final int getBranchOffset() {
267 if (VM.VerifyAssertions) {
268 VM._assert((opcode >= JBC_ifeq && opcode <= JBC_ifle) ||
269 (opcode >= JBC_if_icmpeq && opcode <= JBC_if_icmple) ||
270 opcode == JBC_if_acmpeq ||
271 opcode == JBC_if_acmpne ||
272 opcode == JBC_ifnull ||
273 opcode == JBC_ifnonnull ||
274 opcode == JBC_goto ||
275 opcode == JBC_jsr);
276 }
277 return readSignedShort();
278 }
279
280 /**
281 * Returns the wide offset of the branch (as a signed int)
282 * Used for goto_w, jsr_w
283 * @return wide branch offset
284 * @see #getBranchOffset()
285 */
286 public final int getWideBranchOffset() {
287 if (VM.VerifyAssertions) {
288 VM._assert(opcode == JBC_goto_w || opcode == JBC_jsr_w);
289 }
290 return readSignedInt();
291 }
292
293 /**
294 * Skips the padding of a switch instruction
295 * Used for tableswitch, lookupswitch
296 */
297 public final void alignSwitch() {
298 if (VM.VerifyAssertions) {
299 VM._assert(opcode == JBC_tableswitch || opcode == JBC_lookupswitch);
300 }
301 int align = bcIndex & 3;
302 if (align != 0) bcIndex += 4 - align; // eat padding
303 }
304
305 /**
306 * Returns the default offset of the switch (as a signed int)
307 * Used for tableswitch, lookupswitch
308 * @return default switch offset
309 */
310 public final int getDefaultSwitchOffset() {
311 if (VM.VerifyAssertions) {
312 VM._assert(opcode == JBC_tableswitch || opcode == JBC_lookupswitch);
313 }
314 return readSignedInt();
315 }
316
317 /**
318 * Returns the lowest value of the tableswitch (as a signed int)
319 * Used for tableswitch
320 * @return lowest switch value
321 * @see #getHighSwitchValue()
322 */
323 public final int getLowSwitchValue() {
324 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch);
325 return readSignedInt();
326 }
327
328 /**
329 * Returns the highest value of the tableswitch (as a signed int)
330 * Used for tableswitch
331 * @return highest switch value
332 * @see #getLowSwitchValue()
333 */
334 public final int getHighSwitchValue() {
335 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch);
336 return readSignedInt();
337 }
338
339 /**
340 * Skips the offsets of a tableswitch instruction
341 * Used for tableswitch
342 * @param num the number of offsets to skip
343 * @see #getTableSwitchOffset(int)
344 */
345 public final void skipTableSwitchOffsets(int num) {
346 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch);
347 bcIndex += (num << LOG_BYTES_IN_INT);
348 }
349
350 /**
351 * Returns the numbered offset of the tableswitch (as a signed int)
352 * Used for tableswitch
353 * The "cursor" has to be positioned at the start of the offset table
354 * NOTE: Will NOT advance cursor
355 * @param num the number of the offset to retrieve
356 * @return switch offset
357 */
358 public final int getTableSwitchOffset(int num) {
359 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch);
360 return getSignedInt(bcIndex + (num << LOG_BYTES_IN_INT));
361 }
362
363 /**
364 * Returns the offset for a given value of the tableswitch (as a signed int)
365 * or 0 if the value is out of range.
366 * Used for tableswitch
367 * The "cursor" has to be positioned at the start of the offset table
368 * NOTE: Will NOT advance cursor
369 * @param value the value to retrieve offset for
370 * @param low the lowest value of the tableswitch
371 * @param high the highest value of the tableswitch
372 * @return switch offset
373 */
374 public final int computeTableSwitchOffset(int value, int low, int high) {
375 if (VM.VerifyAssertions) VM._assert(opcode == JBC_tableswitch);
376 if (value < low || value > high) return 0;
377 return getSignedInt(bcIndex + ((value - low) << LOG_BYTES_IN_INT));
378 }
379
380 /**
381 * Returns the number of match-offset pairs in the lookupswitch
382 * (as a signed int)
383 * Used for lookupswitch
384 * @return number of switch pairs
385 */
386 public final int getSwitchLength() {
387 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch);
388 return readSignedInt();
389 }
390
391 /**
392 * Skips the match-offset pairs of a lookupswitch instruction
393 * Used for lookupswitch
394 * @param num the number of match-offset pairs to skip
395 * @see #getLookupSwitchValue(int)
396 * @see #getLookupSwitchOffset(int)
397 */
398 public final void skipLookupSwitchPairs(int num) {
399 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch);
400 bcIndex += (num << (LOG_BYTES_IN_INT + 1));
401 }
402
403 /**
404 * Returns the numbered offset of the lookupswitch (as a signed int)
405 * Used for lookupswitch
406 * The "cursor" has to be positioned at the start of the pair table
407 * NOTE: Will NOT advance cursor
408 * @param num the number of the offset to retrieve
409 * @return switch offset
410 * @see #getLookupSwitchValue(int)
411 */
412 public final int getLookupSwitchOffset(int num) {
413 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch);
414 return getSignedInt(bcIndex + (num << (LOG_BYTES_IN_INT + 1)) + BYTES_IN_INT);
415 }
416
417 /**
418 * Returns the numbered value of the lookupswitch (as a signed int)
419 * Used for lookupswitch
420 * The "cursor" has to be positioned at the start of the pair table
421 * NOTE: Will NOT advance cursor
422 * @param num the number of the value to retrieve
423 * @return switch value
424 * @see #getLookupSwitchOffset(int)
425 */
426 public final int getLookupSwitchValue(int num) {
427 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch);
428 return getSignedInt(bcIndex + (num << (LOG_BYTES_IN_INT + 1)));
429 }
430
431 /**
432 * Returns the offset for a given value of the lookupswitch
433 * (as a signed int) or 0 if the value is not in the table.
434 * Used for lookupswitch
435 * The "cursor" has to be positioned at the start of the offset table
436 * NOTE: Will NOT advance cursor
437 * WARNING: Uses LINEAR search. Whoever has time on their hands can
438 * re-implement this as a binary search.
439 * @param value the value to retrieve offset for
440 * @param num the number of match-offset pairs in the lookupswitch
441 * @return switch offset
442 */
443 public final int computeLookupSwitchOffset(int value, int num) {
444 if (VM.VerifyAssertions) VM._assert(opcode == JBC_lookupswitch);
445 for (int i = 0; i < num; i++) {
446 if (getSignedInt(bcIndex + (i << (LOG_BYTES_IN_INT + 1))) == value) {
447 return getSignedInt(bcIndex + (i << (LOG_BYTES_IN_INT + 1)) + BYTES_IN_INT);
448 }
449 }
450 return 0;
451 }
452
453 /**
454 * Returns a reference to a field
455 * Used for getstatic, putstatic, getfield, putfield
456 * @return field reference
457 */
458 public final FieldReference getFieldReference() {
459 if (VM.VerifyAssertions) {
460 VM._assert(opcode == JBC_getstatic ||
461 opcode == JBC_putstatic ||
462 opcode == JBC_getfield ||
463 opcode == JBC_putfield);
464 }
465 return getDeclaringClass().getFieldRef(readUnsignedShort());
466 }
467
468 /**
469 * Returns a reference to a field, for use prior to the class being loaded.
470 * Used for getstatic, putstatic, getfield, putfield
471 * @return field reference
472 */
473 public final FieldReference getFieldReference(int[] constantPool) {
474 if (VM.VerifyAssertions) {
475 VM._assert(opcode == JBC_getstatic ||
476 opcode == JBC_putstatic ||
477 opcode == JBC_getfield ||
478 opcode == JBC_putfield);
479 }
480 return ClassFileReader.getFieldRef(constantPool, readUnsignedShort());
481 }
482 /**
483 * Returns a reference to a field
484 * Used for invokevirtual, invokespecial, invokestatic, invokeinterface
485 * @return method reference
486 */
487 public final MethodReference getMethodReference() {
488 if (VM.VerifyAssertions) {
489 VM._assert(opcode == JBC_invokevirtual ||
490 opcode == JBC_invokespecial ||
491 opcode == JBC_invokestatic ||
492 opcode == JBC_invokeinterface);
493 }
494 return getDeclaringClass().getMethodRef(readUnsignedShort());
495 }
496
497 /**
498 * Returns a reference to a field, for use prior to the class being loaded
499 * Used for invokevirtual, invokespecial, invokestatic, invokeinterface
500 * @return method reference
501 */
502 public final MethodReference getMethodReference(int[] constantPool) {
503 if (VM.VerifyAssertions) {
504 VM._assert(opcode == JBC_invokevirtual ||
505 opcode == JBC_invokespecial ||
506 opcode == JBC_invokestatic ||
507 opcode == JBC_invokeinterface);
508 }
509 return ClassFileReader.getMethodRef(constantPool, readUnsignedShort());
510 }
511
512 /**
513 * Skips the extra stuff after an invokeinterface instruction
514 * Used for invokeinterface
515 */
516 public final void alignInvokeInterface() {
517 if (VM.VerifyAssertions) VM._assert(opcode == JBC_invokeinterface);
518 bcIndex += 2; // eat superfluous stuff
519 }
520
521 /**
522 * Returns the type reference (as a RVMType)
523 * Used for new, anewarray, checkcast, instanceof, multianewarray
524 * @return type reference
525 */
526 public final TypeReference getTypeReference() {
527 if (VM.VerifyAssertions) {
528 VM._assert(opcode == JBC_new ||
529 opcode == JBC_anewarray ||
530 opcode == JBC_checkcast ||
531 opcode == JBC_instanceof ||
532 opcode == JBC_multianewarray);
533 }
534 int index = readUnsignedShort();
535 return getDeclaringClass().getTypeRef(index);
536 }
537
538 /**
539 * Returns the element type (primitive) of the array (as an unsigned byte)
540 * Used for newarray
541 * @return array element type
542 * @see #getPrimitiveArrayType()
543 * @see #getPrimitiveArrayType(int)
544 */
545 public final int getArrayElementType() {
546 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray);
547 return readUnsignedByte();
548 }
549
550 /**
551 * Returns the type of the array of given primitive type (as a RVMType)
552 * Used for newarray
553 * @param etype element type
554 * @return array type
555 * @see #getArrayElementType()
556 * @see #getPrimitiveArrayType()
557 */
558 public final RVMArray getPrimitiveArrayType(int etype) {
559 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray);
560 return RVMArray.getPrimitiveArrayType(etype);
561 }
562
563 /**
564 * Returns the type of the primitive array (as a RVMType)
565 * Used for newarray
566 * @return array type
567 * @see #getArrayElementType()
568 * @see #getPrimitiveArrayType(int)
569 */
570 public final RVMType getPrimitiveArrayType() {
571 if (VM.VerifyAssertions) VM._assert(opcode == JBC_newarray);
572 int etype = readUnsignedByte();
573 return RVMArray.getPrimitiveArrayType(etype);
574 }
575
576 /**
577 * Returns the type of the array of given object type (as a RVMType)
578 * Used for anewarray
579 * @param klass element type
580 * @return array type
581 * @see #getTypeReference()
582 * @see #getObjectArrayType()
583 */
584 public final RVMType getObjectArrayType(RVMType klass) {
585 if (VM.VerifyAssertions) VM._assert(opcode == JBC_anewarray);
586 return klass.getArrayTypeForElementType();
587 }
588
589 /**
590 * Returns the type of the object array (as a RVMType)
591 * Used for anewarray
592 * @return array type
593 * @see #getObjectArrayType(RVMType)
594 */
595 public final TypeReference getObjectArrayType() {
596 if (VM.VerifyAssertions) VM._assert(opcode == JBC_anewarray);
597 TypeReference klass = getTypeReference();
598 return klass.getArrayTypeForElementType();
599 }
600
601 /**
602 * Returns the dimension of the array (as an unsigned byte)
603 * Used for multianewarray
604 * @return array dimension
605 */
606 public final int getArrayDimension() {
607 if (VM.VerifyAssertions) VM._assert(opcode == JBC_multianewarray);
608 return readUnsignedByte();
609 }
610
611 /**
612 * Returns the opcode of the wide instruction
613 * Used for wide
614 * Can be one of iload, lload, fload, dload, aload,
615 * istore, lstore, fstore, dstore, astore, iinc
616 * @return the opcode of the wide instruction
617 */
618 public final int getWideOpcode() {
619 if (VM.VerifyAssertions) VM._assert(wide && opcode == JBC_wide);
620 opcode = readUnsignedByte();
621 if (VM.VerifyAssertions) {
622 VM._assert((opcode >= JBC_iload && opcode <= JBC_aload) ||
623 (opcode >= JBC_istore && opcode <= JBC_astore) ||
624 opcode == JBC_iinc);
625 }
626 return opcode;
627 }
628
629 /**
630 * Returns the constant pool index of a constant (as an unsigned byte)
631 * Used for ldc
632 * @return constant index
633 * @see #getWideConstantIndex()
634 * @see #getConstantType(int)
635 * @see #getIntConstant(int)
636 * @see #getLongConstant(int)
637 * @see #getFloatConstant(int)
638 * @see #getDoubleConstant(int)
639 * @see #getStringConstant(int)
640 */
641 public final int getConstantIndex() {
642 if (VM.VerifyAssertions) VM._assert(opcode == JBC_ldc);
643 return readUnsignedByte();
644 }
645
646 /**
647 * Returns the wide constant pool index of a constant (as an unsigned short)
648 * Used for ldc_w, ldc2_w
649 * @return wide constant index
650 * @see #getConstantIndex()
651 * @see #getConstantType(int)
652 * @see #getIntConstant(int)
653 * @see #getLongConstant(int)
654 * @see #getFloatConstant(int)
655 * @see #getDoubleConstant(int)
656 * @see #getStringConstant(int)
657 */
658 public final int getWideConstantIndex() {
659 if (VM.VerifyAssertions) {
660 VM._assert(opcode == JBC_ldc_w || opcode == JBC_ldc2_w);
661 }
662 return readUnsignedShort();
663 }
664
665 /**
666 * Returns the type of a constant at a given constant pool index (as a byte)
667 * Used for ldc, ldc_w, ldc2_w
668 * @return constant type
669 * @see #getConstantIndex()
670 * @see #getWideConstantIndex()
671 * @see #getIntConstant(int)
672 * @see #getLongConstant(int)
673 * @see #getFloatConstant(int)
674 * @see #getDoubleConstant(int)
675 * @see #getStringConstant(int)
676 */
677 public final byte getConstantType(int index) {
678 if (VM.VerifyAssertions) {
679 VM._assert(opcode == JBC_ldc || opcode == JBC_ldc_w || opcode == JBC_ldc2_w);
680 }
681 byte desc = getDeclaringClass().getLiteralDescription(index);
682 return desc;
683 }
684
685 /**
686 * Returns the constant at a given constant pool index (as an int)
687 * Used for ldc, ldc_w
688 * @return int constant
689 * @see #getConstantIndex()
690 * @see #getWideConstantIndex()
691 * @see #getConstantType(int)
692 * @see #getLongConstant(int)
693 * @see #getFloatConstant(int)
694 * @see #getDoubleConstant(int)
695 * @see #getStringConstant(int)
696 */
697 public final int getIntConstant(int index) {
698 if (VM.VerifyAssertions) {
699 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) &&
700 getDeclaringClass().getLiteralDescription(index) == CP_INT);
701 }
702 Offset offset = getDeclaringClass().getLiteralOffset(index);
703 int val = Statics.getSlotContentsAsInt(offset);
704 return val;
705 }
706
707 /**
708 * Returns the constant at a given constant pool index (as a long)
709 * Used for ldc2_w
710 * @return long constant
711 * @see #getConstantIndex()
712 * @see #getWideConstantIndex()
713 * @see #getConstantType(int)
714 * @see #getIntConstant(int)
715 * @see #getFloatConstant(int)
716 * @see #getDoubleConstant(int)
717 * @see #getStringConstant(int)
718 */
719 public final long getLongConstant(int index) {
720 if (VM.VerifyAssertions) {
721 VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == CP_LONG);
722 }
723 Offset offset = getDeclaringClass().getLiteralOffset(index);
724 long val = Statics.getSlotContentsAsLong(offset);
725 return val;
726 }
727
728 /**
729 * Returns the constant at a given constant pool index (as a float)
730 * Used for ldc, ldc_w
731 * @return float constant
732 * @see #getConstantIndex()
733 * @see #getWideConstantIndex()
734 * @see #getConstantType(int)
735 * @see #getIntConstant(int)
736 * @see #getLongConstant(int)
737 * @see #getDoubleConstant(int)
738 * @see #getStringConstant(int)
739 */
740 public final float getFloatConstant(int index) {
741 if (VM.VerifyAssertions) {
742 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) &&
743 getDeclaringClass().getLiteralDescription(index) == CP_FLOAT);
744 }
745 Offset offset = getDeclaringClass().getLiteralOffset(index);
746 int val_raw = Statics.getSlotContentsAsInt(offset);
747 float val = Float.intBitsToFloat(val_raw);
748 return val;
749 }
750
751 /**
752 * Returns the constant at a given constant pool index (as a double)
753 * Used for ldc2_w
754 * @return double constant
755 * @see #getConstantIndex()
756 * @see #getWideConstantIndex()
757 * @see #getConstantType(int)
758 * @see #getIntConstant(int)
759 * @see #getLongConstant(int)
760 * @see #getFloatConstant(int)
761 * @see #getStringConstant(int)
762 */
763 public final double getDoubleConstant(int index) {
764 if (VM.VerifyAssertions) {
765 VM._assert(opcode == JBC_ldc2_w && getDeclaringClass().getLiteralDescription(index) == CP_DOUBLE);
766 }
767 Offset offset = getDeclaringClass().getLiteralOffset(index);
768 long val_raw = Statics.getSlotContentsAsLong(offset);
769 double val = Double.longBitsToDouble(val_raw);
770 return val;
771 }
772
773 /**
774 * Returns the constant at a given constant pool index (as a String)
775 * Used for ldc, ldc_w
776 * @return String constant
777 * @see #getConstantIndex()
778 * @see #getWideConstantIndex()
779 * @see #getConstantType(int)
780 * @see #getIntConstant(int)
781 * @see #getLongConstant(int)
782 * @see #getFloatConstant(int)
783 * @see #getDoubleConstant(int)
784 */
785 public final String getStringConstant(int index) {
786 if (VM.VerifyAssertions) {
787 VM._assert((opcode == JBC_ldc || opcode == JBC_ldc_w) &&
788 getDeclaringClass().getLiteralDescription(index) == CP_STRING);
789 }
790 Offset offset = getDeclaringClass().getLiteralOffset(index);
791 String val = (String) Statics.getSlotContentsAsObject(offset);
792 return val;
793 }
794
795 //// HELPER FUNCTIONS
796
797 // Skip a tableswitch or a lookupswitch instruction
798
799 private void skipSpecialInstruction(int opcode) {
800 switch (opcode) {
801 case JBC_tableswitch: {
802 alignSwitch();
803 getDefaultSwitchOffset();
804 int l = getLowSwitchValue();
805 int h = getHighSwitchValue();
806 skipTableSwitchOffsets(h - l + 1); // jump offsets
807 }
808 break;
809 case JBC_lookupswitch: {
810 alignSwitch();
811 getDefaultSwitchOffset();
812 int n = getSwitchLength();
813 skipLookupSwitchPairs(n); // match-offset pairs
814 }
815 break;
816 case JBC_wide: {
817 int oc = getWideOpcode();
818 int len = JBC_length[oc] - 1;
819 bcIndex += len + len;
820 }
821 break;
822 default:
823 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
824 }
825 }
826
827 public final int nextPseudoInstruction() {
828 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1);
829 return readUnsignedByte();
830 }
831
832 public final int readIntConst() {
833 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1);
834 return readSignedInt();
835 }
836
837 public final long readLongConst() {
838 if (VM.VerifyAssertions) VM._assert(opcode == JBC_impdep1);
839 return readLong();
840 }
841
842 @Inline
843 private long readLong() {
844 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
845 int msb = bcodes[bcIndex++] << (3 * BITS_IN_BYTE);
846 msb |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE);
847 msb |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE;
848 msb |= (bcodes[bcIndex++] & 0xFF);
849 int lsb = bcodes[bcIndex++] << (3 * BITS_IN_BYTE);
850 lsb |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE);
851 lsb |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE;
852 lsb |= (bcodes[bcIndex++] & 0xFF);
853 return (((long)msb) << 32) | (lsb & 0xFFFFFFFFL);
854 }
855
856 //// READ BYTECODES
857 @Inline
858 private byte readSignedByte() {
859 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
860 return bcodes[bcIndex++];
861 }
862
863 @Inline
864 private int readUnsignedByte() {
865 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
866 return bcodes[bcIndex++] & 0xFF;
867 }
868
869 @Inline
870 private int getUnsignedByte(int index) {
871 if (VM.VerifyAssertions) VM._assert(index <= bcLength);
872 return bcodes[index] & 0xFF;
873 }
874
875 @Inline
876 private int readSignedShort() {
877 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
878 int i = bcodes[bcIndex++] << BITS_IN_BYTE;
879 i |= (bcodes[bcIndex++] & 0xFF);
880 return i;
881 }
882
883 @Inline
884 private int readUnsignedShort() {
885 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
886 int i = (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE;
887 i |= (bcodes[bcIndex++] & 0xFF);
888 return i;
889 }
890
891 @Inline
892 private int readSignedInt() {
893 if (VM.VerifyAssertions) VM._assert(bcIndex <= bcLength);
894 int i = bcodes[bcIndex++] << (3 * BITS_IN_BYTE);
895 i |= (bcodes[bcIndex++] & 0xFF) << (2 * BITS_IN_BYTE);
896 i |= (bcodes[bcIndex++] & 0xFF) << BITS_IN_BYTE;
897 i |= (bcodes[bcIndex++] & 0xFF);
898 return i;
899 }
900
901 @Inline
902 private int getSignedInt(int index) {
903 if (VM.VerifyAssertions) VM._assert(index <= bcLength);
904 int i = bcodes[index++] << (3 * BITS_IN_BYTE);
905 i |= (bcodes[index++] & 0xFF) << (2 * BITS_IN_BYTE);
906 i |= (bcodes[index++] & 0xFF) << BITS_IN_BYTE;
907 i |= (bcodes[index] & 0xFF);
908 return i;
909 }
910 }
911