# HG changeset patch # User Christian Wimmer # Date 1428736589 25200 # Node ID c7f1ab98d95021e811efcfe6293e1d52156ad08d # Parent 23433619a7cde8a936f5640bfeb2e2a90fd734be Improve speed of Graph partial evaluation diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EncodedGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EncodedGraph.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EncodedGraph.java Sat Apr 11 00:16:29 2015 -0700 @@ -41,6 +41,12 @@ private final Assumptions assumptions; private final Set inlinedMethods; + /** + * The "table of contents" of the encoded graph, i.e., the mapping from orderId numbers to the + * offset in the encoded byte[] array. Used as a cache during decoding. + */ + protected long[] nodeStartOffsets; + public EncodedGraph(byte[] encoding, long startOffset, Object[] objects, NodeClass[] types, Assumptions assumptions, Set inlinedMethods) { this.encoding = encoding; this.startOffset = startOffset; diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Sat Apr 11 00:16:29 2015 -0700 @@ -227,11 +227,11 @@ * the stack. */ public FrameState duplicateModifiedDuringCall(int newBci, Kind popKind) { - return duplicateModified(newBci, rethrowException, true, popKind); + return duplicateModified(graph(), newBci, rethrowException, true, popKind); } public FrameState duplicateModifiedBeforeCall(int newBci, Kind popKind, ValueNode... pushedValues) { - return duplicateModified(newBci, rethrowException, false, popKind, pushedValues); + return duplicateModified(graph(), newBci, rethrowException, false, popKind, pushedValues); } /** @@ -241,7 +241,7 @@ * followed by a null slot. */ public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) { - return duplicateModified(newBci, newRethrowException, duringCall, popKind, pushedValues); + return duplicateModified(graph(), newBci, newRethrowException, duringCall, popKind, pushedValues); } /** @@ -250,7 +250,7 @@ */ public FrameState duplicateModified(Kind popKind, ValueNode pushedValue) { assert pushedValue != null && pushedValue.getKind() == popKind; - return duplicateModified(bci, rethrowException, duringCall, popKind, pushedValue); + return duplicateModified(graph(), bci, rethrowException, duringCall, popKind, pushedValue); } /** @@ -259,7 +259,7 @@ * correctly in slot encoding: a long or double will be followed by a null slot. The bci will be * changed to newBci. */ - private FrameState duplicateModified(int newBci, boolean newRethrowException, boolean newDuringCall, Kind popKind, ValueNode... pushedValues) { + public FrameState duplicateModified(StructuredGraph graph, int newBci, boolean newRethrowException, boolean newDuringCall, Kind popKind, ValueNode... pushedValues) { ArrayList copy; if (newRethrowException && !rethrowException && popKind == Kind.Void) { assert popKind == Kind.Void; @@ -285,7 +285,7 @@ copy.addAll(values.subList(localsSize + stackSize, values.size())); assert checkStackDepth(bci, stackSize, duringCall, rethrowException, newBci, newStackSize, newDuringCall, newRethrowException); - return graph().add(new FrameState(outerFrameState(), method, newBci, copy, localsSize, newStackSize, newRethrowException, newDuringCall, monitorIds, virtualObjectMappings)); + return graph.add(new FrameState(outerFrameState(), method, newBci, copy, localsSize, newStackSize, newRethrowException, newDuringCall, monitorIds, virtualObjectMappings)); } /** diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Sat Apr 11 00:16:29 2015 -0700 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.util.*; import com.oracle.graal.debug.*; @@ -70,48 +71,38 @@ protected static class MethodScope { /** The target graph where decoded nodes are added to. */ public final StructuredGraph graph; - /** The state of the caller method. Only non-null during method inlining. */ - public final MethodScope caller; /** The encode graph that is decoded. */ public final EncodedGraph encodedGraph; /** Access to the encoded graph. */ public final TypeReader reader; - /** - * The "table of contents" of the encoded graph, i.e., the mapping from orderId numbers to - * the offset in the encoded byte[] array. - */ - public final long[] nodeStartOffsets; /** The kind of loop explosion to be performed during decoding. */ public final LoopExplosionKind loopExplosion; - /** - * The start node of the decoded graph. This is a temporary node for inlined graphs that - * needs to be deleted after inlining. - */ - public StartNode startNode; /** All return nodes encountered during decoding. */ public final List returnNodes; /** The exception unwind node encountered during decoding, or null. */ public UnwindNode unwindNode; - protected MethodScope(StructuredGraph graph, MethodScope caller, EncodedGraph encodedGraph, LoopExplosionKind loopExplosion) { + protected MethodScope(StructuredGraph graph, EncodedGraph encodedGraph, LoopExplosionKind loopExplosion) { this.graph = graph; - this.caller = caller; this.encodedGraph = encodedGraph; this.loopExplosion = loopExplosion; this.returnNodes = new ArrayList<>(); - reader = new UnsafeArrayTypeReader(encodedGraph.getEncoding(), encodedGraph.getStartOffset()); - int nodeCount = reader.getUVInt(); - nodeStartOffsets = new long[nodeCount]; - for (int i = 0; i < nodeCount; i++) { - nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUV(); + if (encodedGraph != null) { + reader = new UnsafeArrayTypeReader(encodedGraph.getEncoding(), encodedGraph.getStartOffset()); + if (encodedGraph.nodeStartOffsets == null) { + int nodeCount = reader.getUVInt(); + long[] nodeStartOffsets = new long[nodeCount]; + for (int i = 0; i < nodeCount; i++) { + nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUV(); + } + encodedGraph.nodeStartOffsets = nodeStartOffsets; + } + } else { + reader = null; } } - - public boolean isInlinedMethod() { - return caller != null; - } } /** Decoding state maintained for each loop in the encoded graph. */ @@ -153,7 +144,7 @@ this.iterationStates = null; this.loopBeginOrderId = -1; - int nodeCount = methodScope.nodeStartOffsets.length; + int nodeCount = methodScope.encodedGraph.nodeStartOffsets.length; this.nodesToProcess = new BitSet(nodeCount); this.initialCreatedNodes = new Node[nodeCount]; this.createdNodes = new Node[nodeCount]; @@ -226,22 +217,55 @@ } } + /** + * Additional information encoded for {@link Invoke} nodes to allow method inlining without + * decoding the frame state and successors beforehand. + */ + protected static class InvokeData { + public final Invoke invoke; + public final ResolvedJavaType contextType; + public final int invokeOrderId; + public final int callTargetOrderId; + public final int stateAfterOrderId; + public final int nextOrderId; + + public final int nextNextOrderId; + public final int exceptionOrderId; + public final int exceptionStateOrderId; + public final int exceptionNextOrderId; + + protected InvokeData(Invoke invoke, ResolvedJavaType contextType, int invokeOrderId, int callTargetOrderId, int stateAfterOrderId, int nextOrderId, int nextNextOrderId, int exceptionOrderId, + int exceptionStateOrderId, int exceptionNextOrderId) { + this.invoke = invoke; + this.contextType = contextType; + this.invokeOrderId = invokeOrderId; + this.callTargetOrderId = callTargetOrderId; + this.stateAfterOrderId = stateAfterOrderId; + this.nextOrderId = nextOrderId; + this.nextNextOrderId = nextNextOrderId; + this.exceptionOrderId = exceptionOrderId; + this.exceptionStateOrderId = exceptionStateOrderId; + this.exceptionNextOrderId = exceptionNextOrderId; + } + } + public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) { - MethodScope methodScope = new MethodScope(graph, null, encodedGraph, LoopExplosionKind.NONE); - decode(methodScope); + MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE); + decode(methodScope, null); cleanupGraph(methodScope); methodScope.graph.verify(); } - protected final void decode(MethodScope methodScope) { + protected final void decode(MethodScope methodScope, FixedWithNextNode startNode) { LoopScope loopScope = new LoopScope(methodScope); - if (methodScope.isInlinedMethod()) { - methodScope.startNode = methodScope.graph.add(new StartNode()); - methodScope.startNode.setNext(makeStubNode(methodScope, loopScope, GraphEncoder.FIRST_NODE_ORDER_ID)); + FixedNode firstNode; + if (startNode != null) { + firstNode = makeStubNode(methodScope, loopScope, GraphEncoder.FIRST_NODE_ORDER_ID); + startNode.setNext(firstNode); loopScope.nodesToProcess.set(GraphEncoder.FIRST_NODE_ORDER_ID); } else { - methodScope.startNode = methodScope.graph.start(); - registerNode(loopScope, GraphEncoder.START_NODE_ORDER_ID, methodScope.startNode, false, false); + firstNode = methodScope.graph.start(); + registerNode(loopScope, GraphEncoder.START_NODE_ORDER_ID, firstNode, false, false); loopScope.nodesToProcess.set(GraphEncoder.START_NODE_ORDER_ID); } @@ -262,7 +286,7 @@ if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { cleanupGraph(methodScope); Debug.dump(methodScope.graph, "Before loop detection"); - detectLoops(methodScope.graph, methodScope.startNode); + detectLoops(methodScope.graph, firstNode); } } @@ -275,6 +299,18 @@ return loopScope; } + if ((node instanceof MergeNode || (node instanceof LoopBeginNode && (methodScope.loopExplosion == LoopExplosionKind.FULL_UNROLL || methodScope.loopExplosion == LoopExplosionKind.FULL_EXPLODE))) && + ((AbstractMergeNode) node).forwardEndCount() == 1) { + AbstractMergeNode merge = (AbstractMergeNode) node; + EndNode singleEnd = merge.forwardEndAt(0); + FixedNode next = makeStubNode(methodScope, loopScope, nodeOrderId + GraphEncoder.BEGIN_NEXT_ORDER_ID_OFFSET); + singleEnd.replaceAtPredecessor(next); + + merge.safeDelete(); + singleEnd.safeDelete(); + return loopScope; + } + LoopScope successorAddScope = loopScope; boolean updatePredecessors = true; if (node instanceof LoopExitNode) { @@ -282,7 +318,7 @@ updatePredecessors = methodScope.loopExplosion == LoopExplosionKind.NONE; } - methodScope.reader.setByteIndex(methodScope.nodeStartOffsets[nodeOrderId]); + methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); int typeId = methodScope.reader.getUVInt(); assert node.getNodeClass() == methodScope.encodedGraph.getNodeClasses()[typeId]; readProperties(methodScope, node); @@ -299,7 +335,7 @@ if (methodScope.loopExplosion != LoopExplosionKind.NONE) { handleLoopExplosionProxyNodes(methodScope, loopScope, (LoopExitNode) node, nodeOrderId); } else { - handleProxyNodes(methodScope, loopScope); + handleProxyNodes(methodScope, loopScope, (LoopExitNode) node); } } else if (node instanceof AbstractEndNode) { @@ -311,7 +347,7 @@ phiNodeScope = loopScope.nextIterations.getLast(); } - int mergeOrderId = methodScope.reader.getUVInt(); + int mergeOrderId = readOrderId(methodScope); AbstractMergeNode merge = (AbstractMergeNode) lookupNode(phiNodeScope, mergeOrderId); if (merge == null) { merge = (AbstractMergeNode) makeStubNode(methodScope, phiNodeScope, mergeOrderId); @@ -332,7 +368,8 @@ handlePhiFunctions(methodScope, phiInputScope, phiNodeScope, (AbstractEndNode) node, merge); } else if (node instanceof Invoke) { - simplifyInvoke(methodScope, loopScope, nodeOrderId, (Invoke) node); + InvokeData invokeData = readInvokeData(methodScope, nodeOrderId, (Invoke) node); + handleInvoke(methodScope, loopScope, invokeData); } else if (node instanceof ReturnNode) { methodScope.returnNodes.add((ReturnNode) node); @@ -347,15 +384,45 @@ return resultScope; } + private InvokeData readInvokeData(MethodScope methodScope, int invokeOrderId, Invoke invoke) { + ResolvedJavaType contextType = (ResolvedJavaType) readObject(methodScope); + int callTargetOrderId = readOrderId(methodScope); + int stateAfterOrderId = readOrderId(methodScope); + int nextOrderId = readOrderId(methodScope); + + if (invoke instanceof InvokeWithExceptionNode) { + int nextNextOrderId = readOrderId(methodScope); + int exceptionOrderId = readOrderId(methodScope); + int exceptionStateOrderId = readOrderId(methodScope); + int exceptionNextOrderId = readOrderId(methodScope); + return new InvokeData(invoke, contextType, invokeOrderId, callTargetOrderId, stateAfterOrderId, nextOrderId, nextNextOrderId, exceptionOrderId, exceptionStateOrderId, exceptionNextOrderId); + } else { + return new InvokeData(invoke, contextType, invokeOrderId, callTargetOrderId, stateAfterOrderId, nextOrderId, -1, -1, -1, -1); + } + } + /** - * Hook for subclasses. - * - * @param methodScope The current method. - * @param loopScope The current loop. - * @param invokeOrderId The orderId of the method invocation node. - * @param invoke The invocation node. + * {@link Invoke} nodes do not have the {@link CallTargetNode}, {@link FrameState}, and + * successors encoded. Instead, this information is provided separately to allow method inlining + * without decoding and adding them to the graph upfront. For non-inlined methods, this method + * restores the normal state. Subclasses can override it to perform method inlining. */ - protected void simplifyInvoke(MethodScope methodScope, LoopScope loopScope, int invokeOrderId, Invoke invoke) { + protected void handleInvoke(MethodScope methodScope, LoopScope loopScope, InvokeData invokeData) { + assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke"; + CallTargetNode callTarget = (CallTargetNode) ensureNodeCreated(methodScope, loopScope, invokeData.callTargetOrderId); + if (invokeData.invoke instanceof InvokeWithExceptionNode) { + ((InvokeWithExceptionNode) invokeData.invoke).setCallTarget(callTarget); + } else { + ((InvokeNode) invokeData.invoke).setCallTarget(callTarget); + } + + assert invokeData.invoke.stateAfter() == null && invokeData.invoke.stateDuring() == null : "FrameState edges are ignored during decoding of Invoke"; + invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId)); + + invokeData.invoke.setNext(makeStubNode(methodScope, loopScope, invokeData.nextOrderId)); + if (invokeData.invoke instanceof InvokeWithExceptionNode) { + ((InvokeWithExceptionNode) invokeData.invoke).setExceptionEdge((AbstractBeginNode) makeStubNode(methodScope, loopScope, invokeData.exceptionOrderId)); + } } protected void handleLoopExplosionBegin(MethodScope methodScope, LoopScope loopScope, LoopBeginNode loopBegin) { @@ -432,10 +499,14 @@ protected void simplifyFixedNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) { } - protected void handleProxyNodes(MethodScope methodScope, LoopScope loopScope) { + protected void handleProxyNodes(MethodScope methodScope, LoopScope loopScope, LoopExitNode loopExit) { + assert loopExit.stateAfter() == null; + int stateAfterOrderId = readOrderId(methodScope); + loopExit.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, stateAfterOrderId)); + int numProxies = methodScope.reader.getUVInt(); for (int i = 0; i < numProxies; i++) { - int proxyOrderId = methodScope.reader.getUVInt(); + int proxyOrderId = readOrderId(methodScope); ProxyNode proxy = (ProxyNode) ensureNodeCreated(methodScope, loopScope, proxyOrderId); /* * The ProxyNode transports a value from the loop to the outer scope. We therefore @@ -446,9 +517,11 @@ } protected void handleLoopExplosionProxyNodes(MethodScope methodScope, LoopScope loopScope, LoopExitNode loopExit, int loopExitOrderId) { + assert loopExit.stateAfter() == null; + int stateAfterOrderId = readOrderId(methodScope); + BeginNode begin = methodScope.graph.add(new BeginNode()); - FrameState loopExitState = loopExit.stateAfter(); FixedNode loopExitSuccessor = loopExit.next(); loopExit.replaceAtPredecessor(begin); @@ -457,33 +530,43 @@ * iterations now take the same loop exit, so we have to introduce a new merge node to * handle the merge. */ - MergeNode merge; - if (lookupNode(loopScope.outer, loopExitOrderId) == null) { + MergeNode merge = null; + Node existingExit = lookupNode(loopScope.outer, loopExitOrderId); + if (existingExit == null) { + /* First loop iteration that exits. No merge necessary yet. */ + registerNode(loopScope.outer, loopExitOrderId, begin, false, false); + begin.setNext(loopExitSuccessor); + + } else if (existingExit instanceof BeginNode) { + /* Second loop iteration that exits. Create the merge. */ merge = methodScope.graph.add(new MergeNode()); - registerNode(loopScope.outer, loopExitOrderId, merge, false, false); + registerNode(loopScope.outer, loopExitOrderId, merge, true, false); + /* Add the first iteration. */ + EndNode firstEnd = methodScope.graph.add(new EndNode()); + ((BeginNode) existingExit).setNext(firstEnd); + merge.addForwardEnd(firstEnd); merge.setNext(loopExitSuccessor); + } else { - merge = (MergeNode) loopScope.outer.createdNodes[loopExitOrderId]; + /* Subsequent loop iteration. Merge already created. */ + merge = (MergeNode) existingExit; } - FrameState oldStateAfter = merge.stateAfter(); - merge.setStateAfter(loopExitState); - if (oldStateAfter != null) { - oldStateAfter.safeDelete(); + if (merge != null) { + EndNode end = methodScope.graph.add(new EndNode()); + begin.setNext(end); + merge.addForwardEnd(end); } - EndNode end = methodScope.graph.add(new EndNode()); - begin.setNext(end); - merge.addForwardEnd(end); - /* * Possibly create phi nodes for the original proxy nodes that flow out of the loop. Note * that we definitely do not need a proxy node itself anymore, since the loop was exploded * and is no longer present. */ int numProxies = methodScope.reader.getUVInt(); + boolean phiCreated = false; for (int i = 0; i < numProxies; i++) { - int proxyOrderId = methodScope.reader.getUVInt(); + int proxyOrderId = readOrderId(methodScope); ProxyNode proxy = (ProxyNode) ensureNodeCreated(methodScope, loopScope, proxyOrderId); ValueNode phiInput = proxy.value(); ValueNode replacement; @@ -508,6 +591,7 @@ phi.addInput(phiInput); registerNode(loopScope.outer, proxyOrderId, phi, true, false); replacement = phi; + phiCreated = true; } else { /* Phi node has been created before, so just add the new input. */ @@ -519,9 +603,22 @@ methodScope.graph.replaceFloating(proxy, replacement); } + if (merge != null && (merge.stateAfter() == null || phiCreated)) { + FrameState oldStateAfter = merge.stateAfter(); + registerNode(loopScope.outer, stateAfterOrderId, null, true, true); + merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope.outer, stateAfterOrderId)); + if (oldStateAfter != null) { + oldStateAfter.safeDelete(); + } + } + loopExit.safeDelete(); assert loopExitSuccessor.predecessor() == null; - merge.getNodeClass().getSuccessorEdges().update(merge, null, loopExitSuccessor); + if (merge != null) { + merge.getNodeClass().getSuccessorEdges().update(merge, null, loopExitSuccessor); + } else { + begin.getNodeClass().getSuccessorEdges().update(begin, null, loopExitSuccessor); + } } protected void handlePhiFunctions(MethodScope methodScope, LoopScope phiInputScope, LoopScope phiNodeScope, AbstractEndNode end, AbstractMergeNode merge) { @@ -555,8 +652,8 @@ boolean lazyPhi = !(merge instanceof LoopBeginNode) || methodScope.loopExplosion != LoopExplosionKind.NONE; int numPhis = methodScope.reader.getUVInt(); for (int i = 0; i < numPhis; i++) { - int phiInputOrderId = methodScope.reader.getUVInt(); - int phiNodeOrderId = methodScope.reader.getUVInt(); + int phiInputOrderId = readOrderId(methodScope); + int phiNodeOrderId = readOrderId(methodScope); ValueNode phiInput = (ValueNode) ensureNodeCreated(methodScope, phiInputScope, phiInputOrderId); @@ -588,7 +685,7 @@ } protected Node instantiateNode(MethodScope methodScope, int nodeOrderId) { - methodScope.reader.setByteIndex(methodScope.nodeStartOffsets[nodeOrderId]); + methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); NodeClass nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()]; return nodeClass.allocateInstance(); } @@ -600,8 +697,7 @@ long primitive = methodScope.reader.getSV(); fields.setRawPrimitive(node, pos, primitive); } else { - int objectId = methodScope.reader.getUVInt(); - Object value = methodScope.encodedGraph.getObjects()[objectId]; + Object value = readObject(methodScope); fields.set(node, pos, value); } } @@ -619,7 +715,7 @@ if (skipEdge(node, edges, index, true, true)) { continue; } - int orderId = methodScope.reader.getUVInt(); + int orderId = readOrderId(methodScope); Node value = ensureNodeCreated(methodScope, loopScope, orderId); Edges.initializeNode(node, edges.getOffsets(), index, value); if (updateUsages && value != null && !value.isDeleted()) { @@ -636,7 +732,7 @@ NodeList nodeList = new NodeInputList<>(node, size); Edges.initializeList(node, edges.getOffsets(), index, nodeList); for (int idx = 0; idx < size; idx++) { - int orderId = methodScope.reader.getUVInt(); + int orderId = readOrderId(methodScope); Node value = ensureNodeCreated(methodScope, loopScope, orderId); nodeList.initialize(idx, value); if (updateUsages && value != null && !value.isDeleted()) { @@ -656,17 +752,7 @@ return node; } - long readerByteIndex = methodScope.reader.getByteIndex(); - node = instantiateNode(methodScope, nodeOrderId); - assert !(node instanceof FixedNode); - - /* Read the properties of the node. */ - readProperties(methodScope, node); - /* There must not be any successors to read, since it is a non-fixed node. */ - assert node.getNodeClass().getEdges(Edges.Type.Successors).getCount() == 0; - /* Read the inputs of the node, possibly creating them recursively. */ - makeInputNodes(methodScope, loopScope, node, false); - methodScope.reader.setByteIndex(readerByteIndex); + node = decodeFloatingNode(methodScope, loopScope, nodeOrderId); if (node instanceof ProxyNode || node instanceof PhiNode) { /* @@ -688,6 +774,24 @@ } /** + * Decodes a non-fixed node, but does not do any post-processing and does not register it. + */ + protected Node decodeFloatingNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId) { + long readerByteIndex = methodScope.reader.getByteIndex(); + Node node = instantiateNode(methodScope, nodeOrderId); + assert !(node instanceof FixedNode); + + /* Read the properties of the node. */ + readProperties(methodScope, node); + /* There must not be any successors to read, since it is a non-fixed node. */ + assert node.getNodeClass().getEdges(Edges.Type.Successors).getCount() == 0; + /* Read the inputs of the node, possibly creating them recursively. */ + makeInputNodes(methodScope, loopScope, node, false); + methodScope.reader.setByteIndex(readerByteIndex); + return node; + } + + /** * Hook for subclasses to process a non-fixed node before it is added to the graph. * * @param methodScope The current method. @@ -722,7 +826,7 @@ if (skipEdge(node, edges, index, true, true)) { continue; } - int orderId = methodScope.reader.getUVInt(); + int orderId = readOrderId(methodScope); Node value = makeStubNode(methodScope, loopScope, orderId); Edges.initializeNode(node, edges.getOffsets(), index, value); if (updatePredecessors && value != null) { @@ -738,7 +842,7 @@ NodeList nodeList = new NodeSuccessorList<>(node, size); Edges.initializeList(node, edges.getOffsets(), index, nodeList); for (int idx = 0; idx < size; idx++) { - int orderId = methodScope.reader.getUVInt(); + int orderId = readOrderId(methodScope); Node value = makeStubNode(methodScope, loopScope, orderId); nodeList.initialize(idx, value); if (updatePredecessors && value != null) { @@ -792,6 +896,26 @@ assert index == edges.getCount() - 1 : "MergeNode has one variable size input (the ends)"; assert Edges.getNodeList(node, edges.getOffsets(), index) != null : "Input list must have been already created"; return true; + + } else if (node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class) { + /* The stateAfter of the loop exit is filled manually. */ + return true; + + } else if (node instanceof Invoke) { + assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes"; + assert direct : "Invoke and InvokeWithException only have direct successor and input edges"; + if (edges.type() == Edges.Type.Successors) { + assert edges.getCount() == (node instanceof InvokeWithExceptionNode ? 2 : 1) : "InvokeNode has one successor (next); InvokeWithExceptionNode has two successors (next, exceptionEdge)"; + return true; + } else { + assert edges.type() == Edges.Type.Inputs; + if (edges.getType(index) == CallTargetNode.class) { + return true; + } else if (edges.getType(index) == FrameState.class) { + assert edges.get(node, index) == null || edges.get(node, index) == ((Invoke) node).stateAfter() : "Only stateAfter can be a FrameState during encoding"; + return true; + } + } } return false; } @@ -807,6 +931,14 @@ loopScope.createdNodes[nodeOrderId] = node; } + protected int readOrderId(MethodScope methodScope) { + return methodScope.reader.getUVInt(); + } + + protected Object readObject(MethodScope methodScope) { + return methodScope.encodedGraph.getObjects()[methodScope.reader.getUVInt()]; + } + /* * The following methods are a literal copy from GraphBuilderPhase. */ diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java Sat Apr 11 00:16:29 2015 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.java.*; /** * Encodes a {@link StructuredGraph} to a compact byte[] array. All nodes of the graph and edges @@ -100,6 +101,12 @@ public static final int FIRST_NODE_ORDER_ID = 2; /** + * The known offset between the orderId of a {@link AbstractBeginNode} and its + * {@link AbstractBeginNode#next() successor}. + */ + protected static final int BEGIN_NEXT_ORDER_ID_OFFSET = 1; + + /** * Collects all non-primitive data referenced from nodes. The encoding uses an index into an * array for decoding. Because of the variable-length encoding, it is beneficial that frequently * used objects have the small indices. @@ -148,6 +155,9 @@ objects.addObject(nodeClass.getData().get(node, i)); } } + if (node instanceof Invoke) { + objects.addObject(((Invoke) node).getContextType()); + } } } @@ -182,7 +192,10 @@ long[] nodeStartOffsets = new long[nodeCount]; for (Map.Entry entry : nodeOrder.orderIds.entries()) { Node node = entry.getKey(); - nodeStartOffsets[entry.getValue()] = writer.getBytesWritten(); + Integer orderId = entry.getValue(); + + assert !(node instanceof AbstractBeginNode) || nodeOrder.orderIds.get(((AbstractBeginNode) node).next()) == orderId + BEGIN_NEXT_ORDER_ID_OFFSET; + nodeStartOffsets[orderId] = writer.getBytesWritten(); /* Write out the type, properties, and edges. */ NodeClass nodeClass = node.getNodeClass(); @@ -213,11 +226,30 @@ } else if (node instanceof LoopExitNode) { LoopExitNode exit = (LoopExitNode) node; + writeOrderId(exit.stateAfter(), nodeOrder); /* Write all proxy nodes of the LoopExitNode. */ writer.putUV(exit.proxies().count()); for (ProxyNode proxy : exit.proxies()) { writeOrderId(proxy, nodeOrder); } + + } else if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + assert invoke.stateDuring() == null : "stateDuring is not used in high-level graphs"; + + writeObjectId(invoke.getContextType()); + writeOrderId(invoke.callTarget(), nodeOrder); + writeOrderId(invoke.stateAfter(), nodeOrder); + writeOrderId(invoke.next(), nodeOrder); + if (invoke instanceof InvokeWithExceptionNode) { + InvokeWithExceptionNode invokeWithExcpetion = (InvokeWithExceptionNode) invoke; + ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithExcpetion.exceptionEdge(); + + writeOrderId(invokeWithExcpetion.next().next(), nodeOrder); + writeOrderId(invokeWithExcpetion.exceptionEdge(), nodeOrder); + writeOrderId(exceptionEdge.stateAfter(), nodeOrder); + writeOrderId(exceptionEdge.next(), nodeOrder); + } } } @@ -252,13 +284,8 @@ FixedNode current = graph.start(); do { add(current); - if (current instanceof InvokeWithExceptionNode) { - /* - * Special handling for invokes: the orderID of the invocation, the regular - * successor, and the exception edge must be consecutive. - */ - add(((InvokeWithExceptionNode) current).next()); - add(((InvokeWithExceptionNode) current).exceptionEdge()); + if (current instanceof AbstractBeginNode) { + add(((AbstractBeginNode) current).next()); } if (current instanceof FixedWithNextNode) { @@ -308,7 +335,7 @@ writer.putSV(primitive); } else { Object property = fields.get(node, idx); - writer.putUV(objects.getIndex(property)); + writeObjectId(property); } } } @@ -343,6 +370,10 @@ writer.putUV(node == null ? NULL_ORDER_ID : nodeOrder.orderIds.get(node)); } + protected void writeObjectId(Object object) { + writer.putUV(objects.getIndex(object)); + } + /** * Verification code that checks that the decoding of an encode graph is the same as the * original graph. @@ -365,7 +396,7 @@ pushToWorklist(expectedGraph.start(), actualGraph.start(), nodeMapping, workList); while (!workList.isEmpty()) { - Pair pair = workList.pop(); + Pair pair = workList.removeFirst(); Node expectedNode = pair.first; Node actualNode = pair.second; assert expectedNode.getClass() == actualNode.getClass(); @@ -377,7 +408,7 @@ /* The order of the ends can be different, so ignore them. */ verifyNodesEqual(expectedNode.inputs(), actualNode.inputs(), nodeMapping, workList, true); } else if (expectedNode instanceof PhiNode) { - /* The order of phi inputs can be different, so they are checked manually below. */ + verifyPhi((PhiNode) expectedNode, (PhiNode) actualNode, nodeMapping, workList); } else { verifyNodesEqual(expectedNode.inputs(), actualNode.inputs(), nodeMapping, workList, false); } @@ -413,20 +444,34 @@ return true; } + protected static void verifyPhi(PhiNode expectedPhi, PhiNode actualPhi, NodeMap nodeMapping, Deque> workList) { + AbstractMergeNode expectedMergeNode = expectedPhi.merge(); + AbstractMergeNode actualMergeNode = actualPhi.merge(); + assert actualMergeNode == nodeMapping.get(expectedMergeNode); + + for (EndNode expectedEndNode : expectedMergeNode.ends) { + EndNode actualEndNode = (EndNode) nodeMapping.get(expectedEndNode); + if (actualEndNode != null) { + ValueNode expectedPhiInput = expectedPhi.valueAt(expectedEndNode); + ValueNode actualPhiInput = actualPhi.valueAt(actualEndNode); + verifyNodeEqual(expectedPhiInput, actualPhiInput, nodeMapping, workList, false); + } + } + } + protected static void verifyPhis(AbstractEndNode expectedEndNode, AbstractEndNode actualEndNode, NodeMap nodeMapping, Deque> workList) { AbstractMergeNode expectedMergeNode = expectedEndNode.merge(); AbstractMergeNode actualMergeNode = (AbstractMergeNode) nodeMapping.get(expectedMergeNode); - - Iterator actualPhis = actualMergeNode.phis().iterator(); - for (PhiNode expectedPhi : expectedMergeNode.phis()) { - PhiNode actualPhi = actualPhis.next(); - verifyNodeEqual(expectedPhi, actualPhi, nodeMapping, workList, false); + assert actualMergeNode != null; - ValueNode expectedPhiInput = expectedPhi.valueAt(expectedEndNode); - ValueNode actualPhiInput = actualPhi.valueAt(actualEndNode); - verifyNodeEqual(expectedPhiInput, actualPhiInput, nodeMapping, workList, false); + for (PhiNode expectedPhi : expectedMergeNode.phis()) { + PhiNode actualPhi = (PhiNode) nodeMapping.get(expectedPhi); + if (actualPhi != null) { + ValueNode expectedPhiInput = expectedPhi.valueAt(expectedEndNode); + ValueNode actualPhiInput = actualPhi.valueAt(actualEndNode); + verifyNodeEqual(expectedPhiInput, actualPhiInput, nodeMapping, workList, false); + } } - assert !actualPhis.hasNext(); } private static void verifyNodesEqual(NodeIterable expectedNodes, NodeIterable actualNodes, NodeMap nodeMapping, Deque> workList, boolean ignoreEndNode) { @@ -453,7 +498,12 @@ protected static void pushToWorklist(Node expectedNode, Node actualNode, NodeMap nodeMapping, Deque> workList) { nodeMapping.set(expectedNode, actualNode); - workList.push(new Pair<>(expectedNode, actualNode)); + if (expectedNode instanceof AbstractEndNode) { + /* To ensure phi nodes have been added, we handle everything before block ends. */ + workList.addLast(new Pair<>(expectedNode, actualNode)); + } else { + workList.addFirst(new Pair<>(expectedNode, actualNode)); + } } } diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat Apr 11 00:16:29 2015 -0700 @@ -140,6 +140,15 @@ return super.verify(); } + public void eliminateNegation() { + AbstractBeginNode oldTrueSuccessor = trueSuccessor; + AbstractBeginNode oldFalseSuccessor = falseSuccessor; + trueSuccessor = oldFalseSuccessor; + falseSuccessor = oldTrueSuccessor; + trueSuccessorProbability = 1 - trueSuccessorProbability; + setCondition(((LogicNegationNode) condition).getValue()); + } + @Override public void simplify(SimplifierTool tool) { if (trueSuccessor().next() instanceof DeoptimizeNode) { @@ -155,15 +164,7 @@ } if (condition() instanceof LogicNegationNode) { - AbstractBeginNode trueSucc = trueSuccessor(); - AbstractBeginNode falseSucc = falseSuccessor(); - setTrueSuccessor(null); - setFalseSuccessor(null); - LogicNegationNode negation = (LogicNegationNode) condition(); - IfNode newIfNode = graph().add(new IfNode(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability)); - predecessor().replaceFirstSuccessor(this, newIfNode); - GraphUtil.killWithUnusedFloatingInputs(this); - return; + eliminateNegation(); } if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition(); diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Apr 11 00:16:29 2015 -0700 @@ -64,6 +64,11 @@ return callTarget; } + void setCallTarget(CallTargetNode callTarget) { + updateUsages(this.callTarget, callTarget); + this.callTarget = callTarget; + } + @Override public boolean isPolymorphic() { return polymorphic; diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Sat Apr 11 00:16:29 2015 -0700 @@ -81,6 +81,11 @@ return callTarget; } + void setCallTarget(CallTargetNode callTarget) { + updateUsages(this.callTarget, callTarget); + this.callTarget = callTarget; + } + public MethodCallTargetNode methodCallTarget() { return (MethodCallTargetNode) callTarget; } diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Sat Apr 11 00:16:29 2015 -0700 @@ -306,7 +306,7 @@ if (callerLockDepth != 0) { for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.TYPE)) { MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); - processMonitorId(invoke, monitor); + processMonitorId(invoke.stateAfter(), monitor); } } } else { @@ -432,8 +432,7 @@ return pos; } - public static void processMonitorId(Invoke invoke, MonitorIdNode monitorIdNode) { - FrameState stateAfter = invoke.stateAfter(); + public static void processMonitorId(FrameState stateAfter, MonitorIdNode monitorIdNode) { if (stateAfter != null) { int callerLockDepth = stateAfter.nestedLockDepth(); monitorIdNode.setLockDepth(monitorIdNode.getLockDepth() + callerLockDepth); @@ -579,26 +578,43 @@ } public static ValueNode mergeReturns(AbstractMergeNode merge, List returnNodes, List canonicalizedNodes) { + ValueNode singleReturnValue = null; PhiNode returnValuePhi = null; - for (ReturnNode returnNode : returnNodes) { - // create and wire up a new EndNode - EndNode endNode = merge.graph().add(new EndNode()); - merge.addForwardEnd(endNode); + if (returnNode.result() != null) { + if (returnValuePhi == null && (singleReturnValue == null || singleReturnValue == returnNode.result())) { + /* Only one return value, so no need yet for a phi node. */ + singleReturnValue = returnNode.result(); - if (returnNode.result() != null) { - if (returnValuePhi == null) { + } else if (returnValuePhi == null) { + /* Found a second return value, so create phi node. */ returnValuePhi = merge.graph().addWithoutUnique(new ValuePhiNode(returnNode.result().stamp().unrestricted(), merge)); if (canonicalizedNodes != null) { canonicalizedNodes.add(returnValuePhi); } + for (int i = 0; i < merge.forwardEndCount(); i++) { + returnValuePhi.addInput(singleReturnValue); + } + returnValuePhi.addInput(returnNode.result()); + + } else { + /* Multiple return values, just add to existing phi node. */ + returnValuePhi.addInput(returnNode.result()); } - returnValuePhi.addInput(returnNode.result()); } + + // create and wire up a new EndNode + EndNode endNode = merge.graph().add(new EndNode()); + merge.addForwardEnd(endNode); returnNode.replaceAndDelete(endNode); - } - return returnValuePhi; + + if (returnValuePhi != null) { + assert returnValuePhi.verify(); + return returnValuePhi; + } else { + return singleReturnValue; + } } private static boolean checkContainsOnlyInvalidOrAfterFrameState(Map duplicates) { diff -r 23433619a7cd -r c7f1ab98d950 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Sat Apr 11 00:16:29 2015 -0700 @@ -29,13 +29,14 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; import com.oracle.graal.java.*; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.extended.*; @@ -63,8 +64,11 @@ protected final StampProvider stampProvider; protected class PEMethodScope extends MethodScope { + /** The state of the caller method. Only non-null during method inlining. */ + protected final PEMethodScope caller; + protected final LoopScope callerLoopScope; protected final ResolvedJavaMethod method; - protected final Invoke invoke; + protected final InvokeData invokeData; protected final int inliningDepth; protected final LoopExplosionPlugin loopExplosionPlugin; @@ -73,15 +77,20 @@ protected final ParameterPlugin parameterPlugin; protected final ValueNode[] arguments; - protected FrameState outerFrameState; + protected FrameState outerState; + protected FrameState exceptionState; + protected ExceptionPlaceholderNode exceptionPlaceholderNode; protected BytecodePosition bytecodePosition; - protected PEMethodScope(StructuredGraph targetGraph, MethodScope caller, EncodedGraph encodedGraph, ResolvedJavaMethod method, Invoke invoke, int inliningDepth, - LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin, ParameterPlugin parameterPlugin, ValueNode[] arguments) { - super(targetGraph, caller, encodedGraph, loopExplosionKind(method, loopExplosionPlugin)); + protected PEMethodScope(StructuredGraph targetGraph, PEMethodScope caller, LoopScope callerLoopScope, EncodedGraph encodedGraph, ResolvedJavaMethod method, InvokeData invokeData, + int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin, ParameterPlugin parameterPlugin, + ValueNode[] arguments) { + super(targetGraph, encodedGraph, loopExplosionKind(method, loopExplosionPlugin)); + this.caller = caller; + this.callerLoopScope = callerLoopScope; this.method = method; - this.invoke = invoke; + this.invokeData = invokeData; this.inliningDepth = inliningDepth; this.loopExplosionPlugin = loopExplosionPlugin; this.invocationPlugins = invocationPlugins; @@ -89,6 +98,10 @@ this.parameterPlugin = parameterPlugin; this.arguments = arguments; } + + public boolean isInlinedMethod() { + return caller != null; + } } protected class PECanonicalizerTool implements CanonicalizerTool { @@ -114,7 +127,7 @@ } protected class PENonAppendGraphBuilderContext implements GraphBuilderContext { - private final PEMethodScope methodScope; + protected final PEMethodScope methodScope; public PENonAppendGraphBuilderContext(PEMethodScope methodScope) { this.methodScope = methodScope; @@ -212,13 +225,11 @@ } protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext { - protected final Invoke invoke; protected FixedWithNextNode lastInstr; protected ValueNode pushedNode; - public PEAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke, FixedWithNextNode lastInstr) { + public PEAppendGraphBuilderContext(PEMethodScope methodScope, FixedWithNextNode lastInstr) { super(methodScope); - this.invoke = invoke; this.lastInstr = lastInstr; } @@ -232,7 +243,9 @@ @Override public FrameState createStateAfter() { - return invoke.stateAfter().duplicate(); + Node stateAfter = decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId); + getGraph().add(stateAfter); + return (FrameState) handleFloatingNodeAfterAdd(methodScope.caller, methodScope.callerLoopScope, stateAfter); } @Override @@ -274,6 +287,15 @@ } } + @NodeInfo + static class ExceptionPlaceholderNode extends ValueNode { + public static final NodeClass TYPE = NodeClass.create(ExceptionPlaceholderNode.class); + + public ExceptionPlaceholderNode() { + super(TYPE, StampFactory.object()); + } + } + public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; @@ -294,8 +316,9 @@ public void decode(StructuredGraph targetGraph, ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin, ParameterPlugin parameterPlugin) { - PEMethodScope methodScope = new PEMethodScope(targetGraph, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin, parameterPlugin, null); - decode(methodScope); + PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin, + parameterPlugin, null); + decode(methodScope, null); cleanupGraph(methodScope); methodScope.graph.verify(); } @@ -310,8 +333,6 @@ protected void checkLoopExplosionIteration(MethodScope s, LoopScope loopScope) { PEMethodScope methodScope = (PEMethodScope) s; - Debug.dump(methodScope.graph, "Loop iteration " + loopScope.loopIteration); - if (loopScope.loopIteration > MaximumLoopExplosionCount.getValue()) { String message = "too many loop explosion iterations - does the explosion not terminate for method " + methodScope.method + "?"; if (FailedLoopExplosionIsFatal.getValue()) { @@ -323,39 +344,52 @@ } @Override - protected void simplifyInvoke(MethodScope s, LoopScope loopScope, int invokeOrderId, Invoke invoke) { - if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { - return; - } + protected void handleInvoke(MethodScope s, LoopScope loopScope, InvokeData invokeData) { PEMethodScope methodScope = (PEMethodScope) s; - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + + /* + * Decode the call target, but do not add it to the graph yet. This avoids adding usages for + * all the arguments, which are expensive to remove again when we can inline the method. + */ + assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke"; + CallTargetNode callTarget = (CallTargetNode) decodeFloatingNode(methodScope, loopScope, invokeData.callTargetOrderId); + if (!(callTarget instanceof MethodCallTargetNode) || !trySimplifyInvoke(methodScope, loopScope, invokeData, (MethodCallTargetNode) callTarget)) { + /* We know that we need an invoke, so now we can add the call target to the graph. */ + methodScope.graph.add(callTarget); + registerNode(loopScope, invokeData.callTargetOrderId, callTarget, false, false); + super.handleInvoke(methodScope, loopScope, invokeData); + } + } + + protected boolean trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { // attempt to devirtualize the call - ResolvedJavaType contextType = (invoke.stateAfter() == null && invoke.stateDuring() == null) ? null : invoke.getContextType(); - ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(callTarget.invokeKind(), callTarget.receiver(), callTarget.targetMethod(), contextType); + ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(callTarget.invokeKind(), callTarget.receiver(), callTarget.targetMethod(), invokeData.contextType); if (specialCallTarget != null) { callTarget.setTargetMethod(specialCallTarget); callTarget.setInvokeKind(InvokeKind.Special); } - if (tryInvocationPlugin(methodScope, loopScope, invokeOrderId, invoke)) { - return; + if (tryInvocationPlugin(methodScope, loopScope, invokeData, callTarget)) { + return true; } - if (tryInline(methodScope, loopScope, invokeOrderId, invoke)) { - return; + if (tryInline(methodScope, loopScope, invokeData, callTarget)) { + return true; } if (methodScope.inlineInvokePlugin != null) { - methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope), callTarget.targetMethod(), invoke); + methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope), callTarget.targetMethod(), invokeData.invoke); } + return false; } - protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, int invokeOrderId, Invoke invoke) { + protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { if (methodScope.invocationPlugins == null) { return false; } - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + Invoke invoke = invokeData.invoke; + ResolvedJavaMethod targetMethod = callTarget.targetMethod(); InvocationPlugin invocationPlugin = methodScope.invocationPlugins.lookupInvocation(targetMethod); if (invocationPlugin == null) { @@ -364,52 +398,41 @@ ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]); FixedWithNextNode invokePredecessor = (FixedWithNextNode) invoke.asNode().predecessor(); - FixedNode invokeNext = invoke.next(); - AbstractBeginNode invokeException = null; - if (invoke instanceof InvokeWithExceptionNode) { - invokeException = ((InvokeWithExceptionNode) invoke).exceptionEdge(); - } + /* Remove invoke from graph so that invocation plugin can append nodes to the predecessor. */ invoke.asNode().replaceAtPredecessor(null); - PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, invoke, invokePredecessor); + PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin, + methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments); + PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor); InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext); + if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) { if (graphBuilderContext.lastInstr != null) { - registerNode(loopScope, invokeOrderId, graphBuilderContext.pushedNode, true, true); + registerNode(loopScope, invokeData.invokeOrderId, graphBuilderContext.pushedNode, true, true); invoke.asNode().replaceAtUsages(graphBuilderContext.pushedNode); + graphBuilderContext.lastInstr.setNext(nodeAfterInvoke(methodScope, loopScope, invokeData)); } else { assert graphBuilderContext.pushedNode == null : "Why push a node when the invoke does not return anyway?"; invoke.asNode().replaceAtUsages(null); } deleteInvoke(invoke); - if (invokeException != null) { - invokeException.safeDelete(); - } - - if (graphBuilderContext.lastInstr != null) { - graphBuilderContext.lastInstr.setNext(invokeNext); - } else { - invokeNext.replaceAtPredecessor(null); - invokeNext.safeDelete(); - } return true; } else { - /* Restore original state: invoke is in Graph. */ + /* Intrinsification failed, restore original state: invoke is in Graph. */ invokePredecessor.setNext(invoke.asNode()); return false; } } - protected boolean tryInline(PEMethodScope methodScope, LoopScope loopScope, int invokeOrderId, Invoke invoke) { - if (methodScope.inlineInvokePlugin == null || !invoke.getInvokeKind().isDirect()) { + protected boolean tryInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { + if (methodScope.inlineInvokePlugin == null || !callTarget.invokeKind().isDirect()) { return false; } - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); if (!targetMethod.canBeInlined()) { return false; @@ -429,50 +452,72 @@ return false; } - int exceptionObjectOrderId = -1; - if (invoke instanceof InvokeWithExceptionNode) { - /* - * We need to have the regular next node (usually a KillingBeginNode) and the exception - * edge node (always an ExceptionObjectNode) fully decoded, because both can be changed - * or replaced as part of the inlining process. The GraphEncoder adds these two - * successors in a known order (first the regular next node, then the exception edge) - * that we can rely on here. - */ - assert ((InvokeWithExceptionNode) invoke).next().next() == null; - processNextNode(methodScope, loopScope); - assert ((InvokeWithExceptionNode) invoke).next().next() != null; + Invoke invoke = invokeData.invoke; + FixedNode invokeNode = invoke.asNode(); + FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor(); + invokeNode.replaceAtPredecessor(null); - assert ((InvokeWithExceptionNode) invoke).exceptionEdge().next() == null; - exceptionObjectOrderId = loopScope.nodesToProcess.nextSetBit(0); - processNextNode(methodScope, loopScope); - assert ((InvokeWithExceptionNode) invoke).exceptionEdge().next() != null; - } - - PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, graphToInline, inlineMethod, invoke, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin, - methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments); + PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1, + methodScope.loopExplosionPlugin, methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments); /* Do the actual inlining by decoding the inlineMethod */ - decode(inlineScope); + decode(inlineScope, predecessor); ValueNode exceptionValue = null; if (inlineScope.unwindNode != null) { exceptionValue = inlineScope.unwindNode.exception(); } + UnwindNode unwindNode = inlineScope.unwindNode; - FixedNode firstInlinedNode = inlineScope.startNode.next(); - /* The StartNode was only necessary as a placeholder during decoding. */ - inlineScope.startNode.safeDelete(); + if (invoke instanceof InvokeWithExceptionNode) { + InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke); + assert invokeWithException.next() == null; + assert invokeWithException.exceptionEdge() == null; + + if (unwindNode != null) { + assert unwindNode.predecessor() != null; + Node n = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId); + unwindNode.replaceAndDelete(n); + } + + } else { + if (unwindNode != null && !unwindNode.isDeleted()) { + DeoptimizeNode deoptimizeNode = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + unwindNode.replaceAndDelete(deoptimizeNode); + } + } + + assert invoke.next() == null; - assert inlineScope.startNode.stateAfter() == null; - ValueNode returnValue = InliningUtil.finishInlining(invoke, methodScope.graph, firstInlinedNode, inlineScope.returnNodes, inlineScope.unwindNode, inlineScope.encodedGraph.getAssumptions(), - inlineScope.encodedGraph.getInlinedMethods(), null); + ValueNode returnValue; + List returnNodes = inlineScope.returnNodes; + if (!returnNodes.isEmpty()) { + FixedNode n; + n = nodeAfterInvoke(methodScope, loopScope, invokeData); + if (returnNodes.size() == 1) { + ReturnNode returnNode = returnNodes.get(0); + returnValue = returnNode.result(); + returnNode.replaceAndDelete(n); + } else { + AbstractMergeNode merge = methodScope.graph.add(new MergeNode()); + merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId)); + returnValue = InliningUtil.mergeReturns(merge, returnNodes, null); + merge.setNext(n); + } + } else { + returnValue = null; + } + invokeNode.replaceAtUsages(returnValue); /* * Usage the handles that we have on the return value and the exception to update the * orderId->Node table. */ - registerNode(loopScope, invokeOrderId, returnValue, true, true); + registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true); if (invoke instanceof InvokeWithExceptionNode) { - registerNode(loopScope, exceptionObjectOrderId, exceptionValue, true, true); + registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true); + } + if (inlineScope.exceptionPlaceholderNode != null) { + inlineScope.exceptionPlaceholderNode.replaceAndDelete(exceptionValue); } deleteInvoke(invoke); @@ -480,6 +525,16 @@ return true; } + public FixedNode nodeAfterInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData) { + FixedNode n; + if (invokeData.invoke instanceof InvokeWithExceptionNode) { + n = makeStubNode(methodScope, loopScope, invokeData.nextNextOrderId); + } else { + n = makeStubNode(methodScope, loopScope, invokeData.nextOrderId); + } + return n; + } + private static void deleteInvoke(Invoke invoke) { /* * Clean up unused nodes. We cannot just call killCFG on the invoke node because that can @@ -487,7 +542,7 @@ */ FrameState frameState = invoke.stateAfter(); invoke.asNode().safeDelete(); - invoke.callTarget().safeDelete(); + assert invoke.callTarget() == null : "must not have been added to the graph yet"; if (frameState != null && frameState.hasNoUsages()) { frameState.safeDelete(); } @@ -499,15 +554,20 @@ protected void simplifyFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) { PEMethodScope methodScope = (PEMethodScope) s; - if (node instanceof IfNode && ((IfNode) node).condition() instanceof LogicConstantNode) { + if (node instanceof IfNode) { IfNode ifNode = (IfNode) node; - boolean condition = ((LogicConstantNode) ifNode.condition()).getValue(); - AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition); - AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition); + if (ifNode.condition() instanceof LogicNegationNode) { + ifNode.eliminateNegation(); + } + if (ifNode.condition() instanceof LogicConstantNode) { + boolean condition = ((LogicConstantNode) ifNode.condition()).getValue(); + AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition); + AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition); - methodScope.graph.removeSplit(ifNode, survivingSuccessor); - assert deadSuccessor.next() == null : "must not be parsed yet"; - deadSuccessor.safeDelete(); + methodScope.graph.removeSplit(ifNode, survivingSuccessor); + assert deadSuccessor.next() == null : "must not be parsed yet"; + deadSuccessor.safeDelete(); + } } else if (node instanceof IntegerSwitchNode && ((IntegerSwitchNode) node).value().isConstant()) { IntegerSwitchNode switchNode = (IntegerSwitchNode) node; @@ -587,31 +647,68 @@ return node; } + protected void ensureOuterStateDecoded(PEMethodScope methodScope) { + if (methodScope.outerState == null && methodScope.caller != null) { + FrameState stateAtReturn = methodScope.invokeData.invoke.stateAfter(); + if (stateAtReturn == null) { + stateAtReturn = (FrameState) decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId); + } + + Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind(); + FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind); + + if (methodScope.caller != null) { + ensureOuterStateDecoded(methodScope.caller); + outerState.setOuterFrameState(methodScope.caller.outerState); + } + methodScope.outerState = outerState; + } + } + + protected void ensureStateAfterDecoded(PEMethodScope methodScope) { + if (methodScope.invokeData.invoke.stateAfter() == null) { + methodScope.invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId)); + } + } + + protected void ensureExceptionStateDecoded(PEMethodScope methodScope) { + if (methodScope.exceptionState == null && methodScope.caller != null && methodScope.invokeData.invoke instanceof InvokeWithExceptionNode) { + ensureStateAfterDecoded(methodScope); + + assert methodScope.exceptionPlaceholderNode == null; + methodScope.exceptionPlaceholderNode = methodScope.graph.add(new ExceptionPlaceholderNode()); + registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false); + FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId); + + if (methodScope.caller != null) { + ensureOuterStateDecoded(methodScope.caller); + exceptionState.setOuterFrameState(methodScope.caller.outerState); + } + methodScope.exceptionState = exceptionState; + } + } + @Override protected Node handleFloatingNodeAfterAdd(MethodScope s, LoopScope loopScope, Node node) { PEMethodScope methodScope = (PEMethodScope) s; if (methodScope.isInlinedMethod()) { if (node instanceof SimpleInfopointNode) { - methodScope.bytecodePosition = InliningUtil.processSimpleInfopoint(methodScope.invoke, (SimpleInfopointNode) node, methodScope.bytecodePosition); + methodScope.bytecodePosition = InliningUtil.processSimpleInfopoint(methodScope.invokeData.invoke, (SimpleInfopointNode) node, methodScope.bytecodePosition); return node; } else if (node instanceof FrameState) { - FrameState stateAtExceptionEdge = null; - if (methodScope.invoke instanceof InvokeWithExceptionNode) { - InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) methodScope.invoke); - ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge(); - stateAtExceptionEdge = obj.stateAfter(); + FrameState frameState = (FrameState) node; + + ensureOuterStateDecoded(methodScope); + if (frameState.bci < 0) { + ensureExceptionStateDecoded(methodScope); } - if (methodScope.outerFrameState == null) { - FrameState stateAtReturn = methodScope.invoke.stateAfter(); - Kind invokeReturnKind = methodScope.invoke.asNode().getKind(); - methodScope.outerFrameState = stateAtReturn.duplicateModifiedDuringCall(methodScope.invoke.bci(), invokeReturnKind); - } - return InliningUtil.processFrameState((FrameState) node, methodScope.invoke, methodScope.method, stateAtExceptionEdge, methodScope.outerFrameState, true); + return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true); } else if (node instanceof MonitorIdNode) { - InliningUtil.processMonitorId(methodScope.invoke, (MonitorIdNode) node); + ensureOuterStateDecoded(methodScope); + InliningUtil.processMonitorId(methodScope.outerState, (MonitorIdNode) node); return node; } } diff -r 23433619a7cd -r c7f1ab98d950 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 Sat Apr 11 00:15:55 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Sat Apr 11 00:16:29 2015 -0700 @@ -164,28 +164,74 @@ private class PEInlineInvokePlugin implements InlineInvokePlugin { - private final boolean duringParsing; private Deque inlining; private OptimizedDirectCallNode lastDirectCallNode; private final Replacements replacements; - private final InvocationPlugins invocationPlugins; - private final LoopExplosionPlugin loopExplosionPlugin; - - public PEInlineInvokePlugin(TruffleInlining inlining, Replacements replacements, boolean duringParsing, InvocationPlugins invocationPlugins, LoopExplosionPlugin loopExplosionPlugin) { + public PEInlineInvokePlugin(TruffleInlining inlining, Replacements replacements) { this.inlining = new ArrayDeque<>(); this.inlining.push(inlining); this.replacements = replacements; - this.duringParsing = duringParsing; + } + + @Override + public InlineInfo getInlineInfo(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { + if (original.getAnnotation(TruffleBoundary.class) != null) { + return null; + } + if (replacements != null && replacements.hasSubstitution(original)) { + return null; + } + assert !builder.parsingReplacement(); + if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { + if (original.equals(callSiteProxyMethod)) { + ValueNode arg1 = arguments[0]; + if (!arg1.isConstant()) { + GraalInternalError.shouldNotReachHere("The direct call node does not resolve to a constant!"); + } + + Object callNode = snippetReflection.asObject(Object.class, (JavaConstant) arg1.asConstant()); + if (callNode instanceof OptimizedDirectCallNode) { + OptimizedDirectCallNode directCallNode = (OptimizedDirectCallNode) callNode; + lastDirectCallNode = directCallNode; + } + } else if (original.equals(callDirectMethod)) { + TruffleInliningDecision decision = getDecision(inlining.peek(), lastDirectCallNode); + lastDirectCallNode = null; + if (decision != null && decision.isInline()) { + inlining.push(decision); + builder.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); + return new InlineInfo(callInlinedMethod, false, false); + } + } + } + + return new InlineInfo(original, false, false); + } + + @Override + public void postInline(ResolvedJavaMethod inlinedTargetMethod) { + if (inlinedTargetMethod.equals(callInlinedMethod)) { + inlining.pop(); + } + } + } + + private class ParsingInlineInvokePlugin implements InlineInvokePlugin { + + private final Replacements replacements; + private final InvocationPlugins invocationPlugins; + private final LoopExplosionPlugin loopExplosionPlugin; + private final boolean inlineDuringParsing; + + public ParsingInlineInvokePlugin(Replacements replacements, InvocationPlugins invocationPlugins, LoopExplosionPlugin loopExplosionPlugin, boolean inlineDuringParsing) { + this.replacements = replacements; this.invocationPlugins = invocationPlugins; this.loopExplosionPlugin = loopExplosionPlugin; + this.inlineDuringParsing = inlineDuringParsing; } private boolean hasMethodHandleArgument(ValueNode[] arguments) { - /* - * We want to process invokes that have a constant MethodHandle parameter. And the - * method must be statically bound, otherwise we do not have a single target method. - */ for (ValueNode argument : arguments) { if (argument.isConstant()) { JavaConstant constant = argument.asJavaConstant(); @@ -197,58 +243,31 @@ return false; } + @Override public InlineInfo getInlineInfo(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { - if (duringParsing && (invocationPlugins.lookupInvocation(original) != null || loopExplosionPlugin.shouldExplodeLoops(original))) { + if (invocationPlugins.lookupInvocation(original) != null || loopExplosionPlugin.shouldExplodeLoops(original)) { return null; } - if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } if (replacements != null && replacements.hasSubstitution(original)) { return null; } - assert !builder.parsingReplacement(); - if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { - if (original.equals(callSiteProxyMethod)) { - if (duringParsing) { - return null; - } - ValueNode arg1 = arguments[0]; - if (!arg1.isConstant()) { - GraalInternalError.shouldNotReachHere("The direct call node does not resolve to a constant!"); - } - - Object callNode = snippetReflection.asObject(Object.class, (JavaConstant) arg1.asConstant()); - if (callNode instanceof OptimizedDirectCallNode) { - OptimizedDirectCallNode directCallNode = (OptimizedDirectCallNode) callNode; - lastDirectCallNode = directCallNode; - } - } else if (original.equals(callDirectMethod)) { - if (duringParsing) { - return null; - } - TruffleInliningDecision decision = getDecision(inlining.peek(), lastDirectCallNode); - lastDirectCallNode = null; - if (decision != null && decision.isInline()) { - inlining.push(decision); - builder.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); - return new InlineInfo(callInlinedMethod, false, false); - } - } - } - - if (duringParsing && (!original.hasBytecodes() || original.getCode().length >= TrivialInliningSize.getValue() || builder.getDepth() >= InlineDuringParsingMaxDepth.getValue()) && - !hasMethodHandleArgument(arguments)) { + if (original.equals(callSiteProxyMethod) || original.equals(callDirectMethod)) { return null; } - return new InlineInfo(original, false, false); - } - - public void postInline(ResolvedJavaMethod inlinedTargetMethod) { - if (inlinedTargetMethod.equals(callInlinedMethod)) { - inlining.pop(); + if (hasMethodHandleArgument(arguments)) { + /* + * We want to inline invokes that have a constant MethodHandle parameter to remove + * invokedynamic related calls as early as possible. + */ + return new InlineInfo(original, false, false); } + if (inlineDuringParsing && original.hasBytecodes() && original.getCode().length < TrivialInliningSize.getValue() && builder.getDepth() < InlineDuringParsingMaxDepth.getValue()) { + return new InlineInfo(original, false, false); + } + return null; } } @@ -279,7 +298,7 @@ plugins.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); - InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements(), false, null, null); + InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) { inlinePlugin = new HistogramInlineInvokePlugin(graph, inlinePlugin); } @@ -303,7 +322,7 @@ newConfig.setUseProfiling(false); Plugins plugins = newConfig.getPlugins(); plugins.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); - plugins.setInlineInvokePlugin(new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements(), true, parsingInvocationPlugins, loopExplosionPlugin)); + plugins.setInlineInvokePlugin(new ParsingInlineInvokePlugin(providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin, !PrintTruffleExpansionHistogram.getValue())); CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null)); @@ -311,7 +330,7 @@ InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(providers.getMetaAccess()); TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false, snippetReflection); - InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements(), false, decodingInvocationPlugins, loopExplosionPlugin); + InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) { decodingInlinePlugin = new HistogramInlineInvokePlugin(graph, decodingInlinePlugin); }