diff graal/Compiler/src/com/sun/c1x/value/MutableFrameState.java @ 2507:9ec15d6914ca

Pull over of compiler from maxine repository.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:43:22 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/Compiler/src/com/sun/c1x/value/MutableFrameState.java	Wed Apr 27 11:43:22 2011 +0200
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2010, 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.sun.c1x.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+
+
+/**
+ * The {@code MutableFrameState} class extends abstract {@link FrameState} with methods modifying the frame state.
+ * Only {@code MutableFrameState} can be instantiated and thus the object references in which it is stored decide
+ * whether it is used as immutable or not. Thus and because they can be shared at different places in the compiler,
+ * {@link FrameState}s must not be cast to {@code MutableFrameState}s. Instead, a new copy must be created using
+ * {@link FrameState#copy()}.
+ * Contrariwise and as an optimization, an instance referenced as {@code MutableFrameState} can be assigned to
+ * a variable, field, or method parameter of type {@link FrameState} without creating an immutable copy before
+ * (using {@link #immutableCopy(int)}) if the state is not mutated after the assignment.
+ *
+ * @author Michael Duller
+ */
+public final class MutableFrameState extends FrameState {
+
+    public MutableFrameState(IRScope irScope, int bci, int maxLocals, int maxStack) {
+        super(irScope, bci, maxLocals, maxStack);
+    }
+
+    /**
+     * Replace the local variables in this frame state with the local variables from the specified frame state. This is
+     * used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceLocals(FrameState with) {
+        assert with.maxLocals == maxLocals;
+        System.arraycopy(with.values, 0, values, 0, maxLocals);
+    }
+
+    /**
+     * Replace the stack in this frame state with the stack from the specified frame state. This is used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceStack(FrameState with) {
+        System.arraycopy(with.values, with.maxLocals, values, maxLocals, with.stackIndex);
+        stackIndex = with.stackIndex;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * Replace the locks in this frame state with the locks from the specified frame state. This is used in inlining.
+     *
+     * @param with the frame state containing the new local variables
+     */
+    public void replaceLocks(FrameState with) {
+        if (with.locks == null) {
+            locks = null;
+        } else {
+            locks = Util.uncheckedCast(with.locks.clone());
+        }
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackIndex = 0;
+    }
+
+    public void clearLocals() {
+        for (int i = 0; i < maxLocals; i++) {
+            values[i] = null;
+        }
+    }
+
+    /**
+     * Truncates this stack to the specified size.
+     * @param size the size to truncate to
+     */
+    public void truncateStack(int size) {
+        stackIndex = size;
+        assert stackIndex >= 0;
+    }
+
+    /**
+     * 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) {
+        assert stackIndex >= 0;
+        assert maxLocals + stackIndex < values.length;
+        values[maxLocals + 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() {
+        assert stackIndex >= 1;
+        return values[maxLocals + --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());
+    }
+
+    private static Value assertKind(CiKind kind, Value x) {
+        assert x != null && (x.kind == kind || !isTypesafe()) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind);
+        return x;
+    }
+
+    private static Value assertLong(Value x) {
+        assert x != null && (x.kind == CiKind.Long || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertJsr(Value x) {
+        assert x != null && (x.kind == CiKind.Jsr || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertInt(Value x) {
+        assert x != null && (x.kind == CiKind.Int || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertFloat(Value x) {
+        assert x != null && (x.kind == CiKind.Float || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertObject(Value x) {
+        assert x != null && (x.kind == CiKind.Object || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertWord(Value x) {
+        assert x != null && (x.kind == CiKind.Word || !isTypesafe());
+        return x;
+    }
+
+    private static Value assertDouble(Value x) {
+        assert x != null && (x.kind == CiKind.Double || !isTypesafe());
+        return x;
+    }
+
+    /**
+     * 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];
+        int y = maxLocals + base;
+        for (int i = 0; i < size; ++i) {
+            assert values[y] != null || values[y - 1].kind.jvmSlots == 2;
+            r[i] = values[y++];
+        }
+        stackIndex = base;
+        assert stackIndex >= 0;
+        return r;
+    }
+
+    /**
+     * 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(IRScope scope, Value obj, int totalNumberOfLocks) {
+        if (locks == null) {
+            locks = new ArrayList<Value>(4);
+        }
+        locks.add(obj);
+        scope.updateMaxLocks(totalNumberOfLocks);
+    }
+
+    /**
+     * Unlock the lock on the top of the stack.
+     */
+    public void unlock() {
+        locks.remove(locks.size() - 1);
+    }
+
+    /**
+     * Gets an immutable copy of this state.
+     * @param bci the bytecode index of the new frame state
+     */
+    public FrameState immutableCopy(int bci) {
+        return copy(bci, true, true, true);
+    }
+
+    /**
+     * Determines if the current compilation is typesafe.
+     */
+    private static boolean isTypesafe() {
+        return C1XCompilation.compilation().isTypesafe();
+    }
+
+    private static void assertHigh(Value x) {
+        assert x == null;
+    }
+
+}