Skip to content

Commit 51a8273

Browse files
committed
[GR-31076] Get pypy-raycaster demo to work
PullRequest: graalpython/1770
2 parents 85e0648 + abe3ae7 commit 51a8273

File tree

14 files changed

+314
-21
lines changed

14 files changed

+314
-21
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ Py_ssize_t get_tp_dictoffset(PyTypeObject* obj) {
334334
return obj->tp_dictoffset;
335335
}
336336

337+
/** to be used from Java code only; reads native 'tp_weaklistoffset' field */
338+
Py_ssize_t get_tp_weaklistoffset(PyTypeObject* obj) {
339+
return obj->tp_weaklistoffset;
340+
}
341+
337342
/** to be used from Java code only; reads native 'tp_itemsize' field */
338343
Py_ssize_t get_tp_itemsize(PyTypeObject* obj) {
339344
return obj->tp_itemsize;
@@ -482,7 +487,7 @@ const char* PyTruffle_StringToCstr(void* o, int32_t strLen) {
482487

483488
written = polyglot_as_string(o, buffer, bufsize, SRC_CS) + 1;
484489

485-
str = (const char*) malloc(written * sizeof(char));
490+
str = (const char*) PyMem_RawMalloc(written * sizeof(char));
486491
memcpy(str, buffer, written * sizeof(char));
487492
free(buffer);
488493

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,8 @@ UPCALL_ID(PyDict_Merge);
207207
int PyDict_Merge(PyObject *a, PyObject *b, int override) {
208208
return UPCALL_CEXT_I(_jls_PyDict_Merge, native_to_java(a), native_to_java(b), override);
209209
}
210+
211+
UPCALL_ID(PyDict_Values);
212+
PyObject * PyDict_Values(PyObject *dict) {
213+
return UPCALL_CEXT_O(_jls_PyDict_Values, native_to_java(dict));
214+
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,26 @@ int get_buffer_rw(PyObject *arg, Py_buffer *view) {
7979
return 0;
8080
}
8181

82+
Py_ssize_t convertbuffer(PyObject *arg, const void **p) {
83+
PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;
84+
Py_ssize_t count;
85+
Py_buffer view;
86+
87+
*p = NULL;
88+
if (pb != NULL && pb->bf_releasebuffer != NULL) {
89+
// *errmsg = "read-only bytes-like object";
90+
return -3;
91+
}
92+
93+
int get_buffer_result = get_buffer_r(arg, &view);
94+
if (get_buffer_result < 0) {
95+
return get_buffer_result;
96+
}
97+
count = view.len;
98+
*p = view.buf;
99+
PyBuffer_Release(&view);
100+
return count;
101+
}
82102

83103
typedef int (*parseargs_func)(PyObject *argv, PyObject *kwds, const char *format, void* kwdnames, void* varargs);
84104

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,10 @@ int PyOS_InterruptOccurred(void) {
5656
PyErr_SetString(PyExc_SystemError, "'PyOS_InterruptOccurred' not implemented");
5757
return -1;
5858
}
59+
60+
typedef void (*py_atexit_fun_t)(void (*func)(void));
61+
UPCALL_TYPED_ID(Py_AtExit, py_atexit_fun_t);
62+
int Py_AtExit(void (*func)(void)) {
63+
_jls_Py_AtExit(func);
64+
return 0;
65+
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,21 @@ PyTypeObject _PyWeakref_CallableProxyType = PY_TRUFFLE_TYPE("weakcallableproxy",
4747
void PyObject_ClearWeakRefs(PyObject *object) {
4848
// TODO: implement
4949
}
50+
51+
void *PY_WEAKREF_MODULE;
52+
__attribute__((constructor (__COUNTER__)))
53+
static void initialize_upcall_functions() {
54+
PY_WEAKREF_MODULE = (void*)polyglot_eval("python", "import _weakref\n_weakref");
55+
}
56+
57+
PyObject *PyWeakref_NewRef(PyObject *object, PyObject *callback) {
58+
if (callback == NULL) {
59+
return UPCALL_O(PY_WEAKREF_MODULE, polyglot_from_string("ReferenceType", SRC_CS), native_to_java(object));
60+
} else {
61+
return UPCALL_O(PY_WEAKREF_MODULE, polyglot_from_string("ReferenceType", SRC_CS), native_to_java(object), native_to_java(callback));
62+
}
63+
}
64+
65+
PyObject *PyWeakref_GetObject(PyObject *ref) {
66+
return UPCALL_O(native_to_java(ref), polyglot_from_string("__call__", SRC_CS));
67+
}

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

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def compile_module(self, name):
163163
*objOut = PySequence_Size(obj) == 0 ? Py_False : Py_True;
164164
return 1;
165165
}
166-
166+
167167
static PyObject* wrap_PyArg_ParseTuple(PyObject* argTuple) {
168168
PyObject* out = NULL;
169169
Py_INCREF(argTuple);
@@ -394,6 +394,131 @@ def compile_module(self, name):
394394
cmpfunc=unhandled_error_compare
395395
)
396396

397+
test_parseargs_y_lower = CPyExtFunction(
398+
lambda args: args[0][0].decode(),
399+
lambda: (
400+
((b'', ), ),
401+
((b'helloworld', ), ),
402+
),
403+
code='''
404+
static const char * wrap_PyArg_ParseTuple(PyObject* argTuple) {
405+
const char *out = NULL;
406+
Py_INCREF(argTuple);
407+
if (PyArg_ParseTuple(argTuple, "y", &out) == 0) {
408+
return NULL;
409+
}
410+
Py_DECREF(argTuple);
411+
return out;
412+
}
413+
''',
414+
resultspec="s",
415+
argspec="O",
416+
arguments=["PyObject* argTuple"],
417+
callfunction="wrap_PyArg_ParseTuple",
418+
cmpfunc=unhandled_error_compare
419+
)
420+
421+
test_parseargs_y_hash = CPyExtFunction(
422+
lambda args: (args[0][0].decode(), len(args[0][0])),
423+
lambda: (
424+
((b'', ), ),
425+
((b'helloworld', ), ),
426+
),
427+
code='''
428+
static PyObject * wrap_PyArg_ParseTuple(PyObject* argTuple) {
429+
const char *out = NULL;
430+
Py_ssize_t cnt = 0;
431+
Py_INCREF(argTuple);
432+
if (PyArg_ParseTuple(argTuple, "y#", &out, &cnt) == 0) {
433+
return NULL;
434+
}
435+
Py_DECREF(argTuple);
436+
return Py_BuildValue("si", out, cnt);
437+
}
438+
''',
439+
resultspec="O",
440+
argspec="O",
441+
arguments=["PyObject* argTuple"],
442+
callfunction="wrap_PyArg_ParseTuple",
443+
cmpfunc=unhandled_error_compare
444+
)
445+
446+
test_parseargs_y_star = CPyExtFunction(
447+
lambda args: (args[0][0].decode(), len(args[0][0])),
448+
lambda: (
449+
((b'', ), ),
450+
((b'helloworld', ), ),
451+
),
452+
code='''
453+
static PyObject * wrap_PyArg_ParseTuple(PyObject* argTuple) {
454+
Py_buffer view;
455+
Py_INCREF(argTuple);
456+
if (PyArg_ParseTuple(argTuple, "y*", &view) == 0) {
457+
return NULL;
458+
}
459+
Py_DECREF(argTuple);
460+
PyObject *result = Py_BuildValue("si", (char*)view.buf, view.len);
461+
PyBuffer_Release(&view);
462+
return result;
463+
}
464+
''',
465+
resultspec="O",
466+
argspec="O",
467+
arguments=["PyObject* argTuple"],
468+
callfunction="wrap_PyArg_ParseTuple",
469+
cmpfunc=unhandled_error_compare
470+
)
471+
472+
test_parseargs_es = CPyExtFunction(
473+
lambda args: args[0][0].decode() if isinstance(args[0][0], bytes) else args[0][0],
474+
lambda: (
475+
(('helloworld', ), ),
476+
),
477+
code='''
478+
static PyObject * wrap_PyArg_ParseTuple(PyObject* argTuple) {
479+
const char * out;
480+
Py_INCREF(argTuple);
481+
if (PyArg_ParseTuple(argTuple, "es", "UTF-8", &out) == 0) {
482+
return NULL;
483+
}
484+
Py_DECREF(argTuple);
485+
PyObject *result = PyUnicode_FromString(out);
486+
PyMem_Free(out);
487+
return result;
488+
}
489+
''',
490+
resultspec="O",
491+
argspec="O",
492+
arguments=["PyObject* argTuple"],
493+
callfunction="wrap_PyArg_ParseTuple",
494+
cmpfunc=unhandled_error_compare
495+
)
496+
497+
test_parseargs_et = CPyExtFunction(
498+
lambda args: args[0][0].decode() if isinstance(args[0][0], bytes) else args[0][0],
499+
lambda: (
500+
(('helloworld', ), ),
501+
),
502+
code='''
503+
static PyObject * wrap_PyArg_ParseTuple(PyObject* argTuple) {
504+
const char * out;
505+
Py_INCREF(argTuple);
506+
if (PyArg_ParseTuple(argTuple, "es", "UTF-8", &out) == 0) {
507+
return NULL;
508+
}
509+
Py_DECREF(argTuple);
510+
PyObject *result = PyUnicode_FromString(out);
511+
PyMem_Free(out);
512+
return result;
513+
}
514+
''',
515+
resultspec="O",
516+
argspec="O",
517+
arguments=["PyObject* argTuple"],
518+
callfunction="wrap_PyArg_ParseTuple",
519+
cmpfunc=unhandled_error_compare
520+
)
521+
397522
test_parseargs_valist = CPyExtFunction(
398523
lambda args: args[0],
399524
lambda: (

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PythonCextBuiltins.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
import com.oracle.graal.python.util.BufferFormat;
253253
import com.oracle.graal.python.util.OverflowException;
254254
import com.oracle.graal.python.util.PythonUtils;
255+
import com.oracle.graal.python.util.ShutdownHook;
255256
import com.oracle.truffle.api.CompilerDirectives;
256257
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
257258
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -4176,4 +4177,25 @@ int doGeneric(Object ptrObject) {
41764177
return 0;
41774178
}
41784179
}
4180+
4181+
// directly called without landing function
4182+
@Builtin(name = "Py_AtExit", minNumOfPositionalArgs = 1)
4183+
@GenerateNodeFactory
4184+
abstract static class PyAtExit extends PythonUnaryBuiltinNode {
4185+
4186+
@Specialization
4187+
@TruffleBoundary
4188+
int doGeneric(Object funcPtr) {
4189+
getContext().registerAtexitHook(new ShutdownHook() {
4190+
public void call(@SuppressWarnings("unused") PythonContext context) {
4191+
try {
4192+
InteropLibrary.getUncached().execute(funcPtr);
4193+
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
4194+
// ignored
4195+
}
4196+
}
4197+
});
4198+
return 0;
4199+
}
4200+
}
41794201
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ public long getId() {
767767

768768
/**
769769
* Enum of basic C types. These type names need to stay in sync with the declarations in
770-
* 'capi.c'.
770+
* 'modsupport.c'.
771771
*/
772772
public enum LLVMType {
773773
int_t,

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
import com.oracle.graal.python.builtins.modules.PythonCextBuiltins;
6262
import com.oracle.graal.python.builtins.objects.PNone;
6363
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
64+
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
65+
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
6466
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
6567
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
6668
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
@@ -1475,10 +1477,26 @@ Object doString(String str,
14751477
return callStringToCstrNode.call(FUN_PY_TRUFFLE_STRING_TO_CSTR, str, str.length());
14761478
}
14771479

1480+
@Specialization
1481+
Object doBytes(PBytes bytes,
1482+
@CachedContext(PythonLanguage.class) PythonContext context,
1483+
@Shared("toBytes") @Cached SequenceStorageNodes.ToByteArrayNode toBytesNode,
1484+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
1485+
return doByteArray(toBytesNode.execute(bytes.getSequenceStorage()), context, callByteArrayToNativeNode);
1486+
}
1487+
1488+
@Specialization
1489+
Object doBytes(PByteArray bytes,
1490+
@CachedContext(PythonLanguage.class) PythonContext context,
1491+
@Shared("toBytes") @Cached SequenceStorageNodes.ToByteArrayNode toBytesNode,
1492+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
1493+
return doByteArray(toBytesNode.execute(bytes.getSequenceStorage()), context, callByteArrayToNativeNode);
1494+
}
1495+
14781496
@Specialization
14791497
Object doByteArray(byte[] arr,
14801498
@CachedContext(PythonLanguage.class) PythonContext context,
1481-
@Exclusive @Cached PCallCapiFunction callByteArrayToNativeNode) {
1499+
@Shared("callByteArrayToNativeNode") @Cached PCallCapiFunction callByteArrayToNativeNode) {
14821500
return callByteArrayToNativeNode.call(FUN_PY_TRUFFLE_BYTE_ARRAY_TO_NATIVE, context.getEnv().asGuestValue(arr), arr.length);
14831501
}
14841502

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public enum NativeCAPISymbol implements NativeCExtSymbol {
117117
FUN_GET_TP_FLAGS("get_tp_flags"),
118118
FUN_GET_TP_SUBCLASSES("get_tp_subclasses"),
119119
FUN_GET_TP_DICTOFFSET("get_tp_dictoffset"),
120+
FUN_GET_TP_WEAKLISTOFFSET("get_tp_weaklistoffset"),
120121
FUN_GET_TP_BASICSIZE("get_tp_basicsize"),
121122
FUN_GET_TP_ITEMSIZE("get_tp_itemsize"),
122123
FUN_GET_TP_AS_BUFFER("get_tp_as_buffer"),
@@ -146,6 +147,7 @@ public enum NativeCAPISymbol implements NativeCExtSymbol {
146147
FUN_GET_NEWFUNC_TYPE_ID("get_newfunc_typeid"),
147148
FUN_GET_BUFFER_R("get_buffer_r"),
148149
FUN_GET_BUFFER_RW("get_buffer_rw"),
150+
FUN_CONVERTBUFFER("convertbuffer"),
149151
FUN_NATIVE_UNICODE_AS_STRING("native_unicode_as_string"),
150152
FUN_PY_UNICODE_GET_LENGTH("PyUnicode_GetLength"),
151153
FUN_GET_UINT32_ARRAY_TYPE_ID("get_uint32_array_typeid"),

0 commit comments

Comments
 (0)