Skip to content

Commit b8ba18b

Browse files
committed
provide frame argument to calls if possible, pass frame to varargs builtins, implement super.__init__ as builtin
1 parent dd7e6c1 commit b8ba18b

33 files changed

+378
-224
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/runtime/PythonModuleTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import com.oracle.graal.python.PythonLanguage;
3838
import com.oracle.graal.python.builtins.objects.function.PArguments;
39+
import com.oracle.graal.python.builtins.objects.function.PKeyword;
3940
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
4041
import com.oracle.graal.python.builtins.objects.module.PythonModule;
4142
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
@@ -66,15 +67,15 @@ public void pythonModuleTest() {
6667
public void builtinsMinTest() {
6768
final PythonModule builtins = context.getBuiltins();
6869
PBuiltinMethod min = (PBuiltinMethod) builtins.getAttribute(BuiltinNames.MIN);
69-
Object returnValue = InvokeNode.create(min).invoke(createWithUserArguments(builtins, 4, 2, 1));
70+
Object returnValue = InvokeNode.create(min).execute(null, createWithUserArguments(builtins, 4, 2, 1), PKeyword.EMPTY_KEYWORDS);
7071
assertEquals(1, returnValue);
7172
}
7273

7374
@Test
7475
public void builtinsIntTest() {
7576
final PythonModule builtins = context.getBuiltins();
7677
PythonBuiltinClass intClass = (PythonBuiltinClass) builtins.getAttribute(BuiltinNames.INT);
77-
Object returnValue = InvokeNode.create(intClass).invoke(createWithUserArguments(intClass, "42"));
78+
Object returnValue = InvokeNode.create(intClass).execute(null, createWithUserArguments(intClass, "42"), PKeyword.EMPTY_KEYWORDS);
7879
assertEquals(42, returnValue);
7980
}
8081

@@ -83,7 +84,7 @@ public void mainModuleTest() {
8384
PythonModule main = context.getMainModule();
8485
PythonModule builtins = (PythonModule) main.getAttribute(__BUILTINS__);
8586
PBuiltinMethod abs = (PBuiltinMethod) builtins.getAttribute(BuiltinNames.ABS);
86-
Object returned = InvokeNode.create(abs).invoke(createWithUserArguments(builtins, -42));
87+
Object returned = InvokeNode.create(abs).execute(null, createWithUserArguments(builtins, -42), PKeyword.EMPTY_KEYWORDS);
8788
assertEquals(42, returned);
8889
}
8990

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
3838
import com.oracle.graal.python.builtins.objects.function.PArguments;
3939
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
40+
import com.oracle.graal.python.builtins.objects.function.PKeyword;
4041
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
4142
import com.oracle.graal.python.builtins.objects.module.PythonModule;
4243
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -356,7 +357,7 @@ protected String toString(PythonContext context, Object value) {
356357
Object[] userArgs = PArguments.create(2);
357358
PArguments.setArgument(userArgs, 0, PNone.NONE);
358359
PArguments.setArgument(userArgs, 1, value);
359-
Object res = InvokeNode.create(reprMethod).invoke(userArgs);
360+
Object res = InvokeNode.create(reprMethod).execute(null, userArgs, PKeyword.EMPTY_KEYWORDS);
360361
return res.toString();
361362
}
362363

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ protected AtExitCallTarget(TruffleLanguage<?> language, Object callable, Object[
8484

8585
@Override
8686
public Object execute(VirtualFrame frame) {
87-
return callNode.execute(callable, arguments, keywords);
87+
return callNode.execute(frame, callable, arguments, keywords);
8888
}
8989
}
9090

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@
159159
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
160160
import com.oracle.truffle.api.dsl.Specialization;
161161
import com.oracle.truffle.api.dsl.TypeSystemReference;
162+
import com.oracle.truffle.api.frame.VirtualFrame;
162163
import com.oracle.truffle.api.nodes.UnexpectedResultException;
163164
import com.oracle.truffle.api.profiles.BranchProfile;
164165
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -1175,8 +1176,8 @@ public PList listObject(@SuppressWarnings("unused") Object cls, Object arg) {
11751176
@GenerateNodeFactory
11761177
public abstract static class ObjectNode extends PythonVarargsBuiltinNode {
11771178
@Override
1178-
public final Object varArgExecute(Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported {
1179-
return execute(PNone.NO_VALUE, arguments, keywords);
1179+
public final Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported {
1180+
return execute(frame, PNone.NO_VALUE, arguments, keywords);
11801181
}
11811182

11821183
@Specialization
@@ -1500,8 +1501,7 @@ public Object type(Object cls, Object obj, PNone bases, PNone dict, PKeyword[] k
15001501
}
15011502

15021503
@Specialization(guards = {"!isNoValue(bases)", "!isNoValue(namespace)"})
1503-
@TruffleBoundary
1504-
public Object type(PythonClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds,
1504+
public Object type(VirtualFrame frame, PythonClass cls, String name, PTuple bases, PDict namespace, PKeyword[] kwds,
15051505
@Cached("create()") GetClassNode getMetaclassNode,
15061506
@Cached("create(__NEW__)") LookupInheritedAttributeNode getNewFuncNode,
15071507
@Cached("create()") CallDispatchNode callNewFuncNode,
@@ -1512,9 +1512,14 @@ public Object type(PythonClass cls, String name, PTuple bases, PDict namespace,
15121512
if (newFunc instanceof PBuiltinFunction && (((PBuiltinFunction) newFunc).getFunctionRootNode() == getRootNode())) {
15131513
// the new metaclass has the same __new__ function as we are in
15141514
} else {
1515-
return callNewFuncNode.executeCall(newFunc, createArgs.execute(metaclass, name, bases, namespace), kwds);
1515+
return callNewFuncNode.executeCall(frame, newFunc, createArgs.execute(metaclass, name, bases, namespace), kwds);
15161516
}
15171517
}
1518+
return typeMetaclass(name, bases, namespace, metaclass);
1519+
}
1520+
1521+
@TruffleBoundary
1522+
private Object typeMetaclass(String name, PTuple bases, PDict namespace, PythonClass metaclass) {
15181523
if (name.indexOf('\0') != -1) {
15191524
throw raise(ValueError, "type name must not contain null characters");
15201525
}
@@ -1566,14 +1571,14 @@ private static boolean isSubType(PythonClass subclass, PythonClass superclass) {
15661571
return false;
15671572
}
15681573

1569-
protected abstract Object execute(Object cls, Object name, Object bases, Object dict, PKeyword[] kwds);
1574+
protected abstract Object execute(VirtualFrame frame, Object cls, Object name, Object bases, Object dict, PKeyword[] kwds);
15701575

15711576
protected static TypeNode create() {
15721577
return BuiltinConstructorsFactory.TypeNodeFactory.create(null);
15731578
}
15741579

15751580
@Specialization(guards = {"!isNoValue(bases)", "!isNoValue(dict)"})
1576-
public Object typeGeneric(Object cls, Object name, Object bases, Object dict, PKeyword[] kwds,
1581+
public Object typeGeneric(VirtualFrame frame, Object cls, Object name, Object bases, Object dict, PKeyword[] kwds,
15771582
@Cached("create()") TypeNode nextTypeNode) {
15781583
if (PGuards.isNoValue(bases) && !PGuards.isNoValue(dict) || !PGuards.isNoValue(bases) && PGuards.isNoValue(dict)) {
15791584
throw raise(TypeError, "type() takes 1 or 3 arguments");
@@ -1587,7 +1592,7 @@ public Object typeGeneric(Object cls, Object name, Object bases, Object dict, PK
15871592
// TODO: this is actually allowed, deal with it
15881593
throw raise(NotImplementedError, "creating a class with non-class metaclass");
15891594
}
1590-
return nextTypeNode.execute(cls, name, bases, dict, kwds);
1595+
return nextTypeNode.execute(frame, cls, name, bases, dict, kwds);
15911596
}
15921597
}
15931598

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ public Object minmaxBinaryWithKey(Object arg1, Object[] args, PythonObject keywo
10071007
}
10081008

10091009
private static Object applyKeyFunction(PythonObject keywordArg, CallNode keyCall, Object currentValue) {
1010-
return keyCall == null ? currentValue : keyCall.execute(keywordArg, new Object[]{currentValue}, PKeyword.EMPTY_KEYWORDS);
1010+
return keyCall == null ? currentValue : keyCall.execute(null, keywordArg, new Object[]{currentValue}, PKeyword.EMPTY_KEYWORDS);
10111011
}
10121012
}
10131013

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

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASS__;
4344
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
4445

4546
import java.io.IOException;
@@ -53,11 +54,21 @@
5354
import com.oracle.graal.python.builtins.CoreFunctions;
5455
import com.oracle.graal.python.builtins.PythonBuiltins;
5556
import com.oracle.graal.python.builtins.objects.PNone;
57+
import com.oracle.graal.python.builtins.objects.cell.PCell;
5658
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
59+
import com.oracle.graal.python.builtins.objects.function.PArguments;
60+
import com.oracle.graal.python.builtins.objects.function.PKeyword;
5761
import com.oracle.graal.python.builtins.objects.ints.PInt;
5862
import com.oracle.graal.python.builtins.objects.str.PString;
63+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
64+
import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode;
65+
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
66+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
67+
import com.oracle.graal.python.nodes.frame.ReadLocalVariableNode;
68+
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
5969
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6070
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
71+
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
6172
import com.oracle.graal.python.runtime.PythonContext;
6273
import com.oracle.graal.python.runtime.PythonCore;
6374
import com.oracle.graal.python.runtime.exception.PException;
@@ -67,12 +78,18 @@
6778
import com.oracle.truffle.api.Truffle;
6879
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
6980
import com.oracle.truffle.api.TruffleOptions;
81+
import com.oracle.truffle.api.dsl.Cached;
82+
import com.oracle.truffle.api.dsl.Fallback;
7083
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7184
import com.oracle.truffle.api.dsl.NodeFactory;
7285
import com.oracle.truffle.api.dsl.Specialization;
86+
import com.oracle.truffle.api.frame.Frame;
87+
import com.oracle.truffle.api.frame.FrameSlot;
88+
import com.oracle.truffle.api.frame.FrameSlotTypeException;
7389
import com.oracle.truffle.api.frame.VirtualFrame;
7490
import com.oracle.truffle.api.nodes.DirectCallNode;
7591
import com.oracle.truffle.api.nodes.RootNode;
92+
import com.oracle.truffle.api.profiles.ConditionProfile;
7693

7794
@CoreFunctions(defineModule = "sys")
7895
public class SysModuleBuiltins extends PythonBuiltins {
@@ -182,6 +199,143 @@ public void initialize(PythonCore core) {
182199
super.initialize(core);
183200
}
184201

202+
@Builtin(name = "__super__init__", minNumOfArguments = 1, takesVariableArguments = true, takesVariableKeywords = true)
203+
@GenerateNodeFactory
204+
public abstract static class SuperInitNode extends PythonVarargsBuiltinNode {
205+
206+
@Child private SetAttributeNode setTypeAttribute = SetAttributeNode.create("__type__");
207+
@Child private SetAttributeNode setObjAttribute = SetAttributeNode.create("__obj__");
208+
209+
@Override
210+
public Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported {
211+
if (keywords.length != 0) {
212+
throw raise(PythonErrorType.RuntimeError, "super(): unexpected keyword arguments");
213+
}
214+
if (arguments.length == 1) {
215+
return execute(frame, arguments[0], PNone.NO_VALUE, PNone.NO_VALUE);
216+
} else if (arguments.length == 2) {
217+
return execute(frame, arguments[0], arguments[1], PNone.NO_VALUE);
218+
} else if (arguments.length == 3) {
219+
return execute(frame, arguments[0], arguments[1], arguments[2]);
220+
} else {
221+
throw raise(PythonErrorType.RuntimeError, "super(): invalid number of arguments");
222+
}
223+
}
224+
225+
@Override
226+
public final Object execute(VirtualFrame frame, Object self, Object[] arguments, PKeyword[] keywords) {
227+
if (keywords.length != 0) {
228+
throw raise(PythonErrorType.RuntimeError, "super(): unexpected keyword arguments");
229+
}
230+
if (arguments.length == 0) {
231+
return execute(frame, self, PNone.NO_VALUE, PNone.NO_VALUE);
232+
} else if (arguments.length == 1) {
233+
return execute(frame, self, arguments[0], PNone.NO_VALUE);
234+
} else if (arguments.length == 2) {
235+
return execute(frame, self, arguments[0], arguments[1]);
236+
} else {
237+
throw raise(PythonErrorType.RuntimeError, "super(): too many arguments");
238+
}
239+
}
240+
241+
protected abstract Object execute(VirtualFrame frame, Object self, Object cls, Object obj);
242+
243+
@Specialization(guards = {"!isNoValue(cls)", "!isNoValue(obj)"})
244+
PNone init(Object self, Object cls, Object obj) {
245+
if (!(cls instanceof PythonClass)) {
246+
throw raise(PythonErrorType.RuntimeError, "super(): __class__ is not a type (%p)", cls);
247+
}
248+
setTypeAttribute.execute(self, cls);
249+
setObjAttribute.execute(self, obj);
250+
return PNone.NONE;
251+
}
252+
253+
protected boolean isInBuiltinFunctionRoot() {
254+
return getRootNode() instanceof BuiltinFunctionRootNode;
255+
}
256+
257+
protected ReadLocalVariableNode createRead(VirtualFrame frame) {
258+
FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(__CLASS__);
259+
if (slot == null) {
260+
throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell");
261+
}
262+
return ReadLocalVariableNode.create(slot);
263+
}
264+
265+
/**
266+
* Executed with the frame of the calling method - direct access to the frame.
267+
*/
268+
@Specialization(guards = {"!isInBuiltinFunctionRoot()", "isNoValue(clsArg)", "isNoValue(objArg)"})
269+
PNone initInPlace(VirtualFrame frame, Object self, @SuppressWarnings("unused") PNone clsArg, @SuppressWarnings("unused") PNone objArg,
270+
@Cached("createRead(frame)") ReadLocalVariableNode readClass,
271+
@Cached("create(0)") ReadIndexedArgumentNode readArgument,
272+
@Cached("createBinaryProfile()") ConditionProfile isCellProfile) {
273+
Object obj = readArgument.execute(frame);
274+
if (obj == PNone.NONE) {
275+
throw raise(PythonErrorType.RuntimeError, "super(): no arguments");
276+
}
277+
Object cls = readClass.execute(frame);
278+
if (isCellProfile.profile(cls instanceof PCell)) {
279+
cls = ((PCell) cls).getPythonRef();
280+
}
281+
if (cls == PNone.NONE) {
282+
throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell");
283+
}
284+
return init(self, cls, obj);
285+
}
286+
287+
/**
288+
* Executed within a {@link BuiltinFunctionRootNode} - indirect access to the frame.
289+
*/
290+
@Specialization(guards = {"isInBuiltinFunctionRoot()", "isNoValue(clsArg)", "isNoValue(objArg)"})
291+
PNone init(VirtualFrame frame, Object self, @SuppressWarnings("unused") PNone clsArg, @SuppressWarnings("unused") PNone objArg,
292+
@Cached("create(0)") ReadCallerFrameNode readCaller) {
293+
Frame target = readCaller.executeWith(frame);
294+
if (target == null) {
295+
throw raise(PythonErrorType.RuntimeError, "super(): no current frame");
296+
}
297+
Object[] arguments = target.getArguments();
298+
if (arguments.length <= PArguments.USER_ARGUMENTS_OFFSET) {
299+
throw raise(PythonErrorType.RuntimeError, "super(): no arguments");
300+
}
301+
Object obj = arguments[PArguments.USER_ARGUMENTS_OFFSET];
302+
if (obj == PNone.NONE) {
303+
throw raise(PythonErrorType.RuntimeError, "super(): no arguments");
304+
}
305+
306+
return initFromFrame(self, target, obj);
307+
}
308+
309+
@TruffleBoundary
310+
private PNone initFromFrame(Object self, Frame target, Object obj) {
311+
// TODO: remove me
312+
// TODO: do it properly via the python API in super.__init__ :
313+
// sys._getframe(1).f_code.co_closure?
314+
FrameSlot classSlot = target.getFrameDescriptor().findFrameSlot(__CLASS__);
315+
Object cls = PNone.NONE;
316+
if (classSlot != null) {
317+
try {
318+
cls = target.getObject(classSlot);
319+
if (cls instanceof PCell) {
320+
cls = ((PCell) cls).getPythonRef();
321+
}
322+
} catch (FrameSlotTypeException e) {
323+
// fallthrough
324+
}
325+
}
326+
if (cls == PNone.NONE) {
327+
throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell");
328+
}
329+
return init(self, cls, obj);
330+
}
331+
332+
@SuppressWarnings("unused")
333+
@Fallback
334+
PNone initFallback(Object self, Object cls, Object obj) {
335+
throw raise(PythonErrorType.RuntimeError, "super(): invalid arguments");
336+
}
337+
}
338+
185339
@Builtin(name = "exc_info", fixedNumOfArguments = 0)
186340
@GenerateNodeFactory
187341
public static abstract class ExcInfoNode extends PythonBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/ManagedMethodWrappersMR.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public Object access(MethKeywords object, Object[] arguments) {
9797
CompilerDirectives.transferToInterpreterAndInvalidate();
9898
dispatch = insert(CallNode.create());
9999
}
100-
return toSulongNode.execute(dispatch.execute(object.getDelegate(), pArgs, kwArgsArray));
100+
return toSulongNode.execute(dispatch.execute(null, object.getDelegate(), pArgs, kwArgsArray));
101101
}
102102

103103
@ExplodeLoop

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ public double fromhexFloat(PythonClass cl, String arg) {
489489
public Object fromhexO(PythonClass cl, String arg,
490490
@Cached("create(__CALL__)") LookupAndCallVarargsNode constr) {
491491
double value = fromHex(arg);
492-
return constr.execute(cl, new Object[]{cl, value});
492+
return constr.execute(null, cl, new Object[]{cl, value});
493493
}
494494

495495
@Fallback

0 commit comments

Comments
 (0)