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