Skip to content

Commit b649860

Browse files
committed
Add Garbage collection for CDataObject memory
1 parent 4b8b38a commit b649860

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CtypesNodes.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FFI_TYPES;
6161
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer;
6262
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
63+
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerReference;
6364
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
6465
import com.oracle.graal.python.builtins.objects.type.TypeNodes.InlinedIsSameTypeNode;
6566
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -332,14 +333,19 @@ public abstract static class CreateCDataObjectNode extends Node {
332333
public abstract CDataObject execute(Node inliningTarget, Object type, Pointer pointer, int size, boolean needsfree);
333334

334335
@Specialization
335-
static CDataObject doCreate(Object type, Pointer pointer, int size, boolean needsfree,
336+
static CDataObject doCreate(Node inliningTarget, Object type, Pointer pointer, int size, boolean needsfree,
336337
@Cached IsSubtypeNode isSubtypeNode,
337338
@Cached PythonObjectFactory factory) {
339+
CDataObject result;
338340
if (isSubtypeNode.execute(type, PyCFuncPtr)) {
339-
return factory.createPyCFuncPtrObject(type, pointer, size, needsfree);
341+
result = factory.createPyCFuncPtrObject(type, pointer, size, needsfree);
340342
} else {
341-
return factory.createCDataObject(type, pointer, size, needsfree);
343+
result = factory.createCDataObject(type, pointer, size, needsfree);
342344
}
345+
if (needsfree) {
346+
new PointerReference(result, pointer, PythonContext.get(inliningTarget).getSharedFinalizer());
347+
}
348+
return result;
343349
}
344350
}
345351

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,42 @@ static long doNFIPointer(Node inliningTarget, MemoryBlock memory, NFIPointerStor
674674
}
675675
}
676676

677+
@GenerateUncached
678+
@GenerateInline
679+
@GenerateCached(false)
680+
public abstract static class FreeNode extends Node {
681+
public final void execute(Node inliningTarget, Pointer pointer) {
682+
execute(inliningTarget, pointer.memory.storage, pointer.offset);
683+
pointer.memory.storage = Pointer.NULL.memory.storage;
684+
}
685+
686+
abstract void execute(Node inliningTarget, Storage storage, int offset);
687+
688+
@Specialization
689+
void doNativeMemory(LongPointerStorage storage, int offset) {
690+
// TODO check permissions
691+
UNSAFE.freeMemory(storage.pointer + offset);
692+
}
693+
694+
@Specialization
695+
@SuppressWarnings("unused")
696+
void doNFIPointer(NFIPointerStorage storage, int offset) {
697+
/*
698+
* TODO This should call free using NFI. If it ever does, we should probably update
699+
* PointerReference to use a call target around this
700+
*/
701+
}
702+
703+
@Fallback
704+
@SuppressWarnings("unused")
705+
void doNothing(Storage storage, int offset) {
706+
}
707+
708+
public static FreeNode getUncached() {
709+
return PointerNodesFactory.FreeNodeGen.getUncached();
710+
}
711+
}
712+
677713
@GenerateUncached
678714
@GenerateInline
679715
@GenerateCached(false)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.oracle.graal.python.builtins.modules.ctypes.memory;
2+
3+
import com.oracle.graal.python.builtins.modules.ctypes.CDataObject;
4+
import com.oracle.graal.python.runtime.AsyncHandler;
5+
6+
public class PointerReference extends AsyncHandler.SharedFinalizer.FinalizableReference {
7+
8+
public PointerReference(CDataObject cDataObject, Pointer pointer, AsyncHandler.SharedFinalizer sharedFinalizer) {
9+
super(cDataObject, pointer, sharedFinalizer);
10+
}
11+
12+
@Override
13+
public AsyncHandler.AsyncAction release() {
14+
// This node currently doesn't need a call target
15+
return (context) -> PointerNodes.FreeNode.getUncached().execute(null, (Pointer) getReference());
16+
}
17+
}

0 commit comments

Comments
 (0)