001/* 002 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package jdk.internal.jvmci.code; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029/** 030 * Represents the Java bytecode frame state(s) at a given position including {@link Value locations} 031 * where to find the local variables, operand stack values and locked objects of the bytecode 032 * frame(s). 033 */ 034public class BytecodeFrame extends BytecodePosition { 035 036 /** 037 * An array of values representing how to reconstruct the state of the Java frame. This is array 038 * is partitioned as follows: 039 * <p> 040 * <table summary="" border="1" cellpadding="5" frame="void" rules="all"> 041 * <tr> 042 * <th>Start index (inclusive)</th> 043 * <th>End index (exclusive)</th> 044 * <th>Description</th> 045 * </tr> 046 * <tr> 047 * <td>0</td> 048 * <td>numLocals</td> 049 * <td>Local variables</td> 050 * </tr> 051 * <tr> 052 * <td>numLocals</td> 053 * <td>numLocals + numStack</td> 054 * <td>Operand stack</td> 055 * </tr> 056 * <tr> 057 * <td>numLocals + numStack</td> 058 * <td>values.length</td> 059 * <td>Locked objects</td> 060 * </tr> 061 * </table> 062 * <p> 063 * Note that the number of locals and the number of stack slots may be smaller than the maximum 064 * number of locals and stack slots as specified in the compiled method. 065 */ 066 public final Value[] values; 067 068 /** 069 * The number of locals in the values array. 070 */ 071 public final int numLocals; 072 073 /** 074 * The number of stack slots in the values array. 075 */ 076 public final int numStack; 077 078 /** 079 * The number of locks in the values array. 080 */ 081 public final int numLocks; 082 083 /** 084 * True if this is a position inside an exception handler before the exception object has been 085 * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int) 086 * getStackValue(0)} is the location of the exception object. If deoptimization happens at this 087 * position, the interpreter will rethrow the exception instead of executing the bytecode 088 * instruction at this position. 089 */ 090 public final boolean rethrowException; 091 092 public final boolean duringCall; 093 094 /** 095 * This BCI should be used for frame states that are built for code with no meaningful BCI. 096 */ 097 public static final int UNKNOWN_BCI = -5; 098 099 /** 100 * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. 101 * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized, 102 * the monitor is still held. 103 */ 104 public static final int UNWIND_BCI = -1; 105 106 /** 107 * The BCI for the state before starting to execute a method. Note that if the method is 108 * synchronized, the monitor is not yet held. 109 */ 110 public static final int BEFORE_BCI = -2; 111 112 /** 113 * The BCI for the state after finishing the execution of a method and returning normally. Note 114 * that if the method was synchronized the monitor is already released. 115 */ 116 public static final int AFTER_BCI = -3; 117 118 /** 119 * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. 120 * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the 121 * monitor is already released. 122 */ 123 public static final int AFTER_EXCEPTION_BCI = -4; 124 125 /** 126 * This BCI should be used for states that cannot be the target of a deoptimization, like 127 * snippet frame states. 128 */ 129 public static final int INVALID_FRAMESTATE_BCI = -6; 130 131 /** 132 * Determines if a given BCI matches one of the placeholder BCI constants defined in this class. 133 */ 134 public static boolean isPlaceholderBci(int bci) { 135 return bci < 0; 136 } 137 138 /** 139 * Gets the name of a given placeholder BCI. 140 */ 141 public static String getPlaceholderBciName(int bci) { 142 assert isPlaceholderBci(bci); 143 if (bci == BytecodeFrame.AFTER_BCI) { 144 return "AFTER_BCI"; 145 } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { 146 return "AFTER_EXCEPTION_BCI"; 147 } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { 148 return "INVALID_FRAMESTATE_BCI"; 149 } else if (bci == BytecodeFrame.BEFORE_BCI) { 150 return "BEFORE_BCI"; 151 } else if (bci == BytecodeFrame.UNKNOWN_BCI) { 152 return "UNKNOWN_BCI"; 153 } else { 154 assert bci == BytecodeFrame.UNWIND_BCI; 155 return "UNWIND_BCI"; 156 } 157 } 158 159 /** 160 * Creates a new frame object. 161 * 162 * @param caller the caller frame (which may be {@code null}) 163 * @param method the method 164 * @param bci a BCI within the method 165 * @param rethrowException specifies if the VM should re-throw the pending exception when 166 * deopt'ing using this frame 167 * @param values the frame state {@link #values} 168 * @param numLocals the number of local variables 169 * @param numStack the depth of the stack 170 * @param numLocks the number of locked objects 171 */ 172 public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, Value[] values, int numLocals, int numStack, int numLocks) { 173 super(caller, method, bci); 174 assert values != null; 175 this.rethrowException = rethrowException; 176 this.duringCall = duringCall; 177 this.values = values; 178 this.numLocals = numLocals; 179 this.numStack = numStack; 180 this.numLocks = numLocks; 181 assert !rethrowException || numStack == 1 : "must have exception on top of the stack"; 182 } 183 184 /** 185 * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the 186 * slot following a double word item. This should really be checked in FrameState itself but 187 * because of Word type rewriting and alternative backends that can't be done. 188 */ 189 public boolean validateFormat(boolean derivedOk) { 190 if (caller() != null) { 191 caller().validateFormat(derivedOk); 192 } 193 for (int i = 0; i < numLocals + numStack; i++) { 194 if (values[i] != null) { 195 Kind kind = values[i].getKind(); 196 if (kind.needsTwoSlots()) { 197 assert values.length > i + 1 : String.format("missing second word %s", this); 198 assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this; 199 } 200 assert derivedOk || ValueUtil.isIllegal(values[i]) || !values[i].getLIRKind().isUnknownReference() : "Unexpected derived value: " + values[i]; 201 } 202 } 203 return true; 204 } 205 206 /** 207 * Gets the value representing the specified local variable. 208 * 209 * @param i the local variable index 210 * @return the value that can be used to reconstruct the local's current value 211 */ 212 public Value getLocalValue(int i) { 213 return values[i]; 214 } 215 216 /** 217 * Gets the value representing the specified stack slot. 218 * 219 * @param i the stack index 220 * @return the value that can be used to reconstruct the stack slot's current value 221 */ 222 public Value getStackValue(int i) { 223 return values[i + numLocals]; 224 } 225 226 /** 227 * Gets the value representing the specified lock. 228 * 229 * @param i the lock index 230 * @return the value that can be used to reconstruct the lock's current value 231 */ 232 public Value getLockValue(int i) { 233 return values[i + numLocals + numStack]; 234 } 235 236 /** 237 * Gets the caller of this frame. 238 * 239 * @return {@code null} if this frame has no caller 240 */ 241 public BytecodeFrame caller() { 242 return (BytecodeFrame) getCaller(); 243 } 244 245 @Override 246 public boolean equals(Object obj) { 247 if (this == obj) { 248 return true; 249 } 250 if (obj instanceof BytecodeFrame && super.equals(obj)) { 251 BytecodeFrame that = (BytecodeFrame) obj; 252 // @formatter:off 253 if (this.duringCall == that.duringCall && 254 this.rethrowException == that.rethrowException && 255 this.numLocals == that.numLocals && 256 this.numLocks == that.numLocks && 257 this.numStack == that.numStack && 258 Arrays.equals(this.values, that.values)) { 259 return true; 260 } 261 // @formatter:off 262 return true; 263 } 264 return false; 265 } 266 267 @Override 268 public String toString() { 269 return CodeUtil.append(new StringBuilder(100), this).toString(); 270 } 271}