Skip to content

Commit afeb38e

Browse files
committed
generators should take the closure from the generator function that they are created from, not cache them. since the defaults can be changed, no generator function is actually stateless
1 parent 5b8a2a0 commit afeb38e

File tree

4 files changed

+14
-43
lines changed

4 files changed

+14
-43
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/PGenerator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public static PGenerator create(LazyPythonClass clazz, String name, RootCallTarg
6868
for (int i = 0; i < closure.length; i++) {
6969
generatorFrame.setObject(freeVarSlots[i], closure[i]);
7070
}
71+
} else {
72+
assert freeVarSlots.length == 0;
7173
}
7274
// initialize own cell vars to new cells (these cells will be used by nested functions to
7375
// create their own closures)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public FunctionDefinitionNode(String functionName, String enclosingClassName, Ex
6464
this.arity = arity;
6565
assert defaults == null || Arrays.stream(defaults).noneMatch(x -> x == null);
6666
this.defaults = defaults;
67+
assert kwDefaults == null || Arrays.stream(kwDefaults).noneMatch(x -> x == null);
6768
this.kwDefaults = kwDefaults;
6869
}
6970

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

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.oracle.truffle.api.Truffle;
4141
import com.oracle.truffle.api.frame.FrameDescriptor;
4242
import com.oracle.truffle.api.frame.VirtualFrame;
43+
import com.oracle.truffle.api.nodes.ExplodeLoop;
4344

