Skip to content

Commit e40173b

Browse files
committed
Move dealloc of singletons and stubs into methods and document
1 parent 27b7bd3 commit e40173b

File tree

1 file changed

+51
-18
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi

1 file changed

+51
-18
lines changed

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

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.objects.cext.capi;
4242

4343
import static com.oracle.graal.python.PythonLanguage.CONTEXT_INSENSITIVE_SINGLETONS;
44+
import static com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper.IMMORTAL_REFCNT;
4445
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___FILE__;
4546
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___LIBRARY__;
4647
import static com.oracle.graal.python.nodes.StringLiterals.J_LLVM_LANGUAGE;
@@ -423,6 +424,29 @@ public PythonAbstractObjectNativeWrapper getSingletonNativeWrapper(PythonAbstrac
423424
return null;
424425
}
425426

427+
/**
428+
* Deallocates all singleton wrappers (in {@link #singletonNativePtrs}) which are immortal and
429+
* must therefore be explicitly free'd. This method modifies the
430+
* {@link HandleContext#nativeStubLookup stub lookup table} but runs not guest code.
431+
*/
432+
private void freeSingletonNativeWrappers() {
433+
CompilerAsserts.neverPartOfCompilation();
434+
// TODO(fa): this should not require the GIL (GR-51314)
435+
assert getContext().ownsGil();
436+
HandleContext nativeContext = getContext().nativeContext;
437+
for (int i = 0; i < singletonNativePtrs.length; i++) {
438+
PythonAbstractObjectNativeWrapper singletonNativeWrapper = singletonNativePtrs[i];
439+
singletonNativePtrs[i] = null;
440+
assert singletonNativeWrapper != null;
441+
assert getSingletonNativeWrapperIdx(singletonNativeWrapper.getDelegate()) != -1;
442+
assert !singletonNativeWrapper.isNative() || singletonNativeWrapper.getRefCount() == IMMORTAL_REFCNT;
443+
if (singletonNativeWrapper.ref != null) {
444+
CApiTransitions.nativeStubLookupRemove(nativeContext, singletonNativeWrapper.ref);
445+
}
446+
PyTruffleObjectFree.releaseNativeWrapperUncached(singletonNativeWrapper);
447+
}
448+
}
449+
426450
public PrimitiveNativeWrapper getCachedPrimitiveNativeWrapper(int i) {
427451
assert CApiGuards.isSmallInteger(i);
428452
PrimitiveNativeWrapper primitiveNativeWrapper = primitiveNativeWrapperCache[i + 5];
@@ -455,8 +479,16 @@ Object getOrCreateSmallInts() {
455479
return nativeSmallIntsArray;
456480
}
457481

482+
/**
483+
* Deallocates the native small int array (pointer {@link #nativeSmallIntsArray}) and all
484+
* wrappers of the small ints (in {@link #primitiveNativeWrapperCache}) which are immortal and
485+
* must therefore be explicitly free'd. This method modifies the
486+
* {@link HandleContext#nativeStubLookup stub lookup table} but runs not guest code.
487+
*/
458488
private void freeSmallInts() {
459489
CompilerAsserts.neverPartOfCompilation();
490+
// TODO(fa): this should not require the GIL (GR-51314)
491+
assert getContext().ownsGil();
460492
if (nativeSmallIntsArray != null) {
461493
assert verifyNativeSmallInts();
462494
// free the native array used to store the stub pointers of the small int wrappers
@@ -466,7 +498,7 @@ private void freeSmallInts() {
466498
HandleContext nativeContext = getContext().nativeContext;
467499
for (PrimitiveNativeWrapper wrapper : primitiveNativeWrapperCache) {
468500
assert wrapper.isIntLike() && CApiGuards.isSmallLong(wrapper.getLong());
469-
assert !wrapper.isNative() || wrapper.getRefCount() == PythonAbstractObjectNativeWrapper.IMMORTAL_REFCNT;
501+
assert !wrapper.isNative() || wrapper.getRefCount() == IMMORTAL_REFCNT;
470502
if (wrapper.ref != null) {
471503
CApiTransitions.nativeStubLookupRemove(nativeContext, wrapper.ref);
472504
}
@@ -485,7 +517,7 @@ private boolean verifyNativeSmallInts() {
485517
Object elementPtr = ReadPointerNode.getUncached().readArrayElement(nativeSmallIntsArray, i);
486518
PythonNativeWrapper wrapper = ToPythonWrapperNode.executeUncached(elementPtr, false);
487519
if (!(wrapper == primitiveNativeWrapperCache[i] && primitiveNativeWrapperCache[i].isNative() &&
488-
primitiveNativeWrapperCache[i].getRefCount() == PythonAbstractObjectNativeWrapper.IMMORTAL_REFCNT)) {
520+
primitiveNativeWrapperCache[i].getRefCount() == IMMORTAL_REFCNT)) {
489521
return false;
490522
}
491523
}
@@ -876,28 +908,14 @@ public void finalizeCapi() {
876908
CApiTransitions.disableReferenceQueuePolling(getContext().nativeContext);
877909
// TODO(fa): remove GIL acquisition (GR-51314)
878910
try (GilNode.UncachedAcquire gil = GilNode.uncachedAcquire()) {
879-
HandleContext nativeContext = getContext().nativeContext;
880911
freeSmallInts();
881-
for (int i = 0; i < singletonNativePtrs.length; i++) {
882-
PythonNativeWrapper singletonNativeWrapper = singletonNativePtrs[i];
883-
singletonNativePtrs[i] = null;
884-
assert singletonNativeWrapper != null;
885-
if (singletonNativeWrapper.ref != null) {
886-
CApiTransitions.nativeStubLookupRemove(nativeContext, singletonNativeWrapper.ref);
887-
}
888-
PyTruffleObjectFree.releaseNativeWrapperUncached(singletonNativeWrapper);
889-
}
912+
freeSingletonNativeWrappers();
890913
/*
891914
* Clear all remaining native object stubs. This must be done after the small int and
892915
* the singleton wrappers were cleared because they might also end up in the lookup
893916
* table and may otherwise be double-free'd.
894917
*/
895-
for (PythonObjectReference ref : nativeContext.nativeStubLookup) {
896-
if (ref != null) {
897-
CApiTransitions.nativeStubLookupRemove(nativeContext, ref);
898-
CApiTransitions.freeNativeStub(ref);
899-
}
900-
}
918+
freeNativeObjectStubs();
901919
}
902920
if (pyDateTimeCAPICapsule != null) {
903921
PyDateTimeCAPIWrapper.destroyWrapper(pyDateTimeCAPICapsule);
@@ -928,6 +946,21 @@ public void finalizeCapi() {
928946
}
929947
}
930948

949+
/**
950+
* Deallocates any native object stub that is still reachable via the
951+
* {@link HandleContext#nativeStubLookup lookup table}. This method modifies the
952+
* {@link HandleContext#nativeStubLookup stub lookup table} but runs not guest code.
953+
*/
954+
private void freeNativeObjectStubs() {
955+
HandleContext nativeContext = getContext().nativeContext;
956+
for (PythonObjectReference ref : nativeContext.nativeStubLookup) {
957+
if (ref != null) {
958+
CApiTransitions.nativeStubLookupRemove(nativeContext, ref);
959+
CApiTransitions.freeNativeStub(ref);
960+
}
961+
}
962+
}
963+
931964
@TruffleBoundary
932965
public Object initCApiModule(Node location, Object sharedLibrary, TruffleString initFuncName, ModuleSpec spec, InteropLibrary llvmInteropLib, CheckFunctionResultNode checkFunctionResultNode)
933966
throws UnsupportedMessageException, ArityException, UnsupportedTypeException, ImportException {

0 commit comments

Comments
 (0)