# HG changeset patch # User Christian Humer # Date 1414077610 -7200 # Node ID ab62800259ffebfda46bbc741001efd6b752c602 # Parent 94f16a759646293a58cbb706a9d888ea6a09e477 Truffle: renamed the splitting to callTargetCloning. Made RootNode cloning an implementation detail of the Truffle runtime. diff -r 94f16a759646 -r ab62800259ff CHANGELOG.md --- a/CHANGELOG.md Thu Oct 23 13:45:59 2014 +0200 +++ b/CHANGELOG.md Thu Oct 23 17:20:10 2014 +0200 @@ -9,6 +9,11 @@ * Relaxed declared type restriction on child fields to allow for interface types in addition to Node subclasses. * The BranchProfile constructor is now private. Use BranchProfile#create() instead. * Renamed @CompilerDirectives.SlowPath to @CompilerDirectives.TruffleBoundary +* Renamed RootNode#isSplittable to RootNode#isCloningAllowed +* Removed RootNode#split. Cloning ASTs for splitting is now an implementation detail of the Truffle runtime implementation. +* Renamed DirectCallNode#isSplittable to DirectCallNode#isCallTargetCloningAllowed +* Renamed DirectCallNode#split to DirectCallNode#cloneCallTarget +* Renamed DirectCallNode#isSplit to DirectCallNode#isCallTargetCloned * ... ## Version 0.5 diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Oct 23 17:20:10 2014 +0200 @@ -107,18 +107,27 @@ @Override public RootCallTarget createCallTarget(RootNode rootNode) { + return createCallTargetImpl(null, rootNode); + } + + private RootCallTarget createCallTargetImpl(OptimizedCallTarget source, RootNode rootNode) { CompilationPolicy compilationPolicy; if (acceptForCompilation(rootNode)) { compilationPolicy = new CounterBasedCompilationPolicy(); } else { compilationPolicy = new InterpreterOnlyCompilationPolicy(); } - OptimizedCallTarget target = new OptimizedCallTarget(rootNode, this, compilationPolicy, new HotSpotSpeculationLog()); + OptimizedCallTarget target = new OptimizedCallTarget(source, rootNode, this, compilationPolicy, new HotSpotSpeculationLog()); callTargets.put(target, null); return target; } @Override + public RootCallTarget createClonedCallTarget(OptimizedCallTarget source, RootNode root) { + return createCallTargetImpl(source, root); + } + + @Override public Replacements getReplacements() { if (truffleReplacements == null) { truffleReplacements = HotSpotTruffleReplacements.makeInstance(); diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDisableSplittingBuiltin.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDisableSplittingBuiltin.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDisableSplittingBuiltin.java Thu Oct 23 17:20:10 2014 +0200 @@ -42,7 +42,7 @@ public SLFunction disableSplitting(SLFunction function) { OptimizedCallTarget target = (OptimizedCallTarget) function.getCallTarget(); for (OptimizedCallTarget oct : findDuplicateCallTargets(target)) { - ((SLRootNode) oct.getRootNode()).setSplittable(false); + ((SLRootNode) oct.getRootNode()).setCloningAllowed(false); } return function; } @@ -51,7 +51,7 @@ @TruffleBoundary public SLNull disableSplitting(@SuppressWarnings("unused") SLNull argument) { RootNode parentRoot = Truffle.getRuntime().getCallerFrame().getCallNode().getRootNode(); - ((SLRootNode) parentRoot).setSplittable(false); + ((SLRootNode) parentRoot).setCloningAllowed(false); return SLNull.SINGLETON; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGraalRuntimeBuiltin.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGraalRuntimeBuiltin.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGraalRuntimeBuiltin.java Thu Oct 23 17:20:10 2014 +0200 @@ -53,7 +53,7 @@ for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) { if (target instanceof OptimizedCallTarget) { OptimizedCallTarget oct = (OptimizedCallTarget) target; - if (oct.getSplitSource() == originalCallTarget) { + if (oct.getSourceCallTarget() == originalCallTarget) { allCallTargets.add(oct); } } @@ -83,7 +83,7 @@ public boolean visit(Node node) { if (node instanceof DirectCallNode) { DirectCallNode callNode = (DirectCallNode) node; - if (callNode.getCallTarget() == originalCallTarget || callNode.getSplitCallTarget() == originalCallTarget) { + if (callNode.getCallTarget() == originalCallTarget || callNode.getClonedCallTarget() == originalCallTarget) { allCallNodes.add(callNode); } } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java Thu Oct 23 17:20:10 2014 +0200 @@ -42,23 +42,23 @@ } public void forceSplitting() { - if (call.isSplit()) { + if (call.isCallTargetCloned()) { return; } - call.installSplitCallTarget(call.getCallTarget().split()); + call.installSplitCallTarget(call.getCallTarget().cloneUninitialized()); } public void afterCall(Object returnValue) { } private boolean shouldSplit() { - if (call.getSplitCallTarget() != null) { + if (call.getClonedCallTarget() != null) { return false; } if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { return false; } - if (!call.isSplittable()) { + if (!call.isCallTargetCloningAllowed()) { return false; } OptimizedCallTarget splitTarget = call.getCallTarget(); @@ -69,7 +69,7 @@ // disable recursive splitting for now OptimizedCallTarget root = (OptimizedCallTarget) call.getRootNode().getCallTarget(); - if (root == splitTarget || root.getSplitSource() == splitTarget) { + if (root == splitTarget || root.getSourceCallTarget() == splitTarget) { // recursive call found return false; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Thu Oct 23 17:20:10 2014 +0200 @@ -51,7 +51,7 @@ if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { return false; } - if (!call.isSplittable()) { + if (!call.isCallTargetCloningAllowed()) { return false; } if (TruffleCompilerOptions.TruffleSplittingAggressive.getValue()) { @@ -80,8 +80,8 @@ OptimizedCallTarget currentTarget = call.getCurrentCallTarget(); if (splittingForced) { - if (!call.isSplit()) { - call.installSplitCallTarget(currentTarget.split()); + if (!call.isCallTargetCloned()) { + call.installSplitCallTarget(currentTarget.cloneUninitialized()); } return; } @@ -123,7 +123,7 @@ // we are the only caller + the profile is not polluted by other call sites // -> reuse the currentTarget but update the profile if necessary newTarget = currentTarget; - if (currentTarget.getSplitSource() != null) { + if (currentTarget.getSourceCallTarget() != null) { profiles.remove(oldProfile); profiles.put(newProfile, newTarget); } @@ -131,7 +131,7 @@ newTarget = profiles.get(newProfile); if (newTarget == null) { // in case no compatible target was found we need to split - newTarget = target.split(); + newTarget = target.cloneUninitialized(); profiles.put(newProfile, newTarget); split = true; } @@ -141,7 +141,7 @@ call.installSplitCallTarget(newTarget); if (split && TruffleCompilerOptions.TraceTruffleSplitting.getValue()) { - traceSplit(currentTarget.getSplitSource() != null ? oldProfile : currentTarget.getArgumentStamp(), newProfile); + traceSplit(currentTarget.getSourceCallTarget() != null ? oldProfile : currentTarget.getArgumentStamp(), newProfile); } cleanup(currentTarget); @@ -151,7 +151,7 @@ private void traceSplit(TruffleStamp oldStamp, TruffleStamp newStamp) { OptimizedCallTarget callTarget = call.getCallTarget(); Map splitTargets = callTarget.getSplitVersions(); - String label = String.format("split %3s-%-4s-%-4s ", splitChangeCount++, call.getCurrentCallTarget().getSplitIndex(), call.getCallCount()); + String label = String.format("split %3s-%-4s-%-4s ", splitChangeCount++, call.getCurrentCallTarget().getCloneIndex(), call.getCallCount()); OptimizedCallTargetLog.log(0, label, callTarget.toString(), callTarget.getDebugProperties()); logProfile(callTarget.getArgumentStamp(), callTarget, oldStamp, newStamp); for (TruffleStamp profile : splitTargets.keySet()) { @@ -160,7 +160,7 @@ } private static void logProfile(TruffleStamp stamp, OptimizedCallTarget target, TruffleStamp oldStamp, TruffleStamp newStamp) { - String id = String.format("@%8h %s", target.hashCode(), target.getSplitSource() == null ? "orig." : "split"); + String id = String.format("@%8h %s", target.hashCode(), target.getSourceCallTarget() == null ? "orig." : "split"); String plusMinus = stamp.equals(newStamp) ? "+ " : (stamp.equals(oldStamp) ? "- " : ""); System.out.printf("%16s%-20sCallers: %3d, Nodes:%10s %s%n", plusMinus, id, target.getKnownCallSiteCount(), // String.format("%d (%d/%d)", count(target, NodeCost.MONOMORPHIC), count(target, NodeCost.POLYMORPHIC), count(target, NodeCost.MEGAMORPHIC)),// @@ -176,8 +176,8 @@ } private static void cleanup(OptimizedCallTarget currentTarget) { - if (currentTarget.getKnownCallSiteCount() == 0 && currentTarget.getSplitSource() != null) { - OptimizedCallTarget removed = currentTarget.getSplitSource().getSplitVersions().remove(currentTarget.getArgumentStamp()); + if (currentTarget.getKnownCallSiteCount() == 0 && currentTarget.getSourceCallTarget() != null) { + OptimizedCallTarget removed = currentTarget.getSourceCallTarget().getSplitVersions().remove(currentTarget.getArgumentStamp()); if (removed != null) { disposeTarget(removed); } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Thu Oct 23 17:20:10 2014 +0200 @@ -185,6 +185,8 @@ } } + public abstract RootCallTarget createClonedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode root); + public abstract Replacements getReplacements(); public abstract void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous); diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Oct 23 17:20:10 2014 +0200 @@ -52,13 +52,14 @@ private SpeculationLog speculationLog; protected final CompilationProfile compilationProfile; protected final CompilationPolicy compilationPolicy; - private OptimizedCallTarget splitSource; + private final OptimizedCallTarget sourceCallTarget; private final AtomicInteger callSitesKnown = new AtomicInteger(0); @CompilationFinal private Class[] profiledArgumentTypes; @CompilationFinal private Assumption profiledArgumentTypesAssumption; @CompilationFinal private Class profiledReturnType; @CompilationFinal private Assumption profiledReturnTypeAssumption; + private final RootNode uninitializedRootNode; private final RootNode rootNode; /* Experimental fields for new splitting. */ @@ -78,14 +79,16 @@ return rootNode; } - public OptimizedCallTarget(RootNode rootNode, GraalTruffleRuntime runtime, CompilationPolicy compilationPolicy, SpeculationLog speculationLog) { + public OptimizedCallTarget(OptimizedCallTarget sourceCallTarget, RootNode rootNode, GraalTruffleRuntime runtime, CompilationPolicy compilationPolicy, SpeculationLog speculationLog) { super(rootNode.toString()); + this.sourceCallTarget = sourceCallTarget; this.runtime = runtime; this.speculationLog = speculationLog; this.rootNode = rootNode; + this.compilationPolicy = compilationPolicy; this.rootNode.adoptChildren(); this.rootNode.setCallTarget(this); - this.compilationPolicy = compilationPolicy; + this.uninitializedRootNode = sourceCallTarget == null ? cloneRootNode(rootNode) : sourceCallTarget.uninitializedRootNode; if (TruffleCallTargetProfiling.getValue()) { this.compilationProfile = new TraceCompilationProfile(); } else { @@ -94,6 +97,13 @@ this.nodeRewritingAssumption = new CyclicAssumption("nodeRewritingAssumption of " + rootNode.toString()); } + private static RootNode cloneRootNode(RootNode root) { + if (root == null || !root.isCloningAllowed()) { + return null; + } + return NodeUtil.cloneNode(root); + } + public Assumption getNodeRewritingAssumption() { return nodeRewritingAssumption.getAssumption(); } @@ -106,19 +116,19 @@ return argumentStamp; } - private int splitIndex; + private int cloneIndex; - public int getSplitIndex() { - return splitIndex; + public int getCloneIndex() { + return cloneIndex; } - public OptimizedCallTarget split() { - if (!getRootNode().isSplittable()) { + public OptimizedCallTarget cloneUninitialized() { + RootNode copiedRoot = cloneRootNode(uninitializedRootNode); + if (copiedRoot == null) { return null; } - OptimizedCallTarget splitTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(getRootNode().split()); - splitTarget.splitSource = this; - splitTarget.splitIndex = splitIndex++; + OptimizedCallTarget splitTarget = (OptimizedCallTarget) runtime.createClonedCallTarget(this, copiedRoot); + splitTarget.cloneIndex = cloneIndex++; return splitTarget; } @@ -375,12 +385,8 @@ callSitesKnown.decrementAndGet(); } - public final OptimizedCallTarget getSplitSource() { - return splitSource; - } - - public final void setSplitSource(OptimizedCallTarget splitSource) { - this.splitSource = splitSource; + public final OptimizedCallTarget getSourceCallTarget() { + return sourceCallTarget; } @Override @@ -389,8 +395,8 @@ if (isValid()) { superString += " "; } - if (splitSource != null) { - superString += " "; + if (sourceCallTarget != null) { + superString += " "; } return superString; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Thu Oct 23 17:20:10 2014 +0200 @@ -258,8 +258,8 @@ Map> groupedTargets = Truffle.getRuntime().getCallTargets().stream()// .map(target -> (OptimizedCallTarget) target)// .collect(Collectors.groupingBy(target -> { - if (target.getSplitSource() != null) { - return target.getSplitSource(); + if (target.getSourceCallTarget() != null) { + return target.getSourceCallTarget(); } return target; })); diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Thu Oct 23 17:20:10 2014 +0200 @@ -110,8 +110,8 @@ } @Override - public boolean isSplittable() { - return getCallTarget().getRootNode().isSplittable(); + public boolean isCallTargetCloningAllowed() { + return getCallTarget().getRootNode().isCloningAllowed(); } @Override @@ -129,7 +129,7 @@ } @Override - public OptimizedCallTarget getSplitCallTarget() { + public OptimizedCallTarget getClonedCallTarget() { return splitCallTarget; } @@ -158,7 +158,7 @@ // dummy replace to report the split replace(this, "Split call " + newTarget.toString()); - if (newTarget.getSplitSource() == null) { + if (newTarget.getSourceCallTarget() == null) { splitCallTarget = null; } else { splitCallTarget = newTarget; @@ -166,7 +166,7 @@ } @Override - public boolean split() { + public boolean cloneCallTarget() { splittingStrategy.forceSplitting(); return true; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java Thu Oct 23 17:20:10 2014 +0200 @@ -79,17 +79,17 @@ } @Override - public CallTarget getSplitCallTarget() { + public CallTarget getClonedCallTarget() { return null; } @Override - public boolean split() { + public boolean cloneCallTarget() { return false; } @Override - public boolean isSplittable() { + public boolean isCallTargetCloningAllowed() { return false; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Thu Oct 23 17:20:10 2014 +0200 @@ -32,17 +32,17 @@ * {@link CallTarget} remains the same for each consecutive call. This part of the Truffle API * enables the runtime system to perform additional optimizations on direct calls. * - * Optimizations that can be applied to a {@link DirectCallNode} are inlining and splitting. - * Inlining inlines this call site into the call graph of the parent {@link CallTarget}. Splitting - * duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site sensitive - * profiling information. + * Optimizations that can be applied to a {@link DirectCallNode} are inlining and call site + * sensitive AST duplication. Inlining inlines this call site into the call graph of the parent + * {@link CallTarget}. Call site sensitive AST duplication duplicates the {@link CallTarget} in an + * uninitialized state to collect call site sensitive profiling information. * * Please note: This class is not intended to be subclassed by guest language implementations. * * @see IndirectCallNode for calls with a non-constant target * @see TruffleRuntime#createDirectCallNode(CallTarget) * @see #forceInlining() - * @see #split() + * @see #cloneCallTarget() */ public abstract class DirectCallNode extends Node { @@ -111,46 +111,48 @@ } /** - * Returns true if this {@link DirectCallNode} can be split. A - * {@link DirectCallNode} can only be split if the runtime system supports splitting and if the - * {@link RootNode} contained the {@link CallTarget} returns true for - * {@link RootNode#isSplittable()}. + * Returns true if the runtime system supports cloning and the {@link RootNode} + * returns true in {@link RootNode#isCloningAllowed()}. * - * @return true if the target can be split + * @return true if the target is allowed to be cloned. */ - public abstract boolean isSplittable(); + public abstract boolean isCallTargetCloningAllowed(); /** - * Enforces the runtime system to split the {@link CallTarget}. If the {@link DirectCallNode} is - * not splittable this methods has no effect. + * Clones the {@link CallTarget} instance returned by {@link #getCallTarget()} in an + * uninitialized state for this {@link DirectCallNode}. This can be sensible to gather call site + * sensitive profiling information for this {@link DirectCallNode}. If + * {@link #isCallTargetCloningAllowed()} returns false this method has no effect + * and returns false. */ - public abstract boolean split(); + public abstract boolean cloneCallTarget(); /** - * Returns true if the target of the {@link DirectCallNode} was split. + * Returns true if the target of the {@link DirectCallNode} was cloned by the + * runtime system or by the guest language implementation. * * @return if the target was split */ - public final boolean isSplit() { - return getSplitCallTarget() != null; + public final boolean isCallTargetCloned() { + return getClonedCallTarget() != null; } /** - * Returns the split {@link CallTarget} if this method is split. + * Returns the split {@link CallTarget} if this call site's {@link CallTarget} is cloned. * * @return the split {@link CallTarget} */ - public abstract CallTarget getSplitCallTarget(); + public abstract CallTarget getClonedCallTarget(); /** * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the * {@link CallTarget} was split this method returns the {@link CallTarget} returned by - * {@link #getSplitCallTarget()}. + * {@link #getClonedCallTarget()}. * * @return the used {@link CallTarget} when node is called */ public CallTarget getCurrentCallTarget() { - CallTarget split = getSplitCallTarget(); + CallTarget split = getClonedCallTarget(); if (split != null) { return split; } else { diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Thu Oct 23 17:20:10 2014 +0200 @@ -25,6 +25,7 @@ package com.oracle.truffle.api.nodes; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.source.*; @@ -36,7 +37,7 @@ public abstract class RootNode extends Node { private RootCallTarget callTarget; - private final FrameDescriptor frameDescriptor; + @CompilationFinal private FrameDescriptor frameDescriptor; protected RootNode() { this(null, null); @@ -55,26 +56,24 @@ } } - /** - * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should - * return an AST that was never executed and must not be shared with other {@link RootNode} or - * {@link CallTarget} instances. This method is intended to be overridden by a subclass. - * - * @return the split {@link RootNode} - */ - public RootNode split() { - throw new UnsupportedOperationException(); + @Override + public Node copy() { + RootNode root = (RootNode) super.copy(); + root.frameDescriptor = frameDescriptor.shallowCopy(); + return root; } /** - * Returns true if this {@link RootNode} can be split. A {@link RootNode} can be - * split inside of a {@link CallTarget} that is invoked using a {@link DirectCallNode}. If this - * method returns true a proper implementation of {@link #split()} must also be - * provided. This method is intended to be overridden by a subclass. + * Returns true if this {@link RootNode} is allowed to be cloned. The runtime + * system might decide to create deep copies of the {@link RootNode} in order to gather context + * sensitive profiling feedback. The default implementation returns false. Guest + * language specific implementations may want to return true here to indicate that + * gathering call site specific profiling information might make sense for this {@link RootNode} + * . * - * @return true if splittable else false. + * @return true if cloning is allowed else false. */ - public boolean isSplittable() { + public boolean isCloningAllowed() { return false; } diff -r 94f16a759646 -r ab62800259ff graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Thu Oct 23 13:45:59 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Thu Oct 23 17:20:10 2014 +0200 @@ -41,25 +41,16 @@ /** The function body that is executed, and specialized during execution. */ @Child private SLExpressionNode bodyNode; - /** - * A copy of the uninitialized body. When performing method inlining, it is beneficial to inline - * the unspecialized function body, so that it is specialized in the context of the caller. This - * makes the specializations of the inlined function more precise. - */ - private final SLExpressionNode uninitializedBodyNode; - /** The name of the function, for printing purposes only. */ private final String name; /** The Simple execution context for this tree **/ private final SLContext context; - @CompilationFinal private boolean isSplittable; + @CompilationFinal private boolean isCloningAllowed; public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) { super(null, frameDescriptor); - /* Deep copy the body before any specialization occurs during execution. */ - this.uninitializedBodyNode = NodeUtil.cloneNode(bodyNode); this.bodyNode = bodyNode; this.name = name; this.context = context; @@ -74,8 +65,8 @@ return name; } - public void setSplittable(boolean isSplittable) { - this.isSplittable = isSplittable; + public void setCloningAllowed(boolean isCloningAllowed) { + this.isCloningAllowed = isCloningAllowed; } public SLExpressionNode getBodyNode() { @@ -83,13 +74,8 @@ } @Override - public boolean isSplittable() { - return isSplittable; - } - - @Override - public RootNode split() { - return new SLRootNode(this.context, getFrameDescriptor().shallowCopy(), NodeUtil.cloneNode(uninitializedBodyNode), name); + public boolean isCloningAllowed() { + return isCloningAllowed; } @Override