comparison jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/BytecodeFrame.java @ 22054:0e095e2c24e2

Rename com.oracle.jvmci to jdk.internal.jvmci
author twisti
date Mon, 22 Jun 2015 12:12:53 -0700
parents
children 488d54275360
comparison
equal deleted inserted replaced
22053:be8ed2908c59 22054:0e095e2c24e2
1 /*
2 * Copyright (c) 2009, 2014, 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.internal.jvmci.code;
24
25 import java.util.*;
26
27 import jdk.internal.jvmci.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 Value[] values;
67
68 /**
69 * The number of locals in the values array.
70 */
71 public final int numLocals;
72
73 /**
74 * The number of stack slots in the values array.
75 */
76 public final int numStack;
77
78 /**
79 * The number of locks in the values array.
80 */
81 public final int numLocks;
82
83 /**
84 * True if this is a position inside an exception handler before the exception object has been
85 * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
86 * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
87 * position, the interpreter will rethrow the exception instead of executing the bytecode
88 * instruction at this position.
89 */
90 public final boolean rethrowException;
91
92 public final boolean duringCall;
93
94 /**
95 * This BCI should be used for frame states that are built for code with no meaningful BCI.
96 */
97 public static final int UNKNOWN_BCI = -5;
98
99 /**
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().isDerivedReference() : "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 }