30
30
import static com .oracle .graal .python .nodes .truffle .TruffleStringMigrationHelpers .assertNoJavaString ;
31
31
32
32
import java .util .ArrayList ;
33
- import java .util .LinkedHashSet ;
34
- import java .util .Set ;
35
33
36
34
import com .oracle .graal .python .PythonLanguage ;
37
35
import com .oracle .graal .python .builtins .objects .PNone ;
38
36
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .PCallCapiFunction ;
39
37
import com .oracle .graal .python .builtins .objects .cext .capi .NativeCAPISymbol ;
40
38
import com .oracle .graal .python .builtins .objects .cext .capi .PythonClassNativeWrapper ;
41
39
import com .oracle .graal .python .builtins .objects .cext .capi .transitions .CApiTransitionsFactory .PythonToNativeNodeGen ;
40
+ import com .oracle .graal .python .builtins .objects .common .HashingStorage ;
41
+ import com .oracle .graal .python .builtins .objects .common .HashingStorageNodes .HashingStorageCopy ;
42
+ import com .oracle .graal .python .builtins .objects .dict .PDict ;
42
43
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
43
44
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
44
45
import com .oracle .graal .python .builtins .objects .type .TypeNodes .ComputeMroNode ;
46
+ import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetSubclassesAsArrayNode ;
45
47
import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetSubclassesNode ;
46
48
import com .oracle .graal .python .nodes .ErrorMessages ;
47
49
import com .oracle .graal .python .nodes .PGuards ;
48
50
import com .oracle .graal .python .nodes .PRaiseNode ;
51
+ import com .oracle .graal .python .runtime .PythonContext ;
49
52
import com .oracle .graal .python .runtime .exception .PException ;
50
53
import com .oracle .graal .python .runtime .sequence .storage .MroSequenceStorage ;
51
54
import com .oracle .truffle .api .Assumption ;
@@ -65,7 +68,7 @@ public abstract class PythonManagedClass extends PythonObject implements PythonA
65
68
private boolean abstractClass ;
66
69
67
70
// Needs to maintain the order. It would make sense to use weakrefs, but CPython doesn't do that
68
- private final LinkedHashSet < PythonAbstractClass > subClasses = new LinkedHashSet <>() ;
71
+ private final PDict subClasses ;
69
72
@ CompilationFinal private Shape instanceShape ;
70
73
private TruffleString name ;
71
74
private TruffleString qualName ;
@@ -124,6 +127,8 @@ protected PythonManagedClass(PythonLanguage lang, Object typeClass, Shape classS
124
127
// provide our instances with a fresh shape tree
125
128
this .instanceShape = lang .getShapeForClass (this );
126
129
}
130
+
131
+ this .subClasses = new PDict (lang );
127
132
}
128
133
129
134
public boolean isMROInitialized () {
@@ -153,7 +158,7 @@ public Assumption getLookupStableAssumption() {
153
158
public void lookupChanged () {
154
159
CompilerAsserts .neverPartOfCompilation ();
155
160
methodResolutionOrder .lookupChanged ();
156
- for (PythonAbstractClass subclass : getSubClasses ( )) {
161
+ for (PythonAbstractClass subclass : GetSubclassesAsArrayNode . executeUncached ( this )) {
157
162
if (subclass != null ) {
158
163
subclass .lookupChanged ();
159
164
}
@@ -276,7 +281,7 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) {
276
281
Object nativeBase = PythonToNativeNodeGen .getUncached ().execute (base );
277
282
PCallCapiFunction .getUncached ().call (NativeCAPISymbol .FUN_TRUFFLE_CHECK_TYPE_READY , nativeBase );
278
283
}
279
- GetSubclassesNode .executeUncached (base ). add ( this );
284
+ GetSubclassesNode .unsafeAddSubclass (base , this );
280
285
}
281
286
}
282
287
}
@@ -285,16 +290,16 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) {
285
290
public final void setBases (Object newBaseClass , PythonAbstractClass [] newBaseClasses ) {
286
291
ArrayList <Set <PythonAbstractClass >> newBasesSubclasses = new ArrayList <>(newBaseClasses .length );
287
292
for (PythonAbstractClass type : newBaseClasses ) {
288
- newBasesSubclasses .add (GetSubclassesNode .executeUncached (type ));
293
+ HashingStorage storage = GetSubclassesNode .executeUncached (newBase ).getDictStorage ();
294
+ newBasesSubclasses .add (HashingStorageCopy .executeUncached (storage ));
289
295
}
290
296
291
297
Object oldBase = getBase ();
292
298
PythonAbstractClass [] oldBaseClasses = getBaseClasses ();
293
299
PythonAbstractClass [] oldMRO = (PythonAbstractClass []) this .methodResolutionOrder .getInternalArray ();
294
300
295
- Set <PythonAbstractClass > subclasses = GetSubclassesNode .executeUncached (this );
296
- PythonAbstractClass [] subclassesArray = subclasses .toArray (new PythonAbstractClass [subclasses .size ()]);
297
- PythonAbstractClass [][] oldSubClasssMROs = new PythonAbstractClass [subclasses .size ()][];
301
+ PythonAbstractClass [] subclassesArray = GetSubclassesAsArrayNode .executeUncached (this );
302
+ PythonAbstractClass [][] oldSubClasssMROs = new PythonAbstractClass [subclassesArray .length ][];
298
303
for (int i = 0 ; i < subclassesArray .length ; i ++) {
299
304
PythonAbstractClass scls = subclassesArray [i ];
300
305
if (scls instanceof PythonManagedClass ) {
@@ -309,23 +314,35 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
309
314
this .methodResolutionOrder .lookupChanged ();
310
315
this .setMRO (ComputeMroNode .doSlowPath (this ));
311
316
312
- for (PythonAbstractClass scls : subclasses ) {
317
+ for (PythonAbstractClass scls : subclassesArray ) {
313
318
if (scls instanceof PythonManagedClass ) {
314
319
PythonManagedClass pmc = (PythonManagedClass ) scls ;
315
320
pmc .methodResolutionOrder .lookupChanged ();
316
321
pmc .setMRO (ComputeMroNode .doSlowPath (scls ));
317
322
}
318
323
}
324
+
325
+ boolean isCtxInitialized = PythonContext .get (null ).isInitialized ();
319
326
if (this .baseClasses == newBaseClasses ) {
320
327
// take no action if bases were replaced through reentrance
321
328
for (PythonAbstractClass base : oldBaseClasses ) {
322
329
if (base instanceof PythonManagedClass ) {
323
- GetSubclassesNode .executeUncached (base ).remove (this );
330
+ if (isCtxInitialized ) {
331
+ GetSubclassesNode .executeUncached (base ).delItem (this );
332
+ } else {
333
+ // slots aren't populated yet during context initialization
334
+ GetSubclassesNode .unsafeRemoveSubclass (base , this );
335
+ }
324
336
}
325
337
}
326
338
for (PythonAbstractClass base : newBaseClasses ) {
327
339
if (base instanceof PythonManagedClass ) {
328
- GetSubclassesNode .executeUncached (base ).add (this );
340
+ if (isCtxInitialized ) {
341
+ GetSubclassesNode .executeUncached (base ).setItem (this , this );
342
+ } else {
343
+ // slots aren't populated yet during context initialization
344
+ GetSubclassesNode .unsafeAddSubclass (base , this );
345
+ }
329
346
}
330
347
}
331
348
}
@@ -335,9 +352,8 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
335
352
for (int i = 0 ; i < newBaseClasses .length ; i ++) {
336
353
PythonAbstractClass base = newBaseClasses [i ];
337
354
if (base != null ) {
338
- Set <PythonAbstractClass > s = GetSubclassesNode .executeUncached (base );
339
- s .clear ();
340
- s .addAll (newBasesSubclasses .get (i ));
355
+ PDict dict = GetSubclassesNode .executeUncached (base );
356
+ dict .setDictStorage (newBasesSubclasses .get (i ));
341
357
}
342
358
}
343
359
if (this .baseClasses == newBaseClasses ) {
@@ -362,7 +378,7 @@ public final void setBases(Object newBaseClass, PythonAbstractClass[] newBaseCla
362
378
}
363
379
}
364
380
365
- final LinkedHashSet < PythonAbstractClass > getSubClasses () {
381
+ final PDict getSubClasses () {
366
382
return subClasses ;
367
383
}
368
384
0 commit comments