Skip to content

Commit dd598bc

Browse files
committed
Merge branch 'master' into bugfix/GR-9687
2 parents b515edc + 192c4d1 commit dd598bc

Some content is hidden

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

47 files changed

+1690
-326
lines changed

graalpython/com.oracle.graal.python.cext/include/bytesobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ functions should be applied to nil objects.
3636
typedef struct {
3737
PyObject_VAR_HEAD
3838
Py_hash_t ob_shash;
39-
char ob_sval[1];
39+
char *ob_sval;
4040

4141
/* Invariants:
4242
* ob_sval contains space for 'ob_size+1' elements.

graalpython/com.oracle.graal.python.cext/include/polyglot.h

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,28 @@ void *__polyglot_from_typed(void *p, void *typeId);
492492
*/
493493
void *__polyglot_from_typed_array(void *arr, uint64_t length, void *typeId);
494494

495+
496+
#define POLYGLOT_DECLARE_GENERIC_TYPE(typedecl, typename) \
497+
static typedecl __polyglot_typeid_##typename[0]; \
498+
\
499+
__attribute__((always_inline)) static inline typedecl *polyglot_as_##typename(void *p) { \
500+
void *ret = __polyglot_as_typed(p, __polyglot_typeid_##typename); \
501+
return (typedecl *)ret; \
502+
} \
503+
\
504+
__attribute__((always_inline)) static inline typedecl *polyglot_as_##typename##_array(void *p) { \
505+
void *ret = __polyglot_as_typed_array(p, __polyglot_typeid_##typename); \
506+
return (typedecl *)ret; \
507+
} \
508+
\
509+
__attribute__((always_inline)) static void *polyglot_from_##typename(typedecl *s) { \
510+
return __polyglot_from_typed(s, __polyglot_typeid_##typename); \
511+
} \
512+
\
513+
__attribute__((always_inline)) static void *polyglot_from_##typename##_array(typedecl *arr, uint64_t len) { \
514+
return __polyglot_from_typed_array(arr, len, __polyglot_typeid_##typename); \
515+
}
516+
495517
/**
496518
* Declare polyglot conversion functions for a user-defined struct type.
497519
*
@@ -514,26 +536,30 @@ void *__polyglot_from_typed_array(void *arr, uint64_t length, void *typeId);
514536
* void *polyglot_from_MyStruct_array(struct MyStruct *arr, uint64_t len);
515537
* \endcode
516538
*/
517-
#define POLYGLOT_DECLARE_STRUCT(type) \
518-
static struct type __polyglot_typeid_##type[0]; \
519-
\
520-
__attribute__((always_inline)) static inline struct type *polyglot_as_##type(void *p) { \
521-
void *ret = __polyglot_as_typed(p, __polyglot_typeid_##type); \
522-
return (struct type *)ret; \
523-
} \
524-
\
525-
__attribute__((always_inline)) static inline struct type *polyglot_as_##type##_array(void *p) { \
526-
void *ret = __polyglot_as_typed_array(p, __polyglot_typeid_##type); \
527-
return (struct type *)ret; \
528-
} \
529-
\
530-
__attribute__((always_inline)) static void *polyglot_from_##type(struct type *s) { \
531-
return __polyglot_from_typed(s, __polyglot_typeid_##type); \
532-
} \
533-
\
534-
__attribute__((always_inline)) static void *polyglot_from_##type##_array(struct type *arr, uint64_t len) { \
535-
return __polyglot_from_typed_array(arr, len, __polyglot_typeid_##type); \
536-
}
539+
#define POLYGLOT_DECLARE_STRUCT(type) POLYGLOT_DECLARE_GENERIC_TYPE(struct type, type)
540+
/**
541+
* Declare polyglot conversion functions for a user-defined anonymous struct type.
542+
*
543+
* Given this type definition:
544+
* \code
545+
* typedef struct {
546+
* int someMember;
547+
* ...
548+
* } MyType;
549+
*
550+
* POLYGLOT_DECLARE_TYPE(MyType)
551+
* \endcode
552+
*
553+
* This macro will generate the following conversion functions:
554+
*
555+
* \code
556+
* MyType *polyglot_as_MyType(void *value);
557+
* MyType *polyglot_as_MyType_array(void *value);
558+
* void *polyglot_from_MyType(MyType *s);
559+
* void *polyglot_from_MyType_array(MyType *arr, uint64_t len);
560+
* \endcode
561+
*/
562+
#define POLYGLOT_DECLARE_TYPE(type) POLYGLOT_DECLARE_GENERIC_TYPE(type, type)
537563

538564
#ifdef DOXYGEN // documentation only
539565
struct MyStruct;

graalpython/com.oracle.graal.python.cext/include/tupleobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ returned item's reference count.
2929
#ifndef Py_LIMITED_API
3030
typedef struct {
3131
PyObject_VAR_HEAD
32-
PyObject *ob_item[1];
32+
PyObject **ob_item;
3333

3434
/* ob_item contains space for 'ob_size' elements.
3535
* Items must normally not be NULL, except during construction when

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,12 @@ PyObject * PyNumber_Float(PyObject *o) {
199199
}
200200
return to_sulong(result);
201201
}
202+
203+
PyObject * PyIter_Next(PyObject *iter) {
204+
void* result = polyglot_invoke(PY_TRUFFLE_CEXT, "PyIter_Next", to_java(iter), ERROR_MARKER);
205+
if (result == ERROR_MARKER && PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) {
206+
PyErr_Clear();
207+
return NULL;
208+
}
209+
return to_sulong(result);
210+
}

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

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,6 @@
3838
*/
3939
#include "capi.h"
4040

41-
void marry_objects(PyObject* obj, void* jobj) {
42-
obj->ob_refcnt = truffle_handle_for_managed(jobj);
43-
truffle_invoke(PY_TRUFFLE_CEXT, "marry_objects", jobj, obj);
44-
void *type = (PyTypeObject *)truffle_invoke(PY_BUILTIN, "type", jobj);
45-
obj->ob_type = PyObjectHandle_ForJavaType(type);
46-
}
47-
4841
static void initialize_type_structure(PyTypeObject* structure, const char* typname) {
4942
PyTypeObject* ptype = (PyTypeObject *)to_sulong(truffle_invoke(PY_TRUFFLE_CEXT, "PyTruffle_Type", truffle_read_string(typname)));
5043
unsigned long original_flags = structure->tp_flags;
@@ -54,14 +47,19 @@ static void initialize_type_structure(PyTypeObject* structure, const char* typna
5447
}
5548

5649
static void initialize_globals() {
57-
void *jnone = polyglot_as__object(polyglot_invoke(PY_TRUFFLE_CEXT, "Py_None"));
50+
// None
51+
void *jnone = polyglot_as__object(to_sulong(polyglot_invoke(PY_TRUFFLE_CEXT, "Py_None")));
5852
truffle_assign_managed(&_Py_NoneStruct, jnone);
53+
54+
// NotImplemented
5955
void *jnotimpl = polyglot_as__object(polyglot_get_member(PY_BUILTIN, "NotImplemented"));
6056
truffle_assign_managed(&_Py_NotImplementedStruct, jnotimpl);
57+
58+
// True, False
6159
void *jtrue = polyglot_invoke(PY_TRUFFLE_CEXT, "Py_True");
62-
truffle_assign_managed(&_Py_TrueStruct, to_sulong(jtrue));
60+
truffle_assign_managed(&_Py_TrueStruct, polyglot_as__longobject(to_sulong(jtrue)));
6361
void *jfalse = polyglot_invoke(PY_TRUFFLE_CEXT, "Py_False");
64-
truffle_assign_managed(&_Py_FalseStruct, to_sulong(jfalse));
62+
truffle_assign_managed(&_Py_FalseStruct, polyglot_as__longobject(to_sulong(jfalse)));
6563
}
6664

6765
__attribute__((constructor))
@@ -70,6 +68,8 @@ static void initialize_capi() {
7068
initialize_type_structure(&PyType_Type, "type");
7169
initialize_type_structure(&PyBaseObject_Type, "object");
7270
initialize_type_structure(&PySuper_Type, "super");
71+
initialize_type_structure(&_PyNone_Type, "NoneType");
72+
initialize_type_structure(&PyModule_Type, "module");
7373
initialize_type_structure(&PyUnicode_Type, "str");
7474
initialize_type_structure(&PyBool_Type, "bool");
7575
initialize_type_structure(&PyFloat_Type, "float");
@@ -83,6 +83,7 @@ static void initialize_capi() {
8383
initialize_type_structure(&PySlice_Type, "slice");
8484
initialize_type_structure(&PyByteArray_Type, "bytearray");
8585
initialize_type_structure(&_PyNotImplemented_Type, "NotImplementedType");
86+
initialize_type_structure(&PyCapsule_Type, "PyCapsule");
8687

8788
// initialize global variables like '_Py_NoneStruct', etc.
8889
initialize_globals();
@@ -91,37 +92,60 @@ static void initialize_capi() {
9192
initialize_hashes();
9293
}
9394

94-
void* to_java(PyObject* obj) {
95-
if (obj == Py_None) {
95+
void* native_to_java(PyObject* obj) {
96+
if (obj == Py_None) {
9697
return Py_None;
9798
} else if (obj == NULL) {
9899
return Py_NoValue;
99100
} else if (truffle_is_handle_to_managed(obj)) {
100-
void *managed = truffle_managed_from_handle(obj);
101-
if (truffle_invoke(PY_TRUFFLE_CEXT, "is_python_object", managed)) {
102-
return managed;
103-
}
104-
return truffle_invoke(PY_TRUFFLE_CEXT, "to_java", managed);
101+
return truffle_managed_from_handle(obj);
105102
} else if (truffle_is_handle_to_managed(obj->ob_refcnt)) {
106103
return truffle_managed_from_handle(obj->ob_refcnt);
107104
}
105+
return obj;
106+
}
107+
108+
void* to_java(PyObject* obj) {
109+
PyObject* managed_obj = native_to_java(obj);
110+
108111
// Since Python object respond to 'IS_POINTER' with true if there has already
109112
// been a 'TO_NATIVE' before, we need to first check if it is directly a Python
110113
// object to avoid conversion to a pointer.
111-
if (truffle_invoke(PY_TRUFFLE_CEXT, "is_python_object", obj)) {
112-
return obj;
114+
if (truffle_invoke(PY_TRUFFLE_CEXT, "is_python_object", managed_obj)) {
115+
return managed_obj;
113116
}
114-
return truffle_invoke(PY_TRUFFLE_CEXT, "to_java", obj);
117+
return truffle_invoke(PY_TRUFFLE_CEXT, "to_java", managed_obj);
115118
}
116119

117120
void* to_java_type(PyTypeObject* cls) {
118121
return to_java((PyObject*)cls);
119122
}
120123

124+
125+
#define PyTruffle_FastSubclass(__flags, __reference_flags) ((__flags) & (__reference_flags))
126+
127+
__attribute__((always_inline))
128+
static inline PyObject* PyTruffle_Explicit_Cast(PyObject* cobj, unsigned long flags) {
129+
if (PyTruffle_FastSubclass(flags, Py_TPFLAGS_TUPLE_SUBCLASS)) {
130+
return (PyObject*)polyglot_as_PyTupleObject(cobj);
131+
} else if (PyTruffle_FastSubclass(flags, Py_TPFLAGS_LIST_SUBCLASS)) {
132+
return (PyObject*)polyglot_as_PyListObject(cobj);
133+
} else if (PyTruffle_FastSubclass(flags, Py_TPFLAGS_DICT_SUBCLASS)) {
134+
return (PyObject*)polyglot_as_PyDictObject(cobj);
135+
} else if (PyTruffle_FastSubclass(flags, Py_TPFLAGS_UNICODE_SUBCLASS)) {
136+
return (PyObject*)polyglot_as_PyUnicodeObject(cobj);
137+
} else if (PyTruffle_FastSubclass(flags, Py_TPFLAGS_BYTES_SUBCLASS)) {
138+
return (PyObject*)polyglot_as_PyBytesObject(cobj);
139+
}
140+
return (PyObject*)polyglot_as_PyVarObject(cobj);
141+
}
142+
143+
121144
PyObject* to_sulong(void *o) {
122145
PyObject* cobj = truffle_invoke(PY_TRUFFLE_CEXT, "to_sulong", o);
123146
if(polyglot_is_value(cobj)) {
124-
return polyglot_as__object(cobj);
147+
unsigned long flags = polyglot_as_i64(polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_GetTpFlags", cobj));
148+
return PyTruffle_Explicit_Cast(cobj, flags);
125149
}
126150
return cobj;
127151
}
@@ -134,16 +158,19 @@ typedef struct PyObjectHandle {
134158
PyObject_HEAD
135159
} PyObjectHandle;
136160

137-
PyObject* PyNoneHandle(void* jobj) {
138-
return &_Py_NoneStruct;
161+
uint64_t PyTruffle_Wchar_Size() {
162+
return SIZEOF_WCHAR_T;
139163
}
140164

141-
PyObject* PyObjectHandle_ForJavaObject(PyObject* jobject) {
142-
PyObject* obj = (PyObject*)PyObject_Malloc(sizeof(PyObjectHandle));
143-
obj->ob_refcnt = truffle_handle_for_managed(jobject);
144-
void *jtype = (PyTypeObject *)truffle_invoke(PY_BUILTIN, "type", jobject);
145-
obj->ob_type = polyglot_as__typeobject(to_sulong(jtype));
146-
return obj;
165+
PyObject* PyObjectHandle_ForJavaObject(PyObject* jobj, unsigned long flags) {
166+
if (!truffle_is_handle_to_managed(jobj)) {
167+
PyObject* cobj = truffle_invoke(PY_TRUFFLE_CEXT, "to_sulong", jobj);
168+
if(polyglot_is_value(cobj)) {
169+
cobj = PyTruffle_Explicit_Cast(cobj, flags);
170+
}
171+
return truffle_deref_handle_for_managed(cobj);
172+
}
173+
return jobj;
147174
}
148175

149176
/** to be used from Java code only; only creates the deref handle */
@@ -160,12 +187,6 @@ const char* PyTruffle_StringToCstr(void* jlString) {
160187
return truffle_string_to_cstr(jlString);
161188
}
162189

163-
/** like 'truffle_read_string' but uses UTF-8 encoding (also returns a String object) */
164-
void* PyTruffle_Unicode_FromUTF8(const char* o, void *error_marker) {
165-
void* jobj = truffle_read_bytes(o);
166-
return truffle_invoke(PY_TRUFFLE_CEXT, "PyTruffle_Unicode_FromUTF8", jobj, error_marker);
167-
}
168-
169190
#define ReadMember(object, offset, T) ((T*)(((char*)object) + offset))[0]
170191

171192
short ReadShortMember(PyObject* object, int offset) {

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,38 @@
4141

4242
#include "Python.h"
4343

44+
/* Private types are defined here because we need to declare the type cast. */
45+
typedef struct {
46+
PyObject_HEAD
47+
PyObject *md_dict;
48+
struct PyModuleDef *md_def;
49+
void *md_state;
50+
PyObject *md_weaklist;
51+
PyObject *md_name; /* for logging purposes after md_dict is cleared */
52+
} PyModuleObject;
53+
54+
// taken from CPython "Objects/capsule.c"
55+
typedef struct {
56+
PyObject_HEAD
57+
void *pointer;
58+
const char *name;
59+
void *context;
60+
PyCapsule_Destructor destructor;
61+
} PyCapsule;
62+
63+
/* Declare Python structs/types for explicit polyglot typecasts. */
64+
/* NOTE: Also add an appropriate case in 'PyTruffle_Explicit_Cast' ! */
4465
POLYGLOT_DECLARE_STRUCT(_object);
66+
POLYGLOT_DECLARE_TYPE(PyModuleObject);
67+
POLYGLOT_DECLARE_TYPE(PyVarObject);
4568
POLYGLOT_DECLARE_STRUCT(_typeobject);
69+
POLYGLOT_DECLARE_TYPE(PyTupleObject);
70+
POLYGLOT_DECLARE_TYPE(PyListObject);
71+
POLYGLOT_DECLARE_TYPE(PyDictObject);
72+
POLYGLOT_DECLARE_TYPE(PyUnicodeObject);
73+
POLYGLOT_DECLARE_TYPE(PyBytesObject);
74+
POLYGLOT_DECLARE_STRUCT(_longobject);
75+
POLYGLOT_DECLARE_TYPE(PyCapsule);
4676

4777

4878
extern void* to_java(PyObject* obj);
@@ -134,7 +164,6 @@ void initialize_hashes();
134164

135165
int PyTruffle_Debug(void *arg);
136166
PyTypeObject* PyObjectHandle_ForJavaType(void* jobj);
137-
void marry_objects(PyObject* obj, void* jobj);
138167

139168
extern short ReadShortMember(PyObject* object, int offset);
140169
extern int ReadIntMember(PyObject* object, int offset);
@@ -181,7 +210,6 @@ extern PyObject marker_struct;
181210

182211
/* UNICODE */
183212

184-
void* PyTruffle_Unicode_FromUTF8(const char* o, void *error_marker);
185213
void* PyTruffle_Unicode_FromString(const char* o);
186214

187215
/* DICT */

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,26 @@
3838
*/
3939
#include "capi.h"
4040

41+
PyTypeObject PyCapsule_Type = PY_TRUFFLE_TYPE("PyCapsule", &PyType_Type, 0);
42+
4143
PyObject* PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor) {
42-
// TODO: fail for now
43-
return NULL;
44+
return (PyObject *)polyglot_as_PyCapsule(to_sulong(polyglot_invoke(PY_TRUFFLE_CEXT, "PyCapsule", polyglot_from_string(name, "ascii"), pointer, destructor)));
45+
}
46+
47+
void * PyCapsule_GetContext(PyObject *o) {
48+
void *result = polyglot_invoke(PY_TRUFFLE_CEXT, "PyCapsule_GetContext", to_java(o), ERROR_MARKER);
49+
if (result == ERROR_MARKER) {
50+
return NULL;
51+
}
52+
return (void *)as_long(result);
4453
}
54+
55+
void * PyCapsule_GetPointer(PyObject *o, const char *name) {
56+
void *result = polyglot_invoke(PY_TRUFFLE_CEXT, "PyCapsule_GetPointer", to_java(o), polyglot_from_string(name, "ascii"), ERROR_MARKER);
57+
if (result == ERROR_MARKER) {
58+
return NULL;
59+
}
60+
return (void *)as_long(result);
61+
}
62+
63+

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ int PyErr_ExceptionMatches(PyObject *exc) {
149149
}
150150

151151
PyObject* PyTruffle_Err_Format(PyObject* exception, const char* fmt, int s, void* v0, void* v1, void* v2, void* v3, void* v4, void* v5, void* v6, void* v7, void* v8, void* v9) {
152-
char** allocated_strings = calloc(sizeof(char*), s);
153152
PyObject *formatted_msg = PyTruffle_Unicode_FromFormat(fmt, s, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
154153
truffle_invoke(PY_TRUFFLE_CEXT, "PyErr_CreateAndSetException", to_java(exception), to_java(formatted_msg));
155154
return NULL;

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,5 @@
4141
#include <fcntl.h>
4242

4343
#ifdef O_CLOEXEC
44-
/* Does open() support the O_CLOEXEC flag? Possible values:
45-
46-
-1: unknown
47-
0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23
48-
1: open() supports O_CLOEXEC flag, close-on-exec is set
49-
50-
The flag is used by _Py_open(), io.FileIO and os.open() */
5144
int _Py_open_cloexec_works = -1;
5245
#endif

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ PyObject* _Py_BuildValue_SizeT(const char *format, ...) {
262262
if (arg == NULL) {
263263
truffle_invoke(PY_TRUFFLE_CEXT, "PyTuple_SetItem", jtuple, valuen - 1, Py_None);
264264
} else {
265-
truffle_invoke(PY_TRUFFLE_CEXT, "PyTuple_SetItem", jtuple, valuen - 1, PyTruffle_Unicode_FromUTF8((char*)arg, Py_None));
265+
truffle_invoke(PY_TRUFFLE_CEXT, "PyTuple_SetItem", jtuple, valuen - 1, polyglot_from_string((char*)arg, "utf-8"));
266266
}
267267
break;
268268
case 'd':

0 commit comments

Comments
 (0)