Skip to content

Commit e976a81

Browse files
committed
store tp_as_buffer as a proper struct natively and inherit it
1 parent 0067d31 commit e976a81

File tree

5 files changed

+62
-176
lines changed

5 files changed

+62
-176
lines changed

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ void initialize_type_structure(PyTypeObject* structure, PyTypeObject* ptype, pol
115115
destructor dealloc_fun = structure->tp_dealloc;
116116
freefunc free_fun = structure->tp_free;
117117
Py_ssize_t vectorcall_offset = structure->tp_vectorcall_offset;
118+
PyBufferProcs* as_buffer = structure->tp_as_buffer;
118119
PyTypeObject* type_handle = truffle_assign_managed(structure, ptype);
119120
// write flags as specified in the dummy to the PythonClass object
120121
type_handle->tp_flags = original_flags | Py_TPFLAGS_READY;
@@ -135,6 +136,9 @@ void initialize_type_structure(PyTypeObject* structure, PyTypeObject* ptype, pol
135136
if (vectorcall_offset) {
136137
type_handle->tp_vectorcall_offset = vectorcall_offset;
137138
}
139+
if (as_buffer) {
140+
type_handle->tp_as_buffer = as_buffer;
141+
}
138142
}
139143

140144
static void initialize_builtin_type(PyTypeObject* structure, const char* typname, polyglot_typeid tid) {
@@ -322,6 +326,30 @@ static void initialize_bufferprocs() {
322326
polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_SetBufferProcs", native_to_java((PyObject*)&PyByteArray_Type), (getbufferproc)bytearray_getbuffer, (releasebufferproc)bytearray_releasebuffer);
323327
polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_SetBufferProcs", native_to_java((PyObject*)&PyBuffer_Type), (getbufferproc)bufferdecorator_getbuffer, (releasebufferproc)NULL);
324328
polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_SetBufferProcs", native_to_java((PyObject*)&PyMemoryView_Type), (getbufferproc)memoryview_getbuffer, (releasebufferproc)memoryview_releasebuffer);
329+
330+
static PyBufferProcs bytes_as_buffer = {
331+
(getbufferproc)bytes_buffer_getbuffer, /* bf_getbuffer */
332+
(releasebufferproc)NULL, /* bf_releasebuffer */
333+
};
334+
PyBytes_Type.tp_as_buffer = &bytes_as_buffer;
335+
336+
static PyBufferProcs bytearray_as_buffer = {
337+
(getbufferproc)bytearray_getbuffer, /* bf_getbuffer */
338+
(releasebufferproc)bytearray_releasebuffer, /* bf_releasebuffer */
339+
};
340+
PyByteArray_Type.tp_as_buffer = &bytearray_as_buffer;
341+
342+
static PyBufferProcs buffer_as_buffer = {
343+
(getbufferproc)bufferdecorator_getbuffer, /* bf_getbuffer */
344+
(releasebufferproc)NULL, /* bf_releasebuffer */
345+
};
346+
PyBuffer_Type.tp_as_buffer = &buffer_as_buffer;
347+
348+
static PyBufferProcs memory_as_buffer = {
349+
(getbufferproc)memoryview_getbuffer, /* bf_getbuffer */
350+
(releasebufferproc)memoryview_releasebuffer, /* bf_releasebuffer */
351+
};
352+
PyMemoryView_Type.tp_as_buffer = &memory_as_buffer;
325353
}
326354

327355
static void initialize_filesystemencoding() {

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,14 @@ static void inherit_slots(PyTypeObject *type, PyTypeObject *base) {
316316
#define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
317317
#define COPYBUF(SLOT) COPYSLOT(tp_as_buffer->SLOT)
318318

319+
if (type->tp_as_buffer != NULL && base->tp_as_buffer != NULL) {
320+
basebase = base->tp_base;
321+
if (basebase->tp_as_buffer == NULL)
322+
basebase = NULL;
323+
COPYBUF(bf_getbuffer);
324+
COPYBUF(bf_releasebuffer);
325+
}
326+
319327
basebase = base->tp_base;
320328

321329
COPYSLOT(tp_dealloc);
@@ -736,6 +744,21 @@ int PyType_Ready(PyTypeObject* cls) {
736744
}
737745
}
738746

747+
/* Some more special stuff */
748+
base = cls->tp_base;
749+
if (base != NULL) {
750+
// if (cls->tp_as_async == NULL)
751+
// cls->tp_as_async = base->tp_as_async;
752+
// if (cls->tp_as_number == NULL)
753+
// cls->tp_as_number = base->tp_as_number;
754+
// if (cls->tp_as_sequence == NULL)
755+
// cls->tp_as_sequence = base->tp_as_sequence;
756+
// if (cls->tp_as_mapping == NULL)
757+
// cls->tp_as_mapping = base->tp_as_mapping;
758+
if (cls->tp_as_buffer == NULL)
759+
cls->tp_as_buffer = base->tp_as_buffer;
760+
}
761+
739762
/* Link into each base class's list of subclasses */
740763
bases = cls->tp_bases;
741764
n = PyTuple_GET_SIZE(bases);

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

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.OB_REFCNT;
5252
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.OB_TYPE;
5353
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.TP_ALLOC;
54+
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.TP_AS_BUFFER;
5455
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.TP_BASICSIZE;
5556
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.TP_DEALLOC;
5657
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeMember.TP_DEL;
@@ -468,45 +469,9 @@ static Object doTpAsNumber(PythonManagedClass object, @SuppressWarnings("unused"
468469

469470
@Specialization(guards = "eq(TP_AS_BUFFER, key)")
470471
static Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key,
471-
@Cached IsSubtypeNode isSubtype,
472-
@Cached BranchProfile notBytes,
473-
@Cached BranchProfile notBytearray,
474-
@Cached BranchProfile notMemoryview,
475-
@Cached BranchProfile notBuffer,
476-
@Cached BranchProfile notMmap,
477472
@Cached LookupNativeMemberInMRONode lookupTpAsBufferNode,
478473
@Shared("nullToSulongNode") @Cached ToSulongNode toSulongNode) {
479-
Python3Core core = PythonContext.get(toSulongNode);
480-
PythonBuiltinClass pBytes = core.lookupType(PythonBuiltinClassType.PBytes);
481-
if (isSubtype.execute(object, pBytes)) {
482-
return new PyBufferProcsWrapper(pBytes);
483-
}
484-
notBytes.enter();
485-
PythonBuiltinClass pBytearray = core.lookupType(PythonBuiltinClassType.PByteArray);
486-
if (isSubtype.execute(object, pBytearray)) {
487-
return new PyBufferProcsWrapper(pBytearray);
488-
}
489-
notBytearray.enter();
490-
PythonBuiltinClass pMemoryview = core.lookupType(PythonBuiltinClassType.PMemoryView);
491-
if (isSubtype.execute(object, pMemoryview)) {
492-
return new PyBufferProcsWrapper(pMemoryview);
493-
}
494-
notMemoryview.enter();
495-
PythonBuiltinClass pBuffer = core.lookupType(PythonBuiltinClassType.PBuffer);
496-
if (isSubtype.execute(object, pBuffer)) {
497-
return new PyBufferProcsWrapper(pBuffer);
498-
}
499-
notBuffer.enter();
500-
PythonBuiltinClass pMmap = core.lookupType(PythonBuiltinClassType.PMMap);
501-
if (isSubtype.execute(object, pMmap)) {
502-
return new PyBufferProcsWrapper(pMmap);
503-
}
504-
notMmap.enter();
505-
/*
506-
* Managed classes don't store PyBufferProcs objects and so there is no attribute. This
507-
* is why we use managedMemberName == "".
508-
*/
509-
Object result = lookupTpAsBufferNode.execute(object, NativeMember.TP_AS_BUFFER, "");
474+
Object result = lookupTpAsBufferNode.execute(object, NativeMember.TP_AS_BUFFER, TypeBuiltins.TYPE_AS_BUFFER);
510475
if (result == PNone.NO_VALUE) {
511476
// NULL pointer
512477
return toSulongNode.execute(PythonContext.get(toSulongNode).getNativeNull());
@@ -1440,6 +1405,13 @@ static void doTpFree(Object object, @SuppressWarnings("unused") PythonNativeWrap
14401405
writeAttrNode.execute(object, TypeBuiltins.TYPE_FREE, asPythonObjectNode.execute(freeFunc));
14411406
}
14421407

1408+
@Specialization(guards = {"isPythonClass(object)", "eq(TP_AS_BUFFER, key)"})
1409+
static void doTpAsBuffer(Object object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key, Object bufferProcs,
1410+
@Cached WriteAttributeToObjectNode writeAttrNode,
1411+
@Cached WrapVoidPtrNode asPythonObjectNode) {
1412+
writeAttrNode.execute(object, TypeBuiltins.TYPE_AS_BUFFER, asPythonObjectNode.execute(bufferProcs));
1413+
}
1414+
14431415
@GenerateUncached
14441416
static final class EachSubclassAdd extends HashingStorageLibrary.ForEachNode<SubclassAddState> {
14451417

@@ -1616,6 +1588,7 @@ protected boolean isMemberModifiable(String member) {
16161588
MD_STATE.getMemberName().equals(member) ||
16171589
TP_DICT.getMemberName().equals(member) ||
16181590
TP_DICTOFFSET.getMemberName().equals(member) ||
1591+
TP_AS_BUFFER.getMemberName().equals(member) ||
16191592
MEMORYVIEW_EXPORTS.getMemberName().equals(member);
16201593
}
16211594

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

Lines changed: 0 additions & 139 deletions
This file was deleted.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ public class TypeBuiltins extends PythonBuiltins {
172172
public static final HiddenKey TYPE_DEALLOC = new HiddenKey("__dealloc__");
173173
public static final HiddenKey TYPE_DEL = new HiddenKey("__del__");
174174
public static final HiddenKey TYPE_FREE = new HiddenKey("__free__");
175+
public static final HiddenKey TYPE_AS_BUFFER = new HiddenKey("__tp_as_buffer__");
175176
public static final HiddenKey TYPE_FLAGS = new HiddenKey(__FLAGS__);
176177
public static final HiddenKey TYPE_VECTORCALL_OFFSET = new HiddenKey("__vectorcall_offset__");
177178
public static final HiddenKey TYPE_GETBUFFER = new HiddenKey("__getbuffer__");

0 commit comments

Comments
 (0)