diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Fri May 06 17:08:00 2011 +0200
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.c1x.value;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.sun.c1x.graph.*;
+import com.sun.c1x.ir.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+import static com.sun.c1x.value.ValueUtil.*;
+import static java.lang.reflect.Modifier.*;
+
+
+public class FrameStateBuilder {
+
+    private final Graph graph;
+
+    private final Value[] locals;
+    private final Value[] stack;
+    private final ArrayList<Value> locks;
+
+    private int stackIndex;
+
+    public FrameStateBuilder(RiMethod method, Graph graph) {
+        this.graph = graph;
+        this.locals = new Value[method.maxLocals()];
+        this.stack = new Value[method.maxStackSize()];
+
+        int index = 0;
+        if (!isStatic(method.accessFlags())) {
+            // add the receiver and assume it is non null
+            Local local = new Local(method.holder().kind(), index, graph);
+            local.setFlag(Value.Flag.NonNull, true);
+            local.setDeclaredType(method.holder());
+            storeLocal(index, local);
+            index = 1;
+        }
+        RiSignature sig = method.signature();
+        int max = sig.argumentCount(false);
+        RiType accessingClass = method.holder();
+        for (int i = 0; i < max; i++) {
+            RiType type = sig.argumentTypeAt(i, accessingClass);
+            CiKind kind = type.kind().stackKind();
+            Local local = new Local(kind, index, graph);
+            if (type.isResolved()) {
+                local.setDeclaredType(type);
+            }
+            storeLocal(index, local);
+            index += kind.sizeInSlots();
+        }
+        this.locks = new ArrayList<Value>();
+    }
+
+    public void initializeFrom(FrameState other) {
+        assert locals.length == other.localsSize;
+        assert stack.length >= other.stackSize();
+
+        this.stackIndex = other.stackSize();
+        System.arraycopy(other.values, 0, locals, 0, locals.length);
+        System.arraycopy(other.values, other.localsSize(), stack, 0, stackIndex);
+        locks.clear();
+        for (int i = 0; i < other.locksSize(); i++) {
+            locks.add(other.lockAt(i));
+        }
+    }
+
+    public FrameState create(int bci) {
+        return new FrameState(bci, locals, stack, stackIndex, locks);
+    }
+
+    /**
+     * Pushes an instruction onto the stack with the expected type.
+     * @param kind the type expected for this instruction
+     * @param x the instruction to push onto the stack
+     */
+    public void push(CiKind kind, Value x) {
+        assert kind != CiKind.Void;
+        xpush(assertKind(kind, x));
+        if (kind.sizeInSlots() == 2) {
+            xpush(null);
+        }
+    }
+
+    /**
+     * Pushes a value onto the stack without checking the type.
+     * @param x the instruction to push onto the stack
+     */
+    public void xpush(Value x) {
+        stack[stackIndex++] = x;
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an int.
+     * @param x the instruction to push onto the stack
+     */
+    public void ipush(Value x) {
+        xpush(assertInt(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a float.
+     * @param x the instruction to push onto the stack
+     */
+    public void fpush(Value x) {
+        xpush(assertFloat(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an object.
+     * @param x the instruction to push onto the stack
+     */
+    public void apush(Value x) {
+        xpush(assertObject(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a word.
+     * @param x the instruction to push onto the stack
+     */
+    public void wpush(Value x) {
+        xpush(assertWord(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a JSR return address.
+     * @param x the instruction to push onto the stack
+     */
+    public void jpush(Value x) {
+        xpush(assertJsr(x));
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a long.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void lpush(Value x) {
+        xpush(assertLong(x));
+        xpush(null);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a double.
+     * @param x the instruction to push onto the stack
+     */
+    public void dpush(Value x) {
+        xpush(assertDouble(x));
+        xpush(null);
+    }
+
+    /**
+     * Pops an instruction off the stack with the expected type.
+     * @param kind the expected type
+     * @return the instruction on the top of the stack
+     */
+    public Value pop(CiKind kind) {
+        if (kind.sizeInSlots() == 2) {
+            xpop();
+        }
+        return assertKind(kind, xpop());
+    }
+
+    /**
+     * Pops a value off of the stack without checking the type.
+     * @return x the instruction popped off the stack
+     */
+    public Value xpop() {
+        return stack[--stackIndex];
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an int.
+     * @return x the instruction popped off the stack
+     */
+    public Value ipop() {
+        return assertInt(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a float.
+     * @return x the instruction popped off the stack
+     */
+    public Value fpop() {
+        return assertFloat(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an object.
+     * @return x the instruction popped off the stack
+     */
+    public Value apop() {
+        return assertObject(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a word.
+     * @return x the instruction popped off the stack
+     */
+    public Value wpop() {
+        return assertWord(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a JSR return address.
+     * @return x the instruction popped off the stack
+     */
+    public Value jpop() {
+        return assertJsr(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a long.
+     * @return x the instruction popped off the stack
+     */
+    public Value lpop() {
+        assertHigh(xpop());
+        return assertLong(xpop());
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a double.
+     * @return x the instruction popped off the stack
+     */
+    public Value dpop() {
+        assertHigh(xpop());
+        return assertDouble(xpop());
+    }
+
+    /**
+     * Pop the specified number of slots off of this stack and return them as an array of instructions.
+     * @param size the number of arguments off of the stack
+     * @return an array containing the arguments off of the stack
+     */
+    public Value[] popArguments(int size) {
+        int base = stackIndex - size;
+        Value[] r = new Value[size];
+        for (int i = 0; i < size; ++i) {
+            assert stack[base + i] != null || stack[base + i - 1].kind.jvmSlots == 2;
+            r[i] = stack[base + i];
+        }
+        stackIndex = base;
+        return r;
+    }
+
+    /**
+     * Truncates this stack to the specified size.
+     * @param size the size to truncate to
+     */
+    public void truncateStack(int size) {
+        stackIndex = size;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackIndex = 0;
+    }
+
+    /**
+     * Loads the local variable at the specified index.
+     *
+     * @param i the index of the local variable to load
+     * @return the instruction that produced the specified local
+     */
+    public Value loadLocal(int i) {
+        Value x = locals[i];
+        if (x != null) {
+            if (x.isIllegal()) {
+                return null;
+            }
+            assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi;
+        }
+        return x;
+    }
+
+    /**
+     * Stores a given local variable at the specified index. If the value is a {@linkplain CiKind#isDoubleWord() double word},
+     * then the next local variable index is also overwritten.
+     *
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public void storeLocal(int i, Value x) {
+        locals[i] = x;
+        if (isDoubleWord(x)) {
+            // (tw) if this was a double word then kill i+1
+            locals[i + 1] = null;
+        }
+        if (i > 0) {
+            // if there was a double word at i - 1, then kill it
+            Value p = locals[i - 1];
+            if (isDoubleWord(p)) {
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    /**
+     * Locks a new object within the specified IRScope.
+     * @param scope the IRScope in which this locking operation occurs
+     * @param obj the object being locked
+     */
+    public void lock(IR ir, Value obj, int totalNumberOfLocks) {
+        locks.add(obj);
+        ir.updateMaxLocks(totalNumberOfLocks);
+    }
+
+    /**
+     * Unlock the lock on the top of the stack.
+     */
+    public void unlock() {
+        locks.remove(locks.size() - 1);
+    }
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     *
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    public final Value stackAt(int i) {
+        return stack[i];
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index.
+     *
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    public final Value localAt(int i) {
+        return locals[i];
+    }
+
+    /**
+     * Retrieves the lock at the specified index in the lock stack.
+     * @param i the index into the lock stack
+     * @return the instruction which produced the object at the specified location in the lock stack
+     */
+    public final Value lockAt(int i) {
+        return locks.get(i);
+    }
+
+    /**
+     * Returns the size of the local variables.
+     *
+     * @return the size of the local variables
+     */
+    public int localsSize() {
+        return locals.length;
+    }
+
+    /**
+     * Gets number of locks held by this frame state.
+     */
+    public int locksSize() {
+        return locks.size();
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackIndex;
+    }
+
+    public Iterator<Value> locals() {
+        return new ValueArrayIterator(locals);
+    }
+
+    public Iterator<Value> stack() {
+        return new ValueArrayIterator(locals);
+    }
+
+    public List<Value> locks() {
+        return Collections.unmodifiableList(locks);
+    }
+
+
+    private static class ValueArrayIterator implements Iterator<Value> {
+        private final Value[] array;
+        private int index;
+        private int length;
+
+        public ValueArrayIterator(Value[] array, int length) {
+            assert length <= array.length;
+            this.array = array;
+            this.index = 0;
+        }
+
+        public ValueArrayIterator(Value[] array) {
+            this(array, array.length);
+        }
+
+        @Override
+        public boolean hasNext() {
+            return index < array.length;
+        }
+
+        @Override
+        public Value next() {
+            return array[index++];
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("cannot remove from array");
+        }
+
+    }
+
+}