1 /* 2 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 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.*; 26 27 import jdk.vm.ci.meta.*; 28 29 /** 30 * Represents the Java bytecode frame state(s) at a given position including {@link Value locations} 31 * where to find the local variables, operand stack values and locked objects of the bytecode 32 * frame(s). 33 */ 34 public class BytecodeFrame extends BytecodePosition { 35 36 /** 37 * An array of values representing how to reconstruct the state of the Java frame. This is array 38 * is partitioned as follows: 39 * <p> 40 * <table summary="" border="1" cellpadding="5" frame="void" rules="all"> 41 * <tr> 42 * <th>Start index (inclusive)</th> 43 * <th>End index (exclusive)</th> 44 * <th>Description</th> 45 * </tr> 46 * <tr> 47 * <td>0</td> 48 * <td>numLocals</td> 49 * <td>Local variables</td> 50 * </tr> 51 * <tr> 52 * <td>numLocals</td> 53 * <td>numLocals + numStack</td> 54 * <td>Operand stack</td> 55 * </tr> 56 * <tr> 57 * <td>numLocals + numStack</td> 58 * <td>values.length</td> 59 * <td>Locked objects</td> 60 * </tr> 61 * </table> 62 * <p> 63 * Note that the number of locals and the number of stack slots may be smaller than the maximum 64 * number of locals and stack slots as specified in the compiled method. 65 */ 66 public final JavaValue[] values; 67 68 /** 69 * An array describing the Java kind of the {@link #values}. It records a kind for the locals 70 * and the operand stack. 71 */ 72 public final JavaKind[] slotKinds; 73 74 /** 75 * The number of locals in the values array. 76 */ 77 public final int numLocals; 78 79 /** 80 * The number of stack slots in the values array. 81 */ 82 public final int numStack; 83 84 /** 85 * The number of locks in the values array. 86 */ 87 public final int numLocks; 88 89 /** 90 * True if this is a position inside an exception handler before the exception object has been 91 * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int) 92 * getStackValue(0)} is the location of the exception object. If deoptimization happens at this 93 * position, the interpreter will rethrow the exception instead of executing the bytecode 94 * instruction at this position. 95 */ 96 public final boolean rethrowException; 97 98 public final boolean duringCall; 99 100 /** 101 * This BCI should be used for frame states that are built for code with no meaningful BCI. 102 */ 103 public static final int UNKNOWN_BCI = -5; 104 105 /** 106 * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. 107 * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized, 108 * the monitor is still held. 109 */ 110 public static final int UNWIND_BCI = -1; 111 112 /** 113 * The BCI for the state before starting to execute a method. Note that if the method is 114 * synchronized, the monitor is not yet held. 115 */ 116 public static final int BEFORE_BCI = -2; 117 118 /** 119 * The BCI for the state after finishing the execution of a method and returning normally. Note 120 * that if the method was synchronized the monitor is already released. 121 */ 122 public static final int AFTER_BCI = -3; 123 124 /** 125 * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. 126 * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the 127 * monitor is already released. 128 */ 129 public static final int AFTER_EXCEPTION_BCI = -4; 130 131 /** 132 * This BCI should be used for states that cannot be the target of a deoptimization, like 133 * snippet frame states. 134 */ 135 public static final int INVALID_FRAMESTATE_BCI = -6; 136 137 /** 138 * Determines if a given BCI matches one of the placeholder BCI constants defined in this class. 139 */ 140 public static boolean isPlaceholderBci(int bci) { 141 return bci < 0; 142 } 143 144 /** 145 * Gets the name of a given placeholder BCI. 146 */ 147 public static String getPlaceholderBciName(int bci) { 148 assert isPlaceholderBci(bci); 149 if (bci == BytecodeFrame.AFTER_BCI) { 150 return "AFTER_BCI"; 151 } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { 152 return "AFTER_EXCEPTION_BCI"; 153 } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { 154 return "INVALID_FRAMESTATE_BCI"; 155 } else if (bci == BytecodeFrame.BEFORE_BCI) { 156 return "BEFORE_BCI"; 157 } else if (bci == BytecodeFrame.UNKNOWN_BCI) { 158 return "UNKNOWN_BCI"; 159 } else { 160 assert bci == BytecodeFrame.UNWIND_BCI; 161 return "UNWIND_BCI"; 162 } 163 } 164 165 /** 166 * Creates a new frame object. 167 * 168 * @param caller the caller frame (which may be {@code null}) 169 * @param method the method 170 * @param bci a BCI within the method 171 * @param rethrowException specifies if the VM should re-throw the pending exception when 172 * deopt'ing using this frame 173 * @param values the frame state {@link #values} 174 * @param numLocals the number of local variables 175 * @param numStack the depth of the stack 176 * @param numLocks the number of locked objects 177 */ 178 public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack, 179 int numLocks) { 180 super(caller, method, bci); 181 assert values != null; 182 this.rethrowException = rethrowException; 183 this.duringCall = duringCall; 184 this.values = values; 185 this.slotKinds = slotKinds; 186 this.numLocals = numLocals; 187 this.numStack = numStack; 188 this.numLocks = numLocks; 189 assert !rethrowException || numStack == 1 : "must have exception on top of the stack"; 190 } 191 192 /** 193 * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the 194 * slot following a double word item. This should really be checked in FrameState itself but 195 * because of Word type rewriting and alternative backends that can't be done. 196 */ 197 public boolean validateFormat() { 198 if (caller() != null) { 199 caller().validateFormat(); 200 } 201 for (int i = 0; i < numLocals + numStack; i++) { 202 if (values[i] != null) { 203 JavaKind kind = slotKinds[i]; 204 if (kind.needsTwoSlots()) { 205 assert slotKinds.length > i + 1 : String.format("missing second word %s", this); 206 assert slotKinds[i + 1] == JavaKind.Illegal : this; 207 } 208 } 209 } 210 return true; 211 } 212 213 /** 214 * Gets the value representing the specified local variable. 215 * 216 * @param i the local variable index 217 * @return the value that can be used to reconstruct the local's current value 218 */ 219 public JavaValue getLocalValue(int i) { 220 return values[i]; 221 } 222 223 /** 224 * Gets the value representing the specified stack slot. 225 * 226 * @param i the stack index 227 * @return the value that can be used to reconstruct the stack slot's current value 228 */ 229 public JavaValue getStackValue(int i) { 230 return values[i + numLocals]; 231 } 232 233 /** 234 * Gets the value representing the specified lock. 235 * 236 * @param i the lock index 237 * @return the value that can be used to reconstruct the lock's current value 238 */ 239 public JavaValue getLockValue(int i) { 240 return values[i + numLocals + numStack]; 241 } 242 243 /** 244 * Gets the caller of this frame. 245 * 246 * @return {@code null} if this frame has no caller 247 */ 248 public BytecodeFrame caller() { 249 return (BytecodeFrame) getCaller(); 250 } 251 252 @Override 253 public boolean equals(Object obj) { 254 if (this == obj) { 255 return true; 256 } 257 if (obj instanceof BytecodeFrame && super.equals(obj)) { 258 BytecodeFrame that = (BytecodeFrame) obj; 259 // @formatter:off 260 if (this.duringCall == that.duringCall && 261 this.rethrowException == that.rethrowException && 262 this.numLocals == that.numLocals && 263 this.numLocks == that.numLocks && 264 this.numStack == that.numStack && 265 Arrays.equals(this.values, that.values)) { 266 return true; 267 } 268 // @formatter:off 269 return true; 270 } 271 return false; 272 } 273 274 @Override 275 public String toString() { 276 return CodeUtil.append(new StringBuilder(100), this).toString(); 277 } 278 }