Skip to content

Commit fc07038

Browse files
committed
[GR-68601] Remove generator frame from PArguments
PullRequest: graalpython/3973
2 parents 3a537cd + a016a49 commit fc07038

File tree

18 files changed

+223
-293
lines changed

18 files changed

+223
-293
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/advanced/LeakTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,6 @@ protected String getLanguageId() {
346346
return languageId;
347347
}
348348

349-
@Override
350-
protected String[] getDefaultLanguages() {
351-
return new String[]{languageId};
352-
}
353-
354349
@Override
355350
protected void printHelp(OptionCategory maxCategory) {
356351
System.out.println("--lang ID --code CODE --forbidden-class FQN [--forbidden-class FQN]* [--shared-engine] [--keep-dump] [POLYGLOT-OPTIONS]");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextCEvalBuiltins.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyThreadState;
5353
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Void;
5454

55+
import com.oracle.graal.python.PythonLanguage;
5556
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApi11BuiltinNode;
5657
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
5758
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiNullaryBuiltinNode;
@@ -66,6 +67,7 @@
6667
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
6768
import com.oracle.graal.python.builtins.objects.frame.PFrame;
6869
import com.oracle.graal.python.builtins.objects.function.PArguments;
70+
import com.oracle.graal.python.builtins.objects.function.PFunction;
6971
import com.oracle.graal.python.builtins.objects.function.PKeyword;
7072
import com.oracle.graal.python.builtins.objects.function.Signature;
7173
import com.oracle.graal.python.builtins.objects.module.PythonModule;
@@ -81,6 +83,7 @@
8183
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
8284
import com.oracle.graal.python.runtime.GilNode;
8385
import com.oracle.graal.python.runtime.PythonContext;
86+
import com.oracle.graal.python.runtime.object.PFactory;
8487
import com.oracle.truffle.api.RootCallTarget;
8588
import com.oracle.truffle.api.TruffleLogger;
8689
import com.oracle.truffle.api.dsl.Bind;
@@ -151,10 +154,11 @@ Object getFrame(
151154
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, PyObject, PyObject, PyObjectConstPtr, Int, PyObjectConstPtr, Int, PyObjectConstPtr, Int, PyObject, PyObject}, call = Ignored)
152155
abstract static class GraalPyPrivate_Eval_EvalCodeEx extends CApi11BuiltinNode {
153156
@Specialization
154-
static Object doGeneric(PCode code, Object globals, Object locals,
157+
static Object doGeneric(PCode code, PythonObject globals, Object locals,
155158
Object argumentArrayPtr, int argumentCount, Object kwsPtr, int kwsCount, Object defaultValueArrayPtr, int defaultValueCount,
156159
Object kwdefaultsWrapper, Object closureObj,
157160
@Bind Node inliningTarget,
161+
@Bind PythonLanguage language,
158162
@Cached PRaiseNode raiseNode,
159163
@Cached CStructAccess.ReadObjectNode readNode,
160164
@Cached PythonCextBuiltins.CastKwargsNode castKwargsNode,
@@ -185,21 +189,18 @@ static Object doGeneric(PCode code, Object globals, Object locals,
185189
// prepare Python frame arguments
186190
Object[] userArguments = readNode.readPyObjectArray(argumentArrayPtr, argumentCount);
187191
Signature signature = getSignatureNode.execute(inliningTarget, code);
192+
PFunction function = PFactory.createFunction(language, code.getName(), code, globals, closure);
188193
Object[] pArguments = createArgumentsNode.execute(inliningTarget, code, userArguments, keywords, signature, null, null, defaults, kwdefaults, false);
189194

190195
// set custom locals
191196
if (!(locals instanceof PNone)) {
192197
PArguments.setSpecialArgument(pArguments, locals);
193198
}
194-
PArguments.setClosure(pArguments, closure);
199+
PArguments.setFunctionObject(pArguments, function);
195200
// TODO(fa): set builtins in globals
196201
// PythonModule builtins = getContext().getBuiltins();
197202
// setBuiltinsInGlobals(globals, setBuiltins, builtins, lib);
198-
if (globals instanceof PythonObject) {
199-
PArguments.setGlobals(pArguments, (PythonObject) globals);
200-
} else {
201-
// TODO(fa): raise appropriate exception
202-
}
203+
PArguments.setGlobals(pArguments, globals);
203204

204205
RootCallTarget rootCallTarget = getCallTargetNode.execute(inliningTarget, code);
205206
return invoke.execute(null, inliningTarget, rootCallTarget, pArguments);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/asyncio/PAsyncGen.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,24 @@
4242

4343
import com.oracle.graal.python.PythonLanguage;
4444
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
45+
import com.oracle.graal.python.builtins.objects.function.PFunction;
4546
import com.oracle.graal.python.builtins.objects.generator.PGenerator;
4647
import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode;
4748
import com.oracle.truffle.api.RootCallTarget;
48-
import com.oracle.truffle.api.strings.TruffleString;
49+
import com.oracle.truffle.api.frame.MaterializedFrame;
4950

5051
public final class PAsyncGen extends PGenerator {
5152
private boolean closed = false;
5253
private boolean hookCalled = false;
5354
private boolean runningAsync = false;
5455

55-
public static PAsyncGen create(PythonLanguage lang, TruffleString name, TruffleString qualname, PBytecodeRootNode rootNode, RootCallTarget[] callTargets, Object[] arguments) {
56-
rootNode.createGeneratorFrame(arguments);
57-
return new PAsyncGen(lang, name, qualname, rootNode, callTargets, arguments);
56+
public static PAsyncGen create(PythonLanguage lang, PFunction function, PBytecodeRootNode rootNode, RootCallTarget[] callTargets, Object[] arguments) {
57+
MaterializedFrame generatorFrame = rootNode.createGeneratorFrame(arguments);
58+
return new PAsyncGen(lang, function, generatorFrame, rootNode, callTargets, arguments);
5859
}
5960

60-
private PAsyncGen(PythonLanguage lang, TruffleString name, TruffleString qualname, PBytecodeRootNode rootNode, RootCallTarget[] callTargets, Object[] arguments) {
61-
super(lang, name, qualname, arguments, PythonBuiltinClassType.PAsyncGenerator, false, new BytecodeState(rootNode, callTargets));
61+
private PAsyncGen(PythonLanguage lang, PFunction function, MaterializedFrame generatorFrame, PBytecodeRootNode rootNode, RootCallTarget[] callTargets, Object[] arguments) {
62+
super(lang, function, generatorFrame, PythonBuiltinClassType.PAsyncGenerator, false, new BytecodeState(rootNode, callTargets));
6263
}
6364

6465
public boolean isClosed() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PArguments.java

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -25,50 +25,42 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.function;
2727

28-
import com.oracle.graal.python.builtins.objects.cell.PCell;
2928
import com.oracle.graal.python.builtins.objects.frame.PFrame;
3029
import com.oracle.graal.python.builtins.objects.object.PythonObject;
31-
import com.oracle.graal.python.runtime.PythonOptions;
30+
import com.oracle.graal.python.nodes.argument.CreateArgumentsNode;
3231
import com.oracle.graal.python.runtime.exception.PException;
3332
import com.oracle.truffle.api.exception.AbstractTruffleException;
3433
import com.oracle.truffle.api.frame.Frame;
35-
import com.oracle.truffle.api.frame.MaterializedFrame;
3634

37-
//@formatter:off
3835
/**
3936
* The layout of an argument array for a Python frame.
40-
*
41-
* +-------------------+
42-
* INDEX_GENERATOR_FRAME -> | MaterializedFrame |
43-
* +-------------------+
44-
* SPECIAL_ARGUMENT -> | Object |
45-
* +-------------------+
46-
* INDEX_GLOBALS_ARGUMENT -> | PythonObject |
47-
* +-------------------+
48-
* INDEX_CLOSURE -> | PCell[] |
49-
* +-------------------+
50-
* INDEX_CALLER_FRAME_INFO -> | PFrame.Reference |
51-
* +-------------------+
52-
* INDEX_CURRENT_FRAME_INFO -> | PFrame.Reference |
53-
* +-------------------+
54-
* INDEX_CURRENT_EXCEPTION -> | PException |
55-
* +-------------------+
56-
* USER_ARGUMENTS -> | arg_0 |
57-
* | arg_1 |
58-
* | ... |
59-
* | arg_(nArgs-1) |
60-
* +-------------------+
37+
* <ul>
38+
* <li>{@code SPECIAL_ARGUMENT (Object)}</li>
39+
* <li>{@code INDEX_GLOBALS_ARGUMENT (PythonObject)}</li>
40+
* <li>{@code INDEX_FUNCTION_OBJECT (PFunction)}</li>
41+
* <li>{@code INDEX_CALLER_FRAME_INFO (PFrame.Reference)}</li>
42+
* <li>{@code INDEX_CURRENT_FRAME_INFO (PFrame.Reference)}</li>
43+
* <li>{@code INDEX_CURRENT_EXCEPTION (PException)}</li>
44+
* <li>{@code USER_ARGUMENTS (Object...)}; Further defined by a particular call convention:
45+
* <ul>
46+
* <li>Function calls: non-variadic arguments as individual items in order of {@code co_varnames},
47+
* then varargs as {@code Object[]} iff the function takes them, then variadic keywords as
48+
* {@code PKeyword[]} iff the function takes them. Implemented by {@link CreateArgumentsNode}</li>
49+
* <li>Generator resumes (non-DSL): generator frame ({@code MaterializedFrame}), then the send value
50+
* or null</li>
51+
* <li>Generator resumes (DSL): doesn't use PArguments to call the continuation root</li>
52+
* </ul>
53+
* </li>
54+
* </ul>
6155
*/
62-
//@formatter:on
6356
public final class PArguments {
64-
private static final int INDEX_GENERATOR_FRAME = 0;
65-
private static final int INDEX_SPECIAL_ARGUMENT = 1;
66-
private static final int INDEX_GLOBALS_ARGUMENT = 2;
67-
private static final int INDEX_CLOSURE = 3;
68-
private static final int INDEX_CALLER_FRAME_INFO = 4;
69-
private static final int INDEX_CURRENT_FRAME_INFO = 5;
70-
private static final int INDEX_CURRENT_EXCEPTION = 6;
71-
public static final int USER_ARGUMENTS_OFFSET = 7;
57+
private static final int INDEX_SPECIAL_ARGUMENT = 0;
58+
private static final int INDEX_GLOBALS_ARGUMENT = 1;
59+
private static final int INDEX_FUNCTION_OBJECT = 2;
60+
private static final int INDEX_CALLER_FRAME_INFO = 3;
61+
private static final int INDEX_CURRENT_FRAME_INFO = 4;
62+
private static final int INDEX_CURRENT_EXCEPTION = 5;
63+
public static final int USER_ARGUMENTS_OFFSET = 6;
7264

7365
public static boolean isPythonFrame(Frame frame) {
7466
return frame != null && isPythonFrame(frame.getArguments());
@@ -105,8 +97,6 @@ public static void setSpecialArgument(Object[] arguments, Object value) {
10597
/**
10698
* The special argument is used for various purposes, none of which can occur at the same time:
10799
* <ul>
108-
* <li>The value sent to a generator via <code>send</code></li>
109-
* <li>An exception thrown through a generator via <code>throw</code></li>
110100
* <li>The custom locals in a module or class scope when called through <code>exec</code> or
111101
* <code>__build_class__</code></li>
112102
* </ul>
@@ -199,16 +189,12 @@ public static void setExceptionUnchecked(Object[] arguments, Object exc) {
199189
arguments[INDEX_CURRENT_EXCEPTION] = exc;
200190
}
201191

202-
public static void setClosure(Object[] arguments, PCell[] closure) {
203-
arguments[INDEX_CLOSURE] = closure;
204-
}
205-
206-
public static PCell[] getClosure(Object[] arguments) {
207-
return (PCell[]) arguments[INDEX_CLOSURE];
192+
public static PFunction getFunctionObject(Object[] arguments) {
193+
return (PFunction) arguments[INDEX_FUNCTION_OBJECT];
208194
}
209195

210-
public static PCell[] getClosure(Frame frame) {
211-
return getClosure(frame.getArguments());
196+
public static void setFunctionObject(Object[] arguments, PFunction function) {
197+
arguments[INDEX_FUNCTION_OBJECT] = function;
212198
}
213199

214200
public static void setArgument(Object[] arguments, int index, Object value) {
@@ -223,43 +209,6 @@ public static Object getArgument(Frame frame, int index) {
223209
return getArgument(frame.getArguments(), index);
224210
}
225211

226-
public static MaterializedFrame getGeneratorFrame(Object[] arguments) {
227-
assert !PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER;
228-
return (MaterializedFrame) arguments[INDEX_GENERATOR_FRAME];
229-
}
230-
231-
public static MaterializedFrame getGeneratorFrame(Frame frame) {
232-
return getGeneratorFrame(frame.getArguments());
233-
}
234-
235-
public static MaterializedFrame getGeneratorFrameSafe(Frame frame) {
236-
return getGeneratorFrameSafe(frame.getArguments());
237-
}
238-
239-
public static MaterializedFrame getGeneratorFrameSafe(Object[] arguments) {
240-
if (arguments[INDEX_GENERATOR_FRAME] instanceof MaterializedFrame) {
241-
return getGeneratorFrame(arguments);
242-
} else {
243-
return null;
244-
}
245-
}
246-
247-
public static void setGeneratorFrame(Object[] arguments, MaterializedFrame generatorFrame) {
248-
arguments[INDEX_GENERATOR_FRAME] = generatorFrame;
249-
}
250-
251-
/**
252-
* This should be used only in GeneratorFunctionRootNode, later the slot is overwritten with
253-
* generator frame
254-
*/
255-
public static PFunction getGeneratorFunction(Object[] arguments) {
256-
return (PFunction) arguments[INDEX_GENERATOR_FRAME];
257-
}
258-
259-
public static void setGeneratorFunction(Object[] arguments, PFunction generatorFunction) {
260-
arguments[INDEX_GENERATOR_FRAME] = generatorFunction;
261-
}
262-
263212
/**
264213
* Synchronizes the arguments array of a Truffle frame with a {@link PFrame}. Copies only those
265214
* arguments that are necessary to be synchronized between the two.
@@ -271,7 +220,7 @@ public static void synchronizeArgs(Frame frameToMaterialize, PFrame escapedFrame
271220
// copy only some carefully picked internal arguments
272221
setSpecialArgument(copiedArgs, getSpecialArgument(arguments));
273222
setGlobals(copiedArgs, getGlobals(arguments));
274-
setClosure(copiedArgs, getClosure(arguments));
223+
setFunctionObject(copiedArgs, getFunctionObject(arguments));
275224

276225
escapedFrame.setArguments(copiedArgs);
277226
}

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

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
import com.oracle.graal.python.runtime.PythonOptions;
8282
import com.oracle.graal.python.runtime.exception.PException;
8383
import com.oracle.graal.python.runtime.object.PFactory;
84-
import com.oracle.graal.python.util.PythonUtils;
8584
import com.oracle.truffle.api.Truffle;
8685
import com.oracle.truffle.api.bytecode.ContinuationResult;
8786
import com.oracle.truffle.api.dsl.Bind;
@@ -103,36 +102,6 @@
103102

104103
@CoreFunctions(extendClasses = {PythonBuiltinClassType.PCoroutine, PythonBuiltinClassType.PGenerator})
105104
public final class CommonGeneratorBuiltins extends PythonBuiltins {
106-
/**
107-
* Creates a fresh copy of the generator arguments to be used for the next invocation of the
108-
* generator. This is necessary to avoid persisting caller state. For example: If the generator
109-
* is invoked using {@code next(g)} outside of any {@code except} handler but the generator
110-
* requests the exception state, then the exception state will be written into the arguments. If
111-
* we now use the same arguments array every time, the next invocation would think that there is
112-
* not an exception but in fact, a subsequent call to {@code next} may have a different
113-
* exception state.
114-
*
115-
* <pre>
116-
* g = my_generator()
117-
*
118-
* # invoke without any exception context
119-
* next(g)
120-
*
121-
* try:
122-
* raise ValueError
123-
* except ValueError:
124-
* # invoke with exception context
125-
* next(g)
126-
* </pre>
127-
*
128-
* This is necessary for correct chaining of exceptions.
129-
*/
130-
private static Object[] prepareArguments(PGenerator self) {
131-
Object[] generatorArguments = self.getArguments();
132-
Object[] arguments = new Object[generatorArguments.length];
133-
PythonUtils.arraycopy(generatorArguments, 0, arguments, 0, arguments.length);
134-
return arguments;
135-
}
136105

137106
@Override
138107
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
@@ -168,10 +137,7 @@ static Object cached(VirtualFrame frame, Node inliningTarget, PGenerator self, O
168137
@Exclusive @Cached IsBuiltinObjectProfile errorProfile,
169138
@Exclusive @Cached PRaiseNode raiseNode) {
170139
self.setRunning(true);
171-
Object[] arguments = prepareArguments(self);
172-
if (sendValue != null) {
173-
PArguments.setSpecialArgument(arguments, sendValue);
174-
}
140+
Object[] arguments = self.getCallArguments(sendValue);
175141
GeneratorYieldResult result;
176142
try {
177143
result = (GeneratorYieldResult) invoke.execute(frame, inliningTarget, callNode, arguments);
@@ -221,7 +187,7 @@ static Object cachedBytecodeDSL(VirtualFrame frame, Node inliningTarget, PGenera
221187

222188
if (firstCall) {
223189
// First invocation: call the regular root node.
224-
arguments = prepareArguments(self);
190+
arguments = self.getCallArguments(sendValue);
225191
} else {
226192
// Subsequent invocations: call a continuation root node.
227193
arguments = new Object[]{continuation.getFrame(), sendValue};
@@ -249,10 +215,7 @@ static Object generic(VirtualFrame frame, Node inliningTarget, PGenerator self,
249215
@Exclusive @Cached IsBuiltinObjectProfile errorProfile,
250216
@Exclusive @Cached PRaiseNode raiseNode) {
251217
self.setRunning(true);
252-
Object[] arguments = prepareArguments(self);
253-
if (sendValue != null) {
254-
PArguments.setSpecialArgument(arguments, sendValue);
255-
}
218+
Object[] arguments = self.getCallArguments(sendValue);
256219
GeneratorYieldResult result;
257220
try {
258221
result = (GeneratorYieldResult) invoke.execute(frame, inliningTarget, self.getCurrentCallTarget(), arguments);
@@ -282,7 +245,7 @@ static Object genericBytecodeDSL(VirtualFrame frame, Node inliningTarget, PGener
282245
Object[] arguments;
283246
if (firstInvocationProfile.profile(inliningTarget, continuation == null)) {
284247
// First invocation: call the regular root node.
285-
arguments = prepareArguments(self);
248+
arguments = self.getCallArguments(sendValue);
286249
} else {
287250
// Subsequent invocations: call a continuation root node.
288251
arguments = new Object[]{continuation.getFrame(), sendValue};
@@ -418,7 +381,7 @@ static Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object
418381
if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER) {
419382
generatorFrame = Truffle.getRuntime().createMaterializedFrame(PArguments.create(), self.getRootNode().getFrameDescriptor());
420383
} else {
421-
generatorFrame = PArguments.getGeneratorFrame(self.getArguments());
384+
generatorFrame = self.getGeneratorFrame();
422385
}
423386
PFrame pFrame = MaterializeFrameNode.materializeGeneratorFrame(location, generatorFrame, PFrame.Reference.EMPTY);
424387
FrameInfo info = (FrameInfo) generatorFrame.getFrameDescriptor().getInfo();

0 commit comments

Comments
 (0)