Skip to content

Commit 4b8b38a

Browse files
committed
Centralize CDataObject creation
1 parent adee666 commit 4b8b38a

14 files changed

+149
-106
lines changed

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,19 @@
6464
@ExportLibrary(PythonBufferAccessLibrary.class)
6565
public class CDataObject extends PythonBuiltinObject {
6666

67-
Pointer b_ptr; /* pointer to memory block */
68-
boolean b_needsfree; /* need _we_ free the memory? */
67+
final Pointer b_ptr; /* pointer to memory block */
68+
final boolean b_needsfree; /* need _we_ free the memory? */
6969
CDataObject b_base; /* pointer to base object or NULL */
7070
int b_size; /* size of memory block in bytes */
7171
int b_length; /* number of references we need */
7272
int b_index; /* index of this object into base's b_object list */
7373
Object b_objects; /* dictionary of references we need to keep, or Py_None */
7474

75-
public CDataObject(Object cls, Shape instanceShape) {
75+
public CDataObject(Object cls, Shape instanceShape, Pointer b_ptr, int b_size, boolean b_needsfree) {
7676
super(cls, instanceShape);
77-
this.b_ptr = Pointer.NULL;
77+
this.b_ptr = b_ptr;
78+
this.b_size = b_size;
79+
this.b_needsfree = b_needsfree;
7880
}
7981

8082
protected static CDataObjectWrapper createWrapper(StgDictObject dictObject, byte[] storage) {

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

Lines changed: 12 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

43-
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.DICTFLAG_FINAL;
43+
import static com.oracle.graal.python.builtins.modules.ctypes.StgDictObject.DICTFLAG_FINAL;
4444
import static com.oracle.graal.python.nodes.ErrorMessages.BUFFER_SIZE_TOO_SMALL_D_INSTEAD_OF_AT_LEAST_D_BYTES;
4545
import static com.oracle.graal.python.nodes.ErrorMessages.CTYPES_OBJECT_STRUCTURE_TOO_DEEP;
4646
import static com.oracle.graal.python.nodes.ErrorMessages.EXPECTED_P_INSTANCE_GOT_P;
@@ -271,6 +271,7 @@ Object CDataType_from_buffer_copy(Object type, Object buffer, int offset,
271271
@CachedLibrary("buffer") PythonBufferAccessLibrary bufferLib,
272272
@Cached PointerNodes.WriteBytesNode writeBytesNode,
273273
@Cached AuditNode auditNode,
274+
@Cached CtypesNodes.GenericPyCDataNewNode pyCDataNewNode,
274275
@Cached PyTypeStgDictNode pyTypeStgDictNode) {
275276
try {
276277
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, getRaiseNode());
@@ -288,8 +289,7 @@ Object CDataType_from_buffer_copy(Object type, Object buffer, int offset,
288289
// This prints the raw pointer in C, so just print 0
289290
auditNode.audit("ctypes.cdata/buffer", 0, bufferLen, offset);
290291

291-
CDataObject result = factory().createCDataObject(type);
292-
GenericPyCDataNew(dict, result);
292+
CDataObject result = pyCDataNewNode.execute(inliningTarget, type, dict);
293293
byte[] slice = new byte[dict.size];
294294
bufferLib.readIntoByteArray(buffer, offset, slice, 0, dict.size);
295295
writeBytesNode.execute(inliningTarget, result.b_ptr, slice);
@@ -349,49 +349,48 @@ protected abstract static class PyCDataAtAddress extends PNodeWithRaise {
349349
*/
350350
@Specialization
351351
CDataObject PyCData_AtAddress(Object type, Pointer pointer,
352+
@Bind("this") Node inliningTarget,
352353
@Cached PyTypeCheck pyTypeCheck,
353354
@Cached PyTypeStgDictNode pyTypeStgDictNode,
354-
@Cached PythonObjectFactory factory) {
355+
@Cached CtypesNodes.CreateCDataObjectNode createCDataObjectNode) {
355356
// auditNode.audit("ctypes.cdata", buf);
356357
// assert(PyType_Check(type));
357358
StgDictObject stgdict = pyTypeStgDictNode.checkAbstractClass(type, getRaiseNode());
358359
stgdict.flags |= DICTFLAG_FINAL;
359360

360-
CDataObject pd = factory.createCDataObject(type);
361+
CDataObject pd = createCDataObjectNode.execute(inliningTarget, type, pointer, stgdict.size, false);
361362
assert pyTypeCheck.isCDataObject(pd);
362-
pd.b_ptr = pointer;
363363
pd.b_length = stgdict.length;
364-
pd.b_size = stgdict.size;
365364
return pd;
366365
}
367366
}
368367

369368
// corresponds to PyCData_get
370369
@ImportStatic(FieldGet.class)
371370
protected abstract static class PyCDataGetNode extends PNodeWithRaise {
372-
protected abstract Object execute(Object type, FieldGet getfunc, Object src, int index, int size, Pointer adr);
371+
protected abstract Object execute(Object type, FieldGet getfunc, CDataObject src, int index, int size, Pointer adr);
373372

374373
@Specialization(guards = "getfunc != nil")
375374
@SuppressWarnings("unused")
376-
Object withFunc(Object type, FieldGet getfunc, Object src, int index, int size, Pointer adr,
375+
Object withFunc(Object type, FieldGet getfunc, CDataObject src, int index, int size, Pointer adr,
377376
@Cached GetFuncNode getFuncNode) {
378377
return getFuncNode.execute(getfunc, adr, size);
379378
}
380379

381380
@Specialization(guards = "getfunc == nil")
382-
Object WithoutFunc(Object type, @SuppressWarnings("unused") FieldGet getfunc, Object src, int index, int size, Pointer adr,
383-
@Cached PythonObjectFactory factory,
381+
Object withoutFunc(Object type, @SuppressWarnings("unused") FieldGet getfunc, CDataObject src, int index, int size, Pointer adr,
384382
@Bind("this") Node inliningTarget,
385383
@Cached PyTypeCheck pyTypeCheck,
386384
@Cached InlinedIsSameTypeNode isSameTypeNode,
387385
@Cached GetBaseClassNode getBaseClassNode,
388386
@Cached GetFuncNode getFuncNode,
389-
@Cached PyTypeStgDictNode pyTypeStgDictNode) {
387+
@Cached PyTypeStgDictNode pyTypeStgDictNode,
388+
@Cached CtypesNodes.PyCDataFromBaseObjNode fromBaseObjNode) {
390389
StgDictObject dict = pyTypeStgDictNode.execute(type);
391390
if (dict != null && dict.getfunc != FieldGet.nil && !pyTypeCheck.ctypesSimpleInstance(inliningTarget, type, getBaseClassNode, isSameTypeNode)) {
392391
return getFuncNode.execute(dict.getfunc, adr, size);
393392
}
394-
return PyCData_FromBaseObj(type, src, index, adr, factory, getRaiseNode(), pyTypeStgDictNode);
393+
return fromBaseObjNode.execute(inliningTarget, type, src, index, adr);
395394
}
396395
}
397396

@@ -612,45 +611,4 @@ static TruffleString unique_key(CDataObject cdata, int index,
612611
private static String toHex(int value) {
613612
return Integer.toHexString(value);
614613
}
615-
616-
static void PyCData_MallocBuffer(CDataObject obj, StgDictObject dict) {
617-
obj.b_ptr = dict.size > 0 ? Pointer.allocate(dict.ffi_type_pointer, dict.size) : Pointer.NULL;
618-
obj.b_size = dict.size;
619-
obj.b_needsfree = true;
620-
}
621-
622-
static CDataObject PyCData_FromBaseObj(Object type, Object base, int index, Pointer adr,
623-
PythonObjectFactory factory,
624-
PRaiseNode raiseNode,
625-
PyTypeStgDictNode pyTypeStgDictNode) {
626-
// assert(PyType_Check(type));
627-
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, raiseNode);
628-
dict.flags |= DICTFLAG_FINAL;
629-
CDataObject cmem = factory.createCDataObject(type);
630-
631-
cmem.b_length = dict.length;
632-
cmem.b_size = dict.size;
633-
if (base != null) { /* use base's buffer */
634-
cmem.b_ptr = adr;
635-
cmem.b_needsfree = false;
636-
cmem.b_base = (CDataObject) base;
637-
} else { /* copy contents of adr */
638-
PyCData_MallocBuffer(cmem, dict);
639-
// memcpy(cmem.b_ptr, adr, dict.size); TODO
640-
cmem.b_ptr = adr;
641-
}
642-
cmem.b_index = index;
643-
return cmem;
644-
}
645-
646-
// corresponds to GenericPyCData_new
647-
protected static CDataObject GenericPyCDataNew(StgDictObject dict, CDataObject obj) {
648-
dict.flags |= DICTFLAG_FINAL;
649-
obj.b_base = null;
650-
obj.b_index = 0;
651-
obj.b_objects = null;
652-
obj.b_length = dict.length;
653-
PyCData_MallocBuffer(obj, dict);
654-
return obj;
655-
}
656614
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ protected Object doit(CFieldObject self, Object inst, @SuppressWarnings("unused"
177177
throw raise(TypeError, NOT_A_CTYPE_INSTANCE);
178178
}
179179
CDataObject src = (CDataObject) inst;
180-
return pyCDataGetNode.execute(self.proto, self.getfunc, inst, self.index, self.size, src.b_ptr.withOffset(self.offset));
180+
return pyCDataGetNode.execute(self.proto, self.getfunc, src, self.index, self.size, src.b_ptr.withOffset(self.offset));
181181
}
182182
}
183183

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCFuncPtr;
4545
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCPointer;
4646
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCPointerType;
47-
import static com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.PyCData_FromBaseObj;
4847
import static com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.PyCData_GetContainer;
4948
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.WCHAR_T_ENCODING;
5049
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.WCHAR_T_SIZE;
@@ -233,8 +232,6 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
233232
protected static final int TYPEFLAG_HASUNION = 0x400;
234233
protected static final int TYPEFLAG_HASBITFIELD = 0x800;
235234

236-
protected static final int DICTFLAG_FINAL = 0x1000;
237-
238235
@Override
239236
public void initialize(Python3Core core) {
240237
super.initialize(core);
@@ -1350,15 +1347,14 @@ static Object callResType(Object restype, @SuppressWarnings("unused") FFIType rt
13501347
static Object callGetFunc(Object restype, FFIType rtype, Object result, Object checker,
13511348
@Bind("this") Node inliningTarget,
13521349
@CachedLibrary("result") InteropLibrary ilib,
1353-
@Shared @Cached PyTypeStgDictNode pyTypeStgDictNode,
1350+
@SuppressWarnings("unused") @Shared @Cached PyTypeStgDictNode pyTypeStgDictNode,
13541351
@Bind("getStgDict(restype, pyTypeStgDictNode)") StgDictObject dict,
13551352
@Cached CallNode callNode,
13561353
@Cached PyTypeCheck pyTypeCheck,
13571354
@Cached GetBaseClassNode getBaseClassNode,
13581355
@Cached InlinedIsSameTypeNode isSameTypeNode,
13591356
@Cached GetFuncNode getFuncNode,
1360-
@Cached PRaiseNode raiseNode,
1361-
@Cached PythonObjectFactory factory) {
1357+
@Cached CtypesNodes.PyCDataFromBaseObjNode fromBaseObjNode) {
13621358
Pointer resultPtr;
13631359
try {
13641360
resultPtr = switch (rtype.type) {
@@ -1397,7 +1393,7 @@ static Object callGetFunc(Object restype, FFIType rtype, Object result, Object c
13971393
if (dict.getfunc != FieldGet.nil && !pyTypeCheck.ctypesSimpleInstance(inliningTarget, restype, getBaseClassNode, isSameTypeNode)) {
13981394
retval = getFuncNode.execute(dict.getfunc, resultPtr, dict.size);
13991395
} else {
1400-
retval = PyCData_FromBaseObj(restype, null, 0, resultPtr, factory, raiseNode, pyTypeStgDictNode);
1396+
retval = fromBaseObjNode.execute(inliningTarget, restype, null, 0, resultPtr);
14011397
}
14021398
assert retval != null : "Should have raised an error earlier!";
14031399
if (PGuards.isPNone(checker) || checker == null) {

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCStructType;
5252
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SimpleCData;
5353
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.UnionType;
54+
import static com.oracle.graal.python.builtins.modules.ctypes.StgDictObject.DICTFLAG_FINAL;
5455
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.isJavaString;
5556
import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR;
5657
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
@@ -61,9 +62,11 @@
6162
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
6263
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
6364
import com.oracle.graal.python.builtins.objects.type.TypeNodes.InlinedIsSameTypeNode;
65+
import com.oracle.graal.python.nodes.PRaiseNode;
6466
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
6567
import com.oracle.graal.python.nodes.object.InlinedGetClassNode;
6668
import com.oracle.graal.python.runtime.PythonContext;
69+
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
6770
import com.oracle.truffle.api.CompilerDirectives;
6871
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6972
import com.oracle.truffle.api.dsl.Bind;
@@ -293,4 +296,78 @@ static Object convert(Node inliningTarget, Object pointerObj,
293296
return handleFromPointerNode.execute(inliningTarget, pointer);
294297
}
295298
}
299+
300+
@GenerateInline
301+
@GenerateCached(false)
302+
public abstract static class PyCDataFromBaseObjNode extends Node {
303+
public abstract CDataObject execute(Node inliningTarget, Object type, CDataObject base, int index, Pointer adr);
304+
305+
@Specialization
306+
static CDataObject PyCData_FromBaseObj(Node inliningTarget, Object type, CDataObject base, int index, Pointer adr,
307+
@Cached PRaiseNode raiseNode,
308+
@Cached StgDictBuiltins.PyTypeStgDictNode pyTypeStgDictNode,
309+
@Cached CreateCDataObjectNode createCDataObjectNode,
310+
@Cached PyCDataMallocBufferNode mallocBufferNode,
311+
@Cached PointerNodes.MemcpyNode memcpyNode) {
312+
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, raiseNode);
313+
dict.flags |= DICTFLAG_FINAL;
314+
CDataObject cmem;
315+
316+
if (base != null) { /* use base's buffer */
317+
cmem = createCDataObjectNode.execute(inliningTarget, type, adr, dict.size, false);
318+
cmem.b_base = base;
319+
} else { /* copy contents of adr */
320+
cmem = mallocBufferNode.execute(inliningTarget, type, dict);
321+
memcpyNode.execute(inliningTarget, cmem.b_ptr, adr, dict.size);
322+
}
323+
cmem.b_length = dict.length;
324+
cmem.b_index = index;
325+
return cmem;
326+
}
327+
}
328+
329+
@GenerateInline
330+
@GenerateCached(false)
331+
public abstract static class CreateCDataObjectNode extends Node {
332+
public abstract CDataObject execute(Node inliningTarget, Object type, Pointer pointer, int size, boolean needsfree);
333+
334+
@Specialization
335+
static CDataObject doCreate(Object type, Pointer pointer, int size, boolean needsfree,
336+
@Cached IsSubtypeNode isSubtypeNode,
337+
@Cached PythonObjectFactory factory) {
338+
if (isSubtypeNode.execute(type, PyCFuncPtr)) {
339+
return factory.createPyCFuncPtrObject(type, pointer, size, needsfree);
340+
} else {
341+
return factory.createCDataObject(type, pointer, size, needsfree);
342+
}
343+
}
344+
}
345+
346+
@GenerateInline
347+
@GenerateCached(false)
348+
public abstract static class PyCDataMallocBufferNode extends Node {
349+
public abstract CDataObject execute(Node inliningTarget, Object type, StgDictObject dict);
350+
351+
@Specialization
352+
static CDataObject doCreate(Node inliningTarget, Object type, StgDictObject dict,
353+
@Cached CreateCDataObjectNode createCDataObjectNode) {
354+
Pointer pointer = dict.size > 0 ? Pointer.allocate(dict.ffi_type_pointer, dict.size) : Pointer.NULL;
355+
return createCDataObjectNode.execute(inliningTarget, type, pointer, dict.size, true);
356+
}
357+
}
358+
359+
@GenerateInline
360+
@GenerateCached(false)
361+
public abstract static class GenericPyCDataNewNode extends Node {
362+
public abstract CDataObject execute(Node inliningTarget, Object type, StgDictObject dict);
363+
364+
@Specialization
365+
static CDataObject doCreate(Node inliningTarget, Object type, StgDictObject dict,
366+
@Cached PyCDataMallocBufferNode mallocBufferNode) {
367+
CDataObject obj = mallocBufferNode.execute(inliningTarget, type, dict);
368+
obj.b_length = dict.length;
369+
dict.flags |= DICTFLAG_FINAL;
370+
return obj;
371+
}
372+
}
296373
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCArray;
44-
import static com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.GenericPyCDataNew;
4544
import static com.oracle.graal.python.nodes.ErrorMessages.ARRAY_DOES_NOT_SUPPORT_ITEM_DELETION;
4645
import static com.oracle.graal.python.nodes.ErrorMessages.CAN_ONLY_ASSIGN_SEQUENCE_OF_SAME_SIZE;
4746
import static com.oracle.graal.python.nodes.ErrorMessages.INDICES_MUST_BE_INTEGER;
@@ -87,12 +86,14 @@
8786
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
8887
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
8988
import com.oracle.graal.python.util.PythonUtils;
89+
import com.oracle.truffle.api.dsl.Bind;
9090
import com.oracle.truffle.api.dsl.Cached;
9191
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
9292
import com.oracle.truffle.api.dsl.NodeFactory;
9393
import com.oracle.truffle.api.dsl.Specialization;
9494
import com.oracle.truffle.api.frame.VirtualFrame;
9595
import com.oracle.truffle.api.library.CachedLibrary;
96+
import com.oracle.truffle.api.nodes.Node;
9697
import com.oracle.truffle.api.strings.TruffleString;
9798

9899
@CoreFunctions(extendClasses = PyCArray)
@@ -108,9 +109,11 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
108109
protected abstract static class NewNode extends PythonBuiltinNode {
109110
@Specialization
110111
protected Object newCData(Object type, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") PKeyword[] kwds,
111-
@Cached PyTypeStgDictNode pyTypeStgDictNode) {
112+
@Bind("this") Node inliningTarget,
113+
@Cached PyTypeStgDictNode pyTypeStgDictNode,
114+
@Cached CtypesNodes.GenericPyCDataNewNode newNode) {
112115
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, getRaiseNode());
113-
return GenericPyCDataNew(dict, factory().createCDataObject(type));
116+
return newNode.execute(inliningTarget, type, dict);
114117
}
115118
}
116119

0 commit comments

Comments
 (0)