# HG changeset patch # User Christos Kotselidis # Date 1365499962 -7200 # Node ID 7c488a696276eaa9855d58168d019e588ddb15ec # Parent 81ef56feff1b4c2ee369b0d185343e7e396b1a4f# Parent f2bddf68d293e8404ed817ef0f810282019f3edf Merge diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Apr 09 11:32:42 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())); } diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Apr 09 11:32:42 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"); diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Apr 09 11:32:42 2013 +0200 @@ -713,6 +713,7 @@ if (onStackReplacement) { phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); } + phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); return phasePlan; } diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 09 11:32:42 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; diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- /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 11:32:42 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()))); + } + } + +} diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Tue Apr 09 11:32:42 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 diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Tue Apr 09 11:32:42 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 diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Tue Apr 09 11:32:42 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(); } diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Tue Apr 09 11:32:42 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); } } diff -r f2bddf68d293 -r 7c488a696276 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Tue Apr 09 10:11:52 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Tue Apr 09 11:32:42 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; diff -r f2bddf68d293 -r 7c488a696276 mx/projects --- a/mx/projects Tue Apr 09 10:11:52 2013 +0200 +++ b/mx/projects Tue Apr 09 11:32:42 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