# HG changeset patch # User Lukas Stadler # Date 1389617125 -3600 # Node ID f4c776ad613e54126fda858d2a015c323e769a97 # Parent 0774f3303c2e98e99315e18d106da787a5c21e46# Parent 428403544e77f5764faee653e2692d01d2ac137d Merge diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Jan 13 13:45:25 2014 +0100 @@ -183,7 +183,7 @@ * increasing order of priority are are used to optimize spilling when multiple overlapping * intervals compete for limited registers. */ - enum RegisterPriority { + public enum RegisterPriority { /** * No special reason for an interval to be allocated a register. */ diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Jan 13 13:45:25 2014 +0100 @@ -1036,7 +1036,7 @@ // detection of method-parameters and roundfp-results interval.setSpillState(SpillState.StartInMemory); } - interval.addMaterializationValue(gen.getMaterializedValue(op, operand)); + interval.addMaterializationValue(gen.getMaterializedValue(op, operand, interval)); Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jan 13 13:45:25 2014 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -192,14 +193,29 @@ * * @param op An instruction which defines a value * @param operand The destination operand of the instruction + * @param interval The interval for this defined value. * @return Returns the value which is moved to the instruction and which can be reused at all * reload-locations in case the interval of this instruction is spilled. Currently this * can only be a {@link Constant}. */ - public Constant getMaterializedValue(LIRInstruction op, Value operand) { + public Constant getMaterializedValue(LIRInstruction op, Value operand, Interval interval) { if (op instanceof MoveOp) { MoveOp move = (MoveOp) op; if (move.getInput() instanceof Constant) { + /* + * Check if the interval has any uses which would accept an stack location (priority + * == ShouldHaveRegister). Rematerialization of such intervals can result in a + * degradation, because rematerialization always inserts a constant load, even if + * the value is not needed in a register. + */ + Interval.UsePosList usePosList = interval.usePosList(); + int numUsePos = usePosList.size(); + for (int useIdx = 0; useIdx < numUsePos; useIdx++) { + Interval.RegisterPriority priority = usePosList.registerPriority(useIdx); + if (priority == Interval.RegisterPriority.ShouldHaveRegister) { + return null; + } + } return (Constant) move.getInput(); } } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Jan 13 13:45:25 2014 +0100 @@ -98,7 +98,7 @@ ResolvedJavaMethod initMethod = null; try { Class rjm = ResolvedJavaMethod.class; - makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, SnippetInliningPolicy.class, boolean.class)); + makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, rjm, SnippetInliningPolicy.class, boolean.class, boolean.class)); initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class)); } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Jan 13 13:45:25 2014 +0100 @@ -107,7 +107,7 @@ final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet); snippetGraph = null; try (Scope s = Debug.scope("ArrayCopySnippet", snippetMethod)) { - snippetGraph = replacements.getSnippet(snippetMethod).copy(); + snippetGraph = replacements.getSnippet(snippetMethod, getTargetMethod()).copy(); } catch (Throwable e) { throw Debug.handle(e); } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java Mon Jan 13 13:45:25 2014 +0100 @@ -158,7 +158,7 @@ public void inline(InvokeNode invoke) { ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget()); - StructuredGraph calleeGraph = repl.makeGraph(method, null, null, false); + StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, false, false); InliningUtil.inline(invoke, calleeGraph, false); } } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAllocateInstance01.java diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Jan 13 13:45:25 2014 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -public class DynamicNewInstanceNode extends AbstractNewObjectNode { +public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable { @Input private ValueNode clazz; @@ -45,11 +45,11 @@ Class staticClass = (Class) clazzConstant.asObject(); ResolvedJavaType type = tool.getMetaAccess().lookupJavaType(staticClass); if (type.isInitialized()) { - return new NewInstanceNode(type, fillContents()); + return graph().add(new NewInstanceNode(type, fillContents())); } } } - return super.canonical(tool); + return this; } public ValueNode getInstanceType() { diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Mon Jan 13 13:45:25 2014 +0100 @@ -42,6 +42,16 @@ StructuredGraph getSnippet(ResolvedJavaMethod method); /** + * Gets the snippet graph derived from a given method. + * + * @param recursiveEntry if the snippet contains a call to this method, it's considered as + * recursive call and won't be processed for {@linkplain MethodSubstitution + * substitutions} or {@linkplain MacroSubstitution macro nodes}. + * @return the snippet graph, if any, that is derived from {@code method} + */ + StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry); + + /** * Registers a method as snippet. */ void registerSnippet(ResolvedJavaMethod method); diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Mon Jan 13 13:45:25 2014 +0100 @@ -37,7 +37,7 @@ public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { super(Kind.Object); - assert !exactType || (type != null && (!Modifier.isAbstract(type.getModifiers()) || type.isArray())); + assert !exactType || (type != null && (isConcreteType(type))); this.type = type; this.exactType = exactType; this.nonNull = nonNull; @@ -198,7 +198,7 @@ } if (joinAlwaysNull && joinNonNull) { return StampFactory.illegal(Kind.Object); - } else if (joinExactType && Modifier.isAbstract(joinType.getModifiers()) && !joinType.isArray()) { + } else if (joinExactType && !isConcreteType(joinType)) { return StampFactory.illegal(Kind.Object); } if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { @@ -210,6 +210,10 @@ } } + public static boolean isConcreteType(ResolvedJavaType type) { + return !(Modifier.isAbstract(type.getModifiers()) && !type.isArray()); + } + private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) { if (a == b) { return a; diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jan 13 13:45:25 2014 +0100 @@ -218,7 +218,11 @@ } public static Stamp exactNonNull(ResolvedJavaType type) { - return new ObjectStamp(type, true, true, false); + if (ObjectStamp.isConcreteType(type)) { + return new ObjectStamp(type, true, true, false); + } else { + return illegal(Kind.Object); + } } public static Stamp exact(ResolvedJavaType type) { diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Jan 13 13:45:25 2014 +0100 @@ -234,7 +234,6 @@ public boolean baseTryCanonicalize(final Node node, NodeClass nodeClass) { if (nodeClass.isCanonicalizable()) { - assert !nodeClass.isSimplifiable(); METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); try (Scope s = Debug.scope("CanonicalizeNode", node)) { Node canonical = node.canonical(tool); @@ -242,7 +241,9 @@ } catch (Throwable e) { throw Debug.handle(e); } - } else if (nodeClass.isSimplifiable()) { + } + + if (nodeClass.isSimplifiable()) { Debug.log("Canonicalizer: simplifying %s", node); METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); try (Scope s = Debug.scope("SimplifyNode", node)) { diff -r 0774f3303c2e -r f4c776ad613e 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 Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Jan 13 13:45:25 2014 +0100 @@ -328,7 +328,7 @@ assert inlineable instanceof InlineableMacroNode; Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); - inlineMacroNode(invoke, concrete, graph, macroNodeClass); + inlineMacroNode(invoke, concrete, macroNodeClass); } InlinedBytecodes.add(concrete.getCodeSize()); @@ -1492,7 +1492,8 @@ return replacements.getMacroSubstitution(target); } - public static FixedWithNextNode inlineMacroNode(Invoke invoke, ResolvedJavaMethod concrete, StructuredGraph graph, Class macroNodeClass) throws GraalInternalError { + public static FixedWithNextNode inlineMacroNode(Invoke invoke, ResolvedJavaMethod concrete, Class macroNodeClass) throws GraalInternalError { + StructuredGraph graph = invoke.asNode().graph(); if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) { assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static; InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Jan 13 13:45:25 2014 +0100 @@ -491,7 +491,7 @@ return latestBlock; } - Stack path = computePathInDominatorTree(earliestBlock, latestBlock); + Deque path = computePathInDominatorTree(earliestBlock, latestBlock); Debug.printf("|path| is %d: %s\n", path.size(), path); // follow path, start at earliest schedule @@ -542,8 +542,8 @@ * * @return the order of the stack is such as the first element is the earliest schedule. */ - private static Stack computePathInDominatorTree(Block earliestBlock, Block latestBlock) { - Stack path = new Stack<>(); + private static Deque computePathInDominatorTree(Block earliestBlock, Block latestBlock) { + Deque path = new LinkedList<>(); Block currentBlock = latestBlock; while (currentBlock != null && earliestBlock.dominates(currentBlock)) { path.push(currentBlock); @@ -559,17 +559,17 @@ */ private static HashSet computeRegion(Block dominatorBlock, Block dominatedBlock) { HashSet region = new HashSet<>(); - Stack workList = new Stack<>(); + Queue workList = new LinkedList<>(); region.add(dominatorBlock); - workList.addAll(0, dominatorBlock.getSuccessors()); + workList.addAll(dominatorBlock.getSuccessors()); while (workList.size() > 0) { - Block current = workList.pop(); + Block current = workList.poll(); if (current != dominatedBlock) { region.add(current); for (Block b : current.getSuccessors()) { if (!region.contains(b) && !workList.contains(b)) { - workList.add(b); + workList.offer(b); } } } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Jan 13 13:45:25 2014 +0100 @@ -54,7 +54,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); + return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), false, false); } @Test diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Jan 13 13:45:25 2014 +0100 @@ -60,7 +60,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); + return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), false, false); } @Test diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Mon Jan 13 13:45:25 2014 +0100 @@ -49,7 +49,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = getMetaAccess().lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get(), false); + return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), false, false); } @LongTest diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Jan 13 13:45:25 2014 +0100 @@ -93,7 +93,7 @@ */ protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) { InstanceOfUsageReplacer replacer; - if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode) { + if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode || usage instanceof ConditionAnchorNode) { replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage); } else { assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage; diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Jan 13 13:45:25 2014 +0100 @@ -84,15 +84,19 @@ private static final boolean UseSnippetGraphCache = Boolean.parseBoolean(System.getProperty("graal.useSnippetGraphCache", "true")); private static final DebugTimer SnippetPreparationTime = Debug.timer("SnippetPreparationTime"); + public StructuredGraph getSnippet(ResolvedJavaMethod method) { + return getSnippet(method, null); + } + @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method) { + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; StructuredGraph graph = UseSnippetGraphCache ? graphs.get(method) : null; if (graph == null) { try (TimerCloseable a = SnippetPreparationTime.start()) { - StructuredGraph newGraph = makeGraph(method, null, inliningPolicy(method), method.getAnnotation(Snippet.class).removeAllFrameStates()); + StructuredGraph newGraph = makeGraph(method, recursiveEntry, recursiveEntry, inliningPolicy(method), method.getAnnotation(Snippet.class).removeAllFrameStates(), false); Debug.metric("SnippetNodeCount[" + method.getName() + "]").add(newGraph.getNodeCount()); if (!UseSnippetGraphCache) { return newGraph; @@ -127,7 +131,7 @@ } StructuredGraph graph = graphs.get(substitute); if (graph == null) { - graphs.putIfAbsent(substitute, makeGraph(substitute, original, inliningPolicy(substitute), false)); + graphs.putIfAbsent(substitute, makeGraph(substitute, original, substitute, inliningPolicy(substitute), false, true)); graph = graphs.get(substitute); } return graph; @@ -259,15 +263,16 @@ * @param policy the inlining policy to use during preprocessing * @param removeAllFrameStates removes all frame states from side effecting instructions */ - public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, SnippetInliningPolicy policy, boolean removeAllFrameStates) { - return createGraphMaker(method, original).makeGraph(policy, removeAllFrameStates); + public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, ResolvedJavaMethod recursiveEntry, SnippetInliningPolicy policy, boolean removeAllFrameStates, + boolean isMethodSubstitution) { + return createGraphMaker(method, original, recursiveEntry, isMethodSubstitution).makeGraph(policy, removeAllFrameStates); } /** * Can be overridden to return an object that specializes various parts of graph preprocessing. */ - protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original) { - return new GraphMaker(substitute, original); + protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original, ResolvedJavaMethod recursiveEntry, boolean isMethodSubstitution) { + return new GraphMaker(substitute, original, recursiveEntry, isMethodSubstitution); } /** @@ -279,23 +284,32 @@ * Creates and preprocesses a graph for a replacement. */ protected class GraphMaker { - /** * The method for which a graph is being created. */ protected final ResolvedJavaMethod method; /** - * The original method if {@link #method} is a {@linkplain MethodSubstitution substitution} - * otherwise null. + * The method which is used when a call to {@link #recursiveEntry} is found. */ - protected final ResolvedJavaMethod original; + protected final ResolvedJavaMethod substitutedMethod; + + /** + * The method which is used to detect a recursive call. + */ + protected final ResolvedJavaMethod recursiveEntry; - boolean substituteCallsOriginal; + /** + * Controls if FrameStates should be removed or processed with the + * {@link SnippetFrameStateCleanupPhase}. + */ + protected final boolean isMethodSubstitution; - protected GraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original) { + protected GraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, ResolvedJavaMethod recursiveEntry, boolean isMethodSubstitution) { this.method = substitute; - this.original = original; + this.substitutedMethod = substitutedMethod; + this.recursiveEntry = recursiveEntry; + this.isMethodSubstitution = isMethodSubstitution; } public StructuredGraph makeGraph(final SnippetInliningPolicy policy, final boolean removeAllFrameStates) { @@ -325,7 +339,7 @@ } new ConvertDeoptimizeToGuardPhase().apply(graph); - if (original == null) { + if (!isMethodSubstitution) { if (removeAllFrameStates) { for (Node node : graph.getNodes()) { if (node instanceof StateSplit) { @@ -405,38 +419,44 @@ } private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) { - assert !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers()) : methodToParse; + assert isInlinableSnippet(methodToParse) : methodToParse; final StructuredGraph graph = buildInitialGraph(methodToParse); try (Scope s = Debug.scope("buildGraph", graph)) { for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { ResolvedJavaMethod callee = callTarget.targetMethod(); - if (callee == method) { - final StructuredGraph originalGraph = buildInitialGraph(original); - InliningUtil.inline(callTarget.invoke(), originalGraph, true); + if (callee == recursiveEntry) { + if (isInlinableSnippet(substitutedMethod)) { + final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod); + InliningUtil.inline(callTarget.invoke(), originalGraph, true); - Debug.dump(graph, "after inlining %s", callee); - afterInline(graph, originalGraph, null); - substituteCallsOriginal = true; + Debug.dump(graph, "after inlining %s", callee); + afterInline(graph, originalGraph, null); + } } else { - StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); - if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && - (policy.shouldInline(callee, methodToParse) || (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)))) { - StructuredGraph targetGraph; - if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) { - targetGraph = intrinsicGraph; - } else { - if (callee.getName().startsWith("$jacoco")) { - throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + format("%H.%n(%p)", callee) + " from " + format("%H.%n(%p)", methodToParse) + - " while preparing replacement " + format("%H.%n(%p)", method) + ". Placing \"//JaCoCo Exclude\" anywhere in " + - methodToParse.getDeclaringClass().getSourceFileName() + " should fix this."); + Class macroNodeClass = InliningUtil.getMacroNodeClass(ReplacementsImpl.this, callee); + if (macroNodeClass != null) { + InliningUtil.inlineMacroNode(callTarget.invoke(), callee, macroNodeClass); + } else { + StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); + if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && + (policy.shouldInline(callee, methodToParse) || (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)))) { + StructuredGraph targetGraph; + if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) { + targetGraph = intrinsicGraph; + } else { + if (callee.getName().startsWith("$jacoco")) { + throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + format("%H.%n(%p)", callee) + " from " + format("%H.%n(%p)", methodToParse) + + " while preparing replacement " + format("%H.%n(%p)", method) + ". Placing \"//JaCoCo Exclude\" anywhere in " + + methodToParse.getDeclaringClass().getSourceFileName() + " should fix this."); + } + targetGraph = parseGraph(callee, policy); } - targetGraph = parseGraph(callee, policy); + Object beforeInlineData = beforeInline(callTarget, targetGraph); + InliningUtil.inline(callTarget.invoke(), targetGraph, true); + Debug.dump(graph, "after inlining %s", callee); + afterInline(graph, targetGraph, beforeInlineData); } - Object beforeInlineData = beforeInline(callTarget, targetGraph); - InliningUtil.inline(callTarget.invoke(), targetGraph, true); - Debug.dump(graph, "after inlining %s", callee); - afterInline(graph, targetGraph, beforeInlineData); } } } @@ -455,6 +475,10 @@ } } + private static boolean isInlinableSnippet(final ResolvedJavaMethod methodToParse) { + return !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers()); + } + private static String originalName(Method substituteMethod, String methodSubstitution) { if (methodSubstitution.isEmpty()) { return substituteMethod.getName(); diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Jan 13 13:45:25 2014 +0100 @@ -38,6 +38,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.replacements.*; public class MacroNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { @@ -86,6 +87,13 @@ protected StructuredGraph getLoweredSubstitutionGraph(LoweringTool tool) { StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod()); if (methodSubstitution != null) { + if (stateAfter() == null) { + /* + * handles the case of a MacroNode inside a snippet used for another MacroNode + * lowering + */ + new SnippetFrameStateCleanupPhase().apply(methodSubstitution); + } return lowerReplacement(methodSubstitution.copy(), tool); } return null; diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Jan 13 13:45:25 2014 +0100 @@ -194,7 +194,7 @@ Replacements replacements = providers.getReplacements(); Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); changed = true; continue; } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jan 13 13:45:25 2014 +0100 @@ -135,7 +135,7 @@ MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); } else { tryCutOffRuntimeExceptions(methodCallTargetNode); } diff -r 0774f3303c2e -r f4c776ad613e graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Jan 13 13:20:30 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Jan 13 13:45:25 2014 +0100 @@ -49,7 +49,7 @@ if (invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special) { Class macroSubstitution = replacements.getMacroSubstitution(methodCallTarget.targetMethod()); if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTarget.invoke(), methodCallTarget.targetMethod(), graph, macroSubstitution); + InliningUtil.inlineMacroNode(methodCallTarget.invoke(), methodCallTarget.targetMethod(), macroSubstitution); Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); } else { StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod());