# HG changeset patch # User Lukas Stadler # Date 1304931249 -7200 # Node ID dfb1a952a2030ddb46ea4f647651c4ad3d7ec78b # Parent 2523de4d378e04914b6eb83c69379ad9fe12b0b6# Parent a57e051b33cd1518abfc95fde5cb7912318c2b8f merge diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Mon May 09 10:43:57 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Mon May 09 10:54:09 2011 +0200 @@ -94,7 +94,7 @@ this.method = method; this.stats = stats == null ? new CiStatistics() : stats; this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method); - this.placeholderState = method != null && method.minimalDebugInfo() ? new MutableFrameState(0, 0, 0) : null; + this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(0, 0, 0, 0) : null; if (compiler.isObserved()) { compiler.fireCompilationStarted(new CompilationEvent(this)); diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/debug/BlockPrinter.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/BlockPrinter.java Mon May 09 10:43:57 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/BlockPrinter.java Mon May 09 10:54:09 2011 +0200 @@ -67,7 +67,7 @@ private static void printFrameState(FrameState newFrameState, LogStream out) { int startPosition = out.position(); - if (newFrameState.stackEmpty()) { + if (newFrameState.stackSize() == 0) { out.print("empty stack"); } else { out.print("stack ["); diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Mon May 09 10:43:57 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Mon May 09 10:54:09 2011 +0200 @@ -81,47 +81,47 @@ public final int mask = 1 << ordinal(); } - final IR ir; - final C1XCompilation compilation; - final CiStatistics stats; + private final IR ir; + private final C1XCompilation compilation; + private final CiStatistics stats; /** * Map used to implement local value numbering for the current block. */ - final ValueMap localValueMap; + private final ValueMap localValueMap; /** * Map used for local load elimination (i.e. within the current block). */ - final MemoryMap memoryMap; + private final MemoryMap memoryMap; - final BytecodeStream stream; // the bytecode stream + private final BytecodeStream stream; // the bytecode stream // bci-to-block mapping - BlockMap blockMap; + private BlockMap blockMap; // the constant pool - final RiConstantPool constantPool; + private final RiConstantPool constantPool; // the worklist of blocks, managed like a sorted list - BlockBegin[] workList; + private BlockBegin[] workList; // the current position in the worklist - int workListIndex; + private int workListIndex; /** * Mask of {@link Flag} values. */ - int flags; + private int flags; // Exception handler list - List exceptionHandlers; + private List exceptionHandlers; - BlockBegin curBlock; // the current block - MutableFrameState curState; // the current execution state - Instruction lastInstr; // the last instruction added - final LogStream log; + private BlockBegin curBlock; // the current block + private FrameStateBuilder frameState; // the current execution state + private Instruction lastInstr; // the last instruction added + private final LogStream log; - boolean skipBlock; // skip processing of the rest of this block + private boolean skipBlock; // skip processing of the rest of this block private Value rootMethodSynchronizedObject; private final Graph graph; @@ -143,6 +143,7 @@ stream = new BytecodeStream(compilation.method.code()); constantPool = compilation.runtime.getConstantPool(compilation.method); this.graph = graph; + this.frameState = new FrameStateBuilder(compilation.method, graph); } /** @@ -181,7 +182,7 @@ flags |= Flag.HasHandler.mask; } - MutableFrameState initialState = stateAtEntry(rootMethod); + FrameState initialState = frameState.create(-1); startBlock.mergeOrClone(initialState, rootMethod); BlockBegin syncHandler = null; @@ -189,7 +190,6 @@ curBlock = startBlock; lastInstr = startBlock; lastInstr.appendNext(null, -1); - curState = initialState; if (isSynchronized(rootMethod.accessFlags())) { // 4A.1 add a monitor enter to the start block @@ -228,7 +228,7 @@ assert curBlock == startBlock; Base base = new Base(stdEntry, graph); appendWithoutOptimization(base, 0); - FrameState stateAfter = curState.immutableCopy(bci()); + FrameState stateAfter = frameState.create(bci()); base.setStateAfter(stateAfter); startBlock.setEnd(base); assert stdEntry.stateBefore() == null; @@ -252,71 +252,71 @@ } private void ipush(Value x) { - curState.ipush(x); + frameState.ipush(x); } private void lpush(Value x) { - curState.lpush(x); + frameState.lpush(x); } private void fpush(Value x) { - curState.fpush(x); + frameState.fpush(x); } private void dpush(Value x) { - curState.dpush(x); + frameState.dpush(x); } private void apush(Value x) { - curState.apush(x); + frameState.apush(x); } private void wpush(Value x) { - curState.wpush(x); + frameState.wpush(x); } private void push(CiKind kind, Value x) { - curState.push(kind, x); + frameState.push(kind, x); } private void pushReturn(CiKind kind, Value x) { if (kind != CiKind.Void) { - curState.push(kind.stackKind(), x); + frameState.push(kind.stackKind(), x); } } private Value ipop() { - return curState.ipop(); + return frameState.ipop(); } private Value lpop() { - return curState.lpop(); + return frameState.lpop(); } private Value fpop() { - return curState.fpop(); + return frameState.fpop(); } private Value dpop() { - return curState.dpop(); + return frameState.dpop(); } private Value apop() { - return curState.apop(); + return frameState.apop(); } private Value wpop() { - return curState.wpop(); + return frameState.wpop(); } private Value pop(CiKind kind) { - return curState.pop(kind); + return frameState.pop(kind); } private CiKind peekKind() { - Value top = curState.stackAt(curState.stackSize() - 1); + Value top = frameState.stackAt(frameState.stackSize() - 1); if (top == null) { - top = curState.stackAt(curState.stackSize() - 2); + top = frameState.stackAt(frameState.stackSize() - 2); assert top != null; assert top.kind.isDoubleWord(); } @@ -324,11 +324,11 @@ } private void loadLocal(int index, CiKind kind) { - push(kind, curState.loadLocal(index)); + push(kind, frameState.loadLocal(index)); } private void storeLocal(CiKind kind, int index) { - curState.storeLocal(index, pop(kind)); + frameState.storeLocal(index, pop(kind)); } List handleException(Instruction x, int bci) { @@ -380,7 +380,7 @@ assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize(); // exception handler starts with an empty expression stack - curState = curState.immutableCopyWithEmptyStack(); + curState = curState.copyWithEmptyStack(); entry.mergeOrClone(curState, method()); @@ -435,7 +435,7 @@ } void genLoadIndexed(CiKind kind) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value index = ipop(); Value array = apop(); Value length = null; @@ -447,7 +447,7 @@ } void genStoreIndexed(CiKind kind) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value value = pop(kind.stackKind()); Value index = ipop(); Value array = apop(); @@ -465,76 +465,76 @@ void stackOp(int opcode) { switch (opcode) { case POP: { - curState.xpop(); + frameState.xpop(); break; } case POP2: { - curState.xpop(); - curState.xpop(); + frameState.xpop(); + frameState.xpop(); break; } case DUP: { - Value w = curState.xpop(); - curState.xpush(w); - curState.xpush(w); + Value w = frameState.xpop(); + frameState.xpush(w); + frameState.xpush(w); break; } case DUP_X1: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - curState.xpush(w1); - curState.xpush(w2); - curState.xpush(w1); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); break; } case DUP_X2: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - Value w3 = curState.xpop(); - curState.xpush(w1); - curState.xpush(w3); - curState.xpush(w2); - curState.xpush(w1); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + Value w3 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); break; } case DUP2: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - curState.xpush(w2); - curState.xpush(w1); - curState.xpush(w2); - curState.xpush(w1); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); break; } case DUP2_X1: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - Value w3 = curState.xpop(); - curState.xpush(w2); - curState.xpush(w1); - curState.xpush(w3); - curState.xpush(w2); - curState.xpush(w1); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + Value w3 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); break; } case DUP2_X2: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - Value w3 = curState.xpop(); - Value w4 = curState.xpop(); - curState.xpush(w2); - curState.xpush(w1); - curState.xpush(w4); - curState.xpush(w3); - curState.xpush(w2); - curState.xpush(w1); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + Value w3 = frameState.xpop(); + Value w4 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w4); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); break; } case SWAP: { - Value w1 = curState.xpop(); - Value w2 = curState.xpop(); - curState.xpush(w1); - curState.xpush(w2); + Value w1 = frameState.xpop(); + Value w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); break; } default: @@ -592,9 +592,9 @@ void genIncrement() { int index = stream().readLocalIndex(); int delta = stream().readIncrement(); - Value x = curState.localAt(index); + Value x = frameState.localAt(index); Value y = append(Constant.forInt(delta, graph)); - curState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), null, graph))); + frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), null, graph))); } void genGoto(int fromBCI, int toBCI) { @@ -612,27 +612,27 @@ void genIfZero(Condition cond) { Value y = appendConstant(CiConstant.INT_0); - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value x = ipop(); ifNode(x, cond, y, stateBefore); } void genIfNull(Condition cond) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value y = appendConstant(CiConstant.NULL_OBJECT); Value x = apop(); ifNode(x, cond, y, stateBefore); } void genIfSame(CiKind kind, Condition cond) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value y = pop(kind); Value x = pop(kind); ifNode(x, cond, y, stateBefore); } void genThrow(int bci) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Throw t = new Throw(apop(), stateBefore, !noSafepoints(), graph); appendWithoutOptimization(t, bci); } @@ -665,7 +665,7 @@ } void genNewInstance(int cpi) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); RiType type = constantPool().lookupType(cpi, NEW); NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore, graph); if (memoryMap != null) { @@ -675,7 +675,7 @@ } void genNewTypeArray(int typeCode) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); CiKind kind = CiKind.fromArrayTypeCode(typeCode); RiType elementType = compilation.runtime.asRiType(kind); apush(append(new NewTypeArray(ipop(), elementType, stateBefore, graph))); @@ -683,14 +683,14 @@ void genNewObjectArray(int cpi) { RiType type = constantPool().lookupType(cpi, ANEWARRAY); - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); NewArray n = new NewObjectArray(type, ipop(), stateBefore, graph); apush(append(n)); } void genNewMultiArray(int cpi) { RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY); - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); int rank = stream().readUByte(bci() + 3); Value[] dims = new Value[rank]; for (int i = rank - 1; i >= 0; i--) { @@ -702,14 +702,14 @@ void genGetField(int cpi, RiField field) { // Must copy the state here, because the field holder must still be on the stack. - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); LoadField load = new LoadField(apop(), field, stateBefore, graph); appendOptimizedLoadField(field.kind(), load); } void genPutField(int cpi, RiField field) { // Must copy the state here, because the field holder must still be on the stack. - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); Value value = pop(field.kind().stackKind()); appendOptimizedStoreField(new StoreField(apop(), field, value, stateBefore, graph)); } @@ -787,28 +787,28 @@ genResolveClass(RiType.Representation.StaticFields, holder, isInitialized, cpi); } - FrameState stateBefore = curState.immutableCopy(bci()); - Value[] args = curState.popArguments(target.signature().argumentSlots(false)); + FrameState stateBefore = frameState.create(bci()); + Value[] args = frameState.popArguments(target.signature().argumentSlots(false)); appendInvoke(INVOKESTATIC, target, args, cpi, constantPool, stateBefore); } void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { - FrameState stateBefore = curState.immutableCopy(bci()); - Value[] args = curState.popArguments(target.signature().argumentSlots(true)); + FrameState stateBefore = frameState.create(bci()); + Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); genInvokeIndirect(INVOKEINTERFACE, target, args, cpi, constantPool, stateBefore); } void genInvokeVirtual(RiMethod target, int cpi, RiConstantPool constantPool) { - FrameState stateBefore = curState.immutableCopy(bci()); - Value[] args = curState.popArguments(target.signature().argumentSlots(true)); + FrameState stateBefore = frameState.create(bci()); + Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); genInvokeIndirect(INVOKEVIRTUAL, target, args, cpi, constantPool, stateBefore); } void genInvokeSpecial(RiMethod target, RiType knownHolder, int cpi, RiConstantPool constantPool) { - FrameState stateBefore = curState.immutableCopy(bci()); - Value[] args = curState.popArguments(target.signature().argumentSlots(true)); + FrameState stateBefore = frameState.create(bci()); + Value[] args = frameState.popArguments(target.signature().argumentSlots(true)); invokeDirect(target, args, knownHolder, cpi, constantPool, stateBefore); } @@ -970,7 +970,7 @@ } void callRegisterFinalizer() { - Value receiver = curState.loadLocal(0); + Value receiver = frameState.loadLocal(0); RiType declaredType = receiver.declaredType(); RiType receiverType = declaredType; RiType exactType = receiver.exactType(); @@ -1003,7 +1003,7 @@ if (needsCheck) { // append a call to the finalizer registration - append(new RegisterFinalizer(curState.loadLocal(0), curState.immutableCopy(bci()), graph)); + append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph)); C1XMetrics.InlinedFinalizerChecks++; } } @@ -1013,18 +1013,18 @@ callRegisterFinalizer(); } - curState.truncateStack(0); + frameState.clearStack(); if (Modifier.isSynchronized(method().accessFlags())) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); // unlock before exiting the method - int lockNumber = curState.locksSize() - 1; + int lockNumber = frameState.locksSize() - 1; MonitorAddress lockAddress = null; if (compilation.runtime.sizeOfBasicObjectLock() != 0) { lockAddress = new MonitorAddress(lockNumber, graph); append(lockAddress); } append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore, graph)); - curState.unlock(); + frameState.unlock(); } append(new Return(x, !noSafepoints(), graph)); } @@ -1033,7 +1033,7 @@ * Gets the number of locks held. */ private int locksSize() { - return curState.locksSize(); + return frameState.locksSize(); } void genMonitorEnter(Value x, int bci) { @@ -1043,17 +1043,15 @@ lockAddress = new MonitorAddress(lockNumber, graph); append(lockAddress); } - curState.push(CiKind.Object, x); - MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, curState.immutableCopy(bci()), graph); - curState.apop(); + MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null, graph); appendWithoutOptimization(monitorEnter, bci); - curState.lock(ir, x, lockNumber + 1); - monitorEnter.setStateAfter(curState.immutableCopy(bci)); + frameState.lock(ir, x, lockNumber + 1); + monitorEnter.setStateAfter(frameState.create(bci)); killMemoryMap(); // prevent any optimizations across synchronization } void genMonitorExit(Value x, int bci) { - int lockNumber = curState.locksSize() - 1; + int lockNumber = frameState.locksSize() - 1; if (lockNumber < 0) { throw new CiBailout("monitor stack underflow"); } @@ -1063,7 +1061,7 @@ append(lockAddress); } appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null, graph), bci); - curState.unlock(); + frameState.unlock(); killMemoryMap(); // prevent any optimizations across synchronization } @@ -1091,7 +1089,7 @@ isBackwards |= offset < 0; // if the default successor is backwards list.add(blockAt(bci + offset)); boolean isSafepoint = isBackwards && !noSafepoints(); - FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; + FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null; append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph)); } @@ -1113,7 +1111,7 @@ isBackwards |= offset < 0; // if the default successor is backwards list.add(blockAt(bci + offset)); boolean isSafepoint = isBackwards && !noSafepoints(); - FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; + FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null; append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint, graph)); } @@ -1191,7 +1189,7 @@ if (x instanceof StateSplit) { StateSplit stateSplit = (StateSplit) x; if (stateSplit.stateBefore() == null) { - stateSplit.setStateBefore(curState.immutableCopy(bci)); + stateSplit.setStateBefore(frameState.create(bci)); } } @@ -1217,33 +1215,6 @@ return result; } - MutableFrameState stateAtEntry(RiMethod method) { - MutableFrameState state = new MutableFrameState(-1, method.maxLocals(), 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()); - state.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); - } - state.storeLocal(index, local); - index += kind.sizeInSlots(); - } - return state; - } - private Value synchronizedObject(FrameState curState2, RiMethod target) { if (isStatic(target.accessFlags())) { Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph); @@ -1255,7 +1226,7 @@ private void fillSyncHandler(Value lock, BlockBegin syncHandler) { BlockBegin origBlock = curBlock; - MutableFrameState origState = curState; + FrameState origState = frameState.create(-1); Instruction origLast = lastInstr; lastInstr = curBlock = syncHandler; @@ -1263,13 +1234,13 @@ // go forward to the end of the block lastInstr = lastInstr.next(); } - curState = syncHandler.stateBefore().copy(); + frameState.initializeFrom(syncHandler.stateBefore()); int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; - Value exception = appendWithoutOptimization(new ExceptionObject(curState.immutableCopy(bci), graph), bci); + Value exception = appendWithoutOptimization(new ExceptionObject(frameState.create(bci), graph), bci); assert lock != null; - assert curState.locksSize() > 0 && curState.lockAt(locksSize() - 1) == lock; + assert frameState.locksSize() > 0 && frameState.lockAt(locksSize() - 1) == lock; if (lock instanceof Instruction) { Instruction l = (Instruction) lock; if (!l.isAppended()) { @@ -1283,10 +1254,10 @@ genThrow(bci); BlockEnd end = (BlockEnd) lastInstr; curBlock.setEnd(end); - end.setStateAfter(curState.immutableCopy(bci())); + end.setStateAfter(frameState.create(bci())); curBlock = origBlock; - curState = origState; + frameState.initializeFrom(origState); lastInstr = origLast; } @@ -1298,7 +1269,7 @@ // now parse the block killMemoryMap(); curBlock = b; - curState = b.stateBefore().copy(); + frameState.initializeFrom(b.stateBefore()); lastInstr = b; b.appendNext(null, -1); @@ -1309,7 +1280,7 @@ private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) { skipBlock = false; - assert curState != null; + assert frameState != null; stream.setBCI(bci); BlockBegin block = curBlock; @@ -1340,7 +1311,7 @@ // push an exception object onto the stack if we are parsing an exception handler if (pushException) { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); apush(append(new ExceptionObject(stateBefore, graph))); pushException = false; } @@ -1368,13 +1339,13 @@ // if the method terminates, we don't need the stack anymore if (end instanceof Return || end instanceof Throw) { - curState.clearStack(); + frameState.clearStack(); } // connect to begin and set state // NOTE that inlining may have changed the block we are parsing assert end != null : "end should exist after iterating over bytecodes"; - end.setStateAfter(curState.immutableCopy(bci())); + end.setStateAfter(frameState.create(bci())); curBlock.setEnd(end); // propagate the state for (BlockBegin succ : end.blockSuccessors()) { @@ -1387,17 +1358,17 @@ private void traceState() { if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { - log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", curState.localsSize(), curState.stackSize(), method())); - for (int i = 0; i < curState.localsSize(); ++i) { - Value value = curState.localAt(i); + log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method())); + for (int i = 0; i < frameState.localsSize(); ++i) { + Value value = frameState.localAt(i); log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); } - for (int i = 0; i < curState.stackSize(); ++i) { - Value value = curState.stackAt(i); + for (int i = 0; i < frameState.stackSize(); ++i) { + Value value = frameState.stackAt(i); log.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); } - for (int i = 0; i < curState.locksSize(); ++i) { - Value value = curState.lockAt(i); + for (int i = 0; i < frameState.locksSize(); ++i) { + Value value = frameState.lockAt(i); log.println(String.format("| lock[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); } } @@ -1508,12 +1479,12 @@ case ISUB : // fall through case IMUL : genArithmeticOp(CiKind.Int, opcode); break; case IDIV : // fall through - case IREM : genArithmeticOp(CiKind.Int, opcode, curState.immutableCopy(bci())); break; + case IREM : genArithmeticOp(CiKind.Int, opcode, frameState.create(bci())); break; case LADD : // fall through case LSUB : // fall through case LMUL : genArithmeticOp(CiKind.Long, opcode); break; case LDIV : // fall through - case LREM : genArithmeticOp(CiKind.Long, opcode, curState.immutableCopy(bci())); break; + case LREM : genArithmeticOp(CiKind.Long, opcode, frameState.create(bci())); break; case FADD : // fall through case FSUB : // fall through case FMUL : // fall through @@ -1634,7 +1605,7 @@ } private void genArrayLength() { - FrameState stateBefore = curState.immutableCopy(bci()); + FrameState stateBefore = frameState.create(bci()); ipush(append(new ArrayLength(apop(), stateBefore, graph))); } diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Mon May 09 10:43:57 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Mon May 09 10:54:09 2011 +0200 @@ -35,11 +35,6 @@ private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; - /** - * Sentinel denoting an explicitly cleared state. - */ - private static final FrameState CLEARED_STATE = new MutableFrameState(-5, 0, 0); - private FrameState stateBefore; /** diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Mon May 09 10:43:57 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Mon May 09 10:54:09 2011 +0200 @@ -26,15 +26,16 @@ import com.oracle.graal.graph.*; import com.sun.c1x.*; -import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; import com.sun.cri.ci.*; +import static com.sun.c1x.value.ValueUtil.*; + /** * The {@code FrameState} class encapsulates the frame state (i.e. local variables and * operand stack) at a particular point in the abstract interpretation. */ -public abstract class FrameState { +public class FrameState { /** * The operand stack and local variables. @@ -50,15 +51,11 @@ protected final Value[] values; /** - * The depth of the operand stack. - * The top of stack value is in {@code values[maxLocals + stackIndex]}. - */ - protected int stackIndex; - - /** * The number of local variables. */ - protected final int maxLocals; + protected final int localsSize; + + protected final int stackSize; /** * The bytecode index to which this frame state applies. This will be {@code -1} @@ -67,101 +64,64 @@ public final int bci; /** - * The list of locks held by this frame state. - * This does not include locks held by parent frames. - */ - protected ArrayList locks; - - /** - * The number of minimum stack slots required for doing IR wrangling during - * {@linkplain GraphBuilder bytecode parsing}. While this may hide stack - * overflow issues in the original bytecode, the assumption is that such - * issues must be caught by the verifier. - */ - private static final int MINIMUM_STACK_SLOTS = 1; - - /** * Creates a {@code FrameState} for the given scope and maximum number of stack and local variables. * - * @param irScope the inlining context of the method * @param bci the bytecode index of the frame state - * @param maxLocals maximum number of locals - * @param maxStack maximum size of the stack + * @param localsSize number of locals + * @param stackSize size of the stack + * @param lockSize number of locks */ - public FrameState(int bci, int maxLocals, int maxStack) { + public FrameState(int bci, int localsSize, int stackSize, int lockSize) { this.bci = bci; - this.values = new Value[maxLocals + Math.max(maxStack, MINIMUM_STACK_SLOTS)]; - this.maxLocals = maxLocals; + this.values = new Value[localsSize + stackSize + lockSize]; + this.localsSize = localsSize; + this.stackSize = stackSize; C1XMetrics.FrameStatesCreated++; C1XMetrics.FrameStateValuesCreated += this.values.length; } - /** - * Copies the contents of this frame state so that further updates to either stack aren't reflected in the other. - * @param bci the bytecode index of the copy - * @param withLocals indicates whether to copy the local state - * @param withStack indicates whether to copy the stack state - * @param withLocks indicates whether to copy the lock state - * - * @return a new frame state with the specified components - */ - public MutableFrameState copy(int bci, boolean withLocals, boolean withStack, boolean withLocks) { - final MutableFrameState other = new MutableFrameState(bci, localsSize(), maxStackSize()); - if (withLocals && withStack) { - // fast path: use array copy - System.arraycopy(values, 0, other.values, 0, valuesSize()); - other.stackIndex = stackIndex; - } else { - if (withLocals) { - other.replaceLocals(this); - } - if (withStack) { - other.replaceStack(this); - } + FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList locks) { + this(bci, locals.length, stackSize, locks.size()); + System.arraycopy(locals, 0, values, 0, locals.length); + System.arraycopy(stack, 0, values, locals.length, stackSize); + for (int i = 0; i < locks.size(); i++) { + values[locals.length + stackSize + i] = locks.get(i); } - if (withLocks) { - other.replaceLocks(this); - } - return other; } /** - * Gets a mutable copy ({@link MutableFrameState}) of this frame state. + * Gets a immutable copy ({@link FrameState}) of this frame state. */ - public MutableFrameState copy() { - return copy(bci, true, true, true); + public FrameState copy() { + FrameState other = new FrameState(bci, localsSize, stackSize, locksSize()); + System.arraycopy(values, 0, other.values, 0, values.length); + return other; } /** * Gets an immutable copy of this frame state but without the stack. */ - public FrameState immutableCopyWithEmptyStack() { - return copy(bci, true, false, true); - } - - /** - * Gets an immutable copy of this frame state but without the frame info. - */ - public FrameState immutableCopyCodePosOnly() { - return copy(bci, false, false, false); + public FrameState copyWithEmptyStack() { + FrameState other = new FrameState(bci, localsSize, 0, locksSize()); + System.arraycopy(values, 0, other.values, 0, localsSize); + System.arraycopy(values, localsSize + stackSize, other.values, localsSize, locksSize()); + return other; } public boolean isCompatibleWith(FrameState other) { if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) { return false; } - for (int i = 0; i < stackIndex; i++) { + for (int i = 0; i < stackSize(); i++) { Value x = stackAt(i); Value y = other.stackAt(i); if (x != y && typeMismatch(x, y)) { return false; } } - if (locks != null) { - for (int i = 0; i < locks.size(); i++) { - if (lockAt(i) != other.lockAt(i)) { - return false; - } + for (int i = 0; i < locksSize(); i++) { + if (lockAt(i) != other.lockAt(i)) { + return false; } } return true; @@ -173,37 +133,21 @@ * @return the size of the local variables */ public int localsSize() { - return maxLocals; - } - - /** - * Gets number of locks held by this frame state. - */ - public int locksSize() { - return locks == null ? 0 : locks.size(); + return localsSize; } /** * Gets the current size (height) of the stack. */ public int stackSize() { - return stackIndex; + return stackSize; } /** - * Gets the maximum size (height) of the stack. -] */ - public int maxStackSize() { - return values.length - maxLocals; - } - - /** - * Checks whether the stack is empty. - * - * @return {@code true} the stack is currently empty + * Gets number of locks held by this frame state. */ - public boolean stackEmpty() { - return stackIndex == 0; + public int locksSize() { + return values.length - localsSize - stackSize; } /** @@ -220,24 +164,6 @@ } /** - * 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) { - assert i < maxLocals : "local variable index out of range: " + i; - Value x = values[i]; - if (x != null) { - if (x.isIllegal()) { - return null; - } - assert x.kind.isSingleWord() || values[i + 1] == null || values[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. * @@ -245,7 +171,7 @@ * @param x the instruction which produces the value for the local */ public void storeLocal(int i, Value x) { - assert i < maxLocals : "local variable index out of range: " + i; + assert i < localsSize : "local variable index out of range: " + i; invalidateLocal(i); values[i] = x; if (isDoubleWord(x)) { @@ -262,25 +188,25 @@ } /** + * 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) { + assert i < localsSize : "local variable index out of range: " + i; + return values[i]; + } + + /** * 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) { - assert i < stackIndex; - return values[i + maxLocals]; - } - - /** - * 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) { - assert i < maxLocals : "local variable index out of range: " + i; - return values[i]; + assert i >= 0 && i < (localsSize + stackSize); + return values[localsSize + i]; } /** @@ -289,7 +215,8 @@ * @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); + assert i >= 0; + return values[localsSize + stackSize + i]; } /** @@ -307,7 +234,7 @@ return; } } - values[maxLocals + i] = new Phi(p.kind, block, -i - 1, graph); + values[localsSize + i] = new Phi(p.kind, block, -i - 1, graph); } } @@ -339,6 +266,7 @@ * @return the value at index {@code i} which may be {@code null} */ public final Value valueAt(int i) { + assert i < (localsSize + stackSize); return values[i]; } @@ -351,7 +279,7 @@ * @return the number of local variables in this frame */ public final int valuesSize() { - return maxLocals + stackIndex; + return localsSize + stackSize; } public void checkPhis(BlockBegin block, FrameState other) { @@ -378,9 +306,9 @@ } private void checkSize(FrameState other) { - if (other.stackIndex != stackIndex) { + if (other.stackSize() != stackSize()) { throw new CiBailout("stack sizes do not match"); - } else if (other.maxLocals != maxLocals) { + } else if (other.localsSize != localsSize) { throw new CiBailout("local sizes do not match"); } } @@ -402,25 +330,18 @@ values[i] = null; continue; } - if (i < maxLocals) { + if (i < localsSize) { // this a local setupPhiForLocal(block, i, graph); } else { // this is a stack slot - setupPhiForStack(block, i - maxLocals, graph); + setupPhiForStack(block, i - localsSize, graph); } } } } } - private static boolean typeMismatch(Value x, Value y) { - return y == null || x.kind != y.kind; - } - - private static boolean isDoubleWord(Value x) { - return x != null && x.kind.isDoubleWord(); - } /** * The interface implemented by a client of {@link FrameState#forEachPhi(BlockBegin, PhiProcedure)} and @@ -431,28 +352,6 @@ } /** - * Traverses all {@linkplain Phi phis} of a given block in this frame state. - * - * @param block only phis {@linkplain Phi#block() associated} with this block are traversed - * @param proc the call back invoked for each live phi traversed - */ - public boolean forEachPhi(BlockBegin block, PhiProcedure proc) { - int max = this.valuesSize(); - for (int i = 0; i < max; i++) { - Value instr = values[i]; - if (instr instanceof Phi && !instr.isDeadPhi()) { - Phi phi = (Phi) instr; - if (block == null || phi.block() == block) { - if (!proc.doPhi(phi)) { - return false; - } - } - } - } - return true; - } - - /** * Traverses all live {@linkplain Phi phis} of a given block in this frame state. * * @param block only phis {@linkplain Phi#block() associated} with this block are traversed @@ -493,27 +392,10 @@ * @param closure the closure to apply to each value */ public void valuesDo(ValueClosure closure) { - valuesDo(this, closure); - } - - /** - * Iterates over all the values of a given frame state and its callers, including the stack, locals, and locks. - * @param closure the closure to apply to each value - */ - public static void valuesDo(FrameState state, ValueClosure closure) { - final int max = state.valuesSize(); - for (int i = 0; i < max; i++) { - if (state.values[i] != null) { - Value newValue = closure.apply(state.values[i]); - state.values[i] = newValue; - } - } - if (state.locks != null) { - for (int i = 0; i < state.locks.size(); i++) { - Value instr = state.locks.get(i); - if (instr != null) { - state.locks.set(i, closure.apply(instr)); - } + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + Value newValue = closure.apply(values[i]); + values[i] = newValue; } } } @@ -544,17 +426,17 @@ public String toString() { StringBuilder sb = new StringBuilder(); String nl = String.format("%n"); - sb.append("[bci: ").append(this.bci).append("]").append(nl); - for (int i = 0; i < this.localsSize(); ++i) { - Value value = this.localAt(i); + sb.append("[bci: ").append(bci).append("]").append(nl); + for (int i = 0; i < localsSize(); ++i) { + Value value = localAt(i); sb.append(String.format(" local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); } - for (int i = 0; i < this.stackSize(); ++i) { - Value value = this.stackAt(i); + for (int i = 0; i < stackSize(); ++i) { + Value value = stackAt(i); sb.append(String.format(" stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); } - for (int i = 0; i < this.locksSize(); ++i) { - Value value = this.lockAt(i); + for (int i = 0; i < locksSize(); ++i) { + Value value = lockAt(i); sb.append(String.format(" lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); } return sb.toString(); diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Mon May 09 10:54:09 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 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(); + } + + 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 locals() { + return new ValueArrayIterator(locals); + } + + public Iterator stack() { + return new ValueArrayIterator(locals); + } + + public List locks() { + return Collections.unmodifiableList(locks); + } + + + private static class ValueArrayIterator implements Iterator { + 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"); + } + + } + +} diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/value/MutableFrameState.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/MutableFrameState.java Mon May 09 10:43:57 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -/* - * 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(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; - } - -} diff -r a57e051b33cd -r dfb1a952a203 graal/GraalCompiler/src/com/sun/c1x/value/ValueUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/ValueUtil.java Mon May 09 10:54:09 2011 +0200 @@ -0,0 +1,83 @@ +/* + * 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 com.sun.c1x.ir.*; +import com.sun.cri.ci.*; + + +public class ValueUtil { + + public 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; + } + + public static Value assertLong(Value x) { + assert x != null && (x.kind == CiKind.Long); + return x; + } + + public static Value assertJsr(Value x) { + assert x != null && (x.kind == CiKind.Jsr); + return x; + } + + public static Value assertInt(Value x) { + assert x != null && (x.kind == CiKind.Int); + return x; + } + + public static Value assertFloat(Value x) { + assert x != null && (x.kind == CiKind.Float); + return x; + } + + public static Value assertObject(Value x) { + assert x != null && (x.kind == CiKind.Object); + return x; + } + + public static Value assertWord(Value x) { + assert x != null && (x.kind == CiKind.Word); + return x; + } + + public static Value assertDouble(Value x) { + assert x != null && (x.kind == CiKind.Double); + return x; + } + + public static void assertHigh(Value x) { + assert x == null; + } + + public static boolean typeMismatch(Value x, Value y) { + return y == null || x.kind != y.kind; + } + + public static boolean isDoubleWord(Value x) { + return x != null && x.kind.isDoubleWord(); + } + +} diff -r a57e051b33cd -r dfb1a952a203 runtests.sh --- a/runtests.sh Mon May 09 10:43:57 2011 +0200 +++ b/runtests.sh Mon May 09 10:54:09 2011 +0200 @@ -11,4 +11,4 @@ echo "GRAAL is not defined. It must point to a maxine repository directory." exit 1; fi -${JDK7}/bin/java -client -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/VM/bin" -Xbootclasspath/p:"${MAXINE}/Base/bin" test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${MAXINE}/VM/test/jtt/bytecode ${MAXINE}/VM/test/jtt/except ${MAXINE}/VM/test/jtt/hotpath ${MAXINE}/VM/test/jtt/jdk ${MAXINE}/VM/test/jtt/lang ${MAXINE}/VM/test/jtt/loop ${MAXINE}/VM/test/jtt/micro ${MAXINE}/VM/test/jtt/optimize ${MAXINE}/VM/test/jtt/reflect ${MAXINE}/VM/test/jtt/threads +${JDK7}/bin/java -client -graal -ea -esa -Xcomp -XX:+PrintCompilation -XX:CompileOnly=jtt -Xbootclasspath/p:"${MAXINE}/VM/bin" -Xbootclasspath/p:"${MAXINE}/Base/bin" $1 test.com.sun.max.vm.compiler.JavaTester -verbose=1 -gen-run-scheme=false -run-scheme-package=all ${MAXINE}/VM/test/jtt/bytecode ${MAXINE}/VM/test/jtt/except ${MAXINE}/VM/test/jtt/hotpath ${MAXINE}/VM/test/jtt/jdk ${MAXINE}/VM/test/jtt/lang ${MAXINE}/VM/test/jtt/loop ${MAXINE}/VM/test/jtt/micro ${MAXINE}/VM/test/jtt/optimize ${MAXINE}/VM/test/jtt/reflect ${MAXINE}/VM/test/jtt/threads