Skip to content

Commit 3f397ce

Browse files
committed
Move replacement logic from all wrappers to the 3 classes that use it
1 parent f314842 commit 3f397ce

File tree

11 files changed

+62
-261
lines changed

11 files changed

+62
-261
lines changed

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,7 @@ 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_type) {
413-
GraalPyPrivate_Log(PY_TRUFFLE_LOG_FINER,
414-
"%s: Object: 0x%zx has no type anymore, we have "
415-
"no idea what it is, we will just free it",
416-
__func__, obj);
417-
free(obj);
418-
} else if (obj->ob_refcnt == _Py_IMMORTAL_REFCNT) {
412+
if (obj->ob_refcnt == _Py_IMMORTAL_REFCNT) {
419413
GraalPyPrivate_Log(PY_TRUFFLE_LOG_FINER,
420414
"%s: Not deallocating immortal object: 0x%zx (%s%s)",
421415
__func__, obj,

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

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,11 @@
4343
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ReleaseNativeWrapperNode;
4444
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonStructNativeWrapper;
4545
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
46-
import com.oracle.graal.python.builtins.objects.ints.PInt;
47-
import com.oracle.graal.python.nodes.ErrorMessages;
4846
import com.oracle.graal.python.runtime.PythonContext;
49-
import com.oracle.graal.python.util.OverflowException;
5047
import com.oracle.graal.python.util.PythonUtils;
5148
import com.oracle.truffle.api.CompilerDirectives;
5249
import com.oracle.truffle.api.dsl.Cached;
53-
import com.oracle.truffle.api.dsl.Cached.Shared;
5450
import com.oracle.truffle.api.interop.InteropLibrary;
55-
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
5651
import com.oracle.truffle.api.interop.UnsupportedMessageException;
5752
import com.oracle.truffle.api.library.CachedLibrary;
5853
import com.oracle.truffle.api.library.ExportLibrary;
@@ -83,7 +78,7 @@ public CPyObjectArrayWrapper(Object[] delegate) {
8378
wrappers = new Object[delegate.length];
8479
}
8580

86-
public Object[] getObjectArray() {
81+
private Object[] getObjectArray() {
8782
return ((Object[]) getDelegate());
8883
}
8984

@@ -97,53 +92,15 @@ long asPointer() {
9792
return getNativePointer();
9893
}
9994

100-
@ExportMessage
101-
long getArraySize() {
102-
return wrappers.length;
103-
}
104-
105-
@ExportMessage
106-
@SuppressWarnings("static-method")
107-
boolean hasArrayElements() {
108-
return true;
109-
}
110-
111-
@ExportMessage
112-
Object readArrayElement(long index,
113-
@Shared("toNativeNode") @Cached PythonToNativeNode toNativeNode) throws InvalidArrayIndexException {
114-
try {
115-
int idx = PInt.intValueExact(index);
116-
if (idx >= 0 && idx < wrappers.length) {
117-
if (wrappers[idx] == null) {
118-
Object[] arr = getObjectArray();
119-
wrappers[idx] = toNativeNode.execute(arr[idx]);
120-
}
121-
return wrappers[idx];
122-
}
123-
} catch (OverflowException e) {
124-
// fall through
125-
}
126-
CompilerDirectives.transferToInterpreterAndInvalidate();
127-
throw InvalidArrayIndexException.create(index);
128-
}
129-
130-
@ExportMessage
131-
boolean isArrayElementReadable(long identifier) {
132-
return 0 <= identifier && identifier < wrappers.length;
133-
}
134-
13595
/**
13696
* Copies a Java {@code Object[]} to a native {@code PyObject *arr[]}. For this, the native
13797
* memory is allocated off-heap using {@code Unsafe}.
13898
*/
13999
@ExportMessage
140100
void toNative(
141-
@Shared("toNativeNode") @Cached PythonToNativeNode toNativeNode,
101+
@Cached PythonToNativeNode toNativeNode,
142102
@CachedLibrary(limit = "3") InteropLibrary interopLib) {
143-
if (!PythonContext.get(toNativeNode).isNativeAccessAllowed()) {
144-
CompilerDirectives.transferToInterpreterAndInvalidate();
145-
throw new RuntimeException(ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED.toJavaStringUncached());
146-
}
103+
assert PythonContext.get(toNativeNode).isNativeAccessAllowed();
147104
if (!isNative()) {
148105
Object[] data = getObjectArray();
149106
long ptr = allocateBoundary((long) wrappers.length * Long.BYTES);
@@ -175,10 +132,7 @@ public void free(ReleaseNativeWrapperNode releaseNativeWrapperNode) {
175132
// releaseNativeWrapperNode.execute(wrappers[i]);
176133
// }
177134
if (isNative()) {
178-
if (!PythonContext.get(releaseNativeWrapperNode).isNativeAccessAllowed()) {
179-
CompilerDirectives.transferToInterpreterAndInvalidate();
180-
throw new RuntimeException(ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED.toJavaStringUncached());
181-
}
135+
assert PythonContext.get(releaseNativeWrapperNode).isNativeAccessAllowed();
182136
freeBoundary(getNativePointer());
183137
}
184138
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public abstract class ManagedMethodWrappers {
7777
public abstract static class MethodWrapper extends PythonStructNativeWrapper {
7878

7979
public MethodWrapper(Object method) {
80-
super(method, false);
80+
super(method);
8181
}
8282

8383
@ExportMessage

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
4646
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
4747
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitionsFactory.PythonToNativeNodeGen;
48+
import com.oracle.graal.python.builtins.objects.cext.common.NativePointer;
4849
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
4950
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
5051
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
@@ -66,6 +67,7 @@
6667
* </p>
6768
*/
6869
public final class PThreadState extends PythonStructNativeWrapper {
70+
private final Object replacement;
6971

7072
/** Same as _PY_NSMALLNEGINTS */
7173
public static final int PY_NSMALLNEGINTS = 5;
@@ -75,12 +77,11 @@ public final class PThreadState extends PythonStructNativeWrapper {
7577

7678
@TruffleBoundary
7779
private PThreadState(PythonThreadState threadState) {
78-
super(threadState, true);
79-
// TODO: this passes false for allocatedFromJava although we actually do allocate it from
80-
// Java, but we currently free it on context exit using a call to
81-
// FUN_PY_GC_COLLECT_NO_FAIL, which can bite us when we change allocators for the Java
82-
// side...
83-
replacement = registerReplacement(allocateCLayout(threadState), false, InteropLibrary.getUncached());
80+
super(threadState);
81+
long ptr = allocateCLayout(threadState);
82+
CApiTransitions.createReference(this, ptr, true);
83+
// TODO: wrap in NativePointer for NFI
84+
replacement = new NativePointer(ptr);
8485
}
8586

8687
public static Object getOrCreateNativeThreadState(PythonLanguage language, PythonContext context) {
@@ -109,10 +110,10 @@ public PythonThreadState getThreadState() {
109110
}
110111

111112
@TruffleBoundary
112-
private static Object allocateCLayout(PythonThreadState threadState) {
113+
private static long allocateCLayout(PythonThreadState threadState) {
113114
PythonToNativeNode toNative = PythonToNativeNodeGen.getUncached();
114115

115-
Object ptr = CStructAccess.AllocateNode.allocUncached(CStructs.PyThreadState);
116+
long ptr = CStructAccess.AllocateNode.allocUncachedPointer(CStructs.PyThreadState.size());
116117
CStructAccess.WritePointerNode writePtrNode = CStructAccess.WritePointerNode.getUncached();
117118
PythonContext pythonContext = PythonContext.get(null);
118119
PDict threadStateDict = threadState.getDict();

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

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
5050
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
5151
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNewRefNode;
52+
import com.oracle.graal.python.builtins.objects.cext.common.NativePointer;
5253
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
5354
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
5455
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess.GetElementPtrNode;
@@ -59,19 +60,15 @@
5960
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6061
import com.oracle.truffle.api.interop.InteropLibrary;
6162
import com.oracle.truffle.api.interop.UnsupportedMessageException;
62-
import com.oracle.truffle.api.library.ExportLibrary;
63-
import com.oracle.truffle.api.library.ExportMessage;
6463

6564
/**
6665
* Wrapper object for {@code PMemoryView}.
6766
*/
68-
@ExportLibrary(InteropLibrary.class)
6967
public final class PyMemoryViewWrapper extends PythonAbstractObjectNativeWrapper {
70-
7168
private Object replacement;
7269

7370
public PyMemoryViewWrapper(PythonObject delegate) {
74-
super(delegate, true);
71+
super(delegate);
7572
assert delegate instanceof PMemoryView;
7673
}
7774

@@ -82,16 +79,15 @@ private static Object intArrayToNativePySSizeArray(int[] intArray) {
8279
}
8380

8481
@TruffleBoundary
85-
private static Object allocate(PMemoryView object) {
82+
private static long allocate(PMemoryView object) {
8683
GetElementPtrNode getElementNode = GetElementPtrNode.getUncached();
8784
CStructAccess.WritePointerNode writePointerNode = CStructAccess.WritePointerNode.getUncached();
8885
CStructAccess.WriteLongNode writeI64Node = CStructAccess.WriteLongNode.getUncached();
8986
CStructAccess.WriteIntNode writeI32Node = CStructAccess.WriteIntNode.getUncached();
9087
CExtNodes.AsCharPointerNode asCharPointerNode = CExtNodes.AsCharPointerNode.getUncached();
9188

92-
Object mem;
9389
long taggedPointer = CApiTransitions.FirstToNativeNode.executeUncached(object.getNativeWrapper(), true /*- TODO: immortal for now */);
94-
mem = CApiTransitions.HandlePointerConverter.pointerToStub(taggedPointer);
90+
long mem = CApiTransitions.HandlePointerConverter.pointerToStub(taggedPointer);
9591
writeI32Node.write(mem, PyMemoryViewObject__flags, object.getFlags());
9692
writeI64Node.write(mem, PyMemoryViewObject__exports, object.getExports().get());
9793
// TODO: ignoring mbuf, hash and weakreflist for now
@@ -150,37 +146,14 @@ private static Object allocate(PMemoryView object) {
150146

151147
public Object getReplacement(InteropLibrary lib) {
152148
if (replacement == null) {
153-
Object pointerObject = allocate((PMemoryView) getDelegate());
149+
long ptr = allocate((PMemoryView) getDelegate());
150+
// TODO: need to convert to interop pointer for NFI for now
151+
replacement = new NativePointer(ptr);
154152
// TODO: this passes "false" for allocatedFromJava, although it actually is. The
155153
// problem, however, is that this struct contains nested allocations from Java. This
156154
// needs to be cleaned up...
157-
replacement = registerReplacement(pointerObject, false, lib);
155+
CApiTransitions.createReference(this, ptr, false);
158156
}
159157
return replacement;
160158
}
161-
162-
@ExportMessage
163-
boolean isPointer() {
164-
return isNative();
165-
}
166-
167-
@ExportMessage
168-
long asPointer() throws UnsupportedMessageException {
169-
if (!isNative()) {
170-
CompilerDirectives.transferToInterpreterAndInvalidate();
171-
throw UnsupportedMessageException.create();
172-
}
173-
return getNativePointer();
174-
}
175-
176-
@ExportMessage
177-
void toNative() {
178-
if (!isNative()) {
179-
/*
180-
* This is a wrapper that is eagerly transformed to its C layout in the Python-to-native
181-
* transition. Therefore, the wrapper is expected to be native already.
182-
*/
183-
throw CompilerDirectives.shouldNotReachHere();
184-
}
185-
}
186159
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public abstract class PyProcsWrapper extends PythonStructNativeWrapper {
120120
protected final CApiTiming timing;
121121

122122
public PyProcsWrapper(Object delegate) {
123-
super(delegate, false);
123+
super(delegate);
124124
this.timing = CApiTiming.create(false, delegate);
125125
}
126126

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

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242

4343
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
4444
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper;
45+
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
4546
import com.oracle.graal.python.builtins.objects.cext.common.CArrayWrappers.CStringWrapper;
47+
import com.oracle.graal.python.builtins.objects.cext.common.NativePointer;
4648
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
4749
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
4850
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess.AllocateNode;
@@ -64,20 +66,18 @@
6466
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6567
import com.oracle.truffle.api.interop.InteropLibrary;
6668
import com.oracle.truffle.api.interop.UnsupportedMessageException;
67-
import com.oracle.truffle.api.library.ExportLibrary;
68-
import com.oracle.truffle.api.library.ExportMessage;
6969
import com.oracle.truffle.api.strings.TruffleString;
7070

7171
/**
7272
* Used to wrap {@link PythonClass} when used in native code. This wrapper is replacing and the
7373
* replacement mimics the correct shape of the corresponding native type {@code struct _typeobject}.
7474
*/
75-
@ExportLibrary(InteropLibrary.class)
7675
public final class PythonClassNativeWrapper extends PythonAbstractObjectNativeWrapper {
7776
private final CStringWrapper nameWrapper;
77+
private Object replacement;
7878

7979
private PythonClassNativeWrapper(PythonManagedClass object, TruffleString name, TruffleString.SwitchEncodingNode switchEncoding) {
80-
super(object, true);
80+
super(object);
8181
this.nameWrapper = new CStringWrapper(switchEncoding.execute(name, TruffleString.Encoding.UTF_8), TruffleString.Encoding.UTF_8);
8282
}
8383

@@ -174,7 +174,13 @@ public static void wrapStaticTypeStructForManagedClass(PythonManagedClass clazz,
174174
* 'getReplacement' for more explanation).
175175
*/
176176
wrapper.replacement = pointer;
177-
wrapper.registerReplacement(pointer, false, lib);
177+
long ptr;
178+
try {
179+
ptr = lib.asPointer(pointer);
180+
} catch (UnsupportedMessageException e) {
181+
throw CompilerDirectives.shouldNotReachHere(e);
182+
}
183+
CApiTransitions.createReference(wrapper, ptr, false);
178184
}
179185

180186
public static void initNative(PythonManagedClass clazz, Object pointer) {
@@ -219,10 +225,11 @@ private void initializeReplacement(InteropLibrary lib) {
219225
size = TypeNodes.GetBasicSizeNode.executeUncached(nativeMetatype);
220226
}
221227
}
222-
Object pointerObject = AllocateNode.allocUncached(size);
223-
replacement = registerReplacement(pointerObject, true, lib);
224-
225-
ToNativeTypeNode.initializeType(this, pointerObject, heaptype);
228+
long ptr = AllocateNode.allocUncachedPointer(size);
229+
// TODO: need to convert to interop pointer for NFI for now
230+
replacement = new NativePointer(ptr);
231+
CApiTransitions.createReference(this, ptr, true);
232+
ToNativeTypeNode.initializeType(this, ptr, heaptype);
226233
}
227234

228235
/**
@@ -231,29 +238,4 @@ private void initializeReplacement(InteropLibrary lib) {
231238
public Object getReplacementIfInitialized() {
232239
return replacement;
233240
}
234-
235-
@ExportMessage
236-
boolean isPointer() {
237-
return isNative();
238-
}
239-
240-
@ExportMessage
241-
long asPointer() throws UnsupportedMessageException {
242-
if (!isNative()) {
243-
CompilerDirectives.transferToInterpreterAndInvalidate();
244-
throw UnsupportedMessageException.create();
245-
}
246-
return getNativePointer();
247-
}
248-
249-
@ExportMessage
250-
void toNative() {
251-
if (!isNative()) {
252-
/*
253-
* This is a wrapper that is eagerly transformed to its C layout in the Python-to-native
254-
* transition. Therefore, the wrapper is expected to be native already.
255-
*/
256-
throw CompilerDirectives.shouldNotReachHere();
257-
}
258-
}
259241
}

0 commit comments

Comments
 (0)