changeset 12444:b6e3b44ab44f

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 15 Oct 2013 13:51:27 +0200
parents 7421885a2b9d (current diff) 8c53ba3efbc9 (diff)
children 66efe95dd46b
files
diffstat 7 files changed, 128 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Tue Oct 15 01:25:31 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java	Tue Oct 15 13:51:27 2013 +0200
@@ -40,12 +40,12 @@
 public class UnsafeLoadSnippets implements Snippets {
 
     @Snippet
-    public static Object lowerUnsafeLoad(Object object, long displacement) {
+    public static Object lowerUnsafeLoad(Object object, long offset) {
         Object fixedObject = FixedValueAnchorNode.getObject(object);
-        if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) {
-            return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.PRECISE, true);
+        if (object instanceof java.lang.ref.Reference && referentOffset() == offset) {
+            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE, true);
         } else {
-            return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.NONE, true);
+            return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE, true);
         }
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Oct 15 01:25:31 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Oct 15 13:51:27 2013 +0200
@@ -1218,12 +1218,12 @@
         return monitorEnter;
     }
 
-    private MonitorExitNode genMonitorExit(ValueNode x) {
+    private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) {
         ValueNode lockedObject = frameState.popLock();
         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 = append(new MonitorExitNode(x, frameState.lockDepth()));
+        MonitorExitNode monitorExit = append(new MonitorExitNode(x, returnValue, frameState.lockDepth()));
         return monitorExit;
     }
 
@@ -1619,7 +1619,7 @@
         assert frameState.stackSize() == 1 : frameState;
         ValueNode exception = frameState.apop();
         append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true));
-        synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI);
+        synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null);
         append(new UnwindNode(exception));
     }
 
@@ -1628,7 +1628,7 @@
         ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
         assert frameState.stackSize() == 0;
 
-        synchronizedEpilogue(FrameState.AFTER_BCI);
+        synchronizedEpilogue(FrameState.AFTER_BCI, x);
         if (frameState.lockDepth() != 0) {
             throw new BailoutException("unbalanced monitors");
         }
@@ -1640,9 +1640,9 @@
         append(new ReturnNode(x));
     }
 
-    private void synchronizedEpilogue(int bci) {
+    private void synchronizedEpilogue(int bci, ValueNode returnValue) {
         if (Modifier.isSynchronized(method.getModifiers())) {
-            MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject);
+            MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue);
             monitorExit.setStateAfter(frameState.create(bci));
             assert !frameState.rethrowException();
         }
@@ -2002,7 +2002,7 @@
             case CHECKCAST      : genCheckCast(); break;
             case INSTANCEOF     : genInstanceOf(); break;
             case MONITORENTER   : genMonitorEnter(frameState.apop()); break;
-            case MONITOREXIT    : genMonitorExit(frameState.apop()); break;
+            case MONITOREXIT    : genMonitorExit(frameState.apop(), null); break;
             case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
             case IFNULL         : genIfNull(Condition.EQ); break;
             case IFNONNULL      : genIfNull(Condition.NE); break;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Oct 15 01:25:31 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Tue Oct 15 13:51:27 2013 +0200
@@ -199,7 +199,7 @@
             case Long:
                 return ConstantNode.forLong(value, graph);
             default:
-                throw new InternalError("Should not reach here");
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
         }
     }
 
@@ -210,7 +210,7 @@
             case Double:
                 return ConstantNode.forDouble(value, graph);
             default:
-                throw new InternalError("Should not reach here");
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Oct 15 01:25:31 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Tue Oct 15 13:51:27 2013 +0200
@@ -34,17 +34,24 @@
 public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference {
 
     private int lockDepth;
+    @Input private ValueNode escapedReturnValue;
 
     /**
      * Creates a new MonitorExitNode.
      * 
      * @param object the instruction produces the object value
      */
-    public MonitorExitNode(ValueNode object, int lockDepth) {
+    public MonitorExitNode(ValueNode object, ValueNode escapedReturnValue, int lockDepth) {
         super(object);
+        this.escapedReturnValue = escapedReturnValue;
         this.lockDepth = lockDepth;
     }
 
+    public void setEscapedReturnValue(ValueNode x) {
+        updateUsages(escapedReturnValue, x);
+        this.escapedReturnValue = x;
+    }
+
     @Override
     public LocationIdentity getLocationIdentity() {
         return LocationIdentity.ANY_LOCATION;
@@ -65,11 +72,20 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(object());
-        if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) {
-            int removedLock = state.removeLock();
-            assert removedLock == getLockDepth();
-            tool.delete();
+        /*
+         * The last MonitorExitNode of a synchronized method cannot be removed anyway, and we need
+         * it to materialize the return value.
+         * 
+         * TODO: replace this with correct handling of AFTER_BCI frame states in the runtime.
+         */
+        if (stateAfter().bci != FrameState.AFTER_BCI) {
+            setEscapedReturnValue(null);
+            State state = tool.getObjectState(object());
+            if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) {
+                int removedLock = state.removeLock();
+                assert removedLock == getLockDepth();
+                tool.delete();
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Oct 15 01:25:31 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Oct 15 13:51:27 2013 +0200
@@ -111,85 +111,6 @@
             return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode);
         }
         if (isMarked) {
-            if (node instanceof NodeWithState) {
-                NodeWithState nodeWithState = (NodeWithState) node;
-                FrameState stateAfter = nodeWithState.getState();
-                if (stateAfter != null) {
-                    if (stateAfter.usages().count() > 1) {
-                        if (nodeWithState instanceof StateSplit) {
-                            StateSplit split = (StateSplit) nodeWithState;
-                            stateAfter = (FrameState) stateAfter.copyWithInputs();
-                            split.setStateAfter(stateAfter);
-                        } else {
-                            throw GraalInternalError.shouldNotReachHere();
-                        }
-                    }
-                    final HashSet<ObjectState> virtual = new HashSet<>();
-                    stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() {
-
-                        @Override
-                        public void apply(Node usage, ValueNode value) {
-                            ObjectState valueObj = getObjectState(state, value);
-                            if (valueObj != null) {
-                                virtual.add(valueObj);
-                                effects.replaceFirstInput(usage, value, valueObj.virtual);
-                            } else if (value instanceof VirtualObjectNode) {
-                                ObjectState virtualObj = null;
-                                for (ObjectState obj : state.getStates()) {
-                                    if (value == obj.virtual) {
-                                        virtualObj = obj;
-                                        break;
-                                    }
-                                }
-                                if (virtualObj != null) {
-                                    virtual.add(virtualObj);
-                                }
-                            }
-                        }
-                    });
-                    for (ObjectState obj : state.getStates()) {
-                        if (obj.isVirtual() && obj.hasLocks()) {
-                            virtual.add(obj);
-                        }
-                    }
-
-                    ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
-                    while (!queue.isEmpty()) {
-                        ObjectState obj = queue.removeLast();
-                        if (obj.isVirtual()) {
-                            for (ValueNode field : obj.getEntries()) {
-                                if (field instanceof VirtualObjectNode) {
-                                    ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
-                                    if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
-                                        virtual.add(fieldObj);
-                                        queue.addLast(fieldObj);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    for (ObjectState obj : virtual) {
-                        EscapeObjectState v;
-                        if (obj.isVirtual()) {
-                            ValueNode[] fieldState = obj.getEntries().clone();
-                            for (int i = 0; i < fieldState.length; i++) {
-                                ObjectState valueObj = getObjectState(state, fieldState[i]);
-                                if (valueObj != null) {
-                                    if (valueObj.isVirtual()) {
-                                        fieldState[i] = valueObj.virtual;
-                                    } else {
-                                        fieldState[i] = valueObj.getMaterializedValue();
-                                    }
-                                }
-                            }
-                            v = new VirtualObjectState(obj.virtual, fieldState);
-                        } else {
-                            v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
-                        }
-                        effects.addVirtualMapping(stateAfter, v);
-                    }
-                }
-            }
             for (ValueNode input : node.inputs().filter(ValueNode.class)) {
                 ObjectState obj = getObjectState(state, input);
                 if (obj != null) {
@@ -201,10 +122,92 @@
                     replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
                 }
             }
+            if (node instanceof NodeWithState) {
+                processNodeWithState((NodeWithState) node, state, effects);
+            }
         }
         return false;
     }
 
+    private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) {
+        FrameState stateAfter = nodeWithState.getState();
+        if (stateAfter != null) {
+            if (stateAfter.usages().count() > 1) {
+                if (nodeWithState instanceof StateSplit) {
+                    StateSplit split = (StateSplit) nodeWithState;
+                    stateAfter = (FrameState) stateAfter.copyWithInputs();
+                    split.setStateAfter(stateAfter);
+                } else {
+                    throw GraalInternalError.shouldNotReachHere();
+                }
+            }
+            final HashSet<ObjectState> virtual = new HashSet<>();
+            stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() {
+
+                @Override
+                public void apply(Node usage, ValueNode value) {
+                    ObjectState valueObj = getObjectState(state, value);
+                    if (valueObj != null) {
+                        virtual.add(valueObj);
+                        effects.replaceFirstInput(usage, value, valueObj.virtual);
+                    } else if (value instanceof VirtualObjectNode) {
+                        ObjectState virtualObj = null;
+                        for (ObjectState obj : state.getStates()) {
+                            if (value == obj.virtual) {
+                                virtualObj = obj;
+                                break;
+                            }
+                        }
+                        if (virtualObj != null) {
+                            virtual.add(virtualObj);
+                        }
+                    }
+                }
+            });
+            for (ObjectState obj : state.getStates()) {
+                if (obj.isVirtual() && obj.hasLocks()) {
+                    virtual.add(obj);
+                }
+            }
+
+            ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
+            while (!queue.isEmpty()) {
+                ObjectState obj = queue.removeLast();
+                if (obj.isVirtual()) {
+                    for (ValueNode field : obj.getEntries()) {
+                        if (field instanceof VirtualObjectNode) {
+                            ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
+                            if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
+                                virtual.add(fieldObj);
+                                queue.addLast(fieldObj);
+                            }
+                        }
+                    }
+                }
+            }
+            for (ObjectState obj : virtual) {
+                EscapeObjectState v;
+                if (obj.isVirtual()) {
+                    ValueNode[] fieldState = obj.getEntries().clone();
+                    for (int i = 0; i < fieldState.length; i++) {
+                        ObjectState valueObj = getObjectState(state, fieldState[i]);
+                        if (valueObj != null) {
+                            if (valueObj.isVirtual()) {
+                                fieldState[i] = valueObj.virtual;
+                            } else {
+                                fieldState[i] = valueObj.getMaterializedValue();
+                            }
+                        }
+                    }
+                    v = new VirtualObjectState(obj.virtual, fieldState);
+                } else {
+                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
+                }
+                effects.addVirtualMapping(stateAfter, v);
+            }
+        }
+    }
+
     private void ensureMaterialized(BlockT state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) {
         assert obj != null;
         if (obj.getState() == EscapeState.Virtual) {
--- a/mx/commands.py	Tue Oct 15 01:25:31 2013 +0200
+++ b/mx/commands.py	Tue Oct 15 13:51:27 2013 +0200
@@ -955,12 +955,11 @@
         vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out)
         tasks.append(t.stop())
 
-    # temporarily disable G1 verification until merge issues are resolved
-    # with VM('graal', 'product'):
-    #     t = Task('BootstrapWithG1GCVerification:product')
-    #     out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write
-    #     vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out)
-    #     tasks.append(t.stop())
+    with VM('graal', 'product'):
+        t = Task('BootstrapWithG1GCVerification:product')
+        out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write
+        vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out)
+        tasks.append(t.stop())
 
     with VM('graal', 'product'):
         t = Task('BootstrapWithRegisterPressure:product')
--- a/src/share/vm/code/nmethod.cpp	Tue Oct 15 01:25:31 2013 +0200
+++ b/src/share/vm/code/nmethod.cpp	Tue Oct 15 13:51:27 2013 +0200
@@ -1405,13 +1405,6 @@
     // cache call.
     if (!is_osr_method() && !is_not_entrant()) {
       address stub = SharedRuntime::get_handle_wrong_method_stub();
-#ifdef GRAAL
-      if (_graal_installed_code != NULL) {
-        // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely.
-        HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
-        _graal_installed_code = NULL;
-      }
-#endif
       NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub);
     }
 
@@ -1491,6 +1484,12 @@
   } else {
     assert(state == not_entrant, "other cases may need to be handled differently");
   }
+#ifdef GRAAL
+      if (_graal_installed_code != NULL) {
+        // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely.
+        HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0);
+      }
+#endif
 
   if (TraceCreateZombies) {
     ResourceMark m;