# HG changeset patch # User Doug Simon # Date 1363012760 -3600 # Node ID a68310b2b8b886cb0efab5010c58f88f33639189 # Parent f54b2344ef3c39f620d16e1af8993f9013b7a0ed made GraphBuilderPhase and SnippetInstaller more extensible (inspired by patch from Mick Jordan) diff -r f54b2344ef3c -r a68310b2b8b8 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 11 15:37:34 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 11 15:39:20 2013 +0100 @@ -62,4 +62,13 @@ public static GraphBuilderConfiguration getSnippetDefault() { return new GraphBuilderConfiguration(true, true); } + + /** + * Returns {@code true} if it is an error for a class/field/method resolution to fail. + * The default is the same result as returned by {@link #eagerResolving()}. + * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}. + */ + public boolean unresolvedIsError() { + return eagerResolving; + } } diff -r f54b2344ef3c -r a68310b2b8b8 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 11 15:37:34 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 11 15:39:20 2013 +0100 @@ -114,6 +114,20 @@ private Block[] loopHeaders; + /** + * Gets the current frame state being processed by this builder. + */ + protected FrameStateBuilder getCurrentFrameState() { + return frameState; + } + + /** + * Gets the graph being processed by this builder. + */ + protected StructuredGraph getGraph() { + return currentGraph; + } + public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; @@ -261,6 +275,99 @@ return handler.catchTypeCPI() == 0; } + /** + * @param type the unresolved type of the constant + */ + protected void handleUnresolvedLoadConstant(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { + BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); + IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); + append(ifNode); + lastInstr = successor; + frameState.ipush(appendConstant(Constant.INT_0)); + } + + /** + * @param type the type being instantiated + */ + protected void handleUnresolvedNewInstance(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type of the array being instantiated + * @param length the length of the array + */ + protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type being instantiated + * @param dims the dimensions for the multi-array + */ + protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param field the unresolved field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { + Kind kind = field.getKind(); + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + + /** + * @param field the unresolved field + * @param value the value being stored to the field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + /** + * @param representation + * @param type + */ + protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { + boolean withReceiver = invokeKind != InvokeKind.Static; + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); + Kind kind = javaMethod.getSignature().getReturnKind(); + if (kind != Kind.Void) { + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + } + private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); @@ -307,8 +414,7 @@ if (type instanceof ResolvedJavaType) { frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph))); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + handleUnresolvedLoadConstant(type); } } else if (con instanceof Constant) { Constant constant = (Constant) con; @@ -636,21 +742,21 @@ private JavaType lookupType(int cpi, int bytecode) { eagerResolvingForSnippets(cpi, bytecode); JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.eagerResolving() || result instanceof ResolvedJavaType; + assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; return result; } private JavaMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; return result; } private JavaField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; } @@ -683,16 +789,13 @@ private void genCheckCast() { int cpi = stream().readCPI(); JavaType type = lookupType(cpi, CHECKCAST); - boolean initialized = type instanceof ResolvedJavaType; - if (initialized) { - ValueNode object = frameState.apop(); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type))); append(checkCast); frameState.apush(checkCast); } else { - ValueNode object = frameState.apop(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedCheckCast(type, object); } } @@ -706,12 +809,7 @@ ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph))); frameState.ipush(append(conditional)); } else { - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); - IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); - append(ifNode); - lastInstr = successor; - frameState.ipush(appendConstant(Constant.INT_0)); + handleUnresolvedInstanceOf(type, object); } } @@ -721,8 +819,7 @@ NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewInstance(type); } } @@ -772,8 +869,7 @@ NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewObjectArray(type, length); } } @@ -789,8 +885,7 @@ FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((ResolvedJavaType) type, dims)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewMultiArray(type, dims); } } @@ -803,8 +898,7 @@ LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (ResolvedJavaField) field)); appendOptimizedLoadField(kind, load); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, receiver); } } @@ -890,7 +984,7 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, receiver); } } @@ -905,8 +999,7 @@ appendOptimizedLoadField(kind, load); } } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, null); } } @@ -916,15 +1009,15 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(null, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, null); } } - private ConstantNode genTypeOrDeopt(Representation representation, JavaType holder, boolean initialized) { + private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) { if (initialized) { - return appendConstant(((ResolvedJavaType) holder).getEncoding(representation)); + return appendConstant(((ResolvedJavaType) type).getEncoding(representation)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedExceptionType(representation, type); return null; } } @@ -944,13 +1037,13 @@ ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false)); appendInvoke(InvokeKind.Static, resolvedTarget, args); } } else { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } } @@ -959,7 +1052,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Interface); } } @@ -968,7 +1061,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Virtual); } } @@ -980,16 +1073,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); invokeDirect((ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); - } - } - - private void genInvokeDeopt(JavaMethod unresolvedTarget, boolean withReceiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.popArguments(unresolvedTarget.getSignature().getParameterSlots(withReceiver), unresolvedTarget.getSignature().getParameterCount(withReceiver)); - Kind kind = unresolvedTarget.getSignature().getReturnKind(); - if (kind != Kind.Void) { - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedInvoke(target, InvokeKind.Special); } } @@ -1213,7 +1297,7 @@ } } - private ConstantNode appendConstant(Constant constant) { + protected ConstantNode appendConstant(Constant constant) { assert constant != null; return ConstantNode.forConstant(constant, runtime, currentGraph); } @@ -1224,7 +1308,7 @@ return fixed; } - private ValueNode append(FixedWithNextNode x) { + protected ValueNode append(FixedWithNextNode x) { return appendWithBCI(x); } @@ -1232,7 +1316,7 @@ return v; } - private ValueNode appendWithBCI(FixedWithNextNode x) { + protected ValueNode appendWithBCI(FixedWithNextNode x) { assert x.predecessor() == null : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; lastInstr.setNext(x); diff -r f54b2344ef3c -r a68310b2b8b8 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Mar 11 15:37:34 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Mar 11 15:39:20 2013 +0100 @@ -53,10 +53,10 @@ */ public class SnippetInstaller { - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Assumptions assumptions; - private final BoxingMethodPool pool; + protected final MetaAccessProvider runtime; + protected final TargetDescription target; + protected final Assumptions assumptions; + protected final BoxingMethodPool pool; private final Thread owner; /** @@ -191,6 +191,19 @@ } } + /** + * Does final processing of a snippet graph. + */ + protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) { + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); + + new SnippetFrameStateCleanupPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + new InsertStateAfterPlaceholderPhase().apply(graph); + } + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable() { @@ -198,13 +211,7 @@ public StructuredGraph call() throws Exception { StructuredGraph graph = parseGraph(method, policy); - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); - - new SnippetFrameStateCleanupPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - new InsertStateAfterPlaceholderPhase().apply(graph); + finalizeGraph(method, graph); Debug.dump(graph, "%s: Final", method.getName()); @@ -222,8 +229,10 @@ return graph; } - private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { - assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + /** + * Builds the initial graph for a snippet. + */ + protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod method) { final StructuredGraph graph = new StructuredGraph(method); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); @@ -232,9 +241,42 @@ Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName()); new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + return graph; + } + + /** + * Called after a graph is inlined. + * + * @param caller the graph into which {@code callee} was inlined + * @param callee the graph that was inlined into {@code caller} + */ + protected void afterInline(StructuredGraph caller, StructuredGraph callee) { + if (GraalOptions.OptCanonicalizer) { + new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); + new CanonicalizerPhase(runtime, assumptions).apply(caller); + } + } + + /** + * Called after all inlining for a given graph is complete. + */ + protected void afterInlining(StructuredGraph graph) { new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); + + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(runtime, assumptions).apply(graph); + } + } + + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + final StructuredGraph graph = buildInitialGraph(method); + for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); ResolvedJavaMethod callee = callTarget.targetMethod(); @@ -244,31 +286,19 @@ InliningUtil.inline(invoke, originalGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, originalGraph); substituteCallsOriginal = true; } else { if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { StructuredGraph targetGraph = parseGraph(callee, policy); InliningUtil.inline(invoke, targetGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, targetGraph); } } } - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - - new DeadCodeEliminationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInlining(graph); for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { end.disableSafepoint();