Skip to content

Commit 902ea93

Browse files
fangerercosminbasca
authored andcommitted
Correctly wrap 'tp_iternext' slot.
1 parent 0f7e1a8 commit 902ea93

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ void initialize_hashes();
295295
#define JWRAPPER_NE (polyglot_invoke(PY_TRUFFLE_CEXT, "METH_NE"))
296296
#define JWRAPPER_GT (polyglot_invoke(PY_TRUFFLE_CEXT, "METH_GT"))
297297
#define JWRAPPER_GE (polyglot_invoke(PY_TRUFFLE_CEXT, "METH_GE"))
298+
#define JWRAPPER_ITERNEXT (polyglot_invoke(PY_TRUFFLE_CEXT, "METH_ITERNEXT"))
298299

299300
#define TDEBUG __builtin_debugtrap()
300301
#define get_method_flags_wrapper(flags) \

graalpython/com.oracle.graal.python.cext/src/typeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ int PyType_Ready(PyTypeObject* cls) {
534534
ADD_SLOT_CONV("__ge__", NULL, cls->tp_richcompare, -2, JWRAPPER_GE);
535535
}
536536
ADD_SLOT("__iter__", cls->tp_iter, -1);
537-
ADD_SLOT("__next__", cls->tp_iternext, -1);
537+
ADD_SLOT_CONV("__next__", NULL, cls->tp_iternext, -1, JWRAPPER_ITERNEXT);
538538
ADD_SLOT("__get__", cls->tp_descr_get, -3);
539539
ADD_SLOT_PRIMITIVE("__set__", cls->tp_descr_set, -3);
540540
ADD_SLOT_PRIMITIVE("__init__", cls->tp_init, METH_KEYWORDS | METH_VARARGS);

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ public Node copy() {
225225
@TruffleBoundary
226226
ExternalFunctionInvokeNode() {
227227
this.toSulongNode = CExtNodes.AllToSulongNode.create();
228+
this.checkResultNode = DefaultCheckFunctionResultNodeGen.create();
228229
}
229230

230231
@TruffleBoundary
@@ -1002,6 +1003,31 @@ public Signature getSignature() {
10021003
}
10031004
}
10041005

1006+
/**
1007+
* Wrapper root node for C function type {@code iternextfunc}.
1008+
*/
1009+
static class IterNextFuncRootNode extends MethodDescriptorRoot {
1010+
1011+
IterNextFuncRootNode(PythonLanguage language, String name, Object callable) {
1012+
super(language, name, callable);
1013+
}
1014+
1015+
IterNextFuncRootNode(PythonLanguage language, String name, Object callable, PExternalFunctionWrapper provider) {
1016+
super(language, name, callable, provider);
1017+
}
1018+
1019+
@Override
1020+
protected Object[] prepareCArguments(VirtualFrame frame) {
1021+
return new Object[]{readSelfNode.execute(frame)};
1022+
}
1023+
1024+
@Override
1025+
public Signature getSignature() {
1026+
// same signature as a method without arguments (just the self)
1027+
return MethNoargsRoot.SIGNATURE;
1028+
}
1029+
}
1030+
10051031
/**
10061032
* We need to inflate all primitives in order to avoid memory leaks. Explanation: Primitives
10071033
* would currently be wrapped into a PrimitiveNativeWrapper. If any of those will receive a

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

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.IntNode;
7272
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.AllocFuncRootNode;
7373
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.GetAttrFuncRootNode;
74+
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.IterNextFuncRootNode;
7475
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.MethDirectRoot;
7576
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.MethFastcallRoot;
7677
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.MethFastcallWithKeywordsRoot;
@@ -85,6 +86,7 @@
8586
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.RichCmpFuncRootNode;
8687
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.SSizeObjArgProcRootNode;
8788
import com.oracle.graal.python.builtins.modules.ExternalFunctionNodes.SetAttrFuncRootNode;
89+
import com.oracle.graal.python.builtins.modules.PythonCextBuiltinsFactory.CheckIterNextResultNodeGen;
8890
import com.oracle.graal.python.builtins.modules.PythonCextBuiltinsFactory.DefaultCheckFunctionResultNodeGen;
8991
import com.oracle.graal.python.builtins.modules.PythonCextBuiltinsFactory.GetByteArrayNodeGen;
9092
import com.oracle.graal.python.builtins.objects.PNone;
@@ -827,7 +829,6 @@ abstract static class PyTruffleGetInheritedNativeSlots extends NativeBuiltin {
827829
* custom slots at a time where the C API is not yet loaded. So we need to check if any of
828830
* the base classes defines custom slots and adapt the basicsize to allocate space for the
829831
* slots and add the native member slot descriptors.
830-
*
831832
*/
832833
@Specialization
833834
Object slots(Object module, Object pythonClass, String subKey,
@@ -990,6 +991,31 @@ protected static boolean isPythonObjectNativeWrapper(Object object) {
990991
}
991992
}
992993

994+
// equivalent to result processing done in 'wrap_next' in 'Objects/typeobject.c'
995+
abstract static class CheckIterNextResultNode extends CheckFunctionResultNode {
996+
997+
@Specialization(limit = "3")
998+
static Object doGeneric(String name, Object result,
999+
@CachedLibrary("result") InteropLibrary lib,
1000+
@CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef,
1001+
@Cached PRaiseNode raiseNode) {
1002+
if (lib.isNull(result)) {
1003+
PythonContext context = contextRef.get();
1004+
PException currentException = context.getCurrentException();
1005+
// if no exception occurred, the iterator is exhausted -> raise StopIteration
1006+
if (currentException == null) {
1007+
throw raiseNode.raise(PythonBuiltinClassType.StopIteration);
1008+
} else {
1009+
// consume exception
1010+
context.setCurrentException(null);
1011+
// re-raise exception
1012+
throw currentException.getExceptionForReraise();
1013+
}
1014+
}
1015+
return result;
1016+
}
1017+
}
1018+
9931019
@Builtin(name = "Py_NoValue")
9941020
@GenerateNodeFactory
9951021
abstract static class Py_NoValue extends PythonBuiltinNode {
@@ -2062,6 +2088,28 @@ protected MethGeNode() {
20622088
}
20632089
}
20642090

2091+
@Builtin(name = "METH_ITERNEXT")
2092+
@GenerateNodeFactory
2093+
public abstract static class MethIterNextNode extends PythonBuiltinNode {
2094+
private static final PExternalFunctionWrapper METH_ITERNEXT_CONVERTER = new PExternalFunctionWrapper(AllToSulongNode::create, CheckIterNextResultNodeGen::create) {
2095+
2096+
@Override
2097+
@TruffleBoundary
2098+
protected RootCallTarget createCallTarget(PythonLanguage language, String name, Object callable, boolean doArgAndResultConversion) {
2099+
if (!doArgAndResultConversion) {
2100+
return createCallTarget(new IterNextFuncRootNode(language, name, callable));
2101+
} else {
2102+
return createCallTarget(new IterNextFuncRootNode(language, name, callable, this));
2103+
}
2104+
}
2105+
};
2106+
2107+
@Specialization
2108+
static PExternalFunctionWrapper call() {
2109+
return METH_ITERNEXT_CONVERTER;
2110+
}
2111+
}
2112+
20652113
@Builtin(name = "PyTruffle_Bytes_EmptyWithCapacity", minNumOfPositionalArgs = 1)
20662114
@GenerateNodeFactory
20672115
abstract static class PyTruffle_Bytes_EmptyWithCapacity extends PythonUnaryBuiltinNode {

0 commit comments

Comments
 (0)