Mercurial > hg > truffle
comparison graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java @ 2611:bd235cb4375a
FrameState cleanup: split into FrameStateBuilder and fixed-size FrameState, removed MutableFrameState
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Fri, 06 May 2011 17:08:00 +0200 |
parents | |
children | 3558ca7088c0 |
comparison
equal
deleted
inserted
replaced
2610:39aa89baa165 | 2611:bd235cb4375a |
---|---|
1 /* | |
2 * Copyright (c) 2011, 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 com.sun.c1x.value; | |
24 | |
25 import java.util.*; | |
26 | |
27 import com.oracle.graal.graph.*; | |
28 import com.sun.c1x.graph.*; | |
29 import com.sun.c1x.ir.*; | |
30 import com.sun.cri.ci.*; | |
31 import com.sun.cri.ri.*; | |
32 | |
33 import static com.sun.c1x.value.ValueUtil.*; | |
34 import static java.lang.reflect.Modifier.*; | |
35 | |
36 | |
37 public class FrameStateBuilder { | |
38 | |
39 private final Graph graph; | |
40 | |
41 private final Value[] locals; | |
42 private final Value[] stack; | |
43 private final ArrayList<Value> locks; | |
44 | |
45 private int stackIndex; | |
46 | |
47 public FrameStateBuilder(RiMethod method, Graph graph) { | |
48 this.graph = graph; | |
49 this.locals = new Value[method.maxLocals()]; | |
50 this.stack = new Value[method.maxStackSize()]; | |
51 | |
52 int index = 0; | |
53 if (!isStatic(method.accessFlags())) { | |
54 // add the receiver and assume it is non null | |
55 Local local = new Local(method.holder().kind(), index, graph); | |
56 local.setFlag(Value.Flag.NonNull, true); | |
57 local.setDeclaredType(method.holder()); | |
58 storeLocal(index, local); | |
59 index = 1; | |
60 } | |
61 RiSignature sig = method.signature(); | |
62 int max = sig.argumentCount(false); | |
63 RiType accessingClass = method.holder(); | |
64 for (int i = 0; i < max; i++) { | |
65 RiType type = sig.argumentTypeAt(i, accessingClass); | |
66 CiKind kind = type.kind().stackKind(); | |
67 Local local = new Local(kind, index, graph); | |
68 if (type.isResolved()) { | |
69 local.setDeclaredType(type); | |
70 } | |
71 storeLocal(index, local); | |
72 index += kind.sizeInSlots(); | |
73 } | |
74 this.locks = new ArrayList<Value>(); | |
75 } | |
76 | |
77 public void initializeFrom(FrameState other) { | |
78 assert locals.length == other.localsSize; | |
79 assert stack.length >= other.stackSize(); | |
80 | |
81 this.stackIndex = other.stackSize(); | |
82 System.arraycopy(other.values, 0, locals, 0, locals.length); | |
83 System.arraycopy(other.values, other.localsSize(), stack, 0, stackIndex); | |
84 locks.clear(); | |
85 for (int i = 0; i < other.locksSize(); i++) { | |
86 locks.add(other.lockAt(i)); | |
87 } | |
88 } | |
89 | |
90 public FrameState create(int bci) { | |
91 return new FrameState(bci, locals, stack, stackIndex, locks); | |
92 } | |
93 | |
94 /** | |
95 * Pushes an instruction onto the stack with the expected type. | |
96 * @param kind the type expected for this instruction | |
97 * @param x the instruction to push onto the stack | |
98 */ | |
99 public void push(CiKind kind, Value x) { | |
100 assert kind != CiKind.Void; | |
101 xpush(assertKind(kind, x)); | |
102 if (kind.sizeInSlots() == 2) { | |
103 xpush(null); | |
104 } | |
105 } | |
106 | |
107 /** | |
108 * Pushes a value onto the stack without checking the type. | |
109 * @param x the instruction to push onto the stack | |
110 */ | |
111 public void xpush(Value x) { | |
112 stack[stackIndex++] = x; | |
113 } | |
114 | |
115 /** | |
116 * Pushes a value onto the stack and checks that it is an int. | |
117 * @param x the instruction to push onto the stack | |
118 */ | |
119 public void ipush(Value x) { | |
120 xpush(assertInt(x)); | |
121 } | |
122 | |
123 /** | |
124 * Pushes a value onto the stack and checks that it is a float. | |
125 * @param x the instruction to push onto the stack | |
126 */ | |
127 public void fpush(Value x) { | |
128 xpush(assertFloat(x)); | |
129 } | |
130 | |
131 /** | |
132 * Pushes a value onto the stack and checks that it is an object. | |
133 * @param x the instruction to push onto the stack | |
134 */ | |
135 public void apush(Value x) { | |
136 xpush(assertObject(x)); | |
137 } | |
138 | |
139 /** | |
140 * Pushes a value onto the stack and checks that it is a word. | |
141 * @param x the instruction to push onto the stack | |
142 */ | |
143 public void wpush(Value x) { | |
144 xpush(assertWord(x)); | |
145 } | |
146 | |
147 /** | |
148 * Pushes a value onto the stack and checks that it is a JSR return address. | |
149 * @param x the instruction to push onto the stack | |
150 */ | |
151 public void jpush(Value x) { | |
152 xpush(assertJsr(x)); | |
153 } | |
154 | |
155 /** | |
156 * Pushes a value onto the stack and checks that it is a long. | |
157 * | |
158 * @param x the instruction to push onto the stack | |
159 */ | |
160 public void lpush(Value x) { | |
161 xpush(assertLong(x)); | |
162 xpush(null); | |
163 } | |
164 | |
165 /** | |
166 * Pushes a value onto the stack and checks that it is a double. | |
167 * @param x the instruction to push onto the stack | |
168 */ | |
169 public void dpush(Value x) { | |
170 xpush(assertDouble(x)); | |
171 xpush(null); | |
172 } | |
173 | |
174 /** | |
175 * Pops an instruction off the stack with the expected type. | |
176 * @param kind the expected type | |
177 * @return the instruction on the top of the stack | |
178 */ | |
179 public Value pop(CiKind kind) { | |
180 if (kind.sizeInSlots() == 2) { | |
181 xpop(); | |
182 } | |
183 return assertKind(kind, xpop()); | |
184 } | |
185 | |
186 /** | |
187 * Pops a value off of the stack without checking the type. | |
188 * @return x the instruction popped off the stack | |
189 */ | |
190 public Value xpop() { | |
191 return stack[--stackIndex]; | |
192 } | |
193 | |
194 /** | |
195 * Pops a value off of the stack and checks that it is an int. | |
196 * @return x the instruction popped off the stack | |
197 */ | |
198 public Value ipop() { | |
199 return assertInt(xpop()); | |
200 } | |
201 | |
202 /** | |
203 * Pops a value off of the stack and checks that it is a float. | |
204 * @return x the instruction popped off the stack | |
205 */ | |
206 public Value fpop() { | |
207 return assertFloat(xpop()); | |
208 } | |
209 | |
210 /** | |
211 * Pops a value off of the stack and checks that it is an object. | |
212 * @return x the instruction popped off the stack | |
213 */ | |
214 public Value apop() { | |
215 return assertObject(xpop()); | |
216 } | |
217 | |
218 /** | |
219 * Pops a value off of the stack and checks that it is a word. | |
220 * @return x the instruction popped off the stack | |
221 */ | |
222 public Value wpop() { | |
223 return assertWord(xpop()); | |
224 } | |
225 | |
226 /** | |
227 * Pops a value off of the stack and checks that it is a JSR return address. | |
228 * @return x the instruction popped off the stack | |
229 */ | |
230 public Value jpop() { | |
231 return assertJsr(xpop()); | |
232 } | |
233 | |
234 /** | |
235 * Pops a value off of the stack and checks that it is a long. | |
236 * @return x the instruction popped off the stack | |
237 */ | |
238 public Value lpop() { | |
239 assertHigh(xpop()); | |
240 return assertLong(xpop()); | |
241 } | |
242 | |
243 /** | |
244 * Pops a value off of the stack and checks that it is a double. | |
245 * @return x the instruction popped off the stack | |
246 */ | |
247 public Value dpop() { | |
248 assertHigh(xpop()); | |
249 return assertDouble(xpop()); | |
250 } | |
251 | |
252 /** | |
253 * Pop the specified number of slots off of this stack and return them as an array of instructions. | |
254 * @param size the number of arguments off of the stack | |
255 * @return an array containing the arguments off of the stack | |
256 */ | |
257 public Value[] popArguments(int size) { | |
258 int base = stackIndex - size; | |
259 Value[] r = new Value[size]; | |
260 for (int i = 0; i < size; ++i) { | |
261 assert stack[base + i] != null || stack[base + i - 1].kind.jvmSlots == 2; | |
262 r[i] = stack[base + i]; | |
263 } | |
264 stackIndex = base; | |
265 return r; | |
266 } | |
267 | |
268 /** | |
269 * Truncates this stack to the specified size. | |
270 * @param size the size to truncate to | |
271 */ | |
272 public void truncateStack(int size) { | |
273 stackIndex = size; | |
274 assert stackIndex >= 0; | |
275 } | |
276 | |
277 /** | |
278 * Clears all values on this stack. | |
279 */ | |
280 public void clearStack() { | |
281 stackIndex = 0; | |
282 } | |
283 | |
284 /** | |
285 * Loads the local variable at the specified index. | |
286 * | |
287 * @param i the index of the local variable to load | |
288 * @return the instruction that produced the specified local | |
289 */ | |
290 public Value loadLocal(int i) { | |
291 Value x = locals[i]; | |
292 if (x != null) { | |
293 if (x.isIllegal()) { | |
294 return null; | |
295 } | |
296 assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi; | |
297 } | |
298 return x; | |
299 } | |
300 | |
301 /** | |
302 * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word}, | |
303 * then the next local variable index is also overwritten. | |
304 * | |
305 * @param i the index at which to store | |
306 * @param x the instruction which produces the value for the local | |
307 */ | |
308 public void storeLocal(int i, Value x) { | |
309 locals[i] = x; | |
310 if (isDoubleWord(x)) { | |
311 // (tw) if this was a double word then kill i+1 | |
312 locals[i + 1] = null; | |
313 } | |
314 if (i > 0) { | |
315 // if there was a double word at i - 1, then kill it | |
316 Value p = locals[i - 1]; | |
317 if (isDoubleWord(p)) { | |
318 locals[i - 1] = null; | |
319 } | |
320 } | |
321 } | |
322 | |
323 /** | |
324 * Locks a new object within the specified IRScope. | |
325 * @param scope the IRScope in which this locking operation occurs | |
326 * @param obj the object being locked | |
327 */ | |
328 public void lock(IR ir, Value obj, int totalNumberOfLocks) { | |
329 locks.add(obj); | |
330 ir.updateMaxLocks(totalNumberOfLocks); | |
331 } | |
332 | |
333 /** | |
334 * Unlock the lock on the top of the stack. | |
335 */ | |
336 public void unlock() { | |
337 locks.remove(locks.size() - 1); | |
338 } | |
339 | |
340 /** | |
341 * Get the value on the stack at the specified stack index. | |
342 * | |
343 * @param i the index into the stack, with {@code 0} being the bottom of the stack | |
344 * @return the instruction at the specified position in the stack | |
345 */ | |
346 public final Value stackAt(int i) { | |
347 return stack[i]; | |
348 } | |
349 | |
350 /** | |
351 * Gets the value in the local variables at the specified index. | |
352 * | |
353 * @param i the index into the locals | |
354 * @return the instruction that produced the value for the specified local | |
355 */ | |
356 public final Value localAt(int i) { | |
357 return locals[i]; | |
358 } | |
359 | |
360 /** | |
361 * Retrieves the lock at the specified index in the lock stack. | |
362 * @param i the index into the lock stack | |
363 * @return the instruction which produced the object at the specified location in the lock stack | |
364 */ | |
365 public final Value lockAt(int i) { | |
366 return locks.get(i); | |
367 } | |
368 | |
369 /** | |
370 * Returns the size of the local variables. | |
371 * | |
372 * @return the size of the local variables | |
373 */ | |
374 public int localsSize() { | |
375 return locals.length; | |
376 } | |
377 | |
378 /** | |
379 * Gets number of locks held by this frame state. | |
380 */ | |
381 public int locksSize() { | |
382 return locks.size(); | |
383 } | |
384 | |
385 /** | |
386 * Gets the current size (height) of the stack. | |
387 */ | |
388 public int stackSize() { | |
389 return stackIndex; | |
390 } | |
391 | |
392 public Iterator<Value> locals() { | |
393 return new ValueArrayIterator(locals); | |
394 } | |
395 | |
396 public Iterator<Value> stack() { | |
397 return new ValueArrayIterator(locals); | |
398 } | |
399 | |
400 public List<Value> locks() { | |
401 return Collections.unmodifiableList(locks); | |
402 } | |
403 | |
404 | |
405 private static class ValueArrayIterator implements Iterator<Value> { | |
406 private final Value[] array; | |
407 private int index; | |
408 private int length; | |
409 | |
410 public ValueArrayIterator(Value[] array, int length) { | |
411 assert length <= array.length; | |
412 this.array = array; | |
413 this.index = 0; | |
414 } | |
415 | |
416 public ValueArrayIterator(Value[] array) { | |
417 this(array, array.length); | |
418 } | |
419 | |
420 @Override | |
421 public boolean hasNext() { | |
422 return index < array.length; | |
423 } | |
424 | |
425 @Override | |
426 public Value next() { | |
427 return array[index++]; | |
428 } | |
429 | |
430 @Override | |
431 public void remove() { | |
432 throw new UnsupportedOperationException("cannot remove from array"); | |
433 } | |
434 | |
435 } | |
436 | |
437 } |