Skip to content

Commit 5ebaecb

Browse files
committed
move PyType_Ready
1 parent 79da2d6 commit 5ebaecb

File tree

2 files changed

+368
-369
lines changed

2 files changed

+368
-369
lines changed

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

Lines changed: 0 additions & 369 deletions
Original file line numberDiff line numberDiff line change
@@ -162,375 +162,6 @@ Py_ssize_t PyObject_Size(PyObject *o) {
162162
return UPCALL_CEXT_L("PyObject_Size", native_to_java(o));
163163
}
164164

165-
static int add_subclass(PyTypeObject *base, PyTypeObject *type) {
166-
void* key = PyLong_FromVoidPtr((void *) type);
167-
if (key == NULL) {
168-
return -1;
169-
}
170-
if (polyglot_is_value(base)) {
171-
return polyglot_as_i32(polyglot_invoke(PY_TRUFFLE_CEXT, "PyTruffle_Add_Subclass", native_to_java((PyObject*)base), native_to_java(key), native_to_java((PyObject*)type)));
172-
} else {
173-
PyObject *dict = base->tp_subclasses;
174-
if (dict == NULL) {
175-
base->tp_subclasses = dict = PyDict_New();
176-
if (dict == NULL) {
177-
return -1;
178-
}
179-
}
180-
// TODO value should be a weak reference !
181-
return PyDict_SetItem(base->tp_subclasses, key, (PyObject*)type);
182-
}
183-
return -1;
184-
}
185-
186-
/* Special C landing functions that convert some arguments to primitives. */
187-
188-
static PyObject* wrap_allocfunc(allocfunc f, PyTypeObject* klass, PyObject* n) {
189-
return f(klass, PyLong_AsSsize_t(n));
190-
}
191-
192-
/* Wrapper around a native function to be called by Python code. */
193-
static PyObject* wrap_getattrfunc(getattrfunc f, PyObject* obj, PyObject* unicode) {
194-
// we really need to provide 'char *' since this often runs non-Sulong code
195-
return f(obj, as_char_pointer(unicode));
196-
}
197-
198-
/* Wrapper around the native function to be called by Python code. */
199-
static PyObject* wrap_setattrfunc(setattrfunc f, PyObject* obj, PyObject* unicode, PyObject* value) {
200-
// we really need to provide 'char *' since this often runs non-Sulong code
201-
return f(obj, as_char_pointer(unicode), value);
202-
}
203-
204-
static PyObject* wrap_setattrofunc(setattrofunc f, PyObject* obj, PyObject* key, PyObject* item) {
205-
return PyLong_FromLong(f(obj, key, item));
206-
}
207-
208-
static PyObject* wrap_richcmpfunc(richcmpfunc f, PyObject* a, PyObject* b, PyObject* n) {
209-
return f(a, b, (int)PyLong_AsLong(n));
210-
}
211-
212-
static PyObject* wrap_ssizeobjargproc(ssizeobjargproc f, PyObject* a, PyObject* size, PyObject* b) {
213-
return PyLong_FromLong(f(a, PyLong_AsSsize_t(size), b));
214-
}
215-
216-
static PyObject* wrap_ssizeargfunc(ssizeargfunc f, PyObject* a, PyObject* size) {
217-
return PyLong_FromLong(f(a, PyLong_AsSsize_t(size)));
218-
}
219-
220-
static PyObject* wrap_initproc(initproc f, PyObject* a, PyObject* b, PyObject* c) {
221-
return PyLong_FromLong(f(a, b, c));
222-
}
223-
224-
static PyObject* wrap_objobjargproc(objobjargproc f, PyObject* a, PyObject* b, PyObject* c) {
225-
return PyLong_FromLong(f(a, b, c));
226-
}
227-
228-
static PyObject* wrap_objobjproc(objobjproc f, PyObject* a, PyObject* b) {
229-
return PyLong_FromLong(f(a, b));
230-
}
231-
232-
static PyObject* wrap_inquiry(inquiry f, PyObject* a) {
233-
return PyLong_FromLong(f(a));
234-
}
235-
236-
/* very special case: operator '**' has an optional third arg */
237-
static PyObject* wrap_pow(ternaryfunc f, ...) {
238-
int nargs = polyglot_get_arg_count();
239-
switch(nargs) {
240-
case 3:
241-
// TODO use 'native_to_java' on result
242-
return f(polyglot_get_arg(1), polyglot_get_arg(2), Py_None);
243-
case 4:
244-
// TODO use 'native_to_java' on result
245-
return f(polyglot_get_arg(1), polyglot_get_arg(2), polyglot_get_arg(3));
246-
}
247-
return Py_NoValue;
248-
}
249-
250-
static PyObject* wrap_lenfunc(lenfunc f, PyObject* a) {
251-
return PyLong_FromSsize_t(f(a));
252-
}
253-
254-
static Py_hash_t wrap_hashfunc(hashfunc f, PyObject* a) {
255-
return PyLong_FromSsize_t(f(a));
256-
}
257-
258-
static PyObject* wrap_reverse_binop(binaryfunc f, PyObject* a, PyObject* b) {
259-
return f(b, a);
260-
}
261-
262-
int PyType_Ready(PyTypeObject* cls) {
263-
#define ADD_IF_MISSING(attr, def) if (!(attr)) { attr = def; }
264-
#define ADD_METHOD(m) ADD_METHOD_OR_SLOT(m.ml_name, get_method_flags_cwrapper(m.ml_flags), m.ml_meth, m.ml_flags, m.ml_doc)
265-
#define ADD_SLOT(name, meth, flags) ADD_METHOD_OR_SLOT(name, get_method_flags_cwrapper(flags), meth, flags, name)
266-
#define ADD_SLOT_CONV(name, clanding, meth, flags) ADD_METHOD_OR_SLOT(name, clanding, meth, flags, name)
267-
#define ADD_METHOD_OR_SLOT(name, clanding, meth, flags, doc) \
268-
if (meth) { \
269-
polyglot_invoke(PY_TRUFFLE_CEXT, \
270-
"AddFunction", \
271-
javacls, \
272-
polyglot_from_string((name), SRC_CS), \
273-
(meth), \
274-
(clanding), \
275-
get_method_flags_wrapper(flags), \
276-
polyglot_from_string(doc, SRC_CS), \
277-
(flags) > 0 && ((flags) & METH_CLASS) != 0, \
278-
(flags) > 0 && ((flags) & METH_STATIC) != 0); \
279-
}
280-
281-
// https://docs.python.org/3/c-api/typeobj.html#Py_TPFLAGS_READY
282-
if ((cls->tp_flags & Py_TPFLAGS_READY) || (cls->tp_flags & Py_TPFLAGS_READYING)) {
283-
return 0;
284-
}
285-
cls->tp_flags = cls->tp_flags | Py_TPFLAGS_READYING;
286-
287-
// https://docs.python.org/3/c-api/typeobj.html#c.PyObject.ob_type
288-
PyTypeObject* base = cls->tp_base;
289-
PyTypeObject* metaclass = Py_TYPE(cls);
290-
if (!base) {
291-
base = &PyBaseObject_Type;
292-
if (!metaclass) {
293-
metaclass = &PyType_Type;
294-
}
295-
} else {
296-
if (!metaclass) {
297-
metaclass = Py_TYPE(base);
298-
}
299-
}
300-
cls->tp_base = base;
301-
Py_TYPE(cls) = metaclass;
302-
303-
if (!(cls->tp_doc)) {
304-
cls->tp_doc = "";
305-
}
306-
307-
/* Initialize tp_bases */
308-
PyObject* bases = cls->tp_bases;
309-
if (bases == NULL) {
310-
if (base == NULL) {
311-
bases = PyTuple_New(0);
312-
} else {
313-
bases = PyTuple_Pack(1, base);
314-
}
315-
if (bases == NULL) {
316-
cls->tp_flags &= ~Py_TPFLAGS_READYING;
317-
return -1;
318-
}
319-
cls->tp_bases = bases;
320-
}
321-
322-
PyObject* native_members = PyDict_New();
323-
PyDict_SetItemString(native_members, "tp_name", polyglot_from_string(cls->tp_name, SRC_CS));
324-
PyDict_SetItemString(native_members, "tp_doc", polyglot_from_string(cls->tp_doc ? cls->tp_doc : "", SRC_CS));
325-
PyDict_SetItemString(native_members, "tp_basicsize", PyLong_FromSsize_t(cls->tp_basicsize));
326-
const char* lastDot = strrchr(cls->tp_name, '.');
327-
if (lastDot) {
328-
PyDict_SetItemString(native_members, "__module__", polyglot_from_string(lastDot + 1, SRC_CS));
329-
}
330-
PyTypeObject* javacls = polyglot_invoke(PY_TRUFFLE_CEXT,
331-
"PyType_Ready",
332-
// no conversion of cls here, because we
333-
// store this into the PyTypeObject
334-
cls,
335-
native_to_java((PyObject*)metaclass),
336-
native_to_java(bases),
337-
native_to_java(native_members));
338-
339-
// remember the managed wrapper
340-
((PyObject*)cls)->ob_refcnt = truffle_handle_for_managed(javacls);
341-
if (cls->tp_dict != NULL) {
342-
// TODO: (tfel) is this always safe?
343-
PyDict_Update(javacls->tp_dict, cls->tp_dict);
344-
}
345-
cls->tp_dict = javacls->tp_dict;
346-
347-
PyMethodDef* methods = cls->tp_methods;
348-
if (methods) {
349-
int idx = 0;
350-
PyMethodDef def = methods[idx];
351-
while (def.ml_name != NULL) {
352-
if (!(def.ml_doc)) {
353-
def.ml_doc = "";
354-
}
355-
ADD_METHOD(def);
356-
def = methods[++idx];
357-
}
358-
}
359-
360-
PyMemberDef* members = cls->tp_members;
361-
if (members) {
362-
int i = 0;
363-
PyMemberDef member = members[i];
364-
while (member.name != NULL) {
365-
polyglot_invoke(PY_TRUFFLE_CEXT,
366-
"AddMember",
367-
// TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
368-
javacls,
369-
polyglot_from_string(member.name, SRC_CS),
370-
member.type,
371-
member.offset,
372-
// TODO: support other flags
373-
native_to_java(((member.flags & READONLY) == 0) ? Py_True : Py_False),
374-
polyglot_from_string(member.doc ? member.doc : "", SRC_CS));
375-
member = members[++i];
376-
}
377-
}
378-
379-
PyGetSetDef* getsets = cls->tp_getset;
380-
if (getsets) {
381-
int i = 0;
382-
PyGetSetDef getset = getsets[i];
383-
while (getset.name != NULL) {
384-
getter getter_fun = getset.get;
385-
setter setter_fun = getset.set;
386-
polyglot_invoke(PY_TRUFFLE_CEXT,
387-
"AddGetSet",
388-
// TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
389-
javacls,
390-
polyglot_from_string(getset.name, SRC_CS),
391-
getter_fun != NULL ? (getter)getter_fun : native_to_java(Py_None),
392-
wrap_direct,
393-
setter_fun != NULL ? (setter)setter_fun : native_to_java(Py_None),
394-
wrap_setter,
395-
getset.doc ? polyglot_from_string(getset.doc, SRC_CS) : polyglot_from_string("", SRC_CS),
396-
// do not convert the closure, it is handed to the
397-
// getter and setter as-is
398-
getset.closure);
399-
getset = getsets[++i];
400-
}
401-
}
402-
403-
ADD_IF_MISSING(cls->tp_alloc, PyType_GenericAlloc);
404-
ADD_IF_MISSING(cls->tp_new, PyType_GenericNew);
405-
406-
// add special methods defined directly on the type structs
407-
ADD_SLOT("__dealloc__", cls->tp_dealloc, -1);
408-
ADD_SLOT("__print__", cls->tp_print, -3);
409-
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_getattr
410-
// tp_getattr and tp_setattr are deprecated, and should be the same as
411-
// tp_getattro and tp_setattro
412-
413-
// NOTE: The slots may be called from managed code, i.e., we need to wrap the functions
414-
// and convert arguments that should be C primitives.
415-
ADD_SLOT_CONV("__getattr__", wrap_getattrfunc, cls->tp_getattr, -2);
416-
ADD_SLOT_CONV("__setattr__", wrap_setattrfunc, cls->tp_setattr, -3);
417-
ADD_SLOT("__repr__", cls->tp_repr, -1);
418-
ADD_SLOT_CONV("__hash__", wrap_hashfunc, cls->tp_hash, -1);
419-
ADD_SLOT("__call__", cls->tp_call, METH_KEYWORDS | METH_VARARGS);
420-
ADD_SLOT("__str__", cls->tp_str, -1);
421-
ADD_SLOT("__getattr__", cls->tp_getattro, -2);
422-
ADD_SLOT_CONV("__setattr__", wrap_setattrofunc, cls->tp_setattro, -3);
423-
ADD_SLOT("__clear__", cls->tp_clear, -1);
424-
ADD_SLOT_CONV("__compare__", wrap_richcmpfunc, cls->tp_richcompare, -3);
425-
ADD_SLOT("__iter__", cls->tp_iter, -1);
426-
ADD_SLOT("__next__", cls->tp_iternext, -1);
427-
ADD_SLOT("__get__", cls->tp_descr_get, -3);
428-
ADD_SLOT("__set__", cls->tp_descr_set, -3);
429-
ADD_SLOT_CONV("__init__", wrap_initproc, cls->tp_init, METH_KEYWORDS | METH_VARARGS);
430-
ADD_SLOT_CONV("__alloc__", wrap_allocfunc, cls->tp_alloc, -2);
431-
ADD_SLOT("__new__", cls->tp_new, METH_KEYWORDS | METH_VARARGS);
432-
ADD_SLOT("__free__", cls->tp_free, -1);
433-
ADD_SLOT("__del__", cls->tp_del, -1);
434-
ADD_SLOT("__finalize__", cls->tp_finalize, -1);
435-
436-
PyNumberMethods* numbers = cls->tp_as_number;
437-
if (numbers) {
438-
ADD_SLOT("__add__", numbers->nb_add, -2);
439-
ADD_SLOT_CONV("__radd__", wrap_reverse_binop, numbers->nb_add, -2);
440-
ADD_SLOT("__sub__", numbers->nb_subtract, -2);
441-
ADD_SLOT_CONV("__rsub__", wrap_reverse_binop, numbers->nb_subtract, -2);
442-
ADD_SLOT("__mul__", numbers->nb_multiply, -2);
443-
ADD_SLOT("__rem__", numbers->nb_remainder, -2);
444-
ADD_SLOT("__divmod__", numbers->nb_divmod, -2);
445-
ADD_SLOT_CONV("__pow__", wrap_pow, numbers->nb_power, -3);
446-
ADD_SLOT("__neg__", numbers->nb_negative, -1);
447-
ADD_SLOT("__pos__", numbers->nb_positive, -1);
448-
ADD_SLOT("__abs__", numbers->nb_absolute, -1);
449-
ADD_SLOT_CONV("__bool__", wrap_inquiry, numbers->nb_bool, -1);
450-
ADD_SLOT("__invert__", numbers->nb_invert, -1);
451-
ADD_SLOT("__lshift__", numbers->nb_lshift, -2);
452-
ADD_SLOT("__rshift__", numbers->nb_rshift, -2);
453-
ADD_SLOT("__and__", numbers->nb_and, -2);
454-
ADD_SLOT("__xor__", numbers->nb_xor, -2);
455-
ADD_SLOT("__or__", numbers->nb_or, -2);
456-
ADD_SLOT("__int__", numbers->nb_int, -1);
457-
ADD_SLOT("__float__", numbers->nb_float, -1);
458-
ADD_SLOT("__iadd__", numbers->nb_inplace_add, -2);
459-
ADD_SLOT("__isub__", numbers->nb_inplace_subtract, -2);
460-
ADD_SLOT("__imul__", numbers->nb_inplace_multiply, -2);
461-
ADD_SLOT("__irem__", numbers->nb_inplace_remainder, -2);
462-
ADD_SLOT("__ipow__", numbers->nb_inplace_power, -2);
463-
ADD_SLOT("__ilshift__", numbers->nb_inplace_lshift, -2);
464-
ADD_SLOT("__irshift__", numbers->nb_inplace_rshift, -2);
465-
ADD_SLOT("__iand__", numbers->nb_inplace_and, -2);
466-
ADD_SLOT("__ixor__", numbers->nb_inplace_xor, -2);
467-
ADD_SLOT("__ior__", numbers->nb_inplace_or, -2);
468-
ADD_SLOT("__floordiv__", numbers->nb_floor_divide, -2);
469-
ADD_SLOT("__truediv__", numbers->nb_true_divide, -2);
470-
ADD_SLOT("__ifloordiv__", numbers->nb_inplace_floor_divide, -2);
471-
ADD_SLOT("__itruediv__", numbers->nb_inplace_true_divide, -2);
472-
ADD_SLOT("__index__", numbers->nb_index, -1);
473-
ADD_SLOT("__matmul__", numbers->nb_matrix_multiply, -2);
474-
ADD_SLOT("__imatmul__", numbers->nb_inplace_matrix_multiply, -2);
475-
}
476-
477-
PySequenceMethods* sequences = cls->tp_as_sequence;
478-
if (sequences) {
479-
ADD_SLOT_CONV("__len__", wrap_lenfunc, sequences->sq_length, -1);
480-
ADD_SLOT("__add__", sequences->sq_concat, -2);
481-
ADD_SLOT_CONV("__mul__", wrap_ssizeargfunc, sequences->sq_repeat, -2);
482-
ADD_SLOT_CONV("__getitem__", wrap_ssizeargfunc, sequences->sq_item, -2);
483-
ADD_SLOT_CONV("__setitem__", wrap_ssizeobjargproc, sequences->sq_ass_item, -3);
484-
ADD_SLOT_CONV("__contains__", wrap_objobjproc, sequences->sq_contains, -2);
485-
ADD_SLOT("__iadd__", sequences->sq_inplace_concat, -2);
486-
ADD_SLOT_CONV("__imul__", wrap_ssizeargfunc, sequences->sq_inplace_repeat, -2);
487-
}
488-
489-
PyMappingMethods* mappings = cls->tp_as_mapping;
490-
if (mappings) {
491-
ADD_SLOT_CONV("__len__", wrap_lenfunc, mappings->mp_length, -1);
492-
ADD_SLOT("__getitem__", mappings->mp_subscript, -2);
493-
ADD_SLOT_CONV("__setitem__", wrap_objobjargproc, mappings->mp_ass_subscript, -3);
494-
}
495-
496-
PyAsyncMethods* async = cls->tp_as_async;
497-
if (async) {
498-
ADD_SLOT("__await__", async->am_await, -1);
499-
ADD_SLOT("__aiter__", async->am_aiter, -1);
500-
ADD_SLOT("__anext__", async->am_anext, -1);
501-
}
502-
503-
PyBufferProcs* buffers = cls->tp_as_buffer;
504-
if (buffers) {
505-
// TODO ...
506-
}
507-
508-
/* Link into each base class's list of subclasses */
509-
bases = cls->tp_bases;
510-
Py_ssize_t n = PyTuple_GET_SIZE(bases);
511-
Py_ssize_t i;
512-
for (i = 0; i < n; i++) {
513-
PyObject* base_class_object = PyTuple_GetItem(bases, i);
514-
PyTypeObject* b = (PyTypeObject*) base_class_object;
515-
if (PyType_Check(b) && add_subclass(b, cls) < 0) {
516-
cls->tp_flags &= ~Py_TPFLAGS_READYING;
517-
return -1;
518-
}
519-
}
520-
521-
// done
522-
cls->tp_flags = cls->tp_flags & ~Py_TPFLAGS_READYING;
523-
cls->tp_flags = cls->tp_flags | Py_TPFLAGS_READY;
524-
525-
return 0;
526-
527-
#undef ADD_IF_MISSING
528-
#undef ADD_METHOD
529-
#undef ADD_SLOT
530-
#undef ADD_METHOD_OR_SLOT
531-
}
532-
533-
534165
PyObject* PyObject_Str(PyObject* o) {
535166
return UPCALL_CEXT_O("PyObject_Str", native_to_java(o));
536167
}

0 commit comments

Comments
 (0)