Skip to content

Commit 1624dd9

Browse files
committed
[GR-8776] [GR-8368] [GR-8561] Improve SRE compatibility.
PullRequest: graalpython/123
2 parents 904acb0 + d05264e commit 1624dd9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1903
-717
lines changed

graalpython/com.oracle.graal.python.cext/modules/_cpython_sre.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ getstring(PyObject* string, Py_ssize_t* p_length,
362362
return view->buf;
363363
}
364364

365+
365366
LOCAL(PyObject*)
366367
state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
367368
Py_ssize_t start, Py_ssize_t end)
@@ -1055,6 +1056,19 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string,
10551056

10561057
}
10571058

1059+
__attribute__((always_inline))
1060+
inline static void *_memchr(const void *s, int c, Py_ssize_t n) {
1061+
unsigned char *p = (unsigned char*)s;
1062+
while(n--) {
1063+
if(*p != (unsigned char)c) {
1064+
p++;
1065+
} else {
1066+
return p;
1067+
}
1068+
}
1069+
return 0;
1070+
}
1071+
10581072
static PyObject*
10591073
pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
10601074
Py_ssize_t count, Py_ssize_t subn)
@@ -1086,7 +1100,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
10861100
b = charsize;
10871101
if (ptr) {
10881102
if (charsize == 1)
1089-
literal = memchr(ptr, '\\', n) == NULL;
1103+
literal = _memchr(ptr, '\\', n) == NULL;
10901104
else
10911105
literal = PyUnicode_FindChar(ptemplate, '\\', 0, n, 1) == -1;
10921106
} else {

graalpython/com.oracle.graal.python.cext/modules/_memoryview.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
/* Memoryview object implementation */
88

9-
#include "Python.h"
9+
#include "../src/capi.h"
1010
#include <limits.h>
1111
/* #include "internal/mem.h" */
1212
/* #include "internal/pystate.h" */
@@ -57,6 +57,8 @@
5757
releasebufferprocs must NOT decrement view.obj.
5858
*/
5959

60+
POLYGLOT_DECLARE_TYPE(PyMemoryViewObject);
61+
6062
extern PyTypeObject PyNativeMemoryView_Type;
6163

6264
#define CHECK_MBUF_RELEASED(mbuf) \
@@ -646,7 +648,7 @@ memory_alloc(int ndim)
646648
mv->weakreflist = NULL;
647649

648650
_PyObject_GC_TRACK(mv);
649-
return mv;
651+
return polyglot_from_PyMemoryViewObject(mv);
650652
}
651653

652654
/*
@@ -966,7 +968,7 @@ memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
966968
return NULL;
967969
}
968970

969-
return PyMemoryView_FromObject(obj);
971+
return polyglot_from_PyMemoryViewObject((PyMemoryViewObject *)PyMemoryView_FromObject(obj));
970972
}
971973

972974

@@ -1413,11 +1415,18 @@ memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
14131415
/* getbuffer */
14141416
/**************************************************************************/
14151417

