Skip to content

Commit 554b876

Browse files
committed
Merge remote-tracking branch 'origin/master' into tim/drop-pypy
2 parents 574577a + 1624dd9 commit 554b876

File tree

75 files changed

+2570
-911
lines changed

Some content is hidden

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

75 files changed

+2570
-911
lines changed

CONTRIBUTING.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
**Thank you for thinking about contributing something to this Python
2+
implementation on Graal!**
3+
4+
## First things first
5+
6+
You will need to sign the [Oracle Contributor
7+
Agreement](http://www.graalvm.org/community/contributors/) for us to be able to
8+
merge your work.
9+
10+
Please also take some time to review our [code of
11+
conduct](http://www.graalvm.org/community/conduct/) for contributors.
12+
13+
## How to contribute?
14+
15+
If you want to make a contribution, it's best to open an issue first about the
16+
area you would like to offer your help with. This implementation is in an early
17+
state and it will make more sense to work on some areas than others, so before
18+
you sink work into a pull request that we won't be able to accept, please talk
19+
to us :)
20+
21+
To get started with development on Python, first make sure you can build at
22+
least the _truffle_ project in the [Graal](https://github.com/oracle/graal)
23+
repository with our build tool [mx](https://github.com/graalvm/mx), as well as
24+
[Sulong](https://github.com/graalvm/sulong).
25+
26+
Once you can build those projects, clone this repository and run
27+
28+
$ mx build
29+
$ mx python -c "print(42)"
30+
31+
If this prints "42", then everything went fine and you just built and ran
32+
Python. Note that you don't need GraalVM for this, but then you'll only run
33+
interpreted, which won't give very good performance (but that might be fine for
34+
development).
35+
36+
When you make your changes, you can test them with `mx python`. Additionally,
37+
there are various "gates" that we use on our CI system to check any code that
38+
goes in. You can run all of these gates using `mx python-gate` or just some by
39+
using `mx python-gate --tags [TAG]`. Two interesting tags to run that cover most
40+
things are:
41+
42+
- python-unittest
43+
- python-graalvm
44+
- python-license

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

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

362+
362363
LOCAL(PyObject*)
363364
state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
364365
Py_ssize_t start, Py_ssize_t end)
@@ -1052,6 +1053,19 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string,
10521053

10531054
}
10541055

1056+
__attribute__((always_inline))
1057+
inline static void *_memchr(const void *s, int c, Py_ssize_t n) {
1058+
unsigned char *p = (unsigned char*)s;
1059+
while(n--) {
1060+
if(*p != (unsigned char)c) {
1061+
p++;
1062+
} else {
1063+
return p;
1064+
}
1065+
}
1066+
return 0;
1067+
}
1068+
10551069
static PyObject*
10561070
pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
10571071
Py_ssize_t count, Py_ssize_t subn)
@@ -1083,7 +1097,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
10831097
b = charsize;
10841098
if (ptr) {
10851099
if (charsize == 1)
1086-
literal = memchr(ptr, '\\', n) == NULL;
1100+
literal = _memchr(ptr, '\\', n) == NULL;
10871101
else
10881102
literal = PyUnicode_FindChar(ptemplate, '\\', 0, n, 1) == -1;
10891103
} 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
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/codeobject.c

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

4343
PyTypeObject PyCode_Type = PY_TRUFFLE_TYPE("code", &PyType_Type, Py_TPFLAGS_DEFAULT, sizeof(PyTypeObject));
4444

45-
PyCodeObject* PyCode_New(int argcount, int kwonlyargcount, int nlocals,
46-
int stacksize, int flags, PyObject *code,
47-
PyObject *consts, PyObject *names, PyObject *varnames,
48-
PyObject *freevars, PyObject *cellvars,
45+
PyCodeObject* PyCode_New(int argcount, int kwonlyargcount,
46+
int nlocals, int stacksize, int flags,
47+
PyObject *code, PyObject *consts, PyObject *names,
48+
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
4949
PyObject *filename, PyObject *name, int firstlineno,
5050
PyObject *lnotab) {
51-
return UPCALL_CEXT_O("PyCode_New", argcount, kwonlyargcount, nlocals,
52-
stacksize, flags, native_to_java(code),
53-
native_to_java(consts), native_to_java(names), native_to_java(varnames),
51+
return UPCALL_CEXT_O("PyCode_New", argcount, kwonlyargcount,
52+
nlocals, stacksize, flags,
53+
native_to_java(code), native_to_java(consts), native_to_java(names),
54+
native_to_java(varnames), native_to_java(freevars), native_to_java(cellvars),
5455
native_to_java(filename), native_to_java(name), firstlineno,
5556
native_to_java(lnotab));
5657
}

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_codeobject.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40-
import sys
4140
import types
42-
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON
41+
42+
import sys
43+
44+
from . import CPyExtTestCase, CPyExtFunction
45+
4346
__dir__ = __file__.rpartition("/")[0]
4447

4548

@@ -63,19 +66,23 @@ def compile_module(self, name):
6366
lambda args: args,
6467
lambda: (
6568
(
66-
1,2,3,4,0,b"",tuple(),tuple(),tuple(),
67-
tuple(),tuple(),"filename","name",1,b"",
69+
1, 2,
70+
3, 4, 0,
71+
b"", tuple(), tuple(),
72+
tuple(), tuple(), tuple(),
73+
"filename", "name", 1,
74+
b"",
6875
),
6976
),
7077
resultspec="O",
7178
argspec="iiiiiOOOOOOOOiO",
7279
arguments=[
73-
"int argcount", "int kwonlyargcount", "int nlocals",
74-
"int stacksize", "int flags", "PyObject* code",
75-
"PyObject* consts", "PyObject* names", "PyObject* varnames",
76-
"PyObject* freevars", "PyObject* cellvars",
80+
"int argcount", "int kwonlyargcount",
81+
"int nlocals", "int stacksize", "int flags",
82+
"PyObject* code", "PyObject* consts", "PyObject* names",
83+
"PyObject* varnames", "PyObject* freevars", "PyObject* cellvars",
7784
"PyObject* filename", "PyObject* name", "int firstlineno",
78-
"PyObject* lnotab"
85+
"PyObject* lnotab",
7986
],
80-
cmpfunc=lambda cr,pr: isinstance(cr, types.CodeType),
87+
cmpfunc=lambda cr, pr: isinstance(cr, types.CodeType),
8188
)

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
)

0 commit comments

Comments
 (0)