# HG changeset patch # User Bernhard Urban # Date 1379744359 -7200 # Node ID a27fcd6707250de541de3d858edd81f401d370b7 # Parent db8cf3957e5bc22386b995e90eddf39436726d72 SnippetTemplate: use FloatingReadPhase to store MemoryMap at ReturnNodes in order to connect the snippet graph properly when inlining it diff -r db8cf3957e5b -r a27fcd670725 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 Thu Sep 19 21:53:20 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Sep 21 08:19:19 2013 +0200 @@ -206,7 +206,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); @@ -238,7 +238,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); diff -r db8cf3957e5b -r a27fcd670725 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Sep 19 21:53:20 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Sep 21 08:19:19 2013 +0200 @@ -34,7 +34,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.StructuredGraph.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -532,13 +532,16 @@ } new DeadCodeEliminationPhase().apply(snippetCopy); + new CanonicalizerPhase(true).apply(snippetCopy, context); assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders); + new FloatingReadPhase(false).apply(snippetCopy); + this.memoryMap = null; + this.snippet = snippetCopy; ReturnNode retNode = null; StartNode entryPointNode = snippet.start(); - nodes = new ArrayList<>(snippet.getNodeCount()); for (Node node : snippet.getNodes()) { if (node == entryPointNode || node == entryPointNode.stateAfter()) { @@ -547,9 +550,15 @@ nodes.add(node); if (node instanceof ReturnNode) { retNode = (ReturnNode) node; + for (MemoryState memstate : retNode.usages().filter(MemoryState.class).snapshot()) { + this.memoryMap = memstate.getMemoryMap(); + memstate.safeDelete(); + } + assert snippet.getNodes().filter(ReturnNode.class).count() == 1; } } } + assert !containsMemoryState(snippet); this.sideEffectNodes = curSideEffectNodes; this.deoptNodes = curDeoptNodes; @@ -560,6 +569,10 @@ this.instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]"); } + private static boolean containsMemoryState(StructuredGraph snippet) { + return snippet.getNodes().filter(MemoryState.class).count() > 0; + } + private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) { for (int i = 0; i < parameterCount; i++) { if (placeholders[i] != null) { @@ -633,6 +646,11 @@ private final ArrayList nodes; /** + * mapping of killing locations to memory checkpoints (nodes). + */ + private MemoryMap memoryMap; + + /** * Gets the instantiation-time bindings to this template's parameters. * * @return the map that will be used to bind arguments to parameters when inlining this template @@ -724,7 +742,7 @@ /** * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}. */ - void replace(ValueNode oldNode, ValueNode newNode); + void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap); } /** @@ -734,11 +752,51 @@ public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() { @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { oldNode.replaceAtUsages(newNode); + if (mmap == null || newNode == null) { + return; + } + for (Node usage : newNode.usages().snapshot()) { + if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).lastLocationAccess() == newNode) { + // TODO: add graph state for FloatingReadPhase + assert newNode.graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal(); + + // lastLocationAccess points into the snippet graph. find a proper + // MemoryCheckPoint inside the snippet graph + FloatingReadNode frn = (FloatingReadNode) usage; + Node newlla = mmap.getLastLocationAccess(frn.location().getLocationIdentity()); + + assert newlla != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)"; + frn.setLastLocationAccess(newlla); + } + } } }; + private class DuplicateMapper implements MemoryMap { + + Map duplicates; + StartNode replaceeStart; + + public DuplicateMapper(Map duplicates, StartNode replaceeStart) { + this.duplicates = duplicates; + this.replaceeStart = replaceeStart; + } + + @Override + public Node getLastLocationAccess(LocationIdentity locationIdentity) { + assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)"; + Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity); + assert lastLocationAccess != null; + if (lastLocationAccess instanceof StartNode) { + return replaceeStart; + } else { + return duplicates.get(lastLocationAccess); + } + } + } + /** * Replaces a given fixed node with this specialized snippet. * @@ -756,6 +814,7 @@ FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph(); IdentityHashMap replacements = bind(replaceeGraph, runtime, args); + replacements.put(entryPointNode, replaceeGraph.start()); Map duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); Debug.dump(replaceeGraph, "After inlining snippet %s", snippet.method()); @@ -801,12 +860,12 @@ returnValue = (ValueNode) duplicates.get(returnNode.result()); } Node returnDuplicate = duplicates.get(returnNode); + MemoryMap mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) { - replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor()); + replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap); } else { assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages(); - replacer.replace(replacee, returnValue); - + replacer.replace(replacee, returnValue, mmap); } if (returnDuplicate.isAlive()) { returnDuplicate.clearInputs(); @@ -850,6 +909,7 @@ FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph(); IdentityHashMap replacements = bind(replaceeGraph, runtime, args); + replacements.put(entryPointNode, replaceeGraph.start()); Map duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); @@ -881,7 +941,7 @@ returnValue = (ValueNode) duplicates.get(returnNode.result()); } assert returnValue != null || replacee.usages().isEmpty(); - replacer.replace(replacee, returnValue); + replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start())); Node returnDuplicate = duplicates.get(returnNode); if (returnDuplicate.isAlive()) {