Skip to content

Commit 88b5bbb

Browse files
committed
Only call tp_dealloc on objects that were only referenced from managed by now
1 parent 6771000 commit 88b5bbb

File tree

2 files changed

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

2 files changed

+20
-18
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -409,18 +409,10 @@ GraalPyPrivate_BulkDealloc(intptr_t ptrArray[], int64_t len)
409409
{
410410
for (int i = 0; i < len; i++) {
411411
PyObject *obj = (PyObject *)ptrArray[i];
412-
if (obj->ob_refcnt == _Py_IMMORTAL_REFCNT) {
413-
GraalPyPrivate_Log(PY_TRUFFLE_LOG_FINER,
414-
"%s: Not deallocating immortal object: 0x%zx (%s%s)",
415-
__func__, obj,
416-
PyType_Check(obj) ? "class " : "a ",
417-
PyType_Check(obj) ? ((PyTypeObject*)obj)->tp_name : Py_TYPE(obj)->tp_name);
418-
} else {
419-
GraalPyPrivate_Log(PY_TRUFFLE_LOG_FINER,
420-
"%s: _Py_Dealloc(0x%zx)",
421-
__func__, obj);
422-
_Py_Dealloc(obj);
423-
}
412+
GraalPyPrivate_Log(PY_TRUFFLE_LOG_FINER,
413+
"%s: _Py_Dealloc(a %s at 0x%zx)",
414+
__func__, Py_TYPE(obj)->tp_name, obj);
415+
_Py_Dealloc(obj);
424416
}
425417
return 0;
426418
}

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,20 @@ public static void deallocNativeReplacements(PythonContext context, HandleContex
653653
IdReference<?> ref = iterator.next().getValue();
654654
if (ref instanceof PythonObjectReference reference) {
655655
if (!reference.isAllocatedFromJava()) {
656-
// This memory must be free from C
657-
referencesToBeFreed.add(reference.pointer);
658-
iterator.remove();
656+
// This memory must be freed from C
657+
if (subNativeRefCount(reference.pointer, MANAGED_REFCNT) == 0) {
658+
// Only the managed references exist, we can dealloc
659+
referencesToBeFreed.add(reference.pointer);
660+
iterator.remove();
661+
} else {
662+
// There is a native reference which presumably will decref this one at a
663+
// later point and call tp_dealloc then
664+
}
659665
}
660666
}
661667
}
662668
releaseNativeObjects(context, referencesToBeFreed);
669+
pollReferenceQueue();
663670
}
664671

665672
public static void freeNativeReplacementStructs(PythonContext context, HandleContext handleContext) {
@@ -668,9 +675,12 @@ public static void freeNativeReplacementStructs(PythonContext context, HandleCon
668675
if (ref instanceof PythonObjectReference reference) {
669676
// We don't expect references to wrappers that would have a native object stub.
670677
assert reference.handleTableIndex == -1;
671-
// We expect at this point that there are only references allocated from Java
672-
assert reference.isAllocatedFromJava();
673-
freeNativeStruct(reference);
678+
// We expect at this point that most if not all references left were allocated
679+
// from Java and can be freed here. There may be stragglers that are waiting
680+
// for a GC though, so we have to check.
681+
if (reference.isAllocatedFromJava()) {
682+
freeNativeStruct(reference);
683+
}
674684
}
675685
});
676686
handleContext.nativeLookup.clear();

0 commit comments

Comments
 (0)