changeset 8591:5c58da5b8233

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 29 Mar 2013 21:39:54 +0100
parents 480c564d90ef (diff) 77970b4f131c (current diff)
children a80bf36c6a1e
files graal/com.oracle.graal.rawnativecall.test/test/com/oracle/graal/rawnativecall/test/InstalledCodeExecuteHelperTest.java graal/com.oracle.graal.rawnativecall/src/com/oracle/graal/rawnativecall/nodes/HotSpotInstalledCodeExecuteNode.java graal/com.oracle.graal.rawnativecall/src/com/oracle/graal/rawnativecall/replacements/HotSpotInstalledCodeIntrinsics.java graal/com.oracle.graal.rawnativecall/src/com/oracle/graal/rawnativecall/replacements/HotSpotInstalledCodeSubstitutions.java
diffstat 29 files changed, 533 insertions(+), 241 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Mar 29 21:39:54 2013 +0100
@@ -43,11 +43,6 @@
     InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult);
 
     /**
-     * Returns the size in bytes for locking information on the stack.
-     */
-    int getSizeOfLockData();
-
-    /**
      * Returns a disassembly of some compiled code.
      * 
      * @param compResult some compiled code
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/MonitorValue.java	Fri Mar 29 18:21:43 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2011, 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.api.code;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents lock information in the debug information.
- */
-public final class MonitorValue extends Value {
-
-    private static final long serialVersionUID = 8241681800464483691L;
-
-    private Value owner;
-    private final Value lockData;
-    private final boolean eliminated;
-
-    public MonitorValue(Value owner, Value lockData, boolean eliminated) {
-        super(Kind.Illegal);
-        this.owner = owner;
-        this.lockData = lockData;
-        this.eliminated = eliminated;
-    }
-
-    public Value getOwner() {
-        return owner;
-    }
-
-    public void setOwner(Value newOwner) {
-        this.owner = newOwner;
-    }
-
-    public Value getLockData() {
-        return lockData;
-    }
-
-    public boolean isEliminated() {
-        return eliminated;
-    }
-
-    @Override
-    public String toString() {
-        return "monitor[" + owner + (lockData != null ? ", " + lockData : "") + (eliminated ? ", eliminated" : "") + "]";
-    }
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Mar 29 21:39:54 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<Value> nodeOperands;
+    protected final NodeMap<Value> nodeOperands;
 
     public DebugInfoBuilder(NodeMap<Value> nodeOperands) {
         this.nodeOperands = nodeOperands;
     }
 
-    private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
-    private IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
+    protected HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
+    protected IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
 
-    public LIRFrameState build(FrameState topState, List<StackSlot> 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) {
@@ -103,43 +106,62 @@
         }
         objectStates.clear();
 
+        return newLIRFrameState(reason, exceptionEdge, frame, virtualObjectsArray);
+    }
+
+    protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
         return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
     }
 
-    private BytecodeFrame computeFrameForState(FrameState state, List<StackSlot> 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<StackSlot> 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);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Mar 29 21:39:54 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<FrameState> 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<Integer> blockLastLockCount;
-
-    /**
-     * Contains the lock data slot for each lock depth (so these may be reused within a compiled
-     * method).
-     */
-    private final ArrayList<StackSlot> 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<Value> 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;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Mar 29 21:39:54 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<AMD64HotSpotEpilogueOp> epilogueOps = new ArrayList<>(2);
 
