# HG changeset patch # User Doug Simon # Date 1364556702 -3600 # Node ID 82f6a25321b8f79444eb68760da7d80b3eb1dc3f # Parent aaf3988bd1b47ed67d44877985666b9fa053e944 modeling of lock state removed from LIR and runtime specific debug info for locks moved into runtime specific classes diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Mar 29 12:31:42 2013 +0100 @@ -34,18 +34,21 @@ import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.virtual.nodes.*; +/** + * Builds {@link LIRFrameState}s from {@link FrameState}s. + */ public class DebugInfoBuilder { - private final NodeMap nodeOperands; + protected final NodeMap nodeOperands; public DebugInfoBuilder(NodeMap nodeOperands) { this.nodeOperands = nodeOperands; } - private HashMap virtualObjects = new HashMap<>(); - private IdentityHashMap objectStates = new IdentityHashMap<>(); + protected HashMap virtualObjects = new HashMap<>(); + protected IdentityHashMap objectStates = new IdentityHashMap<>(); - public LIRFrameState build(FrameState topState, List lockData, short reason, LabelRef exceptionEdge) { + public LIRFrameState build(FrameState topState, short reason, LabelRef exceptionEdge) { assert virtualObjects.size() == 0; assert objectStates.size() == 0; @@ -65,7 +68,7 @@ current = current.outerFrameState(); } while (current != null); - BytecodeFrame frame = computeFrameForState(topState, lockData); + BytecodeFrame frame = computeFrameForState(topState); VirtualObject[] virtualObjectsArray = null; if (virtualObjects.size() != 0) { @@ -106,40 +109,55 @@ return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason); } - private BytecodeFrame computeFrameForState(FrameState state, List lockDataSlots) { + protected BytecodeFrame computeFrameForState(FrameState state) { int numLocals = state.localsSize(); int numStack = state.stackSize(); int numLocks = state.locksSize(); Value[] values = new Value[numLocals + numStack + numLocks]; - for (int i = 0; i < numLocals; i++) { - values[i] = toValue(state.localAt(i)); - } - for (int i = 0; i < numStack; i++) { - values[numLocals + i] = toValue(state.stackAt(i)); - } - for (int i = 0; i < numLocks; i++) { - // frames are traversed from the outside in, so the locks for the current frame are at - // the end of the lockDataSlots list - StackSlot lockData = lockDataSlots.get(lockDataSlots.size() - numLocks + i); - values[numLocals + numStack + i] = new MonitorValue(toValue(state.lockAt(i)), lockData, state.lockAt(i) instanceof VirtualObjectNode); - } + computeLocals(state, numLocals, values); + computeStack(state, numLocals, numStack, values); + computeLocks(state, values); BytecodeFrame caller = null; if (state.outerFrameState() != null) { - // remove the locks that were used for this frame from the lockDataSlots list - List nextLockDataSlots = lockDataSlots.subList(0, lockDataSlots.size() - numLocks); - caller = computeFrameForState(state.outerFrameState(), nextLockDataSlots); - } else { - if (lockDataSlots.size() != numLocks) { - throw new BailoutException("unbalanced monitors: found monitor for unknown frame (%d != %d) at %s", lockDataSlots.size(), numLocks, state); - } + caller = computeFrameForState(state.outerFrameState()); } assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci; return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } - private Value toValue(ValueNode value) { + protected void computeLocals(FrameState state, int numLocals, Value[] values) { + for (int i = 0; i < numLocals; i++) { + values[i] = computeLocalValue(state, i); + } + } + + protected Value computeLocalValue(FrameState state, int i) { + return toValue(state.localAt(i)); + } + + protected void computeStack(FrameState state, int numLocals, int numStack, Value[] values) { + for (int i = 0; i < numStack; i++) { + values[numLocals + i] = computeStackValue(state, i); + } + } + + protected Value computeStackValue(FrameState state, int i) { + return toValue(state.stackAt(i)); + } + + protected void computeLocks(FrameState state, Value[] values) { + for (int i = 0; i < state.locksSize(); i++) { + values[state.localsSize() + state.stackSize() + i] = computeLockValue(state, i); + } + } + + protected Value computeLockValue(FrameState state, int i) { + return toValue(state.lockAt(i)); + } + + protected Value toValue(ValueNode value) { if (value instanceof VirtualObjectNode) { VirtualObjectNode obj = (VirtualObjectNode) value; EscapeObjectState state = objectStates.get(obj); diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Mar 29 12:31:42 2013 +0100 @@ -63,7 +63,7 @@ protected final TargetDescription target; protected final ResolvedJavaMethod method; - private final DebugInfoBuilder debugInfoBuilder; + protected final DebugInfoBuilder debugInfoBuilder; protected Block currentBlock; private ValueNode currentInstruction; @@ -76,22 +76,6 @@ private final BlockMap blockLastState; /** - * The number of currently locked monitors. - */ - private int currentLockCount; - - /** - * Mapping from blocks to the number of locked monitors at the end of the block. - */ - private final BlockMap blockLastLockCount; - - /** - * Contains the lock data slot for each lock depth (so these may be reused within a compiled - * method). - */ - private final ArrayList lockDataSlots; - - /** * Checks whether the supplied constant can be used without loading it into a register for store * operations, i.e., on the right hand side of a memory access. * @@ -109,12 +93,15 @@ this.method = method; this.nodeOperands = graph.createNodeMap(); this.lir = lir; - this.debugInfoBuilder = new DebugInfoBuilder(nodeOperands); - this.blockLastLockCount = new BlockMap<>(lir.cfg); - this.lockDataSlots = new ArrayList<>(); + this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); this.blockLastState = new BlockMap<>(lir.cfg); } + @SuppressWarnings("hiding") + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap nodeOperands) { + return new DebugInfoBuilder(nodeOperands); + } + @Override public TargetDescription target() { return target; @@ -248,7 +235,7 @@ if (needOnlyOopMaps()) { return new LIRFrameState(null, null, null, (short) -1); } - return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge); + return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge); } /** @@ -297,22 +284,10 @@ if (block == lir.cfg.getStartBlock()) { assert block.getPredecessorCount() == 0; - currentLockCount = 0; emitPrologue(); } else { assert block.getPredecessorCount() > 0; - - currentLockCount = -1; - for (Block pred : block.getPredecessors()) { - Integer predLocks = blockLastLockCount.get(pred); - if (currentLockCount == -1) { - currentLockCount = predLocks; - } else { - assert (predLocks == null && pred.isLoopEnd()) || currentLockCount == predLocks; - } - } - FrameState fs = null; for (Block pred : block.getPredecessors()) { @@ -401,7 +376,6 @@ // share the frame state that flowed into the loop assert blockLastState.get(block) == null || blockLastState.get(block) == lastState; - blockLastLockCount.put(currentBlock, currentLockCount); blockLastState.put(block, lastState); currentBlock = null; @@ -480,36 +454,6 @@ append(new ParametersOp(params)); } - /** - * Increases the number of currently locked monitors and makes sure that a lock data slot is - * available for the new lock. - */ - public void lock() { - if (lockDataSlots.size() == currentLockCount) { - lockDataSlots.add(frameMap.allocateStackBlock(runtime.getSizeOfLockData(), false)); - } - currentLockCount++; - } - - /** - * Decreases the number of currently locked monitors. - * - * @throws GraalInternalError if the number of currently locked monitors is already zero. - */ - public void unlock() { - if (currentLockCount == 0) { - throw new GraalInternalError("unmatched locks"); - } - currentLockCount--; - } - - /** - * @return The lock data slot for the topmost locked monitor. - */ - public StackSlot peekLock() { - return lockDataSlots.get(currentLockCount - 1); - } - @Override public void visitReturn(ReturnNode x) { Value operand = Value.ILLEGAL; diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Mar 29 12:31:42 2013 +0100 @@ -35,6 +35,8 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Address.*; import com.oracle.graal.compiler.amd64.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -84,6 +86,19 @@ */ List epilogueOps = new ArrayList<>(2); + @SuppressWarnings("hiding") + @Override + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap nodeOperands) { + assert runtime().config.basicLockSize == 8; + HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long); + return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); + } + + @Override + public StackSlot getLockSlot(int lockDepth) { + return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth); + } + @Override protected void emitPrologue() { diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Fri Mar 29 12:31:42 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.oracle.graal.hotspot; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; + +/** + * Extends {@link DebugInfoBuilder} to allocate the extra debug information required for locks. + */ +public class HotSpotDebugInfoBuilder extends DebugInfoBuilder { + + private final HotSpotLockStack lockStack; + + public HotSpotDebugInfoBuilder(NodeMap nodeOperands, HotSpotLockStack lockStack) { + super(nodeOperands); + this.lockStack = lockStack; + } + + public HotSpotLockStack lockStack() { + return lockStack; + } + + @Override + protected Value computeLockValue(FrameState state, int i) { + int lockDepth = i; + for (FrameState outer = state.outerFrameState(); outer != null; outer = outer.outerFrameState()) { + lockDepth += outer.locksSize(); + } + StackSlot slot = lockStack.makeLockSlot(lockDepth); + ValueNode lock = state.lockAt(i); + Value object = toValue(lock); + boolean eliminated = lock instanceof VirtualObjectNode; + return new MonitorValue(object, slot, eliminated); + } +} diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Fri Mar 29 12:31:42 2013 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.nodes.*; @@ -42,4 +43,9 @@ void emitTailcall(Value[] args, Value address); void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); + + /** + * Gets a stack slot for a lock at a given lock nesting depth. + */ + StackSlot getLockSlot(int lockDepth); } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java Fri Mar 29 12:31:42 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.oracle.graal.hotspot; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; + +/** + * Manages allocation and re-use of lock slots in a scoped manner. The slots are used in HotSpot's + * lightweight locking mechanism to store the mark word of an object being locked. + */ +public class HotSpotLockStack { + + private StackSlot[] locks; + private final FrameMap frameMap; + private final Kind slotKind; + + public HotSpotLockStack(FrameMap frameMap, Kind slotKind) { + this.frameMap = frameMap; + this.slotKind = slotKind; + } + + /** + * Gets a stack slot for a lock at a given lock nesting depth, allocating it first if necessary. + */ + public StackSlot makeLockSlot(int lockDepth) { + if (locks == null) { + locks = new StackSlot[lockDepth + 1]; + } else if (locks.length < lockDepth + 1) { + locks = Arrays.copyOf(locks, lockDepth + 1); + } + if (locks[lockDepth] == null) { + locks[lockDepth] = frameMap.allocateSpillSlot(slotKind); + } + return locks[lockDepth]; + } +} diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Mar 29 12:31:42 2013 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; @@ -37,15 +38,25 @@ * is locked (ensuring the GC sees and updates the object) so it must come after any null pointer * check on the object. */ -public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter { +public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter, MonitorReference { private final boolean eliminated; + private int lockDepth = -1; + public BeginLockScopeNode(boolean eliminated) { super(StampFactory.forWord()); this.eliminated = eliminated; } + public int getLockDepth() { + return lockDepth; + } + + public void setLockDepth(int lockDepth) { + this.lockDepth = lockDepth; + } + @Override public boolean hasSideEffect() { return false; @@ -58,11 +69,12 @@ @Override public void generate(LIRGenerator gen) { - gen.lock(); - StackSlot lockData = gen.peekLock(); + assert lockDepth != -1; assert stateAfter() != null; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + StackSlot slot = hsGen.getLockSlot(lockDepth); if (!eliminated) { - Value result = gen.emitLea(lockData); + Value result = gen.emitLea(slot); gen.setResult(this, result); } } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Fri Mar 29 12:31:42 2013 +0100 @@ -22,26 +22,42 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}. */ -public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable { +public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable, MonitorReference { + + private int lockDepth = -1; public CurrentLockNode() { super(StampFactory.forWord()); } + public int getLockDepth() { + return lockDepth; + } + + public void setLockDepth(int lockDepth) { + this.lockDepth = lockDepth; + } + @Override public void generate(LIRGenerator gen) { + assert lockDepth != -1; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + StackSlot slot = hsGen.getLockSlot(lockDepth); // The register allocator cannot handle stack -> register moves so we use an LEA here - Value result = gen.emitMove(gen.emitLea(gen.peekLock())); + Value result = gen.emitMove(gen.emitLea(slot)); gen.setResult(this, result); } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Fri Mar 29 12:31:42 2013 +0100 @@ -50,7 +50,6 @@ @Override public void generate(LIRGenerator gen) { - gen.unlock(); } @NodeIntrinsic diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Fri Mar 29 12:31:42 2013 +0100 @@ -26,16 +26,19 @@ import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code graal_monitorexit} stub. */ -public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable { +public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable, MonitorReference { @Input private final ValueNode object; + private int lockDepth; public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, void.class, Object.class, Word.class); public MonitorExitStubCall(ValueNode object) { @@ -43,10 +46,21 @@ this.object = object; } + public int getLockDepth() { + return lockDepth; + } + + public void setLockDepth(int lockDepth) { + this.lockDepth = lockDepth; + } + @Override public void generate(LIRGenerator gen) { + assert lockDepth != -1; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + StackSlot slot = hsGen.getLockSlot(lockDepth); RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT); - gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(gen.peekLock())); + gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(slot)); } @NodeIntrinsic diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Mar 29 12:31:42 2013 +0100 @@ -451,6 +451,9 @@ BeginLockScopeNode begin = (BeginLockScopeNode) n; begin.setStateAfter(stateAfter); } + if (n instanceof MonitorReference) { + ((MonitorReference) n).setLockDepth(monitorenterNode.getLockDepth()); + } } } @@ -474,6 +477,9 @@ EndLockScopeNode end = (EndLockScopeNode) n; end.setStateAfter(stateAfter); } + if (n instanceof MonitorReference) { + ((MonitorReference) n).setLockDepth(monitorexitNode.getLockDepth()); + } } } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Fri Mar 29 12:31:42 2013 +0100 @@ -376,10 +376,10 @@ } /** - * @return true if there are no locks within this frame state. + * @return the current lock depth */ - public boolean locksEmpty() { - return locks.length == 0; + public int lockDepth() { + return locks.length; } /** diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Mar 29 12:31:42 2013 +0100 @@ -1153,18 +1153,18 @@ } private MonitorEnterNode genMonitorEnter(ValueNode x) { + MonitorEnterNode monitorEnter = currentGraph.add(new MonitorEnterNode(x, frameState.lockDepth())); frameState.pushLock(x); - MonitorEnterNode monitorEnter = currentGraph.add(new MonitorEnterNode(x)); appendWithBCI(monitorEnter); return monitorEnter; } private MonitorExitNode genMonitorExit(ValueNode x) { ValueNode lockedObject = frameState.popLock(); + MonitorExitNode monitorExit = currentGraph.add(new MonitorExitNode(x, frameState.lockDepth())); if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); } - MonitorExitNode monitorExit = currentGraph.add(new MonitorExitNode(x)); appendWithBCI(monitorExit); return monitorExit; } @@ -1568,7 +1568,7 @@ } synchronizedEpilogue(FrameState.AFTER_BCI); - if (!frameState.locksEmpty()) { + if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } ReturnNode returnNode = currentGraph.add(new ReturnNode(x)); diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MonitorReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MonitorReference.java Fri Mar 29 12:31:42 2013 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2012, 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.oracle.graal.nodes.extended; + +/** + * Denotes an instruction that references a monitor and wants to know its lock nesting depth. + */ +public interface MonitorReference { + + /** + * Sets the depth of the lock referenced by this operation. + */ + void setLockDepth(int lockDepth); + + /** + * Gets the depth of the lock referenced by this operation. + */ + int getLockDepth(); +} diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Fri Mar 29 12:31:42 2013 +0100 @@ -29,15 +29,18 @@ /** * The {@code MonitorEnterNode} represents the acquisition of a monitor. */ -public final class MonitorEnterNode extends AccessMonitorNode implements Lowerable, MonitorEnter { +public final class MonitorEnterNode extends AccessMonitorNode implements Lowerable, MonitorEnter, MonitorReference { + + private int lockDepth; /** * Creates a new MonitorEnterNode. * * @param object the instruction producing the object */ - public MonitorEnterNode(ValueNode object) { + public MonitorEnterNode(ValueNode object, int lockDepth) { super(object); + this.lockDepth = lockDepth; } @Override @@ -48,4 +51,12 @@ public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } + + public int getLockDepth() { + return lockDepth; + } + + public void setLockDepth(int lockDepth) { + this.lockDepth = lockDepth; + } } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri Mar 29 12:31:42 2013 +0100 @@ -30,15 +30,18 @@ /** * The {@code MonitorEnterNode} represents a monitor release. */ -public final class MonitorExitNode extends AccessMonitorNode implements Lowerable, Node.IterableNodeType, MonitorExit { +public final class MonitorExitNode extends AccessMonitorNode implements Lowerable, Node.IterableNodeType, MonitorExit, MonitorReference { + + private int lockDepth; /** * Creates a new MonitorExitNode. * * @param object the instruction produces the object value */ - public MonitorExitNode(ValueNode object) { + public MonitorExitNode(ValueNode object, int lockDepth) { super(object); + this.lockDepth = lockDepth; } @Override @@ -49,4 +52,12 @@ public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } + + public int getLockDepth() { + return lockDepth; + } + + public void setLockDepth(int lockDepth) { + this.lockDepth = lockDepth; + } } diff -r aaf3988bd1b4 -r 82f6a25321b8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Mar 29 12:22:27 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Mar 29 12:31:42 2013 +0100 @@ -1095,6 +1095,7 @@ FrameState outerFrameState = null; double invokeProbability = invoke.node().probability(); + int callerLockDepth = stateAfter.locksSize(); for (Node node : duplicates.values()) { if (GraalOptions.ProbabilityAnalysis) { if (node instanceof FixedNode) { @@ -1138,6 +1139,10 @@ } } } + if (callerLockDepth != 0 && node instanceof MonitorReference) { + MonitorReference monitor = (MonitorReference) node; + monitor.setLockDepth(monitor.getLockDepth() + callerLockDepth); + } } Node returnValue = null;