4445
public class GeneratorFunctionDefinitionNode extends FunctionDefinitionNode {
4546
protected final int numOfActiveFlags;
@@ -62,18 +63,14 @@ public GeneratorFunctionDefinitionNode(String name, String enclosingClassName, E
6263
public static GeneratorFunctionDefinitionNode create(String name, String enclosingClassName, ExpressionNode doc, Arity arity, ExpressionNode[] defaults, KwDefaultExpressionNode[] kwDefaults,
6364
RootCallTarget callTarget, FrameDescriptor frameDescriptor, DefinitionCellSlots definitionCellSlots, ExecutionCellSlots executionCellSlots, int numOfActiveFlags,
6465
int numOfGeneratorBlockNode, int numOfGeneratorForNode) {
65-
if (defaults != null && defaults.length > 0) {
66-
return new GeneratorFunctionDefinitionNode(name, enclosingClassName, doc, arity, defaults, kwDefaults, callTarget,
67-
frameDescriptor, definitionCellSlots, executionCellSlots,
68-
numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
69-
}
70-
71-
return new StatelessGeneratorFunctionDefinitionNode(name, enclosingClassName, doc, arity, callTarget,
66+
return new GeneratorFunctionDefinitionNode(name, enclosingClassName, doc, arity, defaults, kwDefaults, callTarget,
7267
frameDescriptor, definitionCellSlots, executionCellSlots,
7368
numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
7469
}
7570

7671
@Override
72+
@ExplodeLoop // this should always be safe, how many syntactic defaults can one function have...
73+
// and these are constant
7774
public PGeneratorFunction execute(VirtualFrame frame) {
7875
Object[] defaultValues = null;
7976
if (defaults != null) {
@@ -90,45 +87,17 @@ public PGeneratorFunction execute(VirtualFrame frame) {
9087
}
9188
}
9289
PCell[] closure = getClosureFromLocals(frame);
93-
return withDocString(frame, factory().createGeneratorFunction(functionName, enclosingClassName, arity, getGeneratorCallTarget(closure), PArguments.getGlobals(frame), closure, defaultValues,
90+
return withDocString(frame, factory().createGeneratorFunction(functionName, enclosingClassName, arity, getGeneratorCallTarget(), PArguments.getGlobals(frame), closure, defaultValues,
9491
kwDefaultValues));
9592
}
9693

97-
protected RootCallTarget getGeneratorCallTarget(PCell[] closure) {
94+
protected RootCallTarget getGeneratorCallTarget() {
9895
if (generatorCallTarget == null) {
9996
CompilerDirectives.transferToInterpreterAndInvalidate();
10097
GeneratorFunctionRootNode generatorFunctionRootNode = new GeneratorFunctionRootNode(getContext().getLanguage(), callTarget, functionName, frameDescriptor,
101-
closure, executionCellSlots, numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
98+
executionCellSlots, numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
10299
generatorCallTarget = Truffle.getRuntime().createCallTarget(generatorFunctionRootNode);
103100
}
104101
return generatorCallTarget;
105102
}
106-
107-
/**
108-
* Creates a generator function that does not capture any state. Therefore, it can always return
109-
* the same generator function instance.
110-
*/
111-
public static final class StatelessGeneratorFunctionDefinitionNode extends GeneratorFunctionDefinitionNode {
112-
@CompilationFinal private PGeneratorFunction cached;
113-
114-
public StatelessGeneratorFunctionDefinitionNode(String name, String enclosingClassName, ExpressionNode doc, Arity arity, RootCallTarget callTarget,
115-
FrameDescriptor frameDescriptor, DefinitionCellSlots definitionCellSlots, ExecutionCellSlots executionCellSlots,
116-
int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode) {
117-
super(name, enclosingClassName, doc, arity, null, null, callTarget,
118-
frameDescriptor, definitionCellSlots, executionCellSlots,
119-
numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
120-
}
121-
122-
@Override
123-
public PGeneratorFunction execute(VirtualFrame frame) {
124-
if (cached == null) {
125-
CompilerDirectives.transferToInterpreterAndInvalidate();
126-
PCell[] closure = getClosureFromLocals(frame);
127-
cached = withDocString(frame,
128-
factory().createGeneratorFunction(functionName, enclosingClassName, arity, getGeneratorCallTarget(closure), PArguments.getGlobals(frame), closure, null, null));
129-
}
130-
return cached;
131-
}
132-
}
133-
134103
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
package com.oracle.graal.python.nodes.generator;
4242

4343
import com.oracle.graal.python.PythonLanguage;
44-
import com.oracle.graal.python.builtins.objects.cell.PCell;
44+
import com.oracle.graal.python.builtins.objects.function.PArguments;
4545
import com.oracle.graal.python.nodes.PClosureFunctionRootNode;
4646
import com.oracle.graal.python.parser.ExecutionCellSlots;
4747
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
@@ -56,18 +56,16 @@ public class GeneratorFunctionRootNode extends PClosureFunctionRootNode {
5656
private final int numOfActiveFlags;
5757
private final int numOfGeneratorBlockNode;
5858
private final int numOfGeneratorForNode;
59-
private final PCell[] closure;
6059
private final ExecutionCellSlots cellSlots;
6160
private final String name;
6261
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
6362

64-
public GeneratorFunctionRootNode(PythonLanguage language, RootCallTarget callTarget, String name, FrameDescriptor frameDescriptor, PCell[] closure, ExecutionCellSlots executionCellSlots,
63+
public GeneratorFunctionRootNode(PythonLanguage language, RootCallTarget callTarget, String name, FrameDescriptor frameDescriptor, ExecutionCellSlots executionCellSlots,
6564
int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode) {
6665
super(language, frameDescriptor, executionCellSlots);
6766
this.callTarget = callTarget;
6867
this.name = name;
6968
this.frameDescriptor = frameDescriptor;
70-
this.closure = closure;
7169
this.cellSlots = executionCellSlots;
7270
this.numOfActiveFlags = numOfActiveFlags;
7371
this.numOfGeneratorBlockNode = numOfGeneratorBlockNode;
@@ -76,7 +74,8 @@ public GeneratorFunctionRootNode(PythonLanguage language, RootCallTarget callTar
7674

7775
@Override
7876
public Object execute(VirtualFrame frame) {
79-
return factory.createGenerator(getName(), callTarget, frameDescriptor, frame.getArguments(), closure, cellSlots, numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
77+
return factory.createGenerator(getName(), callTarget, frameDescriptor, frame.getArguments(), PArguments.getClosure(frame), cellSlots, numOfActiveFlags, numOfGeneratorBlockNode,
78+
numOfGeneratorForNode);
8079
}
8180

8281
public RootNode getFunctionRootNode() {

0 commit comments

Comments
 (0)