# HG changeset patch # User Christian Wimmer # Date 1393549888 28800 # Node ID ffc6847d87c67f3c1319dbce78e6a4879477572f # Parent 6db511bddb84f48235ad16ec6a63e6739c045586 GraphKit: add support for if-then-else constructs diff -r 6db511bddb84 -r ffc6847d87c6 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Thu Feb 27 17:04:24 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Thu Feb 27 17:11:28 2014 -0800 @@ -237,7 +237,7 @@ int javaParameterOffset = javaParameterOffsetsInKernelParametersBuffer[javaParametersIndex]; LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameter.kind(), javaParameterOffset, getGraph()); append(new WriteNode(buf, javaParameter, location, BarrierType.NONE, false, false)); - updateDimArg(method, providers, sig, sigIndex++, args, javaParameter); + updateDimArg(method, sig, sigIndex++, args, javaParameter); } if (returnKind != Kind.Void) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, bufSize - wordSize, getGraph()); @@ -324,7 +324,7 @@ * Updates the {@code dimX}, {@code dimY} or {@code dimZ} argument passed to the kernel if * {@code javaParameter} is annotated with {@link ParallelOver}. */ - private void updateDimArg(ResolvedJavaMethod method, HotSpotProviders providers, Signature sig, int sigIndex, Map launchArgs, ParameterNode javaParameter) { + private void updateDimArg(ResolvedJavaMethod method, Signature sig, int sigIndex, Map launchArgs, ParameterNode javaParameter) { if (sigIndex >= 0) { ParallelOver parallelOver = getParameterAnnotation(ParallelOver.class, sigIndex, method); if (parallelOver != null && sig.getParameterType(sigIndex, method.getDeclaringClass()).equals(providers.getMetaAccess().lookupJavaType(int[].class))) { diff -r 6db511bddb84 -r ffc6847d87c6 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Thu Feb 27 17:04:24 2014 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Thu Feb 27 17:11:28 2014 -0800 @@ -23,6 +23,7 @@ package com.oracle.graal.replacements; import java.lang.reflect.*; +import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -44,14 +45,24 @@ */ public class GraphKit { - private final Providers providers; - private final StructuredGraph graph; - private FixedWithNextNode lastFixedNode; + protected final Providers providers; + protected final StructuredGraph graph; + protected FixedWithNextNode lastFixedNode; + + private final List structures; + + abstract static class Structure { + } public GraphKit(StructuredGraph graph, Providers providers) { this.providers = providers; this.graph = graph; this.lastFixedNode = graph.start(); + + structures = new ArrayList<>(); + /* Add a dummy element, so that the access of the last element never leads to an exception. */ + structures.add(new Structure() { + }); } public StructuredGraph getGraph() { @@ -83,31 +94,59 @@ return result; } + public InvokeNode createInvoke(Class declaringClass, String name, ValueNode... args) { + return createInvoke(declaringClass, name, InvokeKind.Static, null, FrameState.UNKNOWN_BCI, args); + } + /** * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of - * arguments. + * arguments. The method is looked up via reflection based on the declaring class and name. * * @param declaringClass the class declaring the invoked method * @param name the name of the invoked method * @param args the arguments to the invocation */ - public InvokeNode createInvoke(Class declaringClass, String name, ValueNode... args) { + public InvokeNode createInvoke(Class declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + boolean isStatic = invokeKind == InvokeKind.Static; ResolvedJavaMethod method = null; for (Method m : declaringClass.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { + if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) { assert method == null : "found more than one method in " + declaringClass + " named " + name; method = providers.getMetaAccess().lookupJavaMethod(m); } } assert method != null : "did not find method in " + declaringClass + " named " + name; + return createInvoke(method, invokeKind, frameStateBuilder, bci, args); + } + + /** + * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of + * arguments. + */ + public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static); Signature signature = method.getSignature(); JavaType returnType = signature.getReturnType(null); assert checkArgs(method, args); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, method, args, returnType)); - InvokeNode invoke = append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI)); + MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnType, bci)); + InvokeNode invoke = append(new InvokeNode(callTarget, bci)); + + if (frameStateBuilder != null) { + if (invoke.kind() != Kind.Void) { + frameStateBuilder.push(invoke.kind(), invoke); + } + invoke.setStateAfter(frameStateBuilder.create(0)); + if (invoke.kind() != Kind.Void) { + frameStateBuilder.pop(invoke.kind()); + } + } return invoke; } + protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType, @SuppressWarnings("unused") int bci) { + return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); + } + /** * Determines if a given set of arguments is compatible with the signature of a given method. * @@ -117,14 +156,21 @@ */ public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { Signature signature = method.getSignature(); - if (signature.getParameterCount(false) != args.length) { + boolean isStatic = Modifier.isStatic(method.getModifiers()); + if (signature.getParameterCount(!isStatic) != args.length) { throw new AssertionError(graph + ": wrong number of arguments to " + method); } + int paramNum = 0; for (int i = 0; i != args.length; i++) { - Kind expected = signature.getParameterKind(i).getStackKind(); + Kind expected; + if (i == 0 && !isStatic) { + expected = Kind.Object; + } else { + expected = signature.getParameterKind(paramNum++).getStackKind(); + } Kind actual = args[i].stamp().getStackKind(); if (expected != actual) { - throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of calls to " + method + " [" + actual + " != " + expected + "]"); + throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of call to " + method + " [" + actual + " != " + expected + "]"); } } return true; @@ -161,4 +207,115 @@ StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); InliningUtil.inline(invoke, calleeGraph, false); } + + protected void pushStructure(Structure structure) { + structures.add(structure); + } + + protected T getTopStructure(Class expectedClass) { + return expectedClass.cast(structures.get(structures.size() - 1)); + } + + protected void popStructure() { + structures.remove(structures.size() - 1); + } + + protected enum IfState { + CONDITION, THEN_PART, ELSE_PART, FINISHED + } + + static class IfStructure extends Structure { + protected IfState state; + protected FixedNode thenPart; + protected FixedNode elsePart; + } + + /** + * Starts an if-block. This call can be followed by a call to {@link #thenPart} to start + * emitting the code executed when the condition hold; and a call to {@link #elsePart} to start + * emititng the code when the condition does not hold. It must be followed by a call to + * {@link #endIf} to close the if-block. + * + * @param condition The condition for the if-block + * @param trueProbability The estimated probability the the condition is true + */ + public void startIf(LogicNode condition, double trueProbability) { + BeginNode thenSuccessor = graph.add(new BeginNode()); + BeginNode elseSuccessor = graph.add(new BeginNode()); + append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability)); + lastFixedNode = null; + + IfStructure s = new IfStructure(); + s.state = IfState.CONDITION; + s.thenPart = thenSuccessor; + s.elsePart = elseSuccessor; + pushStructure(s); + } + + private IfStructure saveLastNode() { + IfStructure s = getTopStructure(IfStructure.class); + switch (s.state) { + case CONDITION: + assert lastFixedNode == null; + break; + case THEN_PART: + s.thenPart = lastFixedNode; + break; + case ELSE_PART: + s.elsePart = lastFixedNode; + break; + case FINISHED: + assert false; + break; + } + lastFixedNode = null; + return s; + } + + public void thenPart() { + IfStructure s = saveLastNode(); + lastFixedNode = (FixedWithNextNode) s.thenPart; + s.state = IfState.THEN_PART; + } + + public void elsePart() { + IfStructure s = saveLastNode(); + lastFixedNode = (FixedWithNextNode) s.elsePart; + s.state = IfState.ELSE_PART; + } + + public void endIf() { + IfStructure s = saveLastNode(); + + FixedWithNextNode thenPart = s.thenPart instanceof FixedWithNextNode ? (FixedWithNextNode) s.thenPart : null; + FixedWithNextNode elsePart = s.elsePart instanceof FixedWithNextNode ? (FixedWithNextNode) s.elsePart : null; + + if (thenPart != null && elsePart != null) { + /* Both parts are alive, we need a real merge. */ + EndNode thenEnd = graph.add(new EndNode()); + graph.addAfterFixed(thenPart, thenEnd); + EndNode elseEnd = graph.add(new EndNode()); + graph.addAfterFixed(elsePart, elseEnd); + + MergeNode merge = graph.add(new MergeNode()); + merge.addForwardEnd(thenEnd); + merge.addForwardEnd(elseEnd); + + lastFixedNode = merge; + + } else if (thenPart != null) { + /* elsePart ended with a control sink, so we can continue with thenPart. */ + lastFixedNode = thenPart; + + } else if (elsePart != null) { + /* thenPart ended with a control sink, so we can continue with elsePart. */ + lastFixedNode = elsePart; + + } else { + /* Both parts ended with a control sink, so no nodes can be added after the if. */ + assert lastFixedNode == null; + } + s.state = IfState.FINISHED; + popStructure(); + } }