@@ -159,8 +159,8 @@ public enum SpecialMethodSlot {
159
159
Iter (__ITER__ ),
160
160
Next (__NEXT__ ),
161
161
162
- New (__NEW__ ),
163
- Init (__INIT__ ),
162
+ New (__NEW__ , false ),
163
+ Init (__INIT__ , false ),
164
164
Prepare (__PREPARE__ ),
165
165
SetName (__SET_NAME__ ),
166
166
InstanceCheck (__INSTANCECHECK__ ),
@@ -204,9 +204,32 @@ public enum SpecialMethodSlot {
204
204
205
205
public static final SpecialMethodSlot [] VALUES = values ();
206
206
private final String name ;
207
+ /**
208
+ * Indicates if given slot may or must not store context independent (AST cacheable)
209
+ * {@link BuiltinMethodDescriptor} objects.
210
+ *
211
+ * Values of some slots are always or mostly passed to call node variants that can handle
212
+ * {@link BuiltinMethodDescriptor}. This does not hold most notably for slots that are passed to
213
+ * {@link com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode}, like
214
+ * {@code __new__}. For those we do no allow storing the {@link BuiltinMethodDescriptor} in the
215
+ * slot, so that lookup using that slot always resolves to context dependent runtime object,
216
+ * such as {@link PBuiltinFunction}.
217
+ *
218
+ * An alternative would be to update the whole calling machinery ({@code InvokeNode},
219
+ * {@code GetSignature}, ...) to handle {@link BuiltinMethodDescriptor} and extend
220
+ * {@link BuiltinMethodDescriptor} to contain all the information that is necessary for this
221
+ * (GR-32148).
222
+ */
223
+ private final boolean allowsBuiltinDescriptors ;
207
224
208
225
SpecialMethodSlot (String name ) {
209
226
this .name = name ;
227
+ this .allowsBuiltinDescriptors = true ;
228
+ }
229
+
230
+ SpecialMethodSlot (String name , boolean allowsBuiltinDescriptors ) {
231
+ this .name = name ;
232
+ this .allowsBuiltinDescriptors = allowsBuiltinDescriptors ;
210
233
}
211
234
212
235
public String getName () {
@@ -227,7 +250,7 @@ private void setValue(PythonManagedClass klass, Object value, PythonContext cont
227
250
// For builtin classes, we should see these updates only during initialization
228
251
assert !context .isInitialized () || !(klass instanceof PythonBuiltinClass ) ||
229
252
((PythonBuiltinClass ) klass ).getType ().getSpecialMethodSlots () == null : String .format ("%s.%s = %s" , klass , getName (), value );
230
- klass .specialMethodSlots [ordinal ()] = asSlotValue (value , context .getLanguage ());
253
+ klass .specialMethodSlots [ordinal ()] = asSlotValue (this , value , context .getLanguage ());
231
254
if (klass instanceof PythonClass ) {
232
255
((PythonClass ) klass ).invalidateSlotsFinalAssumption ();
233
256
}
@@ -305,12 +328,12 @@ private static void initializeBuiltinTypeSlotsImpl(Python3Core core) {
305
328
continue ;
306
329
}
307
330
Object value = slot .getValue (klass );
308
- if (value instanceof PBuiltinFunction ) {
331
+ if (value instanceof PBuiltinFunction && slot . allowsBuiltinDescriptors ) {
309
332
BuiltinMethodDescriptor info = BuiltinMethodDescriptor .get ((PBuiltinFunction ) value );
310
333
if (info != null ) {
311
334
typeSlots [slot .ordinal ()] = info ;
312
335
}
313
- } else if (value instanceof BuiltinMethodDescriptor || PythonLanguage .canCache (value )) {
336
+ } else if (( value instanceof BuiltinMethodDescriptor && slot . allowsBuiltinDescriptors ) || PythonLanguage .canCache (value )) {
314
337
typeSlots [slot .ordinal ()] = value ;
315
338
}
316
339
}
@@ -447,7 +470,7 @@ private static void setSlotsFromManaged(Object[] slots, PythonManagedClass sourc
447
470
for (SpecialMethodSlot slot : VALUES ) {
448
471
final Object value = domLib .getOrDefault (source , slot .getName (), PNone .NO_VALUE );
449
472
if (value != PNone .NO_VALUE ) {
450
- slots [slot .ordinal ()] = asSlotValue (value , language );
473
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
451
474
}
452
475
}
453
476
} else {
@@ -456,7 +479,7 @@ private static void setSlotsFromManaged(Object[] slots, PythonManagedClass sourc
456
479
for (SpecialMethodSlot slot : VALUES ) {
457
480
final Object value = hlib .getItem (storage , slot .getName ());
458
481
if (value != null ) {
459
- slots [slot .ordinal ()] = asSlotValue (value , language );
482
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
460
483
}
461
484
}
462
485
}
@@ -467,7 +490,7 @@ private static void setSlotsFromGeneric(Object[] slots, PythonAbstractClass base
467
490
for (SpecialMethodSlot slot : VALUES ) {
468
491
Object value = readAttNode .execute (base , slot .getName ());
469
492
if (value != PNone .NO_VALUE ) {
470
- slots [slot .ordinal ()] = asSlotValue (value , language );
493
+ slots [slot .ordinal ()] = asSlotValue (slot , value , language );
471
494
}
472
495
}
473
496
}
@@ -520,7 +543,7 @@ private static void fixupSpecialMethodSlotInternal(PythonManagedClass klass, Spe
520
543
// If the newly written value is not NO_VALUE, then should either override the slot with
521
544
// the new value or leave it unchanged if it inherited the value from some other class
522
545
assert currentNewValue != PNone .NO_VALUE ;
523
- assert asSlotValue (currentNewValue , context .getLanguage ()) == currentOldValue || currentNewValue == newValue ;
546
+ assert asSlotValue (slot , currentNewValue , context .getLanguage ()) == currentOldValue || currentNewValue == newValue ;
524
547
}
525
548
// Else if the newly written value was NO_VALUE, then we either remove the slot or we pull
526
549
// its value from some other class in the MRO
@@ -547,8 +570,8 @@ private static void fixupSpecialMethodInSubClasses(java.util.Set<PythonAbstractC
547
570
}
548
571
}
549
572
550
- private static Object asSlotValue (Object value , PythonLanguage language ) {
551
- if (value instanceof PBuiltinFunction ) {
573
+ private static Object asSlotValue (SpecialMethodSlot slot , Object value , PythonLanguage language ) {
574
+ if (value instanceof PBuiltinFunction && slot . allowsBuiltinDescriptors ) {
552
575
BuiltinMethodDescriptor info = BuiltinMethodDescriptor .get ((PBuiltinFunction ) value );
553
576
if (info != null ) {
554
577
language .registerBuiltinDescriptorCallTarget (info , ((PBuiltinFunction ) value ).getCallTarget ());
0 commit comments