+    @SuppressWarnings("hiding")
+    @Override
+    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> 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() {
 
--- /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 21:39:54 2013 +0100
@@ -0,0 +1,67 @@
+/*
+ * 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.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+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<Value> nodeOperands, HotSpotLockStack lockStack) {
+        super(nodeOperands);
+        this.lockStack = lockStack;
+    }
+
+    public HotSpotLockStack lockStack() {
+        return lockStack;
+    }
+
+    @Override
+    protected Value computeLockValue(FrameState state, int i) {
+        int lockDepth = i;
+        if (state.outerFrameState() != null) {
+            lockDepth = state.outerFrameState().nestedLockDepth();
+        }
+        StackSlot slot = lockStack.makeLockSlot(lockDepth);
+        ValueNode lock = state.lockAt(i);
+        Value object = toValue(lock);
+        boolean eliminated = lock instanceof VirtualObjectNode;
+        return new HotSpotMonitorValue(object, slot, eliminated);
+    }
+
+    @Override
+    protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
+        return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Fri Mar 29 21:39:54 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+/**
+ * Extends {@link LIRFrameState} to handle {@link HotSpotMonitorValue}s correctly.
+ */
+class HotSpotLIRFrameState extends LIRFrameState {
+
+    public HotSpotLIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) {
+        super(topFrame, virtualObjects, exceptionEdge, deoptimizationReason);
+    }
+
+    @Override
+    protected Value processValue(ValueProcedure proc, Value value) {
+        if (value instanceof HotSpotMonitorValue) {
+            HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
+            if (processed(monitor.getOwner())) {
+                monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
+            }
+            return value;
+        } else {
+            return super.processValue(proc, value);
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Mar 29 21:39:54 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);
 }
--- /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 21:39:54 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];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java	Fri Mar 29 21:39:54 2013 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.hotspot.meta;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents lock information in the debug information.
+ */
+public final class HotSpotMonitorValue extends Value {
+
+    private static final long serialVersionUID = 8241681800464483691L;
+
+    private Value owner;
+    private final StackSlot slot;
+    private final boolean eliminated;
+
+    public HotSpotMonitorValue(Value owner, StackSlot slot, boolean eliminated) {
+        super(Kind.Illegal);
+        this.owner = owner;
+        this.slot = slot;
+        this.eliminated = eliminated;
+    }
+
+    public Value getOwner() {
+        return owner;
+    }
+
+    public void setOwner(Value newOwner) {
+        this.owner = newOwner;
+    }
+
+    public Value getSlot() {
+        return slot;
+    }
+
+    public boolean isEliminated() {
+        return eliminated;
+    }
+
+    @Override
+    public String toString() {
+        return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Mar 29 21:39:54 2013 +0100
@@ -487,11 +487,6 @@
     }
 
     @Override
-    public int getSizeOfLockData() {
-        return config.basicLockSize;
-    }
-
-    @Override
     public boolean constantEquals(Constant x, Constant y) {
         return x.equals(y);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Mar 29 21:39:54 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);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Fri Mar 29 21:39:54 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);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Fri Mar 29 21:39:54 2013 +0100
