Skip to content

Commit 28d3431

Browse files
committed
[GR-49560] [GR-49497] [GR-50157] Refactor Python native wrapper hierarchy.
PullRequest: graalpython/3049
2 parents 41cfa6f + feeaa71 commit 28d3431

33 files changed

+745
-490
lines changed

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

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ PyAPI_FUNC(Py_ssize_t) PyTruffle_bulk_DEALLOC(intptr_t ptrArray[], int64_t len)
456456

457457
/** to be used from Java code only and only at exit; calls _Py_Dealloc */
458458
PyAPI_FUNC(Py_ssize_t) PyTruffle_shutdown_bulk_DEALLOC(intptr_t ptrArray[], int64_t len) {
459-
/* some objects depends on others which might get deallocated in the process
459+
/* some objects depends on others which might get deallocated in the process
460460
of an earlier deallocation of the other object. To avoid double deallocations,
461461
we, temporarly, make all objects immortal artificially */
462462
for (int i = 0; i < len; i++) {
@@ -883,12 +883,41 @@ So we rebind them to no-ops when exiting.
883883
Py_ssize_t nop_GraalPy_get_PyObject_ob_refcnt(PyObject* obj) {
884884
return 100; // large dummy refcount
885885
}
886+
886887
void nop_GraalPy_set_PyObject_ob_refcnt(PyObject* obj, Py_ssize_t refcnt) {
887888
// do nothing
888889
}
889-
PyAPI_FUNC(void) finalizeCAPI() {
890-
GraalPy_get_PyObject_ob_refcnt = nop_GraalPy_get_PyObject_ob_refcnt;
891-
GraalPy_set_PyObject_ob_refcnt = nop_GraalPy_set_PyObject_ob_refcnt;
890+
891+
/*
892+
* This array contains pairs of variable address and "reset value".
893+
* The variable location is usually the address of a function pointer variable
894+
* and the reset value is a new value to set at VM shutdown.
895+
* For further explanation why this is required, see Java method
896+
* 'CApiContext.ensureCapiWasLoaded'.
897+
*
898+
* Array format: [ var_addr, reset_val, var_addr1, reset_val1, ..., NULL ]
899+
*
900+
* ATTENTION: If the structure of the array's content is changed, method
901+
* 'CApiContext.addNativeFinalizer' *MUST BE* adopted.
902+
*
903+
* ATTENTION: the array is expected to be NULL-terminated !
904+
*
905+
*/
906+
static int64_t reset_func_ptrs[] = {
907+
&GraalPy_get_PyObject_ob_refcnt,
908+
nop_GraalPy_get_PyObject_ob_refcnt,
909+
&GraalPy_set_PyObject_ob_refcnt,
910+
nop_GraalPy_set_PyObject_ob_refcnt,
911+
/* sentinel (required) */
912+
NULL
913+
};
914+
915+
/*
916+
* This function is called from Java during C API initialization to get the
917+
* pointer to array 'reset_func_pts'.
918+
*/
919+
PyAPI_FUNC(int64_t *) GraalPy_get_finalize_capi_pointer_array() {
920+
return reset_func_ptrs;
892921
}
893922

894923
static void unimplemented(const char* name) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GraalPythonModuleBuiltins.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
import static com.oracle.graal.python.nodes.SpecialMethodNames.T_INSERT;
5050
import static com.oracle.graal.python.nodes.StringLiterals.J_LLVM_LANGUAGE;
5151
import static com.oracle.graal.python.nodes.StringLiterals.T_COLON;
52-
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
5352
import static com.oracle.graal.python.nodes.StringLiterals.T_LLVM_LANGUAGE;
5453
import static com.oracle.graal.python.nodes.StringLiterals.T_NATIVE;
5554
import static com.oracle.graal.python.nodes.StringLiterals.T_PATH;
@@ -805,7 +804,7 @@ abstract static class StorageToNative extends PythonUnaryBuiltinNode {
805804
@Specialization
806805
@TruffleBoundary
807806
Object toNative(PBytesLike bytes) {
808-
ensureCapi();
807+
CApiContext.ensureCapiWasLoaded();
809808
NativeSequenceStorage newStorage = ToNativeStorageNode.executeUncached(bytes.getSequenceStorage(), true);
810809
bytes.setSequenceStorage(newStorage);
811810
return bytes;
@@ -814,7 +813,7 @@ Object toNative(PBytesLike bytes) {
814813
@Specialization
815814
@TruffleBoundary
816815
Object toNative(PArray array) {
817-
ensureCapi();
816+
CApiContext.ensureCapiWasLoaded();
818817
NativeSequenceStorage newStorage = ToNativeStorageNode.executeUncached(array.getSequenceStorage(), true);
819818
array.setSequenceStorage(newStorage);
820819
return array;
@@ -823,19 +822,11 @@ Object toNative(PArray array) {
823822
@Specialization
824823
@TruffleBoundary
825824
Object toNative(PSequence sequence) {
826-
ensureCapi();
825+
CApiContext.ensureCapiWasLoaded();
827826
NativeSequenceStorage newStorage = ToNativeStorageNode.executeUncached(sequence.getSequenceStorage(), false);
828827
sequence.setSequenceStorage(newStorage);
829828
return sequence;
830829
}
831-
832-
private void ensureCapi() {
833-
try {
834-
CApiContext.ensureCapiWasLoaded(null, getContext(), T_EMPTY_STRING, T_EMPTY_STRING);
835-
} catch (Exception e) {
836-
throw CompilerDirectives.shouldNotReachHere(e);
837-
}
838-
}
839830
}
840831

841832
@Builtin(name = J_EXTEND, minNumOfPositionalArgs = 1, doc = "Extends Java class and return HostAdapterCLass")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
import com.oracle.graal.python.builtins.objects.PNone;
166166
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
167167
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
168-
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
168+
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
169169
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
170170
import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage;
171171
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageSetItem;
@@ -934,13 +934,13 @@ private static String defaultCharsetName() {
934934
public abstract static class GetrefcountNode extends PythonUnaryBuiltinNode {
935935

936936
@Specialization
937-
protected long doGeneric(PythonAbstractObject object,
937+
static long doGeneric(PythonAbstractObject object,
938938
@Cached CStructAccess.ReadI64Node read) {
939939
if (object instanceof PythonAbstractNativeObject nativeKlass) {
940940
return read.readFromObj(nativeKlass, PyObject__ob_refcnt);
941941
}
942942

943-
PythonNativeWrapper wrapper = object.getNativeWrapper();
943+
PythonAbstractObjectNativeWrapper wrapper = object.getNativeWrapper();
944944
if (wrapper == null) {
945945
return -1;
946946
} else {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@
8282
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
8383
import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext;
8484
import com.oracle.graal.python.builtins.objects.cext.capi.CApiGuards;
85-
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ResolveHandleNode;
86-
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
85+
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
86+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ResolvePointerNode;
8787
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.NativeToPythonNode;
8888
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
8989
import com.oracle.graal.python.builtins.objects.cext.common.GetNextVaArgNode;
@@ -142,7 +142,10 @@
142142
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
143143
import com.oracle.truffle.api.strings.TruffleString;
144144

145-
public class PythonCextObjectBuiltins {
145+
public abstract class PythonCextObjectBuiltins {
146+
147+
private PythonCextObjectBuiltins() {
148+
}
146149

147150
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, PyObject, PyObject, Int}, call = Direct)
148151
abstract static class _PyTruffleObject_Call1 extends CApiQuaternaryBuiltinNode {
@@ -592,13 +595,12 @@ int doGeneric(Object ptrObject,
592595
* At this point we don't know if the pointer is invalid, so we try to resolve it to an
593596
* object.
594597
*/
595-
Object resolved = isWrapper ? ptrObject : ResolveHandleNode.executeUncached(ptrObject);
598+
Object resolved = isWrapper ? ptrObject : ResolvePointerNode.executeUncached(ptrObject);
596599
Object pythonObject;
597600
long refCnt;
598601
// We need again check if 'resolved' is a wrapper in case we resolved a handle.
599-
if (CApiGuards.isNativeWrapper(resolved)) {
600-
PythonNativeWrapper wrapper = (PythonNativeWrapper) resolved;
601-
refCnt = wrapper.getRefCount();
602+
if (resolved instanceof PythonAbstractObjectNativeWrapper objectNativeWrapper) {
603+
refCnt = objectNativeWrapper.getRefCount();
602604
} else {
603605
refCnt = readI64.read(PythonToNativeNode.executeUncached(resolved), CFields.PyObject__ob_refcnt);
604606
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextSlotBuiltins.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
import com.oracle.graal.python.builtins.objects.cext.capi.PyProcsWrapper;
111111
import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper;
112112
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
113+
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
113114
import com.oracle.graal.python.builtins.objects.cext.capi.UnicodeObjectNodes.UnicodeAsWideCharNode;
114115
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
115116
import com.oracle.graal.python.builtins.objects.cext.common.CArrayWrappers.CStringWrapper;
@@ -668,7 +669,7 @@ static Object get(PythonModule object) {
668669
abstract static class Py_get_PyObject_ob_refcnt extends CApiUnaryBuiltinNode {
669670

670671
@Specialization
671-
static Object get(PythonNativeWrapper wrapper) {
672+
static Object get(PythonAbstractObjectNativeWrapper wrapper) {
672673
return wrapper.getRefCount();
673674
}
674675
}
@@ -777,7 +778,7 @@ static Object set(PythonModule object, Object value) {
777778
abstract static class Py_set_PyObject_ob_refcnt extends CApiBinaryBuiltinNode {
778779

779780
@Specialization
780-
static Object set(PythonNativeWrapper wrapper, long value) {
781+
static Object set(PythonAbstractObjectNativeWrapper wrapper, long value) {
781782
CApiTransitions.setRefCount(wrapper, value);
782783
return PNone.NONE;
783784
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
4545
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
4646
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary;
47-
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
47+
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonStructNativeWrapper;
4848
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
4949
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
5050
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
@@ -142,7 +142,7 @@ void writeFromByteArray(int destOffset, byte[] src, int srcOffset, int length,
142142

143143
@SuppressWarnings("static-method")
144144
@ExportLibrary(InteropLibrary.class)
145-
public static class CDataObjectWrapper extends PythonNativeWrapper {
145+
public static final class CDataObjectWrapper extends PythonStructNativeWrapper {
146146

147147
final byte[] storage;
148148
final StgDictObject stgDict;
@@ -192,13 +192,13 @@ boolean isMemberReadable(String member,
192192
}
193193

194194
@ExportMessage
195-
final boolean isMemberModifiable(String member,
195+
boolean isMemberModifiable(String member,
196196
@Shared @Cached CastToJavaStringNode toJavaStringNode) {
197197
return isMemberReadable(member, toJavaStringNode);
198198
}
199199

200200
@ExportMessage
201-
final boolean isMemberInsertable(@SuppressWarnings("unused") String member) {
201+
boolean isMemberInsertable(@SuppressWarnings("unused") String member) {
202202
return false;
203203
}
204204

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ static Object doPythonObject(@SuppressWarnings("unused") MemoryBlock memory, Pyt
851851
@Fallback
852852
static Object doGeneric(Node inliningTarget, MemoryBlock memory, Storage storage, int offset,
853853
@Cached GetPointerValueAsObjectNode getPointerValueAsObjectNode,
854-
@Cached CExtNodes.ResolveHandleNode resolveHandleNode,
854+
@Cached CExtNodes.ResolvePointerNode resolveHandleNode,
855855
@Cached(inline = false) CApiTransitions.NativeToPythonNode nativeToPythonNode) {
856856
/*
857857
* We might get a pointer to a PyObject as a long when calling Python C API functions

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
import com.oracle.graal.python.builtins.objects.PythonAbstractObjectFactory.PInteropGetAttributeNodeGen;
7272
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
7373
import com.oracle.graal.python.builtins.objects.cext.capi.CApiGuards;
74-
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
74+
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
7575
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
7676
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
7777
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetIterator;
@@ -174,7 +174,7 @@ public abstract class PythonAbstractObject extends DynamicObject implements Truf
174174

175175
private static final TruffleString T_PRIVATE_PREFIX = tsLiteral("__");
176176
private static final int PRIVATE_PREFIX_LENGTH = T_PRIVATE_PREFIX.codePointLengthUncached(TS_ENCODING);
177-
private PythonNativeWrapper nativeWrapper;
177+
private PythonAbstractObjectNativeWrapper nativeWrapper;
178178

179179
// @ImportStatic doesn't work for this for some reason
180180
protected static final SpecialMethodSlot Iter = SpecialMethodSlot.Iter;
@@ -191,11 +191,11 @@ protected PythonAbstractObject() {
191191
super(ABSTRACT_SHAPE);
192192
}
193193

194-
public final PythonNativeWrapper getNativeWrapper() {
194+
public final PythonAbstractObjectNativeWrapper getNativeWrapper() {
195195
return nativeWrapper;
196196
}
197197

198-
public final void setNativeWrapper(PythonNativeWrapper nativeWrapper) {
198+
public final void setNativeWrapper(PythonAbstractObjectNativeWrapper nativeWrapper) {
199199
assert this.nativeWrapper == null;
200200

201201
// we must not set the native wrapper for one of the context-insensitive singletons

0 commit comments

Comments
 (0)