Mercurial > hg > graal-jvmci-8
view graal/GraalCompiler/src/com/sun/c1x/value/MutableFrameState.java @ 2603:01c5c0443158
new node layout: Phi
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Fri, 06 May 2011 11:18:15 +0200 |
parents | cc1f1d396288 |
children | 39aa89baa165 |
line wrap: on
line source
/* * 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.graph.*; 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(int bci, int maxLocals, int maxStack) { super(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) : "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); return x; } private static Value assertJsr(Value x) { assert x != null && (x.kind == CiKind.Jsr); return x; } private static Value assertInt(Value x) { assert x != null && (x.kind == CiKind.Int); return x; } private static Value assertFloat(Value x) { assert x != null && (x.kind == CiKind.Float); return x; } private static Value assertObject(Value x) { assert x != null && (x.kind == CiKind.Object); return x; } private static Value assertWord(Value x) { assert x != null && (x.kind == CiKind.Word); return x; } private static Value assertDouble(Value x) { assert x != null && (x.kind == CiKind.Double); 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(IR ir, Value obj, int totalNumberOfLocks) { if (locks == null) { locks = new ArrayList<Value>(4); } locks.add(obj); ir.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); } private static void assertHigh(Value x) { assert x == null; } }