Skip to content

Commit 01cec56

Browse files
committed
less cloning when creating functions
1 parent e623945 commit 01cec56

File tree

3 files changed

+48
-21
lines changed

3 files changed

+48
-21
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GraalPythonModuleBuiltins.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,8 @@ public boolean visit(Node node) {
410410
*/
411411
FunctionRootNode functionRootNode = (FunctionRootNode) func.getFunctionRootNode();
412412
assert !functionRootNode.isRewritten() : "a function cannot be annotated as builtin twice";
413-
functionRootNode = functionRootNode.copyWithNewSignature(signature.createWithSelf());
414-
functionRootNode.setRewritten();
415-
functionRootNode.accept(new NodeVisitor() {
413+
414+
functionRootNode = functionRootNode.rewriteWithNewSignature(signature.createWithSelf(), new NodeVisitor() {
416415

417416
public boolean visit(Node node) {
418417
if (node instanceof ReadVarArgsNode) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionRootNode.java

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import com.oracle.truffle.api.frame.VirtualFrame;
4747
import com.oracle.truffle.api.nodes.ExplodeLoop;
4848
import com.oracle.truffle.api.nodes.NodeUtil;
49+
import com.oracle.truffle.api.nodes.NodeVisitor;
50+
import com.oracle.truffle.api.nodes.RootNode;
4951
import com.oracle.truffle.api.profiles.BranchProfile;
5052
import com.oracle.truffle.api.profiles.ConditionProfile;
5153
import com.oracle.truffle.api.profiles.ValueProfile;
@@ -67,26 +69,60 @@ public class FunctionRootNode extends PClosureFunctionRootNode {
6769
@Child private ExpressionNode body;
6870
@Child private CalleeContext calleeContext = CalleeContext.create();
6971

70-
private ExpressionNode uninitializedBody;
71-
private boolean isRewritten = false;
72+
private final ExpressionNode uninitializedBody;
73+
private final boolean isRewritten;
7274

73-
public FunctionRootNode(PythonLanguage language, SourceSection sourceSection, String functionName, boolean isGenerator, boolean isRewritten, FrameDescriptor frameDescriptor, ExpressionNode body,
74-
ExecutionCellSlots executionCellSlots, Signature signature) {
75+
public FunctionRootNode(PythonLanguage language, SourceSection sourceSection, String functionName, boolean isGenerator, boolean isRewritten, FrameDescriptor frameDescriptor,
76+
ExpressionNode uninitializedBody, ExecutionCellSlots executionCellSlots, Signature signature) {
7577
super(language, frameDescriptor, executionCellSlots, signature);
7678
this.executionCellSlots = executionCellSlots;
7779

7880
this.sourceSection = sourceSection;
7981
assert sourceSection != null;
8082
this.functionName = functionName;
8183
this.isGenerator = isGenerator;
82-
this.body = new InnerRootNode(this, NodeUtil.cloneNode(body));
83-
this.uninitializedBody = NodeUtil.cloneNode(body);
84+
this.body = new InnerRootNode(this, NodeUtil.cloneNode(uninitializedBody));
85+
// "uninitializedBody" is never modified or executed
86+
this.uninitializedBody = uninitializedBody;
8487
this.generatorFrameProfile = isGenerator ? ValueProfile.createClassProfile() : null;
8588
this.isRewritten = isRewritten;
8689
}
8790

88-
public FunctionRootNode copyWithNewSignature(Signature newSignature) {
89-
return new FunctionRootNode(PythonLanguage.getCurrent(), getSourceSection(), functionName, isGenerator, isRewritten, getFrameDescriptor(), uninitializedBody, executionCellSlots, newSignature);
91+
/**
92+
* Creates a shallow copy.
93+
*/
94+
private FunctionRootNode(FunctionRootNode other) {
95+
super(PythonLanguage.getCurrent(), other.getFrameDescriptor(), other.executionCellSlots, other.getSignature());
96+
this.executionCellSlots = other.executionCellSlots;
97+
98+
this.sourceSection = other.getSourceSection();
99+
this.functionName = other.functionName;
100+
this.isGenerator = other.isGenerator;
101+
this.generatorFrameProfile = other.isGenerator ? ValueProfile.createClassProfile() : null;
102+
this.isRewritten = other.isRewritten;
103+
this.uninitializedBody = other.uninitializedBody;
104+
}
105+
106+
@Override
107+
protected boolean isCloneUninitializedSupported() {
108+
return true;
109+
}
110+
111+
@Override
112+
protected RootNode cloneUninitialized() {
113+
return new FunctionRootNode(PythonLanguage.getCurrent(), getSourceSection(), functionName, isGenerator, isRewritten, getFrameDescriptor(), uninitializedBody, executionCellSlots,
114+
getSignature());
115+
}
116+
117+
/**
118+
* Returns a new function that has its signature replaced and whose body has been modified by
119+
* the given node visitor.
120+
*/
121+
public FunctionRootNode rewriteWithNewSignature(Signature newSignature, NodeVisitor nodeVisitor) {
122+
ExpressionNode newUninitializedBody = NodeUtil.cloneNode(uninitializedBody);
123+
newUninitializedBody.accept(nodeVisitor);
124+
return new FunctionRootNode(PythonLanguage.getCurrent(), getSourceSection(), functionName, isGenerator, true, getFrameDescriptor(), newUninitializedBody, executionCellSlots,
125+
newSignature);
90126
}
91127

92128
public boolean isLambda() {
@@ -104,8 +140,7 @@ public FrameSlot[] getCellVarSlots() {
104140

105141
@Override
106142
public FunctionRootNode copy() {
107-
return new FunctionRootNode(PythonLanguage.getCurrent(), getSourceSection(), functionName, isGenerator, isRewritten, getFrameDescriptor(), uninitializedBody,
108-
executionCellSlots, getSignature());
143+
return new FunctionRootNode(this);
109144
}
110145

111146
@ExplodeLoop
@@ -175,13 +210,6 @@ public boolean isRewritten() {
175210
return isRewritten;
176211
}
177212

178-
public void setRewritten() {
179-
this.isRewritten = true;
180-
181-
// we need to update the uninitialized body as well
182-
this.uninitializedBody = NodeUtil.cloneNode(body);
183-
}
184-
185213
@Override
186214
public void initializeFrame(VirtualFrame frame) {
187215
initClosureAndCellVars(frame);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorFunctionRootNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public static RootCallTarget[] createYieldTargets(RootCallTarget callTarget) {
100100
RootCallTarget[] callTargets = new RootCallTarget[numYields + 1];
101101
callTargets[0] = callTarget;
102102
for (int i = 1; i < callTargets.length; i++) {
103-
callTargets[i] = Truffle.getRuntime().createCallTarget((RootNode) callTarget.getRootNode().copy());
103+
callTargets[i] = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(callTarget.getRootNode()));
104104
}
105105
return callTargets;
106106
}

0 commit comments

Comments
 (0)