Skip to content

Commit 4331530

Browse files
committed
Implement tp_as_async slots
1 parent bd2f497 commit 4331530

11 files changed

Lines changed: 70 additions & 43 deletions

File tree

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,10 @@ enum SlotKind {
218218
tp_repr("__repr__"),
219219
tp_init("__init__"),
220220
tp_new("__new__"),
221-
tp_call("__call__");
221+
tp_call("__call__"),
222+
am_await("__await__"),
223+
am_aiter("__aiter__"),
224+
am_anext("__anext__");
222225

223226
SlotKind(@SuppressWarnings("unused") String specialMethods) {
224227
}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static String getSlotBaseClass(Slot s) {
5353
return switch (s.value()) {
5454
case nb_bool -> "TpSlotInquiry.TpSlotInquiryBuiltin";
5555
case nb_index, nb_int, nb_float, nb_absolute, nb_positive, nb_negative, nb_invert,
56-
tp_iter, tp_str, tp_repr ->
56+
tp_iter, tp_str, tp_repr, am_aiter, am_anext, am_await ->
5757
"TpSlotUnaryFunc.TpSlotUnaryFuncBuiltin";
5858
case nb_add, nb_subtract, nb_multiply, nb_remainder, nb_divmod, nb_lshift, nb_rshift, nb_and, nb_xor, nb_or,
5959
nb_floor_divide, nb_true_divide, nb_matrix_multiply ->
@@ -90,7 +90,7 @@ static String getSlotNodeBaseClass(Slot s) {
9090
case tp_descr_get -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotDescrGet.DescrGetBuiltinNode";
9191
case nb_bool -> "com.oracle.graal.python.builtins.objects.type.slots.TpSlotInquiry.NbBoolBuiltinNode";
9292
case nb_index, nb_int, nb_float, nb_absolute, nb_positive, nb_negative, nb_invert,
93-
tp_iter, tp_iternext, tp_str, tp_repr ->
93+
tp_iter, tp_iternext, tp_str, tp_repr, am_aiter, am_await, am_anext ->
9494
"com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode";
9595
case nb_add, nb_subtract, nb_multiply, nb_remainder, nb_divmod, nb_lshift, nb_rshift, nb_and, nb_xor, nb_or,
9696
nb_floor_divide, nb_true_divide, nb_matrix_multiply ->
@@ -194,6 +194,9 @@ public static String getExtraCtorArgs(TpSlotData slot) {
194194
case tp_repr -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__";
195195
case tp_init -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___INIT__";
196196
case tp_call -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__";
197+
case am_await -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___AWAIT__";
198+
case am_aiter -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___AITER__";
199+
case am_anext -> ", com.oracle.graal.python.nodes.SpecialMethodNames.J___ANEXT__";
197200
default -> "";
198201
};
199202
}

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/builtin/objects/TpSlotsTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -147,6 +147,7 @@ private static boolean getGroup(TpSlots slots, TpSlotGroup group) {
147147
case AS_NUMBER -> slots.has_as_number();
148148
case AS_SEQUENCE -> slots.has_as_sequence();
149149
case AS_MAPPING -> slots.has_as_mapping();
150+
case AS_ASYNC -> slots.has_as_async();
150151
};
151152
}
152153
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
import com.oracle.graal.python.builtins.objects.array.ArrayBuiltins;
176176
import com.oracle.graal.python.builtins.objects.asyncio.AsyncGenSendBuiltins;
177177
import com.oracle.graal.python.builtins.objects.asyncio.AsyncGenThrowBuiltins;
178+
import com.oracle.graal.python.builtins.objects.asyncio.AsyncGeneratorBuiltins;
178179
import com.oracle.graal.python.builtins.objects.asyncio.CoroutineWrapperBuiltins;
179180
import com.oracle.graal.python.builtins.objects.bool.BoolBuiltins;
180181
import com.oracle.graal.python.builtins.objects.bytes.ByteArrayBuiltins;
@@ -476,7 +477,7 @@ The enumerate object yields pairs containing a count (from start, which
476477
PGenerator("generator", PythonObject, newBuilder().disallowInstantiation().slots(GeneratorBuiltins.SLOTS).methodsFlags(GENERATOR_M_FLAGS)),
477478
PCoroutine("coroutine", PythonObject, newBuilder().slots(CoroutineBuiltins.SLOTS).methodsFlags(COROUTINE_M_FLAGS)),
478479
PCoroutineWrapper("coroutine_wrapper", PythonObject, newBuilder().slots(CoroutineWrapperBuiltins.SLOTS)),
479-
PAsyncGenerator("async_generator", PythonObject, newBuilder().methodsFlags(ASYNC_GENERATOR_M_FLAGS)),
480+
PAsyncGenerator("async_generator", PythonObject, newBuilder().methodsFlags(ASYNC_GENERATOR_M_FLAGS).slots(AsyncGeneratorBuiltins.SLOTS)),
480481
PInt("int", PythonObject, newBuilder().publishInModule(J_BUILTINS).basetype().slots(IntBuiltins.SLOTS).methodsFlags(INT_M_FLAGS).doc("""
481482
int([x]) -> integer
482483
int(x, base=10) -> integer

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

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
package com.oracle.graal.python.builtins;
2727

2828
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___DOC__;
29-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___ANEXT__;
30-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___AWAIT__;
3129
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.assertNoJavaString;
3230
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.ensureNoJavaString;
3331
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
@@ -36,7 +34,6 @@
3634
import java.util.List;
3735
import java.util.Map;
3836
import java.util.Map.Entry;
39-
import java.util.Set;
4037

4138
import com.oracle.graal.python.PythonLanguage;
4239
import com.oracle.graal.python.builtins.objects.PNone;
@@ -96,15 +93,7 @@ public void initialize(Python3Core core) {
9693
builtin.name());
9794
Object builtinDoc = builtin.doc().isEmpty() ? PNone.NONE : toTruffleStringUncached(builtin.doc());
9895
int flags = PBuiltinFunction.getFlags(builtin, callTarget);
99-
PBuiltinFunction function;
100-
if (isSlotMethod(builtin)) {
101-
// HACK: TODO: we should not see any slots here anymore once all are converted
102-
// to slots, then we can make the slot field in PBuiltinFunction final, for now,
103-
// we patch it in TpSlots#wrapBuiltinSlots
104-
function = PFactory.createWrapperDescriptor(language, tsName, null, numDefaults(builtin), flags, callTarget, null, null);
105-
} else {
106-
function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, callTarget);
107-
}
96+
PBuiltinFunction function = PFactory.createBuiltinFunction(language, tsName, null, numDefaults(builtin), flags, callTarget);
10897
function.setAttribute(T___DOC__, builtinDoc);
10998
BoundBuiltinCallable<?> callable = function;
11099
if (builtin.isGetter() || builtin.isSetter()) {
@@ -122,13 +111,6 @@ public void initialize(Python3Core core) {
122111
});
123112
}
124113

125-
// All methods that are really slots in CPython
126-
private static final Set<String> SLOTS = Set.of(J___ANEXT__, J___AWAIT__);
127-
128-
private static boolean isSlotMethod(Builtin builtin) {
129-
return builtin.name().startsWith("__") && SLOTS.contains(builtin.name());
130-
}
131-
132114
/**
133115
* Run any actions that can only be run in the post-initialization step, that is, if we're
134116
* actually going to start running rather than just pre-initializing.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
8181
return AsyncGenSendBuiltinsFactory.getFactories();
8282
}
8383

84-
@Builtin(name = J___AWAIT__, minNumOfPositionalArgs = 1, declaresExplicitSelf = true)
84+
@Slot(value = SlotKind.am_await, isComplex = true)
8585
@GenerateNodeFactory
8686
public abstract static class Await extends PythonUnaryBuiltinNode {
8787
@Specialization

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import static com.oracle.graal.python.builtins.objects.asyncio.PAsyncGenASend.AwaitableState;
4444
import static com.oracle.graal.python.nodes.ErrorMessages.GENERATOR_IGNORED_EXIT;
4545
import static com.oracle.graal.python.nodes.ErrorMessages.SEND_NON_NONE_TO_UNSTARTED_GENERATOR;
46-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___AWAIT__;
4746

4847
import java.util.List;
4948

@@ -84,7 +83,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
8483
return AsyncGenThrowBuiltinsFactory.getFactories();
8584
}
8685

87-
@Builtin(name = J___AWAIT__, minNumOfPositionalArgs = 1, declaresExplicitSelf = true)
86+
@Slot(value = SlotKind.am_await, isComplex = true)
8887
@GenerateNodeFactory
8988
public abstract static class Await extends PythonUnaryBuiltinNode {
9089
@Specialization

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,20 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.asyncio;
4242

43-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___AITER__;
44-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___ANEXT__;
4543
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CLASS_GETITEM__;
4644

4745
import java.util.List;
4846

4947
import com.oracle.graal.python.PythonLanguage;
48+
import com.oracle.graal.python.annotations.Slot;
49+
import com.oracle.graal.python.annotations.Slot.SlotKind;
5050
import com.oracle.graal.python.builtins.Builtin;
5151
import com.oracle.graal.python.builtins.CoreFunctions;
5252
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5353
import com.oracle.graal.python.builtins.PythonBuiltins;
5454
import com.oracle.graal.python.builtins.objects.PNone;
5555
import com.oracle.graal.python.builtins.objects.generator.GeneratorBuiltins;
56+
import com.oracle.graal.python.builtins.objects.type.TpSlots;
5657
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
5758
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5859
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -71,6 +72,9 @@
7172

7273
@CoreFunctions(extendClasses = PythonBuiltinClassType.PAsyncGenerator)
7374
public final class AsyncGeneratorBuiltins extends PythonBuiltins {
75+
76+
public static final TpSlots SLOTS = AsyncGeneratorBuiltinsSlotsGen.SLOTS;
77+
7478
private static void callHooks(VirtualFrame frame, PAsyncGen self, PythonContext.PythonThreadState state, CallUnaryMethodNode invokeFirstIter) {
7579
Object firstIter = state.getAsyncgenFirstIter();
7680
if (firstIter == null) {
@@ -158,7 +162,7 @@ static Object athrow(VirtualFrame frame, PAsyncGen self, Object arg1, Object arg
158162
}
159163
}
160164

161-
@Builtin(name = J___AITER__, declaresExplicitSelf = true, minNumOfPositionalArgs = 1)
165+
@Slot(value = SlotKind.am_aiter, isComplex = true)
162166
@GenerateNodeFactory
163167
public abstract static class AIter extends PythonUnaryBuiltinNode {
164168
@Specialization
@@ -167,7 +171,7 @@ static Object aIter(PAsyncGen self) {
167171
}
168172
}
169173

170-
@Builtin(name = J___ANEXT__, declaresExplicitSelf = true, minNumOfPositionalArgs = 1)
174+
@Slot(value = SlotKind.am_anext, isComplex = true)
171175
@GenerateNodeFactory
172176
public abstract static class ANext extends PythonUnaryBuiltinNode {
173177
@Specialization

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,10 @@ private static boolean hasAsyncMethods(PythonManagedClass obj) {
113113
return (obj.getMethodsFlags() & MethodsFlags.ASYNC_METHODS) != 0;
114114
}
115115

116-
private static Object allocatePyAsyncMethods(PythonManagedClass obj, Object nullValue) {
116+
private static Object allocatePyAsyncMethods(TpSlots slots, Object nullValue) {
117117
Object mem = CStructAccess.AllocateNode.allocUncached(CStructs.PyAsyncMethods);
118118
CStructAccess.WritePointerNode writePointerNode = CStructAccess.WritePointerNode.getUncached();
119-
writePointerNode.write(mem, CFields.PyAsyncMethods__am_await, getSlot(obj, SlotMethodDef.AM_AWAIT));
120-
writePointerNode.write(mem, CFields.PyAsyncMethods__am_aiter, getSlot(obj, SlotMethodDef.AM_AITER));
121-
writePointerNode.write(mem, CFields.PyAsyncMethods__am_anext, getSlot(obj, SlotMethodDef.AM_ANEXT));
122-
writePointerNode.write(mem, CFields.PyAsyncMethods__am_send, nullValue /*- getValue(obj, SlotMethodDef.AM_SEND) */);
119+
writeGroupSlots(CFields.PyTypeObject__tp_as_async, slots, writePointerNode, mem, nullValue);
123120
return mem;
124121
}
125122

@@ -224,7 +221,7 @@ static void initializeType(PythonClassNativeWrapper obj, Object mem, boolean hea
224221
} else {
225222
weaklistoffset = lookupNativeI64MemberInMRO(clazz, PyTypeObject__tp_weaklistoffset, SpecialAttributeNames.T___WEAKLISTOFFSET__);
226223
}
227-
Object asAsync = hasAsyncMethods(clazz) ? allocatePyAsyncMethods(clazz, nullValue) : nullValue;
224+
Object asAsync = slots.has_as_async() ? allocatePyAsyncMethods(slots, nullValue) : nullValue;
228225
Object asNumber = slots.has_as_number() ? allocatePyNumberMethods(slots, nullValue) : nullValue;
229226
Object asSequence = slots.has_as_sequence() ? allocatePySequenceMethods(slots, nullValue) : nullValue;
230227
Object asMapping = slots.has_as_mapping() ? allocatePyMappingMethods(slots, nullValue) : nullValue;

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.generator;
4242

43-
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___AWAIT__;
44-
4543
import java.util.List;
4644

4745
import com.oracle.graal.python.PythonLanguage;
@@ -127,7 +125,7 @@ static boolean suspended(PGenerator self) {
127125
}
128126
}
129127

130-
@Builtin(name = J___AWAIT__, minNumOfPositionalArgs = 1)
128+
@Slot(value = SlotKind.am_await, isComplex = true)
131129
@GenerateNodeFactory
132130
abstract static class AwaitNode extends PythonUnaryBuiltinNode {
133131
@Specialization

0 commit comments

Comments
 (0)