changeset 8935:81ef56feff1b

Move write barriers' addition to a separate stage after lowering
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Tue, 09 Apr 2013 09:45:35 +0200
parents 91c39d0927fb
children 7c488a696276 63eae4723b18
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java mx/projects
diffstat 11 files changed, 143 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Tue Apr 09 09:45:35 2013 +0200
@@ -45,6 +45,7 @@
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.printer.*;
 import com.oracle.graal.test.*;
+import com.oracle.graal.hotspot.phases.WriteBarrierAdditionPhase;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -399,8 +400,10 @@
                 PhasePlan phasePlan = new PhasePlan();
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog());
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                                new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Apr 09 09:45:35 2013 +0200
@@ -218,13 +218,15 @@
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
-        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
-
         // Add safepoints to loops
         new SafepointInsertionPhase().apply(graph);
 
         new GuardLoweringPhase(target).apply(graph);
 
+        plan.runPhases(PhasePosition.LOW_LEVEL, graph);
+
+        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
+
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
         Debug.dump(schedule, "final schedule");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Tue Apr 09 09:45:35 2013 +0200
@@ -713,6 +713,7 @@
         if (onStackReplacement) {
             phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase());
         }
+        phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase());
         return phasePlan;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Apr 09 09:45:35 2013 +0200
@@ -565,7 +565,7 @@
             HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field();
             ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object();
             LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph);
-            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location));
+            WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, false));
             memoryWrite.dependencies().add(tool.createNullCheckGuard(object));
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
@@ -573,9 +573,7 @@
             FixedWithNextNode first = memoryWrite;
 
             if (field.getKind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) {
-                SerialWriteBarrier writeBarrier = graph.add(new SerialWriteBarrier(memoryWrite.object(), location, false));
-                graph.addAfterFixed(memoryWrite, writeBarrier);
-                last = writeBarrier;
+                memoryWrite.setWriteBarrier();
             }
             if (storeField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
@@ -590,13 +588,9 @@
             LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1);
             if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
                 ResolvedJavaType type = cas.object().objectStamp().type();
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    graph.addAfterFixed(cas, graph.add(new SerialWriteBarrier(cas.object(), location, false)));
-                } else {
-                    // This may be an array store so use an array write barrier
-                    graph.addAfterFixed(cas, graph.add(new SerialWriteBarrier(cas.object(), location, true)));
-                }
+                final boolean precise = (type != null && type.isArray() && !MetaUtil.isJavaLangObject(type));
+                cas.setWriteBarrier();
+                cas.setPreciseWriteBarrier(precise);
             }
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
@@ -633,13 +627,13 @@
                     value = checkcast;
                 }
             }
-            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation));
+            WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, true));
             memoryWrite.dependencies().add(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
             if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
-                graph.addAfterFixed(memoryWrite, graph.add(new SerialWriteBarrier(array, arrayLocation, true)));
+                memoryWrite.setWriteBarrier();
             }
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
@@ -654,19 +648,13 @@
             UnsafeStoreNode store = (UnsafeStoreNode) n;
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1);
             ValueNode object = store.object();
-            WriteNode write = graph.add(new WriteNode(object, store.value(), location));
+            ResolvedJavaType type = object.objectStamp().type();
+            final boolean precise = (type != null && type.isArray() && !MetaUtil.isJavaLangObject(type));
+            WriteNode write = graph.add(new WriteNode(object, store.value(), location, precise));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
             if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) {
-                ResolvedJavaType type = object.objectStamp().type();
-                // WriteBarrier writeBarrier;
-                if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
-                    // Use a field write barrier since it's not an array store
-                    graph.addAfterFixed(write, graph.add(new SerialWriteBarrier(object, location, false)));
-                } else {
-                    // This may be an array store so use an array write barrier
-                    graph.addAfterFixed(write, graph.add(new SerialWriteBarrier(object, location, true)));
-                }
+                write.setWriteBarrier();
             }
         } else if (n instanceof LoadHubNode) {
             LoadHubNode loadHub = (LoadHubNode) n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Apr 09 09:45:35 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 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.phases;
+
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+
+public class WriteBarrierAdditionPhase extends Phase {
+
+    public WriteBarrierAdditionPhase() {
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (WriteNode node : graph.getNodes(WriteNode.class)) {
+            addWriteNodeBarriers(node, graph);
+        }
+        for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) {
+            addCASBarriers(node, graph);
+        }
+    }
+
+    private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
+        if (node.needsWriteBarrier()) {
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), node.usePreciseWriteBarriers())));
+        }
+
+    }
+
+    private void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) {
+        if (node.needsWriteBarrier()) {
+            LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, node.expected().kind(), node.displacement(), node.offset(), graph, 1);
+            graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), location, node.usePreciseWriteBarriers())));
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Apr 09 09:45:35 2013 +0200
@@ -25,15 +25,23 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.graph.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
  */
