40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .type ;
42
42
43
+ import static com .oracle .graal .python .builtins .objects .type .SpecialMethodSlot .Flags .NO_BUILTIN_DESCRIPTORS ;
43
44
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__CLASS__ ;
44
45
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICT__ ;
45
46
import static com .oracle .graal .python .nodes .SpecialMethodNames .__ADD__ ;
76
77
import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEW__ ;
77
78
import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEXT__ ;
78
79
import static com .oracle .graal .python .nodes .SpecialMethodNames .__NE__ ;
79
- import static com .oracle .graal .python .nodes .SpecialMethodNames .__PREPARE__ ;
80
80
import static com .oracle .graal .python .nodes .SpecialMethodNames .__RAND__ ;
81
81
import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
82
82
import static com .oracle .graal .python .nodes .SpecialMethodNames .__REVERSED__ ;
@@ -159,13 +159,12 @@ public enum SpecialMethodSlot {
159
159
Iter (__ITER__ ),
160
160
Next (__NEXT__ ),
161
161
162
- New (__NEW__ ),
163
- Init (__INIT__ ),
164
- Prepare (__PREPARE__ ),
165
- SetName (__SET_NAME__ ),
162
+ New (__NEW__ , NO_BUILTIN_DESCRIPTORS ),
163
+ Init (__INIT__ , NO_BUILTIN_DESCRIPTORS ),
164
+ SetName (__SET_NAME__ , NO_BUILTIN_DESCRIPTORS ),
166
165
InstanceCheck (__INSTANCECHECK__ ),
167
166
Subclasscheck (__SUBCLASSCHECK__ ),
168
- Call (__CALL__ ),
167
+ Call (__CALL__ , NO_BUILTIN_DESCRIPTORS ),
169
168
170
169
GetItem (__GETITEM__ ),
171
170
SetItem (__SETITEM__ ),
@@ -202,11 +201,38 @@ public enum SpecialMethodSlot {
202
201
Reversed (__REVERSED__ ),
203
202
Bytes (__BYTES__ );
204
203
204
+ static class Flags {
205
+ static final boolean NO_BUILTIN_DESCRIPTORS = false ;
206
+ }
207
+
205
208
public static final SpecialMethodSlot [] VALUES = values ();
206
209
private final String name ;
210
+ /**
211
+ * Indicates if given slot may or must not store context independent (AST cacheable)
212
+ * {@link BuiltinMethodDescriptor} objects.
213
+ *
214
+ * Values of some slots are always or mostly passed to call node variants that can handle
215
+ * {@link BuiltinMethodDescriptor}. This does not hold most notably for slots that are passed to
216
+ * {@link com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode}, like
217
+ * {@code __new__}. For those we do not allow storing the {@link BuiltinMethodDescriptor} in the
218
+ * slot, so that lookup using that slot always resolves to context dependent runtime object,
219
+ * such as {@link PBuiltinFunction}.
220
+ *
221
+ * An alternative would be to update the whole calling machinery ({@code InvokeNode},
222
+ * {@code GetSignature}, ...) to handle {@link BuiltinMethodDescriptor} and extend
223
+ * {@link BuiltinMethodDescriptor} to contain all the information that is necessary for this
224
+ * (GR-32148).
225
+ */
226
+ private final boolean allowsBuiltinDescriptors ;
207
227
208
228
SpecialMethodSlot (String name ) {
209
229
this .name = name ;
230
+ this .allowsBuiltinDescriptors = true ;
231
+ }
232
+
233
+ SpecialMethodSlot (String name , boolean allowsBuiltinDescriptors ) {
234
+ this .name = name ;
235
+ this .allowsBuiltinDescriptors = allowsBuiltinDescriptors ;
210
236
}
211
237
212
238
public String getName () {
@@ -227,7 +253,7 @@ private void setValue(PythonManagedClass klass, Object value, PythonContext cont
227
253
// For builtin classes, we should see these updates only during initialization
228
254
assert !context .isInitialized () || !(klass instanceof PythonBuiltinClass ) ||
229
255
((PythonBuiltinClass ) klass ).getType ().getSpecialMethodSlots () == null : String .format ("%s.%s = %s" , klass , getName (), value );
230
- klass .specialMethodSlots [ordinal ()] = asSlotValue (value , context .getLanguage ());
256
+ klass .specialMethodSlots [ordinal ()] = asSlotValue (this , value , context .getLanguage ());
231
257
if (klass instanceof PythonClass ) {
232
258
((PythonClass ) klass ).invalidateSlotsFinalAssumption ();
233
259
}
@@ -305,12 +331,12 @@ private static void initializeBuiltinTypeSlotsImpl(Python3Core core) {
305
331
continue ;
306
332
}
307
333
Object value = slot .getValue (klass );
308
- if (value instanceof PBuiltinFunction ) {
334
+ if (value instanceof PBuiltinFunction && slot . allowsBuiltinDescriptors ) {
309
335
BuiltinMethodDescriptor info = BuiltinMethodDescriptor .get ((PBuiltinFunction ) value );
310
336
if (info != null ) {
311
337
typeSlots [slot .ordinal ()] = info ;
312
338
}
313
- } else if (value instanceof BuiltinMethodDescriptor || PythonLanguage .canCache (value )) {
339
+ } else if (( value instanceof BuiltinMethodDescriptor && slot . allowsBuiltinDescriptors ) || PythonLanguage .canCache (value )) {
314
340
typeSlots [slot .ordinal ()] = value ;
315
341
}
316
342
}
@@ -447,7 +473,7 @@ private static void setSlotsFromManaged(Object[] slots, PythonManagedClass sourc
447
473
for (SpecialMethodSlot slot : VALUES ) {
448
474
final Object value = domLib .getOrDefault (source , slot .getName (), PNone .NO_VALUE );
449
475
if (value != PNone .NO_VALUE ) {
450
- slots [slot .ordinal ()] = asSlotValue (value , language );
476
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
451
477
}
452
478
}
453
479
} else {
@@ -456,7 +482,7 @@ private static void setSlotsFromManaged(Object[] slots, PythonManagedClass sourc
456
482
for (SpecialMethodSlot slot : VALUES ) {
457
483
final Object value = hlib .getItem (storage , slot .getName ());
458
484
if (value != null ) {
459
- slots [slot .ordinal ()] = asSlotValue (value , language );
485
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
460
486
}
461
487
}
462
488
}
@@ -467,7 +493,7 @@ private static void setSlotsFromGeneric(Object[] slots, PythonAbstractClass base
467
493
for (SpecialMethodSlot slot : VALUES ) {
468
494
Object value = readAttNode .execute (base , slot .getName ());
469
495
if (value != PNone .NO_VALUE ) {
470
- slots [slot .ordinal ()] = asSlotValue (value , language );
496
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
471
497
}
472
498
}
473
499
}
@@ -520,7 +546,7 @@ private static void fixupSpecialMethodSlotInternal(PythonManagedClass klass, Spe
520
546
// If the newly written value is not NO_VALUE, then should either override the slot with
521
547
// the new value or leave it unchanged if it inherited the value from some other class
522
548
assert currentNewValue != PNone .NO_VALUE ;
523
- assert asSlotValue (currentNewValue , context .getLanguage ()) == currentOldValue || currentNewValue == newValue ;
549
+ assert asSlotValue (slot , currentNewValue , context .getLanguage ()) == currentOldValue || currentNewValue == newValue ;
524
550
}
525
551
// Else if the newly written value was NO_VALUE, then we either remove the slot or we pull
526
552
// its value from some other class in the MRO
@@ -547,8 +573,8 @@ private static void fixupSpecialMethodInSubClasses(java.util.Set<PythonAbstractC
547
573
}
548
574
}
549
575
550
- private static Object asSlotValue (Object value , PythonLanguage language ) {
551
- if (value instanceof PBuiltinFunction ) {
576
+ private static Object asSlotValue (SpecialMethodSlot slot , Object value , PythonLanguage language ) {
577
+ if (value instanceof PBuiltinFunction && slot . allowsBuiltinDescriptors ) {
552
578
BuiltinMethodDescriptor info = BuiltinMethodDescriptor .get ((PBuiltinFunction ) value );
553
579
if (info != null ) {
554
580
language .registerBuiltinDescriptorCallTarget (info , ((PBuiltinFunction ) value ).getCallTarget ());
@@ -639,8 +665,6 @@ public static SpecialMethodSlot findSpecialSlot(String name) {
639
665
return Delete ;
640
666
case __DICT__ :
641
667
return Dict ;
642
- case __PREPARE__ :
643
- return Prepare ;
644
668
case __GT__ :
645
669
return Gt ;
646
670
case __GE__ :
0 commit comments