1418+
static PyMemoryViewObject* PyTruffle_MemoryView_GetDelegate(PyObject* managed_self) {
1419+
return (PyMemoryViewObject*) PyObject_GetAttrString(managed_self, "__c_memoryview");
1420+
}
1421+
14161422
static int
14171423
memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
14181424
{
1419-
Py_buffer *base = &self->view;
1420-
int baseflags = self->flags;
1425+
Py_buffer *base = NULL;
1426+
int baseflags = 0;
1427+
1428+
base = &self->view;
1429+
baseflags = self->flags;
14211430

14221431
CHECK_RELEASED_INT(self);
14231432

@@ -3125,6 +3134,28 @@ PyTypeObject PyNativeMemoryView_Type = {
31253134
memory_new, /* tp_new */
31263135
};
31273136

3137+
3138+
static PyMemoryViewObject* _get_managed_self(PyMemoryViewObject *original_self) {
3139+
PyMemoryViewObject *self = NULL;
3140+
3141+
// this code may be reached over different path; self may therefore be the managed wrapper or the native object
3142+
if (PyMemoryView_Check(original_self)) {
3143+
// we need to get the native delegate of the managed memoryview object
3144+
self = PyTruffle_MemoryView_GetDelegate((PyObject*) original_self);
3145+
}
3146+
assert(self != NULL);
3147+
assert(Py_TYPE(self) == &PyNativeMemoryView_Type);
3148+
return self;
3149+
}
3150+
3151+
static int memory_managed_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) {
3152+
return memory_getbuf(_get_managed_self(self), view, flags);
3153+
}
3154+
3155+
static void memory_managed_releasebuf(PyMemoryViewObject *self, Py_buffer *view) {
3156+
memory_releasebuf(_get_managed_self(self), view);
3157+
}
3158+
31283159
static struct PyModuleDef _memoryviewmodule = {
31293160
PyModuleDef_HEAD_INIT,
31303161
"_memoryview",
@@ -3158,5 +3189,9 @@ PyInit__memoryview(void)
31583189
Py_INCREF((PyObject*)&_PyManagedBuffer_Type);
31593190
PyModule_AddObject(m, "managedbuffer", (PyObject*) &_PyManagedBuffer_Type);
31603191

3192+
3193+
// register buffer procs
3194+
polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_SetBufferProcs", native_to_java((PyObject*)&PyMemoryView_Type), (getbufferproc)memory_managed_getbuf, (releasebufferproc)memory_managed_releasebuf);
3195+
31613196
return m;
31623197
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,7 @@ int bytes_copy2mem(char* target, char* source, size_t nbytes) {
267267
}
268268
return 0;
269269
}
270+
271+
PyObject *_PyBytes_Join(PyObject *sep, PyObject *x) {
272+
return UPCALL_CEXT_O("PyBytes_Join", native_to_java(sep), native_to_java(x));
273+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ int PyType_Ready(PyTypeObject* cls) {
233233
// remember the managed wrapper
234234
((PyObject*)cls)->ob_refcnt = truffle_handle_for_managed(javacls);
235235
if (cls->tp_dict != NULL) {
236-
// TODO: (tfel) is this always safe?
237-
PyDict_Update(javacls->tp_dict, cls->tp_dict);
236+
javacls->tp_dict = native_to_java(cls->tp_dict);
237+
} else {
238+
cls->tp_dict = javacls->tp_dict;
238239
}
239-
cls->tp_dict = javacls->tp_dict;
240240

241241
PyMethodDef* methods = cls->tp_methods;
242242
if (methods) {

graalpython/com.oracle.graal.python.test/src/tests/cpyext/__init__.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,15 @@ def CPyExtType(name, code, **kwargs):
448448
{nb_inplace_floor_divide},
449449
{nb_inplace_true_divide},
450450
{nb_index},
451+
""" + ("""
451452
{nb_matrix_multiply},
452453
{nb_inplace_matrix_multiply},
454+
""" if sys.version_info.minor >= 6 else "") + """
455+
}};
456+
457+
static struct PyMethodDef {name}_methods[] = {{
458+
{tp_methods},
459+
{{NULL, NULL, 0, NULL}}
453460
}};
454461
455462
typedef struct {{
@@ -459,13 +466,13 @@ def CPyExtType(name, code, **kwargs):
459466
static PyTypeObject {name}Type = {{
460467
PyVarObject_HEAD_INIT(NULL, 0)
461468
"{name}.{name}",
462-
sizeof({name}Object), /* tp_basicsize */
463-
0, /* tp_itemsize */
464-
0, /* tp_dealloc */
469+
sizeof({name}Object), /* tp_basicsize */
470+
0, /* tp_itemsize */
471+
0, /* tp_dealloc */
465472
{tp_print},
466473
{tp_getattr},
467474
{tp_setattr},
468-
0, /* tp_reserved */
475+
0, /* tp_reserved */
469476
{tp_repr},
470477
&{name}_number_methods,
471478
{tp_as_sequence},
@@ -478,6 +485,24 @@ def CPyExtType(name, code, **kwargs):
478485
{tp_as_buffer},
479486
Py_TPFLAGS_DEFAULT,
480487
"",
488+
{tp_traverse}, /* tp_traverse */
489+
{tp_clear}, /* tp_clear */
490+
{tp_richcompare}, /* tp_richcompare */
491+
0, /* tp_weaklistoffset */
492+
{tp_iter}, /* tp_iter */
493+
{tp_iternext}, /* tp_iternext */
494+
{name}_methods, /* tp_methods */
495+
NULL, /* tp_members */
496+
0, /* tp_getset */
497+
0, /* tp_base */
498+
{tp_dict}, /* tp_dict */
499+
0, /* tp_descr_get */
500+
0, /* tp_descr_set */
501+
0, /* tp_dictoffset */
502+
{tp_init}, /* tp_init */
503+
PyType_GenericAlloc, /* tp_alloc */
504+
PyType_GenericNew, /* tp_new */
505+
PyObject_Del, /* tp_free */
481506
}};
482507
483508
static PyModuleDef {name}module = {{
@@ -493,10 +518,10 @@ def CPyExtType(name, code, **kwargs):
493518
{{
494519
PyObject* m;
495520
496-
{name}Type.tp_new = PyType_GenericNew;
497521
{ready_code}
498522
if (PyType_Ready(&{name}Type) < 0)
499523
return NULL;
524+
{post_ready_code}
500525
501526
m = PyModule_Create(&{name}module);
502527
if (m == NULL)
@@ -511,6 +536,8 @@ def CPyExtType(name, code, **kwargs):
511536
kwargs["name"] = name
512537
kwargs["code"] = code
513538
kwargs.setdefault("ready_code", "")
539+
kwargs.setdefault("post_ready_code", "")
540+
kwargs.setdefault("tp_methods", "{NULL, NULL, 0, NULL}")
514541
c_source = UnseenFormatter().format(template, **kwargs)
515542

516543
source_file = "%s/%s.c" % (__dir__, name)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ def _reference_set_item(args):
5656
d[args[1]] = args[2]
5757
return 0
5858
except:
59-
raise SystemError
59+
60+
if sys.version_info.minor >= 6:
61+
raise SystemError
62+
else:
63+
return -1
6064

6165

6266
def _reference_del_item(args):
@@ -105,6 +109,8 @@ class SubDict(dict):
105109

106110

107111
ExampleDict = {}
112+
113+
108114
def fresh_dict():
109115
global ExampleDict
110116
ExampleDict = {}
@@ -120,10 +126,16 @@ def compile_module(self, name):
120126
# PyDict_SetItem
121127
test_PyDict_SetItem = CPyExtFunction(
122128
_reference_set_item,
123-
lambda: (({}, "a", "hello"), ({'a': "hello"}, "b", "world")),
129+
lambda: (
130+
({}, "a", "hello")
131+
, ({'a': "hello"}, "b", "world")
132+
# mappingproxy
133+
, (type(type.__dict__)({'a': "hello"}), "b", "world")
134+
),
124135
resultspec="i",
125136
argspec='OOO',
126137
arguments=("PyObject* dict", "PyObject* key", "PyObject* val"),
138+
cmpfunc=unhandled_error_compare
127139
)
128140

129141
# PyDict_GetItem
@@ -316,5 +328,5 @@ def compile_module(self, name):
316328
}
317329
}''',
318330
callfunction="wrap_PyDict_Update",
319-
cmpfunc=lambda cr,pr: (cr == pr or (isinstance(cr, BaseException) and type(cr) == type(pr))) and (ExampleDict.get("a") == 1 or len(ExampleDict) == 0)
331+
cmpfunc=lambda cr, pr: (cr == pr or (isinstance(cr, BaseException) and type(cr) == type(pr))) and (ExampleDict.get("a") == 1 or len(ExampleDict) == 0)
320332
)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ def test_index(self):
100100
nb_index="test_index"
101101
)
102102
tester = TestIndex()
103-
assert [0,1][tester] == 1
103+
assert [0, 1][tester] == 1
104104

105105
def test_getattro(self):
106-
return # TODO: not working yet
106+
return # TODO: not working yet
107107
# XXX: Cludge to get type into C
108108
sys.modules["test_getattro_AttroClass"] = AttroClass
109109
try:
@@ -120,6 +120,31 @@ def test_getattro(self):
120120
tester = TestInt()
121121
assert tester.foo == "foo"
122122

123+
def test_dict(self):
124+
TestDict = CPyExtType("TestDict",
125+
"""static PyObject* custom_dict = NULL;
126+
static PyObject* get_dict(PyObject* self, PyObject* kwargs) {
127+
Py_INCREF(custom_dict);
128+
return custom_dict;
129+
}
130+
""",
131+
ready_code="""
132+
custom_dict = PyDict_New();
133+
PyDict_SetItemString(custom_dict, "hello", PyUnicode_FromString("first custom property"));
134+
TestDictType.tp_dict = custom_dict;
135+
""",
136+
post_ready_code="""
137+
PyDict_SetItemString(TestDictType.tp_dict, "world", PyUnicode_FromString("second custom property"));
138+
""",
139+
tp_methods='{"get_dict", get_dict, METH_NOARGS, ""}'
140+
)
141+
tester = TestDict()
142+
assert tester.hello == "first custom property"
143+
assert tester.world == "second custom property"
144+
assert "hello" in tester.get_dict().keys() and "world" in tester.get_dict().keys(), "was: %s" % tester.get_dict().keys()
145+
tester.get_dict()["extra"] = "blah"
146+
assert tester.extra == "blah"
147+
123148

124149
class TestObjectFunctions(CPyExtTestCase):
125150
def compile_module(self, name):

0 commit comments

Comments
 (0)