@@ -50,7 +50,6 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        gen.unlock();
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Mar 29 21:39:54 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
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Mar 29 21:39:54 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());
+                }
             }
         }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Fri Mar 29 21:39:54 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;
     }
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Mar 29 21:39:54 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));
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Fri Mar 29 21:39:54 2013 +0100
@@ -80,24 +80,23 @@
      * We filter out constant and illegal values ourself before calling the procedure, so
      * {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set.
      */
-    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
+    protected static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
-    private void processValues(Value[] values, ValueProcedure proc) {
+    protected void processValues(Value[] values, ValueProcedure proc) {
         for (int i = 0; i < values.length; i++) {
             Value value = values[i];
-            if (value instanceof MonitorValue) {
-                MonitorValue monitor = (MonitorValue) value;
-                if (processed(monitor.getOwner())) {
-                    monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
-                }
-
-            } else if (processed(value)) {
-                values[i] = proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
-            }
+            values[i] = processValue(proc, value);
         }
     }
 
-    private boolean processed(Value value) {
+    protected Value processValue(ValueProcedure proc, Value value) {
+        if (processed(value)) {
+            return proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
+        }
+        return value;
+    }
+
+    protected boolean processed(Value value) {
         if (isIllegal(value)) {
             // Ignore dead local variables.
             return false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Mar 29 21:39:54 2013 +0100
@@ -273,6 +273,18 @@
     }
 
     /**
+     * Gets the number of locked monitors in this frame state and all
+     * {@linkplain #outerFrameState() outer} frame states.
+     */
+    public int nestedLockDepth() {
+        int depth = locksSize();
+        for (FrameState outer = outerFrameState(); outer != null; outer = outer.outerFrameState()) {
+            depth += outer.locksSize();
+        }
+        return depth;
+    }
+
+    /**
      * Gets the value in the local variables at the specified index.
      * 
      * @param i the index into the locals
--- /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 21:39:54 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();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Fri Mar 29 21:39:54 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;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Fri Mar 29 21:39:54 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;
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Mar 29 18:21:43 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Mar 29 21:39:54 2013 +0100
@@ -1095,6 +1095,7 @@
 
         FrameState outerFrameState = null;
         double invokeProbability = invoke.node().probability();
+        int callerLockDepth = stateAfter.nestedLockDepth();
         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;
--- a/mxtool/mx.py	Fri Mar 29 18:21:43 2013 +0100
+++ b/mxtool/mx.py	Fri Mar 29 21:39:54 2013 +0100
@@ -1659,46 +1659,56 @@
             d = distribution(dname)
             fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path))
             services = tempfile.mkdtemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path))
-            zf = zipfile.ZipFile(tmp, 'w')
-            for p in sorted_deps(d.deps):
-                outputDir = p.output_dir()
-                for root, _, files in os.walk(outputDir):
-                    relpath = root[len(outputDir) + 1:]
-                    if relpath == join('META-INF', 'services'):
-                        for f in files:
-                            with open(join(services, f), 'a') as outfile:
-                                with open(join(root, f), 'r') as infile:
-                                    for line in infile:
-                                        outfile.write(line)
-                    else:
-                        for f in files:
-                            arcname = join(relpath, f).replace(os.sep, '/')
-                            zf.write(join(root, f), arcname)
-            for f in os.listdir(services):
-                arcname = join('META-INF', 'services', f).replace(os.sep, '/')
-                zf.write(join(services, f), arcname)
-            zf.close()
-            os.close(fd)
-            shutil.rmtree(services)
-            # Atomic on Unix
-            shutil.move(tmp, d.path)
-            #print time.time(), 'move:', tmp, '->', d.path
-            d.notify_updated()
+            try:
+                zf = zipfile.ZipFile(tmp, 'w')
+                for p in sorted_deps(d.deps):
+                    outputDir = p.output_dir()
+                    for root, _, files in os.walk(outputDir):
+                        relpath = root[len(outputDir) + 1:]
+                        if relpath == join('META-INF', 'services'):
+                            for f in files:
+                                with open(join(services, f), 'a') as outfile:
+                                    with open(join(root, f), 'r') as infile:
+                                        for line in infile:
+                                            outfile.write(line)
+                        else:
+                            for f in files:
+                                arcname = join(relpath, f).replace(os.sep, '/')
+                                zf.write(join(root, f), arcname)
+                for f in os.listdir(services):
+                    arcname = join('META-INF', 'services', f).replace(os.sep, '/')
+                    zf.write(join(services, f), arcname)
+                zf.close()
+                os.close(fd)
+                shutil.rmtree(services)
+                # Atomic on Unix
+                shutil.move(tmp, d.path)
+                #print time.time(), 'move:', tmp, '->', d.path
+                d.notify_updated()
+            finally:
+                if exists(tmp):
+                    os.remove(tmp)
+                if exists(services):
+                    shutil.rmtree(services)
 
         else:
             p = project(name)
             outputDir = p.output_dir()
             fd, tmp = tempfile.mkstemp(suffix='', prefix=p.name, dir=p.dir)
-            zf = zipfile.ZipFile(tmp, 'w')
-            for root, _, files in os.walk(outputDir):
-                for f in files:
-                    relpath = root[len(outputDir) + 1:]
-                    arcname = join(relpath, f).replace(os.sep, '/')
-                    zf.write(join(root, f), arcname)
-            zf.close()
-            os.close(fd)
-            # Atomic on Unix
-            shutil.move(tmp, join(p.dir, p.name + '.jar'))
+            try:
+                zf = zipfile.ZipFile(tmp, 'w')
+                for root, _, files in os.walk(outputDir):
+                    for f in files:
+                        relpath = root[len(outputDir) + 1:]
+                        arcname = join(relpath, f).replace(os.sep, '/')
+                        zf.write(join(root, f), arcname)
+                zf.close()
+                os.close(fd)
+                # Atomic on Unix
+                shutil.move(tmp, join(p.dir, p.name + '.jar'))
+            finally:
+                if exists(tmp):
+                    os.remove(tmp)
 
 def canonicalizeprojects(args):
     """process all project files to canonicalize the dependencies
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Mar 29 18:21:43 2013 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Mar 29 21:39:54 2013 +0100
@@ -192,6 +192,7 @@
   do_klass(HotSpotResolvedJavaField_klass,        com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField,       Opt) \
   do_klass(HotSpotResolvedJavaMethod_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,      Opt) \
   do_klass(HotSpotResolvedObjectType_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,      Opt) \
+  do_klass(HotSpotMonitorValue_klass,             com_oracle_graal_hotspot_meta_HotSpotMonitorValue,            Opt) \
   do_klass(LocalImpl_klass,                       com_oracle_graal_hotspot_debug_LocalImpl,                     Opt) \
   /* graal.api.code */                                                                                               \
   do_klass(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
@@ -208,7 +209,6 @@
   do_klass(CompilationResult_Mark_klass,          com_oracle_graal_api_code_CompilationResult_Mark,             Opt) \
   do_klass(CompilationResult_Safepoint_klass,     com_oracle_graal_api_code_CompilationResult_Safepoint,        Opt) \
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
-  do_klass(code_MonitorValue_klass,               com_oracle_graal_api_code_MonitorValue,                       Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Mar 29 18:21:43 2013 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Mar 29 21:39:54 2013 +0100
@@ -303,6 +303,7 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField,   "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField")        \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,  "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")       \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType,  "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")       \
+  template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")             \
   template(com_oracle_graal_hotspot_debug_LocalImpl,                 "com/oracle/graal/hotspot/debug/LocalImpl")                      \
   AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\
   /* graal.api.meta */                                                                                                                \
@@ -329,7 +330,6 @@
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
-  template(com_oracle_graal_api_code_MonitorValue,                   "com/oracle/graal/api/code/MonitorValue")                        \
   template(com_oracle_graal_api_code_Register,                       "com/oracle/graal/api/code/Register")                            \
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Mar 29 18:21:43 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Mar 29 21:39:54 2013 +0100
@@ -263,19 +263,19 @@
 }
 
 static MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, OopRecorder* oop_recorder) {
-  guarantee(value->is_a(code_MonitorValue::klass()), "Monitors must be of type MonitorValue");
+  guarantee(value->is_a(HotSpotMonitorValue::klass()), "Monitors must be of type MonitorValue");
 
   ScopeValue* second = NULL;
-  ScopeValue* owner_value = get_hotspot_value(code_MonitorValue::owner(value), total_frame_size, objects, second, oop_recorder);
+  ScopeValue* owner_value = get_hotspot_value(HotSpotMonitorValue::owner(value), total_frame_size, objects, second, oop_recorder);
   assert(second == NULL, "monitor cannot occupy two stack slots");
 
-  ScopeValue* lock_data_value = get_hotspot_value(code_MonitorValue::lockData(value), total_frame_size, objects, second, oop_recorder);
+  ScopeValue* lock_data_value = get_hotspot_value(HotSpotMonitorValue::slot(value), total_frame_size, objects, second, oop_recorder);
   assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
   assert(lock_data_value->is_location(), "invalid monitor location");
   Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
 
   bool eliminated = false;
-  if (code_MonitorValue::eliminated(value)) {
+  if (HotSpotMonitorValue::eliminated(value)) {
     eliminated = true;
   }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Mar 29 18:21:43 2013 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Mar 29 21:39:54 2013 +0100
@@ -197,10 +197,10 @@
     oop_field(VirtualObject, type, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                                             \
     oop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/Value;")                                                                                     \
   end_class                                                                                                                                                    \
-  start_class(code_MonitorValue)                                                                                                                               \
-    oop_field(code_MonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;")                                                                                   \
-    oop_field(code_MonitorValue, lockData, "Lcom/oracle/graal/api/meta/Value;")                                                                                \
-    boolean_field(code_MonitorValue, eliminated)                                                                                                               \
+  start_class(HotSpotMonitorValue)                                                                                                                               \
+    oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;")                                                                                   \
+    oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;")                                                                                \
+    boolean_field(HotSpotMonitorValue, eliminated)                                                                                                               \
   end_class                                                                                                                                                    \
   /* end*/