< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java

Print this page




  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.vm.ci.code;
  24 
  25 import java.util.Arrays;
  26 
  27 import jdk.vm.ci.meta.JavaKind;
  28 import jdk.vm.ci.meta.JavaValue;
  29 import jdk.vm.ci.meta.ResolvedJavaMethod;
  30 import jdk.vm.ci.meta.Value;
  31 
  32 /**
  33  * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
  34  * where to find the local variables, operand stack values and locked objects of the bytecode
  35  * frame(s).
  36  */
  37 public class BytecodeFrame extends BytecodePosition {
  38 
  39     /**
  40      * An array of values representing how to reconstruct the state of the Java frame. This is array
  41      * is partitioned as follows:
  42      * <p>
  43      * <table summary="" border="1" cellpadding="5" frame="void" rules="all">
  44      * <tr>
  45      * <th>Start index (inclusive)</th>
  46      * <th>End index (exclusive)</th>
  47      * <th>Description</th>
  48      * </tr>
  49      * <tr>
  50      * <td>0</td>
  51      * <td>numLocals</td>
  52      * <td>Local variables</td>
  53      * </tr>
  54      * <tr>
  55      * <td>numLocals</td>
  56      * <td>numLocals + numStack</td>
  57      * <td>Operand stack</td>
  58      * </tr>
  59      * <tr>
  60      * <td>numLocals + numStack</td>
  61      * <td>values.length</td>
  62      * <td>Locked objects</td>
  63      * </tr>
  64      * </table>
  65      * <p>
  66      * Note that the number of locals and the number of stack slots may be smaller than the maximum
  67      * number of locals and stack slots as specified in the compiled method.



  68      */

  69     public final JavaValue[] values;
  70 
  71     /**
  72      * An array describing the Java kind of the {@link #values}. It records a kind for the locals
  73      * and the operand stack.
  74      */
  75     public final JavaKind[] slotKinds;
  76 
  77     /**
  78      * The number of locals in the values array.
  79      */
  80     public final int numLocals;
  81 
  82     /**
  83      * The number of stack slots in the values array.
  84      */
  85     public final int numStack;
  86 
  87     /**
  88      * The number of locks in the values array.
  89      */
  90     public final int numLocks;
  91 
  92     /**
  93      * True if this is a position inside an exception handler before the exception object has been
  94      * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
  95      * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
  96      * position, the interpreter will rethrow the exception instead of executing the bytecode
  97      * instruction at this position.
  98      */
  99     public final boolean rethrowException;
 100 
 101     /**
 102      * Specifies if this object represents a frame state in the middle of executing a call. If
 103      * true, the arguments to the call have been popped from the stack and the return value (for a
 104      * non-void call) has not yet been pushed.
 105      */
 106     public final boolean duringCall;
 107 
 108     /**
 109      * This BCI should be used for frame states that are built for code with no meaningful BCI.
 110      */
 111     public static final int UNKNOWN_BCI = -5;
 112 
 113     /**
 114      * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
 115      * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
 116      * the monitor is still held.
 117      */
 118     public static final int UNWIND_BCI = -1;
 119 
 120     /**
 121      * The BCI for the state before starting to execute a method. Note that if the method is
 122      * synchronized, the monitor is not yet held.
 123      */


 161         } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
 162             return "INVALID_FRAMESTATE_BCI";
 163         } else if (bci == BytecodeFrame.BEFORE_BCI) {
 164             return "BEFORE_BCI";
 165         } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
 166             return "UNKNOWN_BCI";
 167         } else {
 168             assert bci == BytecodeFrame.UNWIND_BCI;
 169             return "UNWIND_BCI";
 170         }
 171     }
 172 
 173     /**
 174      * Creates a new frame object.
 175      *
 176      * @param caller the caller frame (which may be {@code null})
 177      * @param method the method
 178      * @param bci a BCI within the method
 179      * @param rethrowException specifies if the VM should re-throw the pending exception when
 180      *            deopt'ing using this frame
 181      * @param values the frame state {@link #values}


 182      * @param numLocals the number of local variables
 183      * @param numStack the depth of the stack
 184      * @param numLocks the number of locked objects
 185      */

 186     public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
 187                     int numLocks) {
 188         super(caller, method, bci);
 189         assert values != null;
 190         this.rethrowException = rethrowException;
 191         this.duringCall = duringCall;
 192         this.values = values;
 193         this.slotKinds = slotKinds;
 194         this.numLocals = numLocals;
 195         this.numStack = numStack;
 196         this.numLocks = numLocks;
 197         assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
 198     }
 199 
 200     /**
 201      * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
 202      * slot following a double word item. This should really be checked in FrameState itself but
 203      * because of Word type rewriting and alternative backends that can't be done.
 204      */
 205     public boolean validateFormat() {
 206         if (caller() != null) {
 207             caller().validateFormat();
 208         }
 209         for (int i = 0; i < numLocals + numStack; i++) {
 210             if (values[i] != null) {
 211                 JavaKind kind = slotKinds[i];
 212                 if (kind.needsTwoSlots()) {
 213                     assert slotKinds.length > i + 1 : String.format("missing second word %s", this);
 214                     assert slotKinds[i + 1] == JavaKind.Illegal : this;
 215                 }
 216             }
 217         }
 218         return true;
 219     }
 220 
 221     /**




























 222      * Gets the value representing the specified local variable.
 223      *
 224      * @param i the local variable index
 225      * @return the value that can be used to reconstruct the local's current value

 226      */
 227     public JavaValue getLocalValue(int i) {



 228         return values[i];
 229     }
 230 
 231     /**
 232      * Gets the value representing the specified stack slot.
 233      *
 234      * @param i the stack index
 235      * @return the value that can be used to reconstruct the stack slot's current value

 236      */
 237     public JavaValue getStackValue(int i) {



 238         return values[i + numLocals];
 239     }
 240 
 241     /**
 242      * Gets the value representing the specified lock.
 243      *
 244      * @param i the lock index
 245      * @return the value that can be used to reconstruct the lock's current value

 246      */
 247     public JavaValue getLockValue(int i) {



 248         return values[i + numLocals + numStack];
 249     }
 250 
 251     /**
 252      * Gets the caller of this frame.
 253      *
 254      * @return {@code null} if this frame has no caller
 255      */
 256     public BytecodeFrame caller() {
 257         return (BytecodeFrame) getCaller();
 258     }
 259 
 260     @Override





 261     public boolean equals(Object obj) {
 262         if (this == obj) {
 263             return true;
 264         }
 265         if (obj instanceof BytecodeFrame && super.equals(obj)) {
 266             BytecodeFrame that = (BytecodeFrame) obj;
 267             // @formatter:off
 268             if (this.duringCall == that.duringCall &&
 269                 this.rethrowException == that.rethrowException &&
 270                 this.numLocals == that.numLocals &&
 271                 this.numLocks == that.numLocks &&
 272                 this.numStack == that.numStack &&
 273                 Arrays.equals(this.values, that.values)) {
 274                 return true;
 275             }
 276             // @formatter:off
 277             return true;
 278         }
 279         return false;
 280     }


  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.vm.ci.code;
  24 
  25 import java.util.Arrays;
  26 
  27 import jdk.vm.ci.meta.JavaKind;
  28 import jdk.vm.ci.meta.JavaValue;
  29 import jdk.vm.ci.meta.ResolvedJavaMethod;
  30 import jdk.vm.ci.meta.Value;
  31 
  32 /**
  33  * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
  34  * where to find the local variables, operand stack values and locked objects of the bytecode
  35  * frame(s).
  36  */
  37 public final class BytecodeFrame extends BytecodePosition {
  38 
  39     /**
  40      * An array of values representing how to reconstruct the state of the Java frame. This is array
  41      * is partitioned as follows:
  42      * <p>
  43      * <table summary="" border="1" cellpadding="5" frame="void" rules="all">
  44      * <tr>
  45      * <th>Start index (inclusive)</th>
  46      * <th>End index (exclusive)</th>
  47      * <th>Description</th>
  48      * </tr>
  49      * <tr>
  50      * <td>0</td>
  51      * <td>numLocals</td>
  52      * <td>Local variables</td>
  53      * </tr>
  54      * <tr>
  55      * <td>numLocals</td>
  56      * <td>numLocals + numStack</td>
  57      * <td>Operand stack</td>
  58      * </tr>
  59      * <tr>
  60      * <td>numLocals + numStack</td>
  61      * <td>values.length</td>
  62      * <td>Locked objects</td>
  63      * </tr>
  64      * </table>
  65      * <p>
  66      * Note that the number of locals and the number of stack slots may be smaller than the maximum
  67      * number of locals and stack slots as specified in the compiled method.
  68      *
  69      * This field is intentionally exposed as a mutable array that a compiler may modify (e.g.
  70      * during register allocation).
  71      */
  72     @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "field is intentionally mutable")//
  73     public final JavaValue[] values;
  74 
  75     /**
  76      * An array describing the Java kinds in {@link #values}. It records a kind for the locals and
  77      * the operand stack.
  78      */
  79     private final JavaKind[] slotKinds;
  80 
  81     /**
  82      * The number of locals in the values array.
  83      */
  84     public final int numLocals;
  85 
  86     /**
  87      * The number of stack slots in the values array.
  88      */
  89     public final int numStack;
  90 
  91     /**
  92      * The number of locks in the values array.
  93      */
  94     public final int numLocks;
  95 
  96     /**
  97      * True if this is a position inside an exception handler before the exception object has been
  98      * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
  99      * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
 100      * position, the interpreter will rethrow the exception instead of executing the bytecode
 101      * instruction at this position.
 102      */
 103     public final boolean rethrowException;
 104 
 105     /**
 106      * Specifies if this object represents a frame state in the middle of executing a call. If true,
 107      * the arguments to the call have been popped from the stack and the return value (for a
 108      * non-void call) has not yet been pushed.
 109      */
 110     public final boolean duringCall;
 111 
 112     /**
 113      * This BCI should be used for frame states that are built for code with no meaningful BCI.
 114      */
 115     public static final int UNKNOWN_BCI = -5;
 116 
 117     /**
 118      * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
 119      * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
 120      * the monitor is still held.
 121      */
 122     public static final int UNWIND_BCI = -1;
 123 
 124     /**
 125      * The BCI for the state before starting to execute a method. Note that if the method is
 126      * synchronized, the monitor is not yet held.
 127      */


 165         } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
 166             return "INVALID_FRAMESTATE_BCI";
 167         } else if (bci == BytecodeFrame.BEFORE_BCI) {
 168             return "BEFORE_BCI";
 169         } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
 170             return "UNKNOWN_BCI";
 171         } else {
 172             assert bci == BytecodeFrame.UNWIND_BCI;
 173             return "UNWIND_BCI";
 174         }
 175     }
 176 
 177     /**
 178      * Creates a new frame object.
 179      *
 180      * @param caller the caller frame (which may be {@code null})
 181      * @param method the method
 182      * @param bci a BCI within the method
 183      * @param rethrowException specifies if the VM should re-throw the pending exception when
 184      *            deopt'ing using this frame
 185      * @param values the frame state {@link #values}.
 186      * @param slotKinds the kinds in {@code values}. This array is now owned by this object and must
 187      *            not be mutated by the caller.
 188      * @param numLocals the number of local variables
 189      * @param numStack the depth of the stack
 190      * @param numLocks the number of locked objects
 191      */
 192     @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
 193     public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
 194                     int numLocks) {
 195         super(caller, method, bci);
 196         assert values != null;
 197         this.rethrowException = rethrowException;
 198         this.duringCall = duringCall;
 199         this.values = values;
 200         this.slotKinds = slotKinds;
 201         this.numLocals = numLocals;
 202         this.numStack = numStack;
 203         this.numLocks = numLocks;
 204         assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
 205     }
 206 
 207     /**
 208      * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
 209      * slot following a double word item. This should really be checked in FrameState itself but
 210      * because of Word type rewriting and alternative backends that can't be done.
 211      */
 212     public boolean validateFormat() {
 213         if (caller() != null) {
 214             caller().validateFormat();
 215         }
 216         for (int i = 0; i < numLocals + numStack; i++) {
 217             if (values[i] != null) {
 218                 JavaKind kind = slotKinds[i];
 219                 if (kind.needsTwoSlots()) {
 220                     assert slotKinds.length > i + 1 : String.format("missing second word %s", this);
 221                     assert slotKinds[i + 1] == JavaKind.Illegal : this;
 222                 }
 223             }
 224         }
 225         return true;
 226     }
 227 
 228     /**
 229      * Gets the kind of a local variable.
 230      *
 231      * @param i the local variable to query
 232      * @return the kind of local variable {@code i}
 233      * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
 234      */
 235     public JavaKind getLocalValueKind(int i) {
 236         if (i < 0 || i >= numLocals) {
 237             throw new IndexOutOfBoundsException();
 238         }
 239         return slotKinds[i];
 240     }
 241 
 242     /**
 243      * Gets the kind of a stack slot.
 244      *
 245      * @param i the local variable to query
 246      * @return the kind of stack slot {@code i}
 247      * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
 248      */
 249     public JavaKind getStackValueKind(int i) {
 250         if (i < 0 || i >= numStack) {
 251             throw new IndexOutOfBoundsException();
 252         }
 253         return slotKinds[i + numLocals];
 254     }
 255 
 256     /**
 257      * Gets the value representing the specified local variable.
 258      *
 259      * @param i the local variable index
 260      * @return the value that can be used to reconstruct the local's current value
 261      * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
 262      */
 263     public JavaValue getLocalValue(int i) {
 264         if (i < 0 || i >= numLocals) {
 265             throw new IndexOutOfBoundsException();
 266         }
 267         return values[i];
 268     }
 269 
 270     /**
 271      * Gets the value representing the specified stack slot.
 272      *
 273      * @param i the stack index
 274      * @return the value that can be used to reconstruct the stack slot's current value
 275      * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
 276      */
 277     public JavaValue getStackValue(int i) {
 278         if (i < 0 || i >= numStack) {
 279             throw new IndexOutOfBoundsException();
 280         }
 281         return values[i + numLocals];
 282     }
 283 
 284     /**
 285      * Gets the value representing the specified lock.
 286      *
 287      * @param i the lock index
 288      * @return the value that can be used to reconstruct the lock's current value
 289      * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocks}
 290      */
 291     public JavaValue getLockValue(int i) {
 292         if (i < 0 || i >= numLocks) {
 293             throw new IndexOutOfBoundsException();
 294         }
 295         return values[i + numLocals + numStack];
 296     }
 297 
 298     /**
 299      * Gets the caller of this frame.
 300      *
 301      * @return {@code null} if this frame has no caller
 302      */
 303     public BytecodeFrame caller() {
 304         return (BytecodeFrame) getCaller();
 305     }
 306 
 307     @Override
 308     public int hashCode() {
 309         return (numLocals + 1) ^ (numStack + 11) ^ (numLocks + 7);
 310     }
 311 
 312     @Override
 313     public boolean equals(Object obj) {
 314         if (this == obj) {
 315             return true;
 316         }
 317         if (obj instanceof BytecodeFrame && super.equals(obj)) {
 318             BytecodeFrame that = (BytecodeFrame) obj;
 319             // @formatter:off
 320             if (this.duringCall == that.duringCall &&
 321                 this.rethrowException == that.rethrowException &&
 322                 this.numLocals == that.numLocals &&
 323                 this.numLocks == that.numLocks &&
 324                 this.numStack == that.numStack &&
 325                 Arrays.equals(this.values, that.values)) {
 326                 return true;
 327             }
 328             // @formatter:off
 329             return true;
 330         }
 331         return false;
 332     }
< prev index next >