Skip to content

Commit fa5c2f9

Browse files
committed
[GR-40247] Reduce C API boundary overhead
PullRequest: graalpython/2694
2 parents 353f7d9 + 354b57b commit fa5c2f9

File tree

98 files changed

+4387
-4935
lines changed

Some content is hidden

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

98 files changed

+4387
-4935
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2020, 2022, Oracle and/or its affiliates.
1+
/* Copyright (c) 2020, 2023, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2020 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -29,7 +29,7 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *);
2929
#define PyTuple_GET_ITEM(op, i) PyTuple_GetItem(_PyObject_CAST(op), (i))
3030

3131
/* Macro, *only* to be used to fill in brand new tuples */
32-
// LS: Py_SetItem behaves differently wrt. the existing element...
33-
#define PyTuple_SET_ITEM(op, i, v) PyTuple_SetItem(_PyObject_CAST(op), (i), (v))
32+
PyAPI_FUNC(int) _PyTuple_SET_ITEM(PyObject *, Py_ssize_t, PyObject *);
33+
#define PyTuple_SET_ITEM(op, i, v) _PyTuple_SET_ITEM(_PyObject_CAST(op), (i), (v))
3434

3535
PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);

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

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ CAPI_BUILTINS
166166

167167
PyAPI_FUNC(void) initialize_builtins(void* (*getBuiltin)(int id)) {
168168
int id = 0;
169+
//#define BUILTIN(NAME, RET, ...) printf("initializing " #NAME "\n"); Graal##NAME = (RET(*)(__VA_ARGS__)) getBuiltin(id++);
169170
#define BUILTIN(NAME, RET, ...) Graal##NAME = (RET(*)(__VA_ARGS__)) getBuiltin(id++);
170171
CAPI_BUILTINS
171172
#undef BUILTIN
@@ -455,6 +456,18 @@ char* get_ob_sval(PyObject* op) {
455456
return ((PyBytesObject *)(op))->ob_sval;
456457
}
457458

459+
// not quite as in CPython, this assumes that x is already a double. The rest of
460+
// the implementation is in the Float constructor in Java
461+
PyObject* float_subtype_new(PyTypeObject *type, double x) {
462+
PyObject* newobj = type->tp_alloc(type, 0);
463+
if (newobj == NULL) {
464+
Py_DECREF(newobj);
465+
return NULL;
466+
}
467+
((PyFloatObject *)newobj)->ob_fval = x;
468+
return newobj;
469+
}
470+
458471
/**
459472
* To be used from Java code only. Reads native 'PyModuleDef.m_methods' field and
460473
* returns a typed pointer that can be used as interop array.
@@ -573,26 +586,11 @@ PyAPI_FUNC(Py_ssize_t) PyTruffle_SUBREF(intptr_t ptr, Py_ssize_t value) {
573586
}
574587

575588
/** to be used from Java code only; calls DECREF */
576-
PyAPI_FUNC(Py_ssize_t) PyTruffle_bulk_SUBREF(PyObject *ptrArray[], Py_ssize_t values[], int64_t len) {
577-
int64_t i;
578-
PyObject *obj;
579-
Py_ssize_t value;
580-
581-
for (i = 0; i < len; i++) {
582-
obj = ptrArray[i];
583-
value = values[i];
584-
/* IMPORTANT: 'value == 0' indicates we should not process the reference at all */
585-
if (value > 0) {
586-
Py_ssize_t new_value = ((obj->ob_refcnt) -= value);
587-
if (new_value == 0) {
588-
_Py_Dealloc(obj);
589-
}
590-
#ifdef Py_REF_DEBUG
591-
else if (new_value < 0) {
592-
_Py_NegativeRefcount(filename, lineno, op);
593-
}
594-
#endif
595-
}
589+
PyAPI_FUNC(Py_ssize_t) PyTruffle_bulk_DEALLOC(intptr_t ptrArray[], int64_t len) {
590+
591+
for (int i = 0; i < len; i++) {
592+
PyObject *obj = (PyObject*) ptrArray[i];
593+
_Py_Dealloc(obj);
596594
}
597595
return 0;
598596
}
@@ -606,11 +604,6 @@ PyAPI_FUNC(void) PyTruffle_Free(intptr_t val) {
606604
PyMem_RawFree((void*) val);
607605
}
608606

609-
/** to be used from Java code only; creates the deref handle for a sequence wrapper */
610-
PyAPI_FUNC(void*) NativeHandle_ForArray(void* jobj, Py_ssize_t element_size) {
611-
return create_deref_handle(jobj);
612-
}
613-
614607
PyAPI_FUNC(const char*) PyTruffle_StringToCstr(void* o, int32_t strLen) {
615608
const char *buffer;
616609
const char *str;
@@ -911,6 +904,10 @@ void PyTruffle_SetStorageItem(PyObject** ptr, int32_t index, PyObject* newitem)
911904
Py_XSETREF(ptr[index], newitem);
912905
}
913906

907+
void PyTruffle_InitializeStorageItem(PyObject** ptr, int32_t index, PyObject* newitem) {
908+
ptr[index] = newitem;
909+
}
910+
914911
PyAPI_FUNC(Py_ssize_t) PyTruffle_Object_Size(PyObject *op) {
915912
return ((PyVarObject*)op)->ob_size;
916913
}
@@ -1240,6 +1237,16 @@ void* truffle_get_constant(int entry) {
12401237
return NULL;
12411238
}
12421239

1240+
/*
1241+
* These locations need to be shared between native and Sulong - if the native parts are initialized,
1242+
* we assign_managed them to share them.
1243+
*/
1244+
PyAPI_FUNC(void) initialize_native_locations(void* allocateMemory, void* maxNativeMemory, void* nativeMemoryGCBarrier) {
1245+
truffle_assign_managed(&PyTruffle_AllocatedMemory, allocateMemory);
1246+
truffle_assign_managed(&PyTruffle_MaxNativeMemory, maxNativeMemory);
1247+
truffle_assign_managed(&PyTruffle_NativeMemoryGCBarrier, nativeMemoryGCBarrier);
1248+
}
1249+
12431250
// defined in 'exceptions.c'
12441251
void initialize_exceptions();
12451252
// defined in 'pyhash.c'
@@ -1511,10 +1518,6 @@ PyAPI_FUNC(int) PyException_SetTraceback(PyObject* a, PyObject* b) {
15111518
PyAPI_FUNC(int) PyFile_WriteObject(PyObject* a, PyObject* b, int c) {
15121519
return GraalPyFile_WriteObject(a, b, c);
15131520
}
1514-
#undef PyFloat_AsDouble
1515-
PyAPI_FUNC(double) PyFloat_AsDouble(PyObject* a) {
1516-
return GraalPyFloat_AsDouble(a);
1517-
}
15181521
#undef PyFloat_FromDouble
15191522
PyAPI_FUNC(PyObject*) PyFloat_FromDouble(double a) {
15201523
return GraalPyFloat_FromDouble(a);
@@ -2179,6 +2182,10 @@ PyAPI_FUNC(PyObject*) _PyTruffleObject_Call1(PyObject* a, PyObject* b, PyObject*
21792182
PyAPI_FUNC(PyObject*) _PyTruffleObject_CallMethod1(PyObject* a, const char* b, PyObject* c, int d) {
21802183
return Graal_PyTruffleObject_CallMethod1(a, truffleString(b), c, d);
21812184
}
2185+
#undef _PyTuple_SET_ITEM
2186+
PyAPI_FUNC(int) _PyTuple_SET_ITEM(PyObject* a, Py_ssize_t b, PyObject* c) {
2187+
return Graal_PyTuple_SET_ITEM(a, b, c);
2188+
}
21822189
#undef _PyType_Lookup
21832190
PyAPI_FUNC(PyObject*) _PyType_Lookup(PyTypeObject* a, PyObject* b) {
21842191
return Graal_PyType_Lookup(a, b);

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

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
#include <graalvm/llvm/polyglot.h>
6363
#include <truffle.h>
6464
#include <graalvm/llvm/handles.h>
65-
#endif
65+
#endif // EXCLUDE_POLYGLOT_API
6666

6767
#define SRC_CS "utf-8"
6868

@@ -153,7 +153,6 @@ typedef struct {
153153
BUILTIN(PyException_SetContext, void, PyObject*, PyObject*) \
154154
BUILTIN(PyException_SetTraceback, int, PyObject*, PyObject*) \
155155
BUILTIN(PyFile_WriteObject, int, PyObject*, PyObject*, int) \
156-
BUILTIN(PyFloat_AsDouble, double, PyObject*) \
157156
BUILTIN(PyFloat_FromDouble, PyObject*, double) \
158157
BUILTIN(PyFrame_New, PyFrameObject*, PyThreadState*, PyCodeObject*, PyObject*, PyObject*) \
159158
BUILTIN(PyFrozenSet_New, PyObject*, PyObject*) \
@@ -280,17 +279,27 @@ typedef struct {
280279
BUILTIN(PyTruffleCMethod_NewEx, PyObject*, PyMethodDef*, const char*, void*, int, int, PyObject*, PyObject*, PyTypeObject*, const char*) \
281280
BUILTIN(PyTruffleComplex_AsCComplex, PyObject*, PyObject*) \
282281
BUILTIN(PyTruffleContextVar_Get, PyObject*, PyObject*, PyObject*, void*) \
282+
BUILTIN(PyTruffleDateTimeCAPI_DateTime_FromDateAndTime, PyObject*, int, int, int, int, int, int, int, PyObject*, PyTypeObject*) \
283+
BUILTIN(PyTruffleDateTimeCAPI_DateTime_FromDateAndTimeAndFold, PyObject*, int, int, int, int, int, int, int, PyObject*, int, PyTypeObject*) \
284+
BUILTIN(PyTruffleDateTimeCAPI_DateTime_FromTimestamp, PyObject*, PyObject*, PyObject*, PyObject*) \
285+
BUILTIN(PyTruffleDateTimeCAPI_Date_FromDate, PyObject*, int, int, int, PyTypeObject*) \
286+
BUILTIN(PyTruffleDateTimeCAPI_Date_FromTimestamp, PyObject*, PyObject*, PyObject*) \
287+
BUILTIN(PyTruffleDateTimeCAPI_Delta_FromDelta, PyObject*, int, int, int, int, PyTypeObject*) \
288+
BUILTIN(PyTruffleDateTimeCAPI_TimeZone_FromTimeZone, PyObject*, PyObject*, PyObject*) \
289+
BUILTIN(PyTruffleDateTimeCAPI_Time_FromTime, PyObject*, int, int, int, int, PyObject*, PyTypeObject*) \
290+
BUILTIN(PyTruffleDateTimeCAPI_Time_FromTimeAndFold, PyObject*, int, int, int, int, PyObject*, int, PyTypeObject*) \
283291
BUILTIN(PyTruffleDescr_NewClassMethod, PyObject*, void*, const char*, const char*, int, int, void*, PyTypeObject*) \
284292
BUILTIN(PyTruffleDescr_NewGetSet, PyObject*, const char*, PyTypeObject*, void*, void*, const char*, void*) \
285293
BUILTIN(PyTruffleDict_Next, PyObject*, PyObject*, Py_ssize_t) \
286294
BUILTIN(PyTruffleErr_Fetch, PyObject*) \
287295
BUILTIN(PyTruffleErr_GetExcInfo, PyObject*) \
296+
BUILTIN(PyTruffleFloat_AsDouble, double, PyObject*) \
288297
BUILTIN(PyTruffleHash_InitSecret, void, void*) \
289298
BUILTIN(PyTruffleLong_AsPrimitive, long, PyObject*, int, long) \
290299
BUILTIN(PyTruffleLong_FromString, PyObject*, const char*, int, int) \
291300
BUILTIN(PyTruffleLong_One, PyObject*) \
292301
BUILTIN(PyTruffleLong_Zero, PyObject*) \
293-
BUILTIN(PyTruffleModule_AddFunctionToModule, int, void*, PyObject*, const char*, void*, int, int, void*) \
302+
BUILTIN(PyTruffleModule_AddFunctionToModule, int, void*, PyObject*, const char*, void*, int, int, const char*) \
294303
BUILTIN(PyTruffleNumber_BinOp, PyObject*, PyObject*, PyObject*, int) \
295304
BUILTIN(PyTruffleNumber_InPlaceBinOp, PyObject*, PyObject*, PyObject*, int) \
296305
BUILTIN(PyTruffleNumber_UnaryOp, PyObject*, PyObject*, int) \
@@ -303,10 +312,10 @@ typedef struct {
303312
BUILTIN(PyTruffleStructSequence_InitType2, int, PyTypeObject*, void*, void*, int) \
304313
BUILTIN(PyTruffleStructSequence_NewType, PyTypeObject*, const char*, const char*, void*, void*, int) \
305314
BUILTIN(PyTruffleToCharPointer, void*, PyObject*) \
306-
BUILTIN(PyTruffleType_AddFunctionToType, int, void*, PyTypeObject*, PyObject*, const char*, void*, int, int, void*) \
307-
BUILTIN(PyTruffleType_AddGetSet, int, PyTypeObject*, PyObject*, const char*, void*, void*, void*, void*) \
308-
BUILTIN(PyTruffleType_AddMember, int, PyTypeObject*, PyObject*, const char*, int, Py_ssize_t, int, void*) \
309-
BUILTIN(PyTruffleType_AddSlot, int, PyTypeObject*, PyObject*, const char*, void*, int, int, void*) \
315+
BUILTIN(PyTruffleType_AddFunctionToType, int, void*, PyTypeObject*, PyObject*, const char*, void*, int, int, const char*) \
316+
BUILTIN(PyTruffleType_AddGetSet, int, PyTypeObject*, PyObject*, const char*, void*, void*, const char*, void*) \
317+
BUILTIN(PyTruffleType_AddMember, int, PyTypeObject*, PyObject*, const char*, int, Py_ssize_t, int, const char*) \
318+
BUILTIN(PyTruffleType_AddSlot, int, PyTypeObject*, PyObject*, const char*, void*, int, int, const char*) \
310319
BUILTIN(PyTruffleUnicode_Decode, PyObject*, PyObject*, const char*, const char*) \
311320
BUILTIN(PyTruffleUnicode_DecodeUTF8Stateful, PyObject*, void*, const char*, int) \
312321
BUILTIN(PyTruffleUnicode_FromUCS, PyObject*, void*, Py_ssize_t, int) \
@@ -326,20 +335,22 @@ typedef struct {
326335
BUILTIN(PyTruffle_FileSystemDefaultEncoding, PyObject*) \
327336
BUILTIN(PyTruffle_Get_Inherited_Native_Slots, void*, PyTypeObject*, const char*) \
328337
BUILTIN(PyTruffle_HashConstant, long, int) \
338+
BUILTIN(PyTruffle_InitialNativeMemory, size_t) \
329339
BUILTIN(PyTruffle_LogString, void, int, const char*) \
340+
BUILTIN(PyTruffle_MaxNativeMemory, size_t) \
330341
BUILTIN(PyTruffle_MemoryViewFromBuffer, PyObject*, void*, PyObject*, Py_ssize_t, int, Py_ssize_t, const char*, int, void*, void*, void*, void*) \
331342
BUILTIN(PyTruffle_Native_Options, int) \
332343
BUILTIN(PyTruffle_NewTypeDict, PyObject*, PyTypeObject*) \
333344
BUILTIN(PyTruffle_NoValue, PyObject*) \
334345
BUILTIN(PyTruffle_None, PyObject*) \
335346
BUILTIN(PyTruffle_NotImplemented, PyObject*) \
336-
BUILTIN(PyTruffle_Object_Alloc, int, void*, long) \
337347
BUILTIN(PyTruffle_Object_Free, int, void*) \
338348
BUILTIN(PyTruffle_Register_NULL, void, void*) \
339349
BUILTIN(PyTruffle_Set_Native_Slots, int, PyTypeObject*, void*, void*) \
340350
BUILTIN(PyTruffle_Set_SulongType, void*, PyTypeObject*, void*) \
341351
BUILTIN(PyTruffle_ToNative, int, void*) \
342352
BUILTIN(PyTruffle_Trace_Type, int, void*, void*) \
353+
BUILTIN(PyTruffle_TriggerGC, void, size_t) \
343354
BUILTIN(PyTruffle_True, PyObject*) \
344355
BUILTIN(PyTruffle_Type, PyTypeObject*, const char*) \
345356
BUILTIN(PyTruffle_Type_Modified, int, PyTypeObject*, const char*, PyObject*) \
@@ -586,7 +597,7 @@ typedef struct {
586597
BUILTIN(_PyTruffleObject_MakeTpCall, PyObject*, PyObject*, void*, int, void*, void*) \
587598
BUILTIN(_PyTruffleSet_NextEntry, PyObject*, PyObject*, Py_ssize_t) \
588599
BUILTIN(_PyTruffle_HashBytes, Py_hash_t, const char*) \
589-
BUILTIN(_PyTruffle_Trace_Free, int, void*, Py_ssize_t) \
600+
BUILTIN(_PyTuple_SET_ITEM, int, PyObject*, Py_ssize_t, PyObject*) \
590601
BUILTIN(_PyType_Lookup, PyObject*, PyTypeObject*, PyObject*) \
591602
BUILTIN(_PyUnicode_AsASCIIString, PyObject*, PyObject*, const char*) \
592603
BUILTIN(_PyUnicode_AsLatin1String, PyObject*, PyObject*, const char*) \
@@ -823,6 +834,7 @@ static void PyTruffle_Log(int level, const char* format, ... ) {
823834
va_list args;
824835
va_start(args, format);
825836
vsprintf(buffer,format, args);
837+
printf("logg\n");
826838
#ifndef EXCLUDE_POLYGLOT_API
827839
GraalPyTruffle_LogString(level, polyglot_from_string(buffer, SRC_CS));
828840
#else
@@ -832,7 +844,11 @@ static void PyTruffle_Log(int level, const char* format, ... ) {
832844
}
833845
}
834846

835-
#ifndef EXCLUDE_POLYGLOT_API
847+
#ifdef EXCLUDE_POLYGLOT_API
848+
849+
#define points_to_py_handle_space(PTR) ((((uintptr_t) (PTR)) & 0x8000000000000000L) != 0)
850+
851+
#else // EXCLUDE_POLYGLOT_API
836852

837853
typedef int (*cache_query_t)(uint64_t);
838854
typedef PyObject* (*ptr_cache_t)(PyObject*);
@@ -990,4 +1006,8 @@ PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
9901006

9911007
#endif // !EXCLUDE_POLYGLOT_API
9921008

1009+
extern size_t PyTruffle_AllocatedMemory;
1010+
extern size_t PyTruffle_MaxNativeMemory;
1011+
extern size_t PyTruffle_NativeMemoryGCBarrier;
1012+
9931013
#endif // CAPI_H

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

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, 2022, Oracle and/or its affiliates.
1+
/* Copyright (c) 2018, 2023, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2017 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -49,19 +49,72 @@ static void init_formats(void) {
4949
float_format = detected_float_format;
5050
}
5151

52-
// not quite as in CPython, this assumes that x is already a double. The rest of
53-
// the implementation is in the Float constructor in Java
54-
PyObject* float_subtype_new(PyTypeObject *type, double x) {
55-
PyObject* newobj = type->tp_alloc(type, 0);
56-
if (newobj == NULL) {
57-
Py_DECREF(newobj);
58-
return NULL;
52+
53+
// Below taken from CPython
54+
55+
56+
double
57+
PyFloat_AsDouble(PyObject *op)
58+
{
59+
if (points_to_py_handle_space(op)) {
60+
return GraalPyTruffleFloat_AsDouble(op);
61+
}
62+
PyNumberMethods *nb;
63+
PyObject *res;
64+
double val;
65+
66+
if (op == NULL) {
67+
PyErr_BadArgument();
68+
return -1;
69+
}
70+
71+
if (PyFloat_Check(op)) {
72+
return ((PyFloatObject*) op)->ob_fval;
73+
}
74+
75+
nb = Py_TYPE(op)->tp_as_number;
76+
if (nb == NULL || nb->nb_float == NULL) {
77+
if (nb && nb->nb_index) {
78+
PyObject *res = _PyNumber_Index(op);
79+
if (!res) {
80+
return -1;
81+
}
82+
double val = PyLong_AsDouble(res);
83+
Py_DECREF(res);
84+
return val;
85+
}
86+
PyErr_Format(PyExc_TypeError, "must be real number, not %.50s",
87+
Py_TYPE(op)->tp_name);
88+
return -1;
89+
}
90+
91+
res = (*nb->nb_float) (op);
92+
if (res == NULL) {
93+
return -1;
94+
}
95+
if (!PyFloat_CheckExact(res)) {
96+
if (!PyFloat_Check(res)) {
97+
PyErr_Format(PyExc_TypeError,
98+
"%.50s.__float__ returned non-float (type %.50s)",
99+
Py_TYPE(op)->tp_name, Py_TYPE(res)->tp_name);
100+
Py_DECREF(res);
101+
return -1;
102+
}
103+
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
104+
"%.50s.__float__ returned non-float (type %.50s). "
105+
"The ability to return an instance of a strict subclass of float "
106+
"is deprecated, and may be removed in a future version of Python.",
107+
Py_TYPE(op)->tp_name, Py_TYPE(res)->tp_name)) {
108+
Py_DECREF(res);
109+
return -1;
110+
}
59111
}
60-
((PyFloatObject *)newobj)->ob_fval = x;
61-
return newobj;
112+
113+
val = PyFloat_AsDouble(res);
114+
Py_DECREF(res);
115+
return val;
62116
}
63117

64-
// Below taken from CPython
65118

66119
/*----------------------------------------------------------------------------
67120
* _PyFloat_{Pack,Unpack}{2,4,8}. See floatobject.h.

0 commit comments

Comments
 (0)