# HG changeset patch # User Lukas Stadler # Date 1358958347 -3600 # Node ID 9e2cbc932853a1e267027ce47fd11fd1194067d6 # Parent 50793b11b74d85365ac7eaa19961b6b2ee86c850# Parent 29b0768b7ba659f44e37ebc6f0e99454ee0610ab Merge diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Wed Jan 23 17:25:47 2013 +0100 @@ -57,7 +57,7 @@ public void run() { StructuredGraph graph = parse(snippet); - new LoweringPhase(runtime(), new Assumptions(false)).apply(graph); + new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 29b0768b7ba6 -r 9e2cbc932853 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 Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Jan 23 17:25:47 2013 +0100 @@ -161,7 +161,7 @@ new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } - new LoweringPhase(runtime, assumptions).apply(graph); + new LoweringPhase(target, runtime, assumptions).apply(graph); if (GraalOptions.CullFrameStates) { new CullFrameStatesPhase().apply(graph); diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java Wed Jan 23 17:25:47 2013 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; @@ -34,99 +35,119 @@ public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable { - public ArrayCopyNode(InvokeNode invoke) { + public ArrayCopyNode(Invoke invoke) { super(invoke); } - public ValueNode src() { + private ValueNode getSource() { return arguments.get(0); } - public ValueNode srcPos() { + private ValueNode getSourcePosition() { return arguments.get(1); } - public ValueNode dest() { + private ValueNode getDestination() { return arguments.get(2); } - public ValueNode destPos() { + private ValueNode getDestinationPosition() { return arguments.get(3); } - public ValueNode length() { + private ValueNode getLength() { return arguments.get(4); } + private ResolvedJavaMethod selectSnippet(LoweringTool tool) { + ResolvedJavaType srcType = getSource().objectStamp().type(); + ResolvedJavaType destType = getDestination().objectStamp().type(); + + if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) { + Kind componentKind = srcType.getComponentType().getKind(); + if (componentKind != Kind.Object) { + if (srcType.getComponentType() == destType.getComponentType()) { + return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); + } + } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && getDestination().objectStamp().isExactType()) { + return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object)); + } + } + return null; + } + + private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) { + snippetGraph.replaceFloating(snippetGraph.getLocal(4), ConstantNode.forInt(length, snippetGraph)); + // the canonicalization before loop unrolling is needed to propagate the length into additions, etc. + new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + } + @Override public void lower(LoweringTool tool) { - ResolvedJavaMethod snippetMethod = null; - ResolvedJavaType srcType = src().objectStamp().type(); - ResolvedJavaType destType = dest().objectStamp().type(); - if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) { - Kind componentKind = srcType.getComponentType().getKind(); - if (componentKind != Kind.Object) { - if (srcType.getComponentType() == destType.getComponentType()) { - snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); - } - } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && dest().objectStamp().isExactType()) { - snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object)); - } - } + ResolvedJavaMethod snippetMethod = selectSnippet(tool); if (snippetMethod == null) { snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.increaseGenericCallCounterMethod); // we will call the generic method. the generic snippet will only increase the counter, // not call the actual // method. therefore we create a second invoke here. ((StructuredGraph) graph()).addAfterFixed(this, createInvoke()); - } else { + } + if (Debug.isLogEnabled()) { Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); } - if (snippetMethod != null) { - StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); - assert snippetGraph != null : "ArrayCopySnippets should be installed"; - InvokeNode invoke = replaceWithInvoke(); - InliningUtil.inline(invoke, snippetGraph, false); - } else { - super.lower(tool); + StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); + assert snippetGraph != null : "ArrayCopySnippets should be installed"; + if (getLength().isConstant()) { + snippetGraph = snippetGraph.copy(); + unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool); } + InvokeNode invoke = replaceWithInvoke(); + InliningUtil.inline(invoke, snippetGraph, false); + } + + private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { + return position >= 0 && position + length <= virtualObject.entryCount(); + } + + private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType) { + if (destComponentType.getKind() == Kind.Object) { + for (int i = 0; i < length; i++) { + if (!destComponentType.isAssignableFrom(srcState.getEntry(srcPos + i).objectStamp().type())) { + return false; + } + } + } + return true; } @Override public void virtualize(VirtualizerTool tool) { - if (srcPos().isConstant() && destPos().isConstant() && length().isConstant()) { - int srcPos = srcPos().asConstant().asInt(); - int destPos = destPos().asConstant().asInt(); - int length = length().asConstant().asInt(); - State srcState = tool.getObjectState(src()); - State destState = tool.getObjectState(dest()); + if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) { + int srcPos = getSourcePosition().asConstant().asInt(); + int destPos = getDestinationPosition().asConstant().asInt(); + int length = getLength().asConstant().asInt(); + State srcState = tool.getObjectState(getSource()); + State destState = tool.getObjectState(getDestination()); if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) { VirtualObjectNode srcVirtual = srcState.getVirtualObject(); VirtualObjectNode destVirtual = destState.getVirtualObject(); - if (length < 0) { - return; - } - if (srcPos < 0 || srcPos + length > srcVirtual.entryCount()) { + if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) { return; } - if (destPos < 0 || destPos + length > destVirtual.entryCount()) { + if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType())) { return; } - ResolvedJavaType destComponentType = destVirtual.type().getComponentType(); - if (destComponentType.getKind() == Kind.Object) { - for (int i = 0; i < length; i++) { - if (!destComponentType.isAssignableFrom(srcState.getEntry(srcPos + i).objectStamp().javaType(tool.getMetaAccessProvider()))) { - return; - } - } - } for (int i = 0; i < length; i++) { tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i)); } tool.delete(); - Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", src(), srcPos, dest(), destPos, length); + if (Debug.isLogEnabled()) { + Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length); + } } } } diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Wed Jan 23 17:25:47 2013 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import java.lang.reflect.*; import java.util.*; @@ -89,6 +90,7 @@ long srcOffset = (long) srcPos * elementSize; long destOffset = (long) destPos * elementSize; if (src == dest && srcPos < destPos) { // bad aliased case + probability(0.1); for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) { UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind); } @@ -109,13 +111,40 @@ } public static void checkInputs(Object src, int srcPos, Object dest, int destPos, int length) { - if (src == null || dest == null) { + if (src == null) { + probability(0.01); checkNPECounter.inc(); - throw new NullPointerException(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + if (dest == null) { + probability(0.01); + checkNPECounter.inc(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + if (srcPos < 0) { + probability(0.01); + checkAIOOBECounter.inc(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > ArrayLengthNode.arrayLength(src) || destPos + length > ArrayLengthNode.arrayLength(dest)) { + if (destPos < 0) { + probability(0.01); + checkAIOOBECounter.inc(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + if (length < 0) { + probability(0.01); checkAIOOBECounter.inc(); - throw new ArrayIndexOutOfBoundsException(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + if (srcPos + length > ArrayLengthNode.arrayLength(src)) { + probability(0.01); + checkAIOOBECounter.inc(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + if (destPos + length > ArrayLengthNode.arrayLength(dest)) { + probability(0.01); + checkAIOOBECounter.inc(); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } checkSuccessCounter.inc(); } diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Wed Jan 23 17:25:47 2013 +0100 @@ -30,6 +30,8 @@ public interface LoweringTool { + TargetDescription getTarget(); + GraalCodeCacheProvider getRuntime(); ValueNode createNullCheckGuard(ValueNode object, long leafGraphId); diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Jan 23 17:25:47 2013 +0100 @@ -225,12 +225,19 @@ assert invoke instanceof InvokeNode; FixedWithNextNode macroNode; try { - macroNode = macroNodeClass.getConstructor(InvokeNode.class).newInstance(invoke); + macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass); } + macroNode.setProbability(invoke.node().probability()); CallTargetNode callTarget = invoke.callTarget(); - graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); + if (invoke instanceof InvokeNode) { + graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); + } else { + InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke; + invokeWithException.killExceptionEdge(); + graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next()); + } GraphUtil.killWithUnusedFloatingInputs(callTarget); } else { StructuredGraph calleeGraph = getIntrinsicGraph(concrete); diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Jan 23 17:25:47 2013 +0100 @@ -43,10 +43,10 @@ final class LoweringToolImpl implements LoweringTool { - final FixedNode guardAnchor; - final NodeBitMap activeGuards; - FixedWithNextNode lastFixedNode; - ControlFlowGraph cfg; + private final FixedNode guardAnchor; + private final NodeBitMap activeGuards; + private FixedWithNextNode lastFixedNode; + private ControlFlowGraph cfg; public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) { this.guardAnchor = guardAnchor; @@ -55,6 +55,11 @@ } @Override + public TargetDescription getTarget() { + return target; + } + + @Override public GraalCodeCacheProvider getRuntime() { return runtime; } @@ -101,12 +106,14 @@ } } + private final TargetDescription target; private final GraalCodeCacheProvider runtime; private final Assumptions assumptions; private boolean deferred; - public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { + public LoweringPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions) { + this.target = target; this.runtime = runtime; this.assumptions = assumptions; } diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Jan 23 17:25:47 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; @@ -98,6 +99,9 @@ int opportunities = 0; while (current instanceof FixedWithNextNode) { current = ((FixedWithNextNode) current).next(); + if (current instanceof VirtualizableAllocation) { + return false; + } for (PhiNode phi : improvements) { for (Node input : current.inputs()) { if (input == phi) { diff -r 29b0768b7ba6 -r 9e2cbc932853 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java Wed Jan 23 16:49:55 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java Wed Jan 23 17:25:47 2013 +0100 @@ -33,14 +33,14 @@ public class MacroNode extends AbstractStateSplit implements Lowerable { - @Input protected NodeInputList arguments; + @Input protected final NodeInputList arguments; private final int bci; private final ResolvedJavaMethod targetMethod; private final JavaType returnType; - protected MacroNode(InvokeNode invoke) { - super(invoke.stamp(), invoke.stateAfter()); + protected MacroNode(Invoke invoke) { + super(invoke.node().stamp(), invoke.stateAfter()); this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments()); this.bci = invoke.bci(); this.targetMethod = invoke.methodCallTarget().targetMethod();