Skip to content

Commit 5e4203d

Browse files
committed
[GR-45273] Additional C API functions in preparation of sqlite.
PullRequest: graalpython/2707
2 parents bc954a2 + 4f5da13 commit 5e4203d

File tree

26 files changed

+1293
-1183
lines changed

26 files changed

+1293
-1183
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2022 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
6+
#ifndef Py_STRCMP_H
7+
#define Py_STRCMP_H
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
PyAPI_FUNC(int) PyOS_mystrnicmp(const char *, const char *, Py_ssize_t);
14+
PyAPI_FUNC(int) PyOS_mystricmp(const char *, const char *);
15+
16+
#ifdef MS_WINDOWS
17+
#define PyOS_strnicmp strnicmp
18+
#define PyOS_stricmp stricmp
19+
#else
20+
#define PyOS_strnicmp PyOS_mystrnicmp
21+
#define PyOS_stricmp PyOS_mystricmp
22+
#endif
23+
24+
#ifdef __cplusplus
25+
}
26+
#endif
27+
28+
#endif /* !Py_STRCMP_H */

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,10 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock a, int b) {
20412041
PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock() {
20422042
return GraalPyThread_allocate_lock();
20432043
}
2044+
#undef PyThread_get_thread_ident
2045+
PyAPI_FUNC(unsigned long) PyThread_get_thread_ident() {
2046+
return GraalPyThread_get_thread_ident();
2047+
}
20442048
#undef PyThread_release_lock
20452049
PyAPI_FUNC(void) PyThread_release_lock(PyThread_type_lock a) {
20462050
GraalPyThread_release_lock(a);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ typedef struct {
268268
BUILTIN(PyThreadState_GetDict, PyObject*) \
269269
BUILTIN(PyThread_acquire_lock, int, PyThread_type_lock, int) \
270270
BUILTIN(PyThread_allocate_lock, PyThread_type_lock) \
271+
BUILTIN(PyThread_get_thread_ident, unsigned long) \
271272
BUILTIN(PyThread_release_lock, void, PyThread_type_lock) \
272273
BUILTIN(PyTraceBack_Here, int, PyFrameObject*) \
273274
BUILTIN(PyTraceMalloc_Track, int, unsigned int, uintptr_t, size_t) \
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2022 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
6+
7+
#include "capi.h"
8+
9+
int
10+
PyDescr_IsData(PyObject *ob)
11+
{
12+
return Py_TYPE(ob)->tp_descr_set != NULL;
13+
}

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

Lines changed: 134 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -125,39 +125,15 @@ int PyObject_GenericInit(PyObject* self, PyObject* args, PyObject* kwds) {
125125
return self;
126126
}
127127

128-
#define IS_SINGLE_ARG(_fmt) ((_fmt[0]) != '\0' && (_fmt[1]) == '\0')
129-
130-
PyObject* PyObject_Call(PyObject* callable, PyObject* args, PyObject* kwargs) {
131-
return Graal_PyTruffleObject_Call1(callable, args, kwargs, 0);
132-
}
133-
134-
PyObject* PyObject_CallObject(PyObject* callable, PyObject* args) {
135-
return Graal_PyTruffleObject_Call1(callable, args, NULL, 0);
136-
}
137-
138-
PyObject* PyObject_CallFunction(PyObject* callable, const char* fmt, ...) {
139-
if (fmt == NULL || fmt[0] == '\0') {
140-
return Graal_PyTruffleObject_Call1(callable, NULL, NULL, 0);
141-
}
142-
va_list va;
143-
va_start(va, fmt);
144-
PyObject* args = Py_VaBuildValue(fmt, va);
145-
va_end(va);
146-
return Graal_PyTruffleObject_Call1(callable, args, NULL, IS_SINGLE_ARG(fmt));
147-
}
148-
149-
PyObject* _PyObject_CallFunction_SizeT(PyObject* callable, const char* fmt, ...) {
150-
if (fmt == NULL || fmt[0] == '\0') {
151-
return Graal_PyTruffleObject_Call1(callable, NULL, NULL, 0);
152-
}
153-
va_list va;
154-
va_start(va, fmt);
155-
PyObject* args = Py_VaBuildValue(fmt, va);
156-
va_end(va);
157-
return Graal_PyTruffleObject_Call1(callable, args, NULL, IS_SINGLE_ARG(fmt));
128+
PyObject * _PyObject_CallMethodIdObjArgs(PyObject *callable, struct _Py_Identifier *name, ...) {
129+
va_list vargs;
130+
va_start(vargs, name);
131+
// the arguments are given as a variable list followed by NULL
132+
PyObject *result = GraalPyTruffleObject_CallMethodObjArgs(callable, _PyUnicode_FromId(name), &vargs);
133+
va_end(vargs);
134+
return result;
158135
}
159136

160-
typedef PyObject *(*call_fun_obj_args_t)(PyObject *, void *);
161137
PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ...) {
162138
va_list vargs;
163139
va_start(vargs, callable);
@@ -167,20 +143,6 @@ PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ...) {
167143
return result;
168144
}
169145

170-
typedef PyObject *(*call_method_t)(PyObject *, void *, void *, int32_t);
171-
PyObject* PyObject_CallMethod(PyObject* object, const char* method, const char* fmt, ...) {
172-
PyObject* args;
173-
if (fmt == NULL || fmt[0] == '\0') {
174-
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), NULL, 0);
175-
}
176-
va_list va;
177-
va_start(va, fmt);
178-
args = Py_VaBuildValue(fmt, va);
179-
va_end(va);
180-
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), args, IS_SINGLE_ARG(fmt));
181-
}
182-
183-
typedef PyObject *(*call_meth_obj_args_t)(PyObject *, void *, void *);
184146
PyObject* PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) {
185147
va_list vargs;
186148
va_start(vargs, name);
@@ -190,18 +152,6 @@ PyObject* PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) {
190152
return result;
191153
}
192154

193-
PyObject* _PyObject_CallMethod_SizeT(PyObject* object, const char* method, const char* fmt, ...) {
194-
PyObject* args;
195-
if (fmt == NULL || fmt[0] == '\0') {
196-
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), NULL, 0);
197-
}
198-
va_list va;
199-
va_start(va, fmt);
200-
args = Py_VaBuildValue(fmt, va);
201-
va_end(va);
202-
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), args, IS_SINGLE_ARG(fmt));
203-
}
204-
205155
PyObject* _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
206156
PyObject *const *args, Py_ssize_t nargs,
207157
PyObject *keywords) {
@@ -345,6 +295,98 @@ PyObject* PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwarg
345295
return result;
346296
}
347297

298+
299+
// Taken from cpython object.c
300+
/* Specialized version of _PyObject_GenericGetAttrWithDict
301+
specifically for the LOAD_METHOD opcode.
302+
303+
Return 1 if a method is found, 0 if it's a regular attribute
304+
from __dict__ or something returned by using a descriptor
305+
protocol.
306+
307+
`method` will point to the resolved attribute or NULL. In the
308+
latter case, an error will be set.
309+
*/
310+
int
311+
_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
312+
{
313+
PyTypeObject *tp = Py_TYPE(obj);
314+
PyObject *descr;
315+
descrgetfunc f = NULL;
316+
PyObject **dictptr, *dict;
317+
PyObject *attr;
318+
int meth_found = 0;
319+
320+
assert(*method == NULL);
321+
322+
if (Py_TYPE(obj)->tp_getattro != PyObject_GenericGetAttr
323+
|| !PyUnicode_Check(name)) {
324+
*method = PyObject_GetAttr(obj, name);
325+
return 0;
326+
}
327+
328+
if (tp->tp_dict == NULL && PyType_Ready(tp) < 0)
329+
return 0;
330+
331+
descr = _PyType_Lookup(tp, name);
332+
if (descr != NULL) {
333+
Py_INCREF(descr);
334+
if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
335+
meth_found = 1;
336+
} else {
337+
f = Py_TYPE(descr)->tp_descr_get;
338+
if (f != NULL && PyDescr_IsData(descr)) {
339+
*method = f(descr, obj, (PyObject *)Py_TYPE(obj));
340+
Py_DECREF(descr);
341+
return 0;
342+
}
343+
}
344+
}
345+
346+
dictptr = _PyObject_GetDictPtr(obj);
347+
if (dictptr != NULL && (dict = *dictptr) != NULL) {
348+
Py_INCREF(dict);
349+
attr = PyDict_GetItemWithError(dict, name);
350+
if (attr != NULL) {
351+
Py_INCREF(attr);
352+
*method = attr;
353+
Py_DECREF(dict);
354+
Py_XDECREF(descr);
355+
return 0;
356+
}
357+
else {
358+
Py_DECREF(dict);
359+
if (PyErr_Occurred()) {
360+
Py_XDECREF(descr);
361+
return 0;
362+
}
363+
}
364+
}
365+
366+
if (meth_found) {
367+
*method = descr;
368+
return 1;
369+
}
370+
371+
if (f != NULL) {
372+
*method = f(descr, obj, (PyObject *)Py_TYPE(obj));
373+
Py_DECREF(descr);
374+
return 0;
375+
}
376+
377+
if (descr != NULL) {
378+
*method = descr;
379+
return 0;
380+
}
381+
382+
PyErr_Format(PyExc_AttributeError,
383+
"'%.50s' object has no attribute '%U'",
384+
tp->tp_name, name);
385+
386+
// set_attribute_error_context(obj, name);
387+
return 0;
388+
}
389+
348390
// Taken from cpython call.c
349391
PyObject* PyObject_VectorcallDict(PyObject *callable, PyObject *const *args,
350392
size_t nargsf, PyObject *kwargs) {
@@ -380,6 +422,41 @@ PyObject* PyObject_VectorcallDict(PyObject *callable, PyObject *const *args,
380422
return res;
381423
}
382424

425+
// Taken from cpython call.c
426+
PyObject *
427+
PyObject_VectorcallMethod(PyObject *name, PyObject *const *args,
428+
size_t nargsf, PyObject *kwnames)
429+
{
430+
assert(name != NULL);
431+
assert(args != NULL);
432+
assert(PyVectorcall_NARGS(nargsf) >= 1);
433+
434+
PyThreadState *tstate = _PyThreadState_GET();
435+
PyObject *callable = NULL;
436+
/* Use args[0] as "self" argument */
437+
int unbound = _PyObject_GetMethod(args[0], name, &callable);
438+
if (callable == NULL) {
439+
return NULL;
440+
}
441+
442+
if (unbound) {
443+
/* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since
444+
* that would be interpreted as allowing to change args[-1] */
445+
nargsf &= ~PY_VECTORCALL_ARGUMENTS_OFFSET;
446+
}
447+
else {
448+
/* Skip "self". We can keep PY_VECTORCALL_ARGUMENTS_OFFSET since
449+
* args[-1] in the onward call is args[0] here. */
450+
args++;
451+
nargsf--;
452+
}
453+
PyObject *result = _PyObject_VectorcallTstate(tstate, callable,
454+
args, nargsf, kwnames);
455+
Py_DECREF(callable);
456+
return result;
457+
}
458+
459+
383460
// Taken from CPython object.c
384461
int
385462
PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,66 @@ void PyObject_GC_Del(void *tp) {
205205
PyObject_Free(tp);
206206
}
207207

208+
#define IS_SINGLE_ARG(_fmt) ((_fmt[0]) != '\0' && (_fmt[1]) == '\0')
209+
210+
PyObject* PyObject_Call(PyObject* callable, PyObject* args, PyObject* kwargs) {
211+
return Graal_PyTruffleObject_Call1(callable, args, kwargs, 0);
212+
}
213+
214+
PyObject* PyObject_CallObject(PyObject* callable, PyObject* args) {
215+
return Graal_PyTruffleObject_Call1(callable, args, NULL, 0);
216+
}
217+
218+
PyObject* PyObject_CallFunction(PyObject* callable, const char* fmt, ...) {
219+
if (fmt == NULL || fmt[0] == '\0') {
220+
return Graal_PyTruffleObject_Call1(callable, NULL, NULL, 0);
221+
}
222+
va_list va;
223+
va_start(va, fmt);
224+
PyObject* args = Py_VaBuildValue(fmt, va);
225+
va_end(va);
226+
// A special case in CPython for backwards compatibility
227+
if (IS_SINGLE_ARG(fmt) && PyTuple_Check(args)) {
228+
return Graal_PyTruffleObject_Call1(callable, args, NULL, 0);
229+
}
230+
return Graal_PyTruffleObject_Call1(callable, args, NULL, IS_SINGLE_ARG(fmt));
231+
}
232+
233+
PyObject* _PyObject_CallFunction_SizeT(PyObject* callable, const char* fmt, ...) {
234+
if (fmt == NULL || fmt[0] == '\0') {
235+
return Graal_PyTruffleObject_Call1(callable, NULL, NULL, 0);
236+
}
237+
va_list va;
238+
va_start(va, fmt);
239+
PyObject* args = Py_VaBuildValue(fmt, va);
240+
va_end(va);
241+
// A special case in CPython for backwards compatibility
242+
if (IS_SINGLE_ARG(fmt) && PyTuple_Check(args)) {
243+
return Graal_PyTruffleObject_Call1(callable, args, NULL, 0);
244+
}
245+
return Graal_PyTruffleObject_Call1(callable, args, NULL, IS_SINGLE_ARG(fmt));
246+
}
247+
248+
PyObject* PyObject_CallMethod(PyObject* object, const char* method, const char* fmt, ...) {
249+
PyObject* args;
250+
if (fmt == NULL || fmt[0] == '\0') {
251+
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), NULL, 0);
252+
}
253+
va_list va;
254+
va_start(va, fmt);
255+
args = Py_VaBuildValue(fmt, va);
256+
va_end(va);
257+
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), args, IS_SINGLE_ARG(fmt));
258+
}
259+
260+
PyObject* _PyObject_CallMethod_SizeT(PyObject* object, const char* method, const char* fmt, ...) {
261+
PyObject* args;
262+
if (fmt == NULL || fmt[0] == '\0') {
263+
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), NULL, 0);
264+
}
265+
va_list va;
266+
va_start(va, fmt);
267+
args = Py_VaBuildValue(fmt, va);
268+
va_end(va);
269+
return Graal_PyTruffleObject_CallMethod1(object, truffleString(method), args, IS_SINGLE_ARG(fmt));
270+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2022 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
6+
/* Cross platform case insensitive string compare functions
7+
*/
8+
9+
#include "Python.h"
10+
11+
int
12+
PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size)
13+
{
14+
const unsigned char *p1, *p2;
15+
if (size == 0)
16+
return 0;
17+
p1 = (const unsigned char *)s1;
18+
p2 = (const unsigned char *)s2;
19+
for (; (--size > 0) && *p1 && *p2 && (tolower(*p1) == tolower(*p2));
20+
p1++, p2++) {
21+
;
22+
}
23+
return tolower(*p1) - tolower(*p2);
24+
}
25+
26+
int
27+
PyOS_mystricmp(const char *s1, const char *s2)
28+
{
29+
const unsigned char *p1 = (const unsigned char *)s1;
30+
const unsigned char *p2 = (const unsigned char *)s2;
31+
for (; *p1 && *p2 && (tolower(*p1) == tolower(*p2)); p1++, p2++) {
32+
;
33+
}
34+
return (tolower(*p1) - tolower(*p2));
35+
}

0 commit comments

Comments
 (0)