Skip to content

Commit 7faf58a

Browse files
committed
Add tp_iternext slot
1 parent 9c88eca commit 7faf58a

67 files changed

Lines changed: 985 additions & 831 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/Slot.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,9 @@ enum SlotKind {
194194
/** set/delete object attribute */
195195
tp_setattro("__setattr__, __delattr__"),
196196
/** iter(obj) */
197-
tp_iter("__iter__");
197+
tp_iter("__iter__"),
198+
/** next(obj) */
199+
tp_iternext("__next__");
198200

199201
SlotKind(@SuppressWarnings("unused") String specialMethods) {
200202
}

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/SlotsMapping.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static String getSlotBaseClass(Slot s) {
7676
case tp_descr_get -> "TpSlotDescrGet.TpSlotDescrGetBuiltin" + getSuffix(s.isComplex());
7777
case tp_descr_set -> "TpSlotDescrSet.TpSlotDescrSetBuiltin";
7878
case tp_setattro -> "TpSlotSetAttr.TpSlotSetAttrBuiltin";
79+
case tp_iternext -> "TpSlotIterNext.TpSlotIterNextBuiltin";
7980
};
8081
}
8182

@@ -84,7 +85,7 @@ static String getSlotNodeBaseClass(Slot s) {
8485
case tp_descr_get -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrGet.DescrGetBuiltinNode";
8586
case nb_bool -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotInquiry.NbBoolBuiltinNode";
8687
case nb_index, nb_int, nb_float, nb_absolute, nb_positive, nb_negative, nb_invert,
87-
tp_iter ->
88+
tp_iter, tp_iternext ->
8889
"com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode";
8990
case nb_add, nb_subtract, nb_multiply, nb_remainder, nb_divmod, nb_lshift, nb_rshift, nb_and, nb_xor, nb_or,
9091
nb_floor_divide, nb_true_divide, nb_matrix_multiply ->

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/datatype/PRangeTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.oracle.graal.python.builtins.objects.range.PRange;
3636
import com.oracle.graal.python.lib.GetNextNode;
3737
import com.oracle.graal.python.lib.PyObjectGetIter;
38+
import com.oracle.graal.python.nodes.PGuards;
3839
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
3940
import com.oracle.graal.python.runtime.exception.PException;
4041
import com.oracle.graal.python.runtime.object.PFactory;
@@ -75,7 +76,7 @@ public void loopWithOnlyStop() throws UnexpectedResultException {
7576

7677
while (true) {
7778
try {
78-
int item = next.executeInt(null, iter);
79+
int item = PGuards.expectInteger(next.execute(null, iter));
7980
assertEquals(index, item);
8081
} catch (PException e) {
8182
e.expectStopIteration(null, errorProfile);
@@ -103,7 +104,7 @@ public void loopWithStep() throws UnexpectedResultException {
103104

104105
while (true) {
105106
try {
106-
int item = next.executeInt(null, iter);
107+
int item = PGuards.expectInteger(next.execute(null, iter));
107108
assertEquals(index, item);
108109
} catch (PException e) {
109110
e.expectStopIteration(null, errorProfile);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@
123123
import com.oracle.graal.python.builtins.modules.ctypes.SimpleCDataBuiltins;
124124
import com.oracle.graal.python.builtins.modules.ctypes.StgDictBuiltins;
125125
import com.oracle.graal.python.builtins.modules.functools.LruCacheWrapperBuiltins;
126+
import com.oracle.graal.python.builtins.modules.io.BufferedReaderMixinBuiltins;
127+
import com.oracle.graal.python.builtins.modules.io.BytesIOBuiltins;
126128
import com.oracle.graal.python.builtins.modules.io.IOBaseBuiltins;
129+
import com.oracle.graal.python.builtins.modules.io.StringIOBuiltins;
130+
import com.oracle.graal.python.builtins.modules.io.TextIOWrapperBuiltins;
127131
import com.oracle.graal.python.builtins.objects.NoneBuiltins;
128132
import com.oracle.graal.python.builtins.objects.array.ArrayBuiltins;
129133
import com.oracle.graal.python.builtins.objects.asyncio.AsyncGenSendBuiltins;
@@ -212,6 +216,7 @@
212216
import com.oracle.graal.python.builtins.objects.type.TpSlots.Builder;
213217
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
214218
import com.oracle.graal.python.builtins.objects.types.GenericAliasBuiltins;
219+
import com.oracle.graal.python.builtins.objects.types.GenericAliasIteratorBuiltins;
215220
import com.oracle.graal.python.builtins.objects.types.UnionTypeBuiltins;
216221
import com.oracle.graal.python.runtime.PythonContext;
217222
import com.oracle.truffle.api.CompilerAsserts;
@@ -317,7 +322,7 @@ public enum PythonBuiltinClassType implements TruffleObject {
317322
Super("super", J_BUILTINS, SuperBuiltins.SLOTS),
318323
PCode("code", Flags.PRIVATE_DERIVED_WODICT),
319324
PGenericAlias("GenericAlias", J_TYPES, Flags.PUBLIC_BASE_WODICT, GENERIC_ALIAS_M_FLAGS, GenericAliasBuiltins.SLOTS),
320-
PGenericAliasIterator("generic_alias_iterator", Flags.PRIVATE_DERIVED_WODICT),
325+
PGenericAliasIterator("generic_alias_iterator", Flags.PRIVATE_DERIVED_WODICT, GenericAliasIteratorBuiltins.SLOTS),
321326
PUnionType("UnionType", J_TYPES, Flags.PUBLIC_DERIVED_WODICT, UNION_TYPE_M_FLAGS, UnionTypeBuiltins.SLOTS),
322327
PZip("zip", J_BUILTINS, PZipBuiltins.SLOTS),
323328
PThread("start_new_thread", J__THREAD),
@@ -367,15 +372,15 @@ public enum PythonBuiltinClassType implements TruffleObject {
367372
PRawIOBase("_RawIOBase", "_io", IOBaseBuiltins.SLOTS),
368373
PTextIOBase("_TextIOBase", "_io", IOBaseBuiltins.SLOTS),
369374
PBufferedIOBase("_BufferedIOBase", "_io", IOBaseBuiltins.SLOTS),
370-
PBufferedReader("BufferedReader", "_io", Flags.PUBLIC_BASE_WDICT),
375+
PBufferedReader("BufferedReader", "_io", Flags.PUBLIC_BASE_WDICT, BufferedReaderMixinBuiltins.SLOTS),
371376
PBufferedWriter("BufferedWriter", "_io", Flags.PUBLIC_BASE_WDICT),
372377
PBufferedRWPair("BufferedRWPair", "_io", Flags.PUBLIC_BASE_WDICT),
373-
PBufferedRandom("BufferedRandom", "_io", Flags.PUBLIC_BASE_WDICT),
378+
PBufferedRandom("BufferedRandom", "_io", Flags.PUBLIC_BASE_WDICT, BufferedReaderMixinBuiltins.SLOTS),
374379
PFileIO("FileIO", "_io", Flags.PUBLIC_BASE_WDICT),
375-
PTextIOWrapper("TextIOWrapper", "_io", Flags.PUBLIC_BASE_WDICT),
380+
PTextIOWrapper("TextIOWrapper", "_io", Flags.PUBLIC_BASE_WDICT, TextIOWrapperBuiltins.SLOTS),
376381
PIncrementalNewlineDecoder("IncrementalNewlineDecoder", "_io", Flags.PUBLIC_BASE_WODICT),
377-
PStringIO("StringIO", "_io", Flags.PUBLIC_BASE_WDICT),
378-
PBytesIO("BytesIO", "_io", Flags.PUBLIC_BASE_WDICT),
382+
PStringIO("StringIO", "_io", Flags.PUBLIC_BASE_WDICT, StringIOBuiltins.SLOTS),
383+
PBytesIO("BytesIO", "_io", Flags.PUBLIC_BASE_WDICT, BytesIOBuiltins.SLOTS),
379384
PBytesIOBuf("_BytesIOBuffer", "_io", Flags.PRIVATE_BASE_WODICT),
380385

381386
PStatResult("stat_result", "os", Flags.PUBLIC_DERIVED_WODICT, TUPLE_M_FLAGS),

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

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.DeprecationWarning;
2929
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
30+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.StopIteration;
3031
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SyntaxError;
3132
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_FLUSH;
3233
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_WRITE;
@@ -84,7 +85,6 @@
8485
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___DICT__;
8586
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___FORMAT__;
8687
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___MRO_ENTRIES__;
87-
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___NEXT__;
8888
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___ROUND__;
8989
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
9090
import static com.oracle.graal.python.nodes.StringLiterals.T_FALSE;
@@ -156,16 +156,21 @@
156156
import com.oracle.graal.python.builtins.objects.object.PythonObject;
157157
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
158158
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
159+
import com.oracle.graal.python.builtins.objects.type.TpSlots;
160+
import com.oracle.graal.python.builtins.objects.type.TpSlots.GetObjectSlotsNode;
159161
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
160162
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
161163
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
162164
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
165+
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotIterNext.CallSlotTpIterNextNode;
163166
import com.oracle.graal.python.compiler.Compiler;
164167
import com.oracle.graal.python.compiler.RaisePythonExceptionErrorCallback;
165168
import com.oracle.graal.python.lib.GetNextNode;
166169
import com.oracle.graal.python.lib.PyCallableCheckNode;
167170
import com.oracle.graal.python.lib.PyEvalGetGlobals;
168171
import com.oracle.graal.python.lib.PyEvalGetLocals;
172+
import com.oracle.graal.python.lib.PyIterCheckNode;
173+
import com.oracle.graal.python.lib.PyIterNextNode;
169174
import com.oracle.graal.python.lib.PyMappingCheckNode;
170175
import com.oracle.graal.python.lib.PyNumberAbsoluteNode;
171176
import com.oracle.graal.python.lib.PyNumberAddNode;
@@ -288,7 +293,6 @@
288293
import com.oracle.truffle.api.nodes.Node;
289294
import com.oracle.truffle.api.nodes.RootNode;
290295
import com.oracle.truffle.api.nodes.UnexpectedResultException;
291-
import com.oracle.truffle.api.profiles.BranchProfile;
292296
import com.oracle.truffle.api.profiles.ConditionProfile;
293297
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
294298
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
@@ -1724,39 +1728,41 @@ static Object min(VirtualFrame frame, Object arg1, Object[] args, Object keyword
17241728
}
17251729

17261730
// next(iterator[, default])
1727-
@SuppressWarnings("unused")
17281731
@Builtin(name = J_NEXT, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2)
17291732
@GenerateNodeFactory
1730-
public abstract static class NextNode extends PythonBinaryBuiltinNode {
1733+
abstract static class NextNode extends PythonBinaryBuiltinNode {
17311734
@Specialization
1732-
public Object next(VirtualFrame frame, Object iterator, Object defaultObject,
1735+
static Object next(VirtualFrame frame, Object iterator, Object defaultObject,
17331736
@Bind("this") Node inliningTarget,
17341737
@Cached InlinedConditionProfile defaultIsNoValue,
1735-
@Cached("createNextCall()") LookupAndCallUnaryNode callNode,
1736-
@Cached IsBuiltinObjectProfile errorProfile) {
1737-
if (defaultIsNoValue.profile(inliningTarget, isNoValue(defaultObject))) {
1738-
return callNode.executeObject(frame, iterator);
1739-
} else {
1740-
try {
1741-
return callNode.executeObject(frame, iterator);
1742-
} catch (PException e) {
1743-
e.expectStopIteration(inliningTarget, errorProfile);
1738+
@Cached GetObjectSlotsNode getSlots,
1739+
@Cached CallSlotTpIterNextNode callIterNext,
1740+
@Cached PRaiseNode raiseTypeError,
1741+
@Cached PRaiseNode raiseStopIteration,
1742+
@Cached IsBuiltinObjectProfile stopIterationProfile) {
1743+
TpSlots slots = getSlots.execute(inliningTarget, iterator);
1744+
if (!PyIterCheckNode.checkSlots(slots)) {
1745+
throw raiseTypeError.raise(inliningTarget, TypeError, ErrorMessages.OBJ_ISNT_ITERATOR, iterator);
1746+
}
1747+
Object result;
1748+
try {
1749+
result = callIterNext.execute(frame, inliningTarget, slots.tp_iternext(), iterator);
1750+
} catch (PException e) {
1751+
if (defaultIsNoValue.profile(inliningTarget, defaultObject == NO_VALUE)) {
1752+
throw e;
1753+
} else {
1754+
e.expectStopIteration(inliningTarget, stopIterationProfile);
17441755
return defaultObject;
17451756
}
17461757
}
1747-
}
1748-
1749-
@NeverDefault
1750-
protected LookupAndCallUnaryNode createNextCall() {
1751-
return LookupAndCallUnaryNode.create(T___NEXT__, () -> new LookupAndCallUnaryNode.NoAttributeHandler() {
1752-
private final BranchProfile errorProfile = BranchProfile.create();
1753-
1754-
@Override
1755-
public Object execute(Object iterator) {
1756-
errorProfile.enter();
1757-
throw PRaiseNode.raiseStatic(this, TypeError, ErrorMessages.OBJ_ISNT_ITERATOR, iterator);
1758+
if (PyIterNextNode.isExhausted(result)) {
1759+
if (defaultIsNoValue.profile(inliningTarget, defaultObject == NO_VALUE)) {
1760+
throw raiseStopIteration.raise(inliningTarget, StopIteration);
1761+
} else {
1762+
return defaultObject;
17581763
}
1759-
});
1764+
}
1765+
return result;
17601766
}
17611767
}
17621768

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ static long collect(VirtualFrame frame, PythonModule self, @SuppressWarnings("un
138138
Object iter = getIter.execute(frame, inliningTarget, callbacks);
139139
Object cb = next.execute(frame, iter);
140140
TruffleString phase = null;
141-
Object info = null;
141+
Object info;
142142
long res = 0;
143-
if (cb != null) {
143+
if (!PyIterNextNode.isExhausted(cb)) {
144144
phase = START;
145145
info = PFactory.createDict(language, new PKeyword[]{
146146
new PKeyword(GENERATION, 2),
@@ -149,7 +149,7 @@ static long collect(VirtualFrame frame, PythonModule self, @SuppressWarnings("un
149149
});
150150
do {
151151
call.executeObject(frame, cb, phase, info);
152-
} while ((cb = next.execute(frame, iter)) != null);
152+
} while (!PyIterNextNode.isExhausted(cb = next.execute(frame, iter)));
153153
}
154154
long freedMemory = javaCollect(inliningTarget, gil);
155155
PythonContext pythonContext = PythonContext.get(inliningTarget);
@@ -168,7 +168,7 @@ static long collect(VirtualFrame frame, PythonModule self, @SuppressWarnings("un
168168
new PKeyword(UNCOLLECTABLE, 0),
169169
});
170170
iter = getIter.execute(frame, inliningTarget, callbacks);
171-
while ((cb = next.execute(frame, iter)) != null) {
171+
while (!PyIterNextNode.isExhausted(cb = next.execute(frame, iter))) {
172172
call.executeObject(frame, cb, phase, info);
173173
}
174174
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ast/Obj2SstBase.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,10 @@ ConstantValue obj2ConstantValue(Object obj) {
290290
boolean isTuple = PyTupleCheckExactNode.executeUncached(obj);
291291
if (isTuple || PyFrozenSetCheckExactNode.executeUncached(obj)) {
292292
Object iter = PyObjectGetIter.executeUncached(obj);
293-
GetNextNode nextNode = GetNextNode.getUncached();
294293
ArrayList<ConstantValue> list = new ArrayList<>();
295294
while (true) {
296295
try {
297-
list.add(obj2ConstantValue(nextNode.execute(iter)));
296+
list.add(obj2ConstantValue(GetNextNode.executeUncached(iter)));
298297
} catch (PException e) {
299298
e.expectStopIteration(null, IsBuiltinObjectProfile.getUncached());
300299
break;

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

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.TupleNode;
6767
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.BinNode;
6868
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.HexNode;
69-
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.NextNode;
7069
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.OctNode;
7170
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode;
7271
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
@@ -95,8 +94,8 @@
9594
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
9695
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
9796
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotMpAssSubscript.CallSlotMpAssSubscriptNode;
98-
import com.oracle.graal.python.lib.GetNextNode;
9997
import com.oracle.graal.python.lib.PyIterCheckNode;
98+
import com.oracle.graal.python.lib.PyIterNextNode;
10099
import com.oracle.graal.python.lib.PyNumberAddNode;
101100
import com.oracle.graal.python.lib.PyNumberAndNode;
102101
import com.oracle.graal.python.lib.PyNumberDivmodNode;
@@ -886,18 +885,12 @@ static int doMapping(Object obj,
886885
abstract static class PyIter_Next extends CApiUnaryBuiltinNode {
887886
@Specialization
888887
Object check(Object object,
889-
@Bind("this") Node inliningTarget,
890-
@Cached NextNode nextNode,
891-
@Cached IsBuiltinObjectProfile isClassProfile) {
892-
try {
893-
return nextNode.execute(null, object, PNone.NO_VALUE);
894-
} catch (PException e) {
895-
if (isClassProfile.profileException(inliningTarget, e, PythonBuiltinClassType.StopIteration)) {
896-
return getNativeNull();
897-
} else {
898-
throw e;
899-
}
888+
@Cached PyIterNextNode nextNode) {
889+
Object result = nextNode.execute(null, object);
890+
if (PyIterNextNode.isExhausted(result)) {
891+
return getNativeNull();
900892
}
893+
return result;
901894
}
902895
}
903896

@@ -908,19 +901,20 @@ Object send(Object iter, Object arg,
908901
@Bind("this") Node inliningTarget,
909902
@Cached PyIterCheckNode pyiterCheck,
910903
@Cached PyObjectCallMethodObjArgs callMethodNode,
911-
@Cached GetNextNode getNextNode,
904+
@Cached PyIterNextNode nextNode,
912905
@Cached IsBuiltinObjectProfile isClassProfile) {
913-
try {
914-
if (arg instanceof PNone && pyiterCheck.execute(inliningTarget, iter)) {
915-
return getNextNode.execute(iter);
916-
} else {
917-
return callMethodNode.execute(null, inliningTarget, iter, T_SEND, arg);
906+
if (arg instanceof PNone && pyiterCheck.execute(inliningTarget, iter)) {
907+
Object result = nextNode.execute(null, iter);
908+
if (PyIterNextNode.isExhausted(result)) {
909+
return getNativeNull();
918910
}
919-
} catch (PException e) {
920-
if (isClassProfile.profileException(inliningTarget, e, PythonBuiltinClassType.StopIteration)) {
911+
return result;
912+
} else {
913+
try {
914+
return callMethodNode.execute(null, inliningTarget, iter, T_SEND, arg);
915+
} catch (PException e) {
916+
e.expectStopIteration(inliningTarget, isClassProfile);
921917
return getNativeNull();
922-
} else {
923-
throw e;
924918
}
925919
}
926920
}

0 commit comments

Comments
 (0)