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