40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .cext .capi ;
42
42
43
+ import static com .oracle .graal .python .PythonLanguage .CONTEXT_INSENSITIVE_SINGLETONS ;
43
44
import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___FILE__ ;
44
45
import static com .oracle .graal .python .nodes .SpecialAttributeNames .T___LIBRARY__ ;
45
46
import static com .oracle .graal .python .nodes .StringLiterals .J_LLVM_LANGUAGE ;
61
62
import java .util .concurrent .atomic .AtomicBoolean ;
62
63
import java .util .concurrent .atomic .AtomicLong ;
63
64
64
- import com .oracle .graal .python .builtins .objects .PythonAbstractObject ;
65
65
import org .graalvm .collections .EconomicMap ;
66
66
import org .graalvm .collections .Pair ;
67
67
import org .graalvm .nativeimage .ImageInfo ;
73
73
import com .oracle .graal .python .builtins .modules .cext .PythonCextBuiltins .CApiBuiltinExecutable ;
74
74
import com .oracle .graal .python .builtins .modules .cext .PythonCextBuiltins .CApiCallPath ;
75
75
import com .oracle .graal .python .builtins .objects .PNone ;
76
+ import com .oracle .graal .python .builtins .objects .PythonAbstractObject ;
76
77
import com .oracle .graal .python .builtins .objects .capsule .PyCapsule ;
77
78
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodesFactory .CreateModuleNodeGen ;
78
79
import com .oracle .graal .python .builtins .objects .cext .capi .PythonNativeWrapper .PythonAbstractObjectNativeWrapper ;
130
131
import com .oracle .truffle .api .interop .UnsupportedTypeException ;
131
132
import com .oracle .truffle .api .library .ExportLibrary ;
132
133
import com .oracle .truffle .api .library .ExportMessage ;
134
+ import com .oracle .truffle .api .nodes .ExplodeLoop ;
135
+ import com .oracle .truffle .api .nodes .ExplodeLoop .LoopExplosionKind ;
133
136
import com .oracle .truffle .api .nodes .Node ;
134
137
import com .oracle .truffle .api .source .Source ;
135
138
import com .oracle .truffle .api .source .Source .SourceBuilder ;
@@ -172,7 +175,7 @@ public final class CApiContext extends CExtContext {
172
175
private Map <Object , AllocInfo > freedNativeMemory ;
173
176
174
177
/** Native wrappers for context-insensitive singletons like {@link PNone#NONE}. */
175
- @ CompilationFinal (dimensions = 1 ) private final PythonAbstractObjectNativeWrapper [] singletonNativePtrs = new PythonAbstractObjectNativeWrapper [ PythonLanguage . getNumberOfSpecialSingletons ()] ;
178
+ @ CompilationFinal (dimensions = 1 ) private final PythonAbstractObjectNativeWrapper [] singletonNativePtrs ;
176
179
177
180
/**
178
181
* This cache is used to cache native wrappers for frequently used primitives. This is strictly
@@ -295,6 +298,20 @@ public CApiContext(PythonContext context, Object llvmLibrary, boolean useNativeB
295
298
CApiContext .nativeSymbolCacheSingleContextUsed = true ;
296
299
}
297
300
301
+ // initialize singleton native wrappers
302
+ singletonNativePtrs = new PythonAbstractObjectNativeWrapper [CONTEXT_INSENSITIVE_SINGLETONS .length ];
303
+ // Other threads must see the nativeWrapper fully initialized once it becomes non-null
304
+ for (int i = 0 ; i < singletonNativePtrs .length ; i ++) {
305
+ assert CApiGuards .isSpecialSingleton (CONTEXT_INSENSITIVE_SINGLETONS [i ]);
306
+ /*
307
+ * Note: this does intentionally not use 'PythonObjectNativeWrapper.wrap' because the
308
+ * wrapper must not be reachable from the Python object since the singletons are shared.
309
+ */
310
+ PythonObjectNativeWrapper singletonWrapper = new PythonObjectNativeWrapper (CONTEXT_INSENSITIVE_SINGLETONS [i ]);
311
+ VarHandle .storeStoreFence ();
312
+ singletonNativePtrs [i ] = singletonWrapper ;
313
+ }
314
+
298
315
// initialize primitive native wrapper cache
299
316
primitiveNativeWrapperCache = new PrimitiveNativeWrapper [PY_NSMALLNEGINTS + PY_NSMALLPOSINTS ];
300
317
for (int i = 0 ; i < primitiveNativeWrapperCache .length ; i ++) {
@@ -387,16 +404,18 @@ public void tssDelete(long key) {
387
404
tssStorage .remove (key );
388
405
}
389
406
390
- public void setSingletonNativeWrapper (PythonAbstractObject obj , PythonAbstractObjectNativeWrapper nativePtr ) {
391
- assert PythonLanguage .getSingletonNativeWrapperIdx (obj ) != -1 : "invalid special singleton object" ;
392
- assert singletonNativePtrs [PythonLanguage .getSingletonNativeWrapperIdx (obj )] == null ;
393
- // Other threads must see the nativeWrapper fully initialized once it becomes non-null
394
- VarHandle .storeStoreFence ();
395
- singletonNativePtrs [PythonLanguage .getSingletonNativeWrapperIdx (obj )] = nativePtr ;
407
+ @ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
408
+ static int getSingletonNativeWrapperIdx (Object obj ) {
409
+ for (int i = 0 ; i < CONTEXT_INSENSITIVE_SINGLETONS .length ; i ++) {
410
+ if (CONTEXT_INSENSITIVE_SINGLETONS [i ] == obj ) {
411
+ return i ;
412
+ }
413
+ }
414
+ return -1 ;
396
415
}
397
416
398
417
public PythonAbstractObjectNativeWrapper getSingletonNativeWrapper (PythonAbstractObject obj ) {
399
- int singletonNativePtrIdx = PythonLanguage .getSingletonNativeWrapperIdx (obj );
418
+ int singletonNativePtrIdx = CApiContext .getSingletonNativeWrapperIdx (obj );
400
419
if (singletonNativePtrIdx != -1 ) {
401
420
return singletonNativePtrs [singletonNativePtrIdx ];
402
421
}
@@ -857,6 +876,15 @@ public void finalizeCapi() {
857
876
// TODO(fa): remove GIL acquisition (GR-51314)
858
877
try (GilNode .UncachedAcquire gil = GilNode .uncachedAcquire ()) {
859
878
freeSmallInts ();
879
+ for (int i = 0 ; i < singletonNativePtrs .length ; i ++) {
880
+ PythonNativeWrapper singletonNativeWrapper = singletonNativePtrs [i ];
881
+ singletonNativePtrs [i ] = null ;
882
+ assert singletonNativeWrapper != null ;
883
+ if (singletonNativeWrapper .ref != null ) {
884
+ CApiTransitions .nativeStubLookupRemove (getContext ().nativeContext , singletonNativeWrapper .ref );
885
+ }
886
+ PyTruffleObjectFree .releaseNativeWrapperUncached (singletonNativeWrapper );
887
+ }
860
888
}
861
889
if (pyDateTimeCAPICapsule != null ) {
862
890
PyDateTimeCAPIWrapper .destroyWrapper (pyDateTimeCAPICapsule );
@@ -869,11 +897,6 @@ public void finalizeCapi() {
869
897
// Shutdown already in progress, let it do the finalization then
870
898
}
871
899
}
872
- for (PythonNativeWrapper singletonNativeWrapper : singletonNativePtrs ) {
873
- if (singletonNativeWrapper != null ) {
874
- PyTruffleObjectFree .releaseNativeWrapperUncached (singletonNativeWrapper );
875
- }
876
- }
877
900
pyCFunctionWrappers .clear ();
878
901
// free all allocated PyMethodDef structures
879
902
for (Object pyMethodDefPointer : methodDefinitions .values ()) {
0 commit comments