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