-public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint {
+public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
 
+    /*
+     * The field below instructs the snippet to use the address of the object or the effective
+     * address of the object element of an array when calculating the card offset.
+     */
+    private final boolean usePreciseWriteBarriers;
+    private boolean needsWriteBarrier;
+
     public FrameState stateAfter() {
         return stateAfter;
     }
@@ -52,9 +60,22 @@
         return value;
     }
 
-    public WriteNode(ValueNode object, ValueNode value, ValueNode location) {
+    public boolean usePreciseWriteBarriers() {
+        return usePreciseWriteBarriers;
+    }
+
+    public boolean needsWriteBarrier() {
+        return needsWriteBarrier;
+    }
+
+    public void setWriteBarrier() {
+        this.needsWriteBarrier = true;
+    }
+
+    public WriteNode(ValueNode object, ValueNode value, ValueNode location, boolean usePreciseWriteBarriers) {
         super(object, location, StampFactory.forVoid());
         this.value = value;
+        this.usePreciseWriteBarriers = usePreciseWriteBarriers;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Apr 09 09:45:35 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,13 +35,19 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint {
+public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
     private final int displacement;
+    /*
+     * The field below instructs the snippet to use the address of the object or the effective
+     * address of the object element of an array when calculating the card offset.
+     */
+    private boolean usePreciseWriteBarriers;
+    private boolean needsWriteBarrier;
 
     public ValueNode object() {
         return object;
@@ -62,6 +69,22 @@
         return displacement;
     }
 
+    public boolean usePreciseWriteBarriers() {
+        return usePreciseWriteBarriers;
+    }
+
+    public boolean needsWriteBarrier() {
+        return needsWriteBarrier;
+    }
+
+    public void setWriteBarrier() {
+        this.needsWriteBarrier = true;
+    }
+
+    public void setPreciseWriteBarrier(boolean precise) {
+        this.usePreciseWriteBarriers = precise;
+    }
+
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
@@ -70,6 +93,7 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
+        this.usePreciseWriteBarriers = false;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Apr 09 09:45:35 2013 +0200
@@ -48,8 +48,15 @@
         //
     }
 
+    private boolean isLowered() {
+        return (stamp() == StampFactory.forVoid());
+    }
+
     @Override
     public void lower(LoweringTool tool) {
+        if (isLowered()) {
+            return;
+        }
         StructuredGraph graph = (StructuredGraph) graph();
         LoadExceptionObjectNode loadException = graph.add(new LoadExceptionObjectNode(stamp()));
         loadException.setStateAfter(stateAfter());
@@ -62,6 +69,9 @@
 
     @Override
     public boolean verify() {
+        if (isLowered()) {
+            return true;
+        }
         assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
         return super.verify();
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Tue Apr 09 09:45:35 2013 +0200
@@ -63,7 +63,7 @@
     public void lower(LoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) this.graph();
         IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1);
-        WriteNode write = graph.add(new WriteNode(object, value, location));
+        WriteNode write = graph.add(new WriteNode(object, value, location, false));
         graph.replaceFixedWithFixed(this, write);
     }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Apr 08 21:33:22 2013 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Apr 09 09:45:35 2013 +0200
@@ -277,7 +277,7 @@
 
     private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Kind writeKind, Object locationIdentity) {
         IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1);
-        WriteNode write = graph.add(new WriteNode(base, value, location));
+        WriteNode write = graph.add(new WriteNode(base, value, location, false));
         write.setStateAfter(invoke.stateAfter());
         graph.addBeforeFixed(invoke.node(), write);
         return write;
--- a/mx/projects	Mon Apr 08 21:33:22 2013 +0200
+++ b/mx/projects	Tue Apr 09 09:45:35 2013 +0200
@@ -125,7 +125,7 @@
 # graal.hotspot.test
 project@com.oracle.graal.hotspot.test@subDir=graal
 project@com.oracle.graal.hotspot.test@sourceDirs=src
-project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot
+project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 
@@ -215,7 +215,7 @@
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
 project@com.oracle.graal.replacements.test@sourceDirs=src
-project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.replacements,com.oracle.graal.compiler.test
+project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.replacements.test@javaCompliance=1.7
 
@@ -333,7 +333,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7