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 }