Mercurial > hg > graal-compiler
comparison graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java @ 2616:3558ca7088c0
FrameState and Graphviz changes:
* removed popx, pushx methods from GraphBuilder
* FrameState subclass of Value
* added String shortName() to Node
* added GraphvizPrinter option to use short names
* small hack in GraphvizPrinter: omit FrameState->Local connections
* added GraalGraphviz to implicit classpatch (read from GRAAL env var)
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Mon, 09 May 2011 17:00:25 +0200 |
parents | bd235cb4375a |
children | dd115f80acf8 |
comparison
equal
deleted
inserted
replaced
2615:5768534fd4e5 | 2616:3558ca7088c0 |
---|---|
24 | 24 |
25 import java.util.*; | 25 import java.util.*; |
26 | 26 |
27 import com.oracle.graal.graph.*; | 27 import com.oracle.graal.graph.*; |
28 import com.sun.c1x.*; | 28 import com.sun.c1x.*; |
29 import com.sun.c1x.debug.*; | |
29 import com.sun.c1x.ir.*; | 30 import com.sun.c1x.ir.*; |
30 import com.sun.cri.ci.*; | 31 import com.sun.cri.ci.*; |
31 | 32 |
32 import static com.sun.c1x.value.ValueUtil.*; | 33 import static com.sun.c1x.value.ValueUtil.*; |
33 | 34 |
34 /** | 35 /** |
35 * The {@code FrameState} class encapsulates the frame state (i.e. local variables and | 36 * The {@code FrameState} class encapsulates the frame state (i.e. local variables and |
36 * operand stack) at a particular point in the abstract interpretation. | 37 * operand stack) at a particular point in the abstract interpretation. |
37 */ | 38 */ |
38 public class FrameState { | 39 public class FrameState extends Value implements FrameStateAccess { |
39 | 40 |
40 /** | |
41 * The operand stack and local variables. | |
42 * The local variables occupy the index range {@code [0 .. maxLocals)}. | |
43 * The operand stack occupies the index range {@code [maxLocals .. values.length)}. | |
44 * The top of the operand stack is at index {@code maxLocals + stackIndex}. | |
45 * This does not include the operand stack or local variables of parent frames. | |
46 * | |
47 * {@linkplain CiKind#isDoubleWord() Double-word} local variables and | |
48 * operand stack values occupy 2 slots in this array with the second slot | |
49 * being {@code null}. | |
50 */ | |
51 protected final Value[] values; | |
52 | |
53 /** | |
54 * The number of local variables. | |
55 */ | |
56 protected final int localsSize; | 41 protected final int localsSize; |
57 | 42 |
58 protected final int stackSize; | 43 protected final int stackSize; |
44 | |
45 protected final int locksSize; | |
46 | |
47 private static final int SUCCESSOR_COUNT = 0; | |
48 | |
49 @Override | |
50 protected int inputCount() { | |
51 return super.inputCount() + localsSize + stackSize + locksSize; | |
52 } | |
53 | |
54 @Override | |
55 protected int successorCount() { | |
56 return super.successorCount() + SUCCESSOR_COUNT; | |
57 } | |
59 | 58 |
60 /** | 59 /** |
61 * The bytecode index to which this frame state applies. This will be {@code -1} | 60 * The bytecode index to which this frame state applies. This will be {@code -1} |
62 * iff this state is mutable. | 61 * iff this state is mutable. |
63 */ | 62 */ |
69 * @param bci the bytecode index of the frame state | 68 * @param bci the bytecode index of the frame state |
70 * @param localsSize number of locals | 69 * @param localsSize number of locals |
71 * @param stackSize size of the stack | 70 * @param stackSize size of the stack |
72 * @param lockSize number of locks | 71 * @param lockSize number of locks |
73 */ | 72 */ |
74 public FrameState(int bci, int localsSize, int stackSize, int lockSize) { | 73 public FrameState(int bci, int localsSize, int stackSize, int locksSize, Graph graph) { |
74 super(CiKind.Illegal, localsSize + stackSize + locksSize, SUCCESSOR_COUNT, graph); | |
75 this.bci = bci; | 75 this.bci = bci; |
76 this.values = new Value[localsSize + stackSize + lockSize]; | |
77 this.localsSize = localsSize; | 76 this.localsSize = localsSize; |
78 this.stackSize = stackSize; | 77 this.stackSize = stackSize; |
78 this.locksSize = locksSize; | |
79 C1XMetrics.FrameStatesCreated++; | 79 C1XMetrics.FrameStatesCreated++; |
80 C1XMetrics.FrameStateValuesCreated += this.values.length; | 80 C1XMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize; |
81 } | 81 } |
82 | 82 |
83 FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks) { | 83 FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks, Graph graph) { |
84 this(bci, locals.length, stackSize, locks.size()); | 84 this(bci, locals.length, stackSize, locks.size(), graph); |
85 System.arraycopy(locals, 0, values, 0, locals.length); | 85 for (int i = 0; i < locals.length; i++) { |
86 System.arraycopy(stack, 0, values, locals.length, stackSize); | 86 inputs().set(i, locals[i]); |
87 } | |
88 for (int i = 0; i < stackSize; i++) { | |
89 inputs().set(i + localsSize, stack[i]); | |
90 } | |
87 for (int i = 0; i < locks.size(); i++) { | 91 for (int i = 0; i < locks.size(); i++) { |
88 values[locals.length + stackSize + i] = locks.get(i); | 92 inputs().set(locals.length + stackSize + i, locks.get(i)); |
89 } | 93 } |
90 } | 94 } |
91 | 95 |
92 /** | 96 /** |
93 * Gets a immutable copy ({@link FrameState}) of this frame state. | 97 * Gets a copy of this frame state. |
94 */ | 98 */ |
95 public FrameState copy() { | 99 public FrameState duplicate() { |
96 FrameState other = new FrameState(bci, localsSize, stackSize, locksSize()); | 100 FrameState other = copy(); |
97 System.arraycopy(values, 0, other.values, 0, values.length); | 101 other.inputs().setAll(inputs()); |
98 return other; | 102 return other; |
99 } | 103 } |
100 | 104 |
101 /** | 105 /** |
102 * Gets an immutable copy of this frame state but without the stack. | 106 * Gets a copy of this frame state without the stack. |
103 */ | 107 */ |
104 public FrameState copyWithEmptyStack() { | 108 public FrameState duplicateWithEmptyStack() { |
105 FrameState other = new FrameState(bci, localsSize, 0, locksSize()); | 109 FrameState other = new FrameState(bci, localsSize, 0, locksSize(), graph()); |
106 System.arraycopy(values, 0, other.values, 0, localsSize); | 110 for (int i = 0; i < localsSize; i++) { |
107 System.arraycopy(values, localsSize + stackSize, other.values, localsSize, locksSize()); | 111 other.inputs().set(i, localAt(i)); |
112 } | |
113 for (int i = 0; i < locksSize; i++) { | |
114 other.inputs().set(localsSize + i, lockAt(i)); | |
115 } | |
108 return other; | 116 return other; |
109 } | 117 } |
110 | 118 |
111 public boolean isCompatibleWith(FrameState other) { | 119 public boolean isCompatibleWith(FrameStateAccess other) { |
112 if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) { | 120 if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) { |
113 return false; | 121 return false; |
114 } | 122 } |
115 for (int i = 0; i < stackSize(); i++) { | 123 for (int i = 0; i < stackSize(); i++) { |
116 Value x = stackAt(i); | 124 Value x = stackAt(i); |
126 } | 134 } |
127 return true; | 135 return true; |
128 } | 136 } |
129 | 137 |
130 /** | 138 /** |
131 * Returns the size of the local variables. | 139 * Gets the size of the local variables. |
132 * | |
133 * @return the size of the local variables | |
134 */ | 140 */ |
135 public int localsSize() { | 141 public int localsSize() { |
136 return localsSize; | 142 return localsSize; |
137 } | 143 } |
138 | 144 |
145 | 151 |
146 /** | 152 /** |
147 * Gets number of locks held by this frame state. | 153 * Gets number of locks held by this frame state. |
148 */ | 154 */ |
149 public int locksSize() { | 155 public int locksSize() { |
150 return values.length - localsSize - stackSize; | 156 return locksSize; |
151 } | 157 } |
152 | 158 |
153 /** | 159 /** |
154 * Invalidates the local variable at the specified index. If the specified index refers to a doubleword local, then | 160 * Invalidates the local variable at the specified index. If the specified index refers to a doubleword local, then |
155 * invalidates the high word as well. | 161 * invalidates the high word as well. |
158 */ | 164 */ |
159 public void invalidateLocal(int i) { | 165 public void invalidateLocal(int i) { |
160 // note that for double word locals, the high slot should already be null | 166 // note that for double word locals, the high slot should already be null |
161 // unless the local is actually dead and the high slot is being reused; | 167 // unless the local is actually dead and the high slot is being reused; |
162 // in either case, it is not necessary to null the high slot | 168 // in either case, it is not necessary to null the high slot |
163 values[i] = null; | 169 inputs().set(i, null); |
164 } | 170 } |
165 | 171 |
166 /** | 172 /** |
167 * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word}, | 173 * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word}, |
168 * then the next local variable index is also overwritten. | 174 * then the next local variable index is also overwritten. |
171 * @param x the instruction which produces the value for the local | 177 * @param x the instruction which produces the value for the local |
172 */ | 178 */ |
173 public void storeLocal(int i, Value x) { | 179 public void storeLocal(int i, Value x) { |
174 assert i < localsSize : "local variable index out of range: " + i; | 180 assert i < localsSize : "local variable index out of range: " + i; |
175 invalidateLocal(i); | 181 invalidateLocal(i); |
176 values[i] = x; | 182 inputs().set(i, x); |
177 if (isDoubleWord(x)) { | 183 if (isDoubleWord(x)) { |
178 // (tw) if this was a double word then kill i+1 | 184 // (tw) if this was a double word then kill i+1 |
179 values[i + 1] = null; | 185 inputs().set(i + 1, null); |
180 } | 186 } |
181 if (i > 0) { | 187 if (i > 0) { |
182 // if there was a double word at i - 1, then kill it | 188 // if there was a double word at i - 1, then kill it |
183 Value p = values[i - 1]; | 189 Value p = localAt(i - 1); |
184 if (isDoubleWord(p)) { | 190 if (isDoubleWord(p)) { |
185 values[i - 1] = null; | 191 inputs().set(i - 1, null); |
186 } | 192 } |
187 } | 193 } |
188 } | 194 } |
189 | 195 |
190 /** | 196 /** |
193 * @param i the index into the locals | 199 * @param i the index into the locals |
194 * @return the instruction that produced the value for the specified local | 200 * @return the instruction that produced the value for the specified local |
195 */ | 201 */ |
196 public final Value localAt(int i) { | 202 public final Value localAt(int i) { |
197 assert i < localsSize : "local variable index out of range: " + i; | 203 assert i < localsSize : "local variable index out of range: " + i; |
198 return values[i]; | 204 return (Value) inputs().get(i); |
199 } | 205 } |
200 | 206 |
201 /** | 207 /** |
202 * Get the value on the stack at the specified stack index. | 208 * Get the value on the stack at the specified stack index. |
203 * | 209 * |
204 * @param i the index into the stack, with {@code 0} being the bottom of the stack | 210 * @param i the index into the stack, with {@code 0} being the bottom of the stack |
205 * @return the instruction at the specified position in the stack | 211 * @return the instruction at the specified position in the stack |
206 */ | 212 */ |
207 public final Value stackAt(int i) { | 213 public final Value stackAt(int i) { |
208 assert i >= 0 && i < (localsSize + stackSize); | 214 assert i >= 0 && i < (localsSize + stackSize); |
209 return values[localsSize + i]; | 215 return (Value) inputs().get(localsSize + i); |
210 } | 216 } |
211 | 217 |
212 /** | 218 /** |
213 * Retrieves the lock at the specified index in the lock stack. | 219 * Retrieves the lock at the specified index in the lock stack. |
214 * @param i the index into the lock stack | 220 * @param i the index into the lock stack |
215 * @return the instruction which produced the object at the specified location in the lock stack | 221 * @return the instruction which produced the object at the specified location in the lock stack |
216 */ | 222 */ |
217 public final Value lockAt(int i) { | 223 public final Value lockAt(int i) { |
218 assert i >= 0; | 224 assert i >= 0; |
219 return values[localsSize + stackSize + i]; | 225 return (Value) inputs().get(localsSize + stackSize + i); |
220 } | 226 } |
221 | 227 |
222 /** | 228 /** |
223 * Inserts a phi statement into the stack at the specified stack index. | 229 * Inserts a phi statement into the stack at the specified stack index. |
224 * @param block the block begin for which we are creating the phi | 230 * @param block the block begin for which we are creating the phi |
225 * @param i the index into the stack for which to create a phi | 231 * @param i the index into the stack for which to create a phi |
226 * @param graph | 232 */ |
227 */ | 233 public void setupPhiForStack(BlockBegin block, int i) { |
228 public void setupPhiForStack(BlockBegin block, int i, Graph graph) { | |
229 Value p = stackAt(i); | 234 Value p = stackAt(i); |
230 if (p != null) { | 235 if (p != null) { |
231 if (p instanceof Phi) { | 236 if (p instanceof Phi) { |
232 Phi phi = (Phi) p; | 237 Phi phi = (Phi) p; |
233 if (phi.block() == block && phi.isOnStack() && phi.stackIndex() == i) { | 238 if (phi.block() == block && phi.isOnStack() && phi.stackIndex() == i) { |
234 return; | 239 return; |
235 } | 240 } |
236 } | 241 } |
237 values[localsSize + i] = new Phi(p.kind, block, -i - 1, graph); | 242 inputs().set(localsSize + i, new Phi(p.kind, block, -i - 1, graph())); |
238 } | 243 } |
239 } | 244 } |
240 | 245 |
241 /** | 246 /** |
242 * Inserts a phi statement for the local at the specified index. | 247 * Inserts a phi statement for the local at the specified index. |
243 * @param block the block begin for which we are creating the phi | 248 * @param block the block begin for which we are creating the phi |
244 * @param i the index of the local variable for which to create the phi | 249 * @param i the index of the local variable for which to create the phi |
245 * @param graph | 250 */ |
246 */ | 251 public void setupPhiForLocal(BlockBegin block, int i) { |
247 public void setupPhiForLocal(BlockBegin block, int i, Graph graph) { | 252 Value p = localAt(i); |
248 Value p = values[i]; | |
249 if (p instanceof Phi) { | 253 if (p instanceof Phi) { |
250 Phi phi = (Phi) p; | 254 Phi phi = (Phi) p; |
251 if (phi.block() == block && phi.isLocal() && phi.localIndex() == i) { | 255 if (phi.block() == block && phi.isLocal() && phi.localIndex() == i) { |
252 return; | 256 return; |
253 } | 257 } |
254 } | 258 } |
255 storeLocal(i, new Phi(p.kind, block, i, graph)); | 259 storeLocal(i, new Phi(p.kind, block, i, graph())); |
256 } | 260 } |
257 | 261 |
258 /** | 262 /** |
259 * Gets the value at a specified index in the set of operand stack and local values represented by this frame. | 263 * Gets the value at a specified index in the set of operand stack and local values represented by this frame. |
260 * This method should only be used to iterate over all the values in this frame, irrespective of whether | 264 * This method should only be used to iterate over all the values in this frame, irrespective of whether |
265 * @param i a value in the range {@code [0 .. valuesSize()]} | 269 * @param i a value in the range {@code [0 .. valuesSize()]} |
266 * @return the value at index {@code i} which may be {@code null} | 270 * @return the value at index {@code i} which may be {@code null} |
267 */ | 271 */ |
268 public final Value valueAt(int i) { | 272 public final Value valueAt(int i) { |
269 assert i < (localsSize + stackSize); | 273 assert i < (localsSize + stackSize); |
270 return values[i]; | 274 return (Value) inputs().get(i); |
271 } | 275 } |
272 | 276 |
273 /** | 277 /** |
274 * The number of operand stack slots and local variables in this frame. | 278 * The number of operand stack slots and local variables in this frame. |
275 * This method should typically only be used in conjunction with {@link #valueAt(int)}. | 279 * This method should typically only be used in conjunction with {@link #valueAt(int)}. |
282 return localsSize + stackSize; | 286 return localsSize + stackSize; |
283 } | 287 } |
284 | 288 |
285 public void checkPhis(BlockBegin block, FrameState other) { | 289 public void checkPhis(BlockBegin block, FrameState other) { |
286 checkSize(other); | 290 checkSize(other); |
287 final int max = valuesSize(); | 291 for (int i = 0; i < valuesSize(); i++) { |
288 for (int i = 0; i < max; i++) { | 292 Value x = valueAt(i); |
289 Value x = values[i]; | 293 Value y = other.valueAt(i); |
290 Value y = other.values[i]; | |
291 if (x != null && x != y) { | 294 if (x != null && x != y) { |
292 if (x instanceof Phi) { | 295 if (x instanceof Phi) { |
293 Phi phi = (Phi) x; | 296 Phi phi = (Phi) x; |
294 if (phi.block() == block) { | 297 if (phi.block() == block) { |
295 for (int j = 0; j < phi.phiInputCount(); j++) { | 298 for (int j = 0; j < phi.phiInputCount(); j++) { |
303 throw new CiBailout("instruction is not a phi or null at " + i); | 306 throw new CiBailout("instruction is not a phi or null at " + i); |
304 } | 307 } |
305 } | 308 } |
306 } | 309 } |
307 | 310 |
308 private void checkSize(FrameState other) { | 311 private void checkSize(FrameStateAccess other) { |
309 if (other.stackSize() != stackSize()) { | 312 if (other.stackSize() != stackSize()) { |
310 throw new CiBailout("stack sizes do not match"); | 313 throw new CiBailout("stack sizes do not match"); |
311 } else if (other.localsSize != localsSize) { | 314 } else if (other.localsSize() != localsSize) { |
312 throw new CiBailout("local sizes do not match"); | 315 throw new CiBailout("local sizes do not match"); |
313 } | 316 } |
314 } | 317 } |
315 | 318 |
316 public void merge(BlockBegin block, FrameState other, Graph graph) { | 319 public void merge(BlockBegin block, FrameStateAccess other) { |
317 checkSize(other); | 320 checkSize(other); |
318 for (int i = 0; i < valuesSize(); i++) { | 321 for (int i = 0; i < valuesSize(); i++) { |
319 Value x = values[i]; | 322 Value x = valueAt(i); |
320 if (x != null) { | 323 if (x != null) { |
321 Value y = other.values[i]; | 324 Value y = other.valueAt(i); |
322 if (x != y) { | 325 if (x != y) { |
323 if (typeMismatch(x, y)) { | 326 if (typeMismatch(x, y)) { |
324 if (x instanceof Phi) { | 327 if (x instanceof Phi) { |
325 Phi phi = (Phi) x; | 328 Phi phi = (Phi) x; |
326 if (phi.block() == block) { | 329 if (phi.block() == block) { |
327 phi.makeDead(); | 330 phi.makeDead(); |
328 } | 331 } |
329 } | 332 } |
330 values[i] = null; | 333 inputs().set(i, null); |
331 continue; | 334 continue; |
332 } | 335 } |
333 if (i < localsSize) { | 336 if (i < localsSize) { |
334 // this a local | 337 // this a local |
335 setupPhiForLocal(block, i, graph); | 338 setupPhiForLocal(block, i); |
336 } else { | 339 } else { |
337 // this is a stack slot | 340 // this is a stack slot |
338 setupPhiForStack(block, i - localsSize, graph); | 341 setupPhiForStack(block, i - localsSize); |
339 } | 342 } |
340 } | 343 } |
341 } | 344 } |
342 } | 345 } |
343 } | 346 } |
356 * | 359 * |
357 * @param block only phis {@linkplain Phi#block() associated} with this block are traversed | 360 * @param block only phis {@linkplain Phi#block() associated} with this block are traversed |
358 * @param proc the call back invoked for each live phi traversed | 361 * @param proc the call back invoked for each live phi traversed |
359 */ | 362 */ |
360 public final boolean forEachLivePhi(BlockBegin block, PhiProcedure proc) { | 363 public final boolean forEachLivePhi(BlockBegin block, PhiProcedure proc) { |
361 int max = this.valuesSize(); | 364 for (int i = 0; i < valuesSize(); i++) { |
362 for (int i = 0; i < max; i++) { | 365 Value instr = valueAt(i); |
363 Value instr = values[i]; | |
364 if (instr instanceof Phi && !instr.isDeadPhi()) { | 366 if (instr instanceof Phi && !instr.isDeadPhi()) { |
365 Phi phi = (Phi) instr; | 367 Phi phi = (Phi) instr; |
366 if (block == null || phi.block() == block) { | 368 if (block == null || phi.block() == block) { |
367 if (!proc.doPhi(phi)) { | 369 if (!proc.doPhi(phi)) { |
368 return false; | 370 return false; |
375 | 377 |
376 /** | 378 /** |
377 * Checks whether this frame state has any {@linkplain Phi phi} statements. | 379 * Checks whether this frame state has any {@linkplain Phi phi} statements. |
378 */ | 380 */ |
379 public boolean hasPhis() { | 381 public boolean hasPhis() { |
380 int max = valuesSize(); | 382 for (int i = 0; i < valuesSize(); i++) { |
381 for (int i = 0; i < max; i++) { | 383 Value value = valueAt(i); |
382 Value value = values[i]; | |
383 if (value instanceof Phi) { | 384 if (value instanceof Phi) { |
384 return true; | 385 return true; |
385 } | 386 } |
386 } | 387 } |
387 return false; | 388 return false; |
388 } | 389 } |
389 | 390 |
390 /** | 391 /** |
391 * Iterates over all the values in this frame state and its callers, including the stack, locals, and locks. | |
392 * @param closure the closure to apply to each value | |
393 */ | |
394 public void valuesDo(ValueClosure closure) { | |
395 for (int i = 0; i < values.length; i++) { | |
396 if (values[i] != null) { | |
397 Value newValue = closure.apply(values[i]); | |
398 values[i] = newValue; | |
399 } | |
400 } | |
401 } | |
402 | |
403 /** | |
404 * The interface implemented by a client of {@link FrameState#forEachLiveStateValue(ValueProcedure)}. | 392 * The interface implemented by a client of {@link FrameState#forEachLiveStateValue(ValueProcedure)}. |
405 */ | 393 */ |
406 public static interface ValueProcedure { | 394 public static interface ValueProcedure { |
407 void doValue(Value value); | 395 void doValue(Value value); |
408 } | 396 } |
411 * Traverses all {@linkplain Value#isLive() live values} of this frame state. | 399 * Traverses all {@linkplain Value#isLive() live values} of this frame state. |
412 * | 400 * |
413 * @param proc the call back called to process each live value traversed | 401 * @param proc the call back called to process each live value traversed |
414 */ | 402 */ |
415 public final void forEachLiveStateValue(ValueProcedure proc) { | 403 public final void forEachLiveStateValue(ValueProcedure proc) { |
416 final int max = this.valuesSize(); | 404 for (int i = 0; i < valuesSize(); i++) { |
417 for (int i = 0; i < max; i++) { | 405 Value value = valueAt(i); |
418 Value value = this.values[i]; | |
419 if (value != null) { | 406 if (value != null) { |
420 proc.doValue(value); | 407 proc.doValue(value); |
421 } | 408 } |
422 } | 409 } |
423 } | 410 } |
439 Value value = lockAt(i); | 426 Value value = lockAt(i); |
440 sb.append(String.format(" lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); | 427 sb.append(String.format(" lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); |
441 } | 428 } |
442 return sb.toString(); | 429 return sb.toString(); |
443 } | 430 } |
431 | |
432 @Override | |
433 public BlockBegin block() { | |
434 return null; | |
435 } | |
436 | |
437 @Override | |
438 public void accept(ValueVisitor v) { | |
439 v.visitFrameState(this); | |
440 } | |
441 | |
442 @Override | |
443 public void print(LogStream out) { | |
444 out.print("FrameState"); | |
445 } | |
446 | |
447 @Override | |
448 public FrameState copy() { | |
449 return new FrameState(bci, localsSize, stackSize, locksSize, graph()); | |
450 } | |
451 | |
452 | |
444 } | 453 } |