Tell Python about obj alloc sizes. As a consequence of Clownfish using Python object allocation internally under the Python bindings, bootstrapping Clownfish Classes and Python type objects requires some intricate interplay.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/c6c74d27 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/c6c74d27 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/c6c74d27 Branch: refs/heads/py_exp13 Commit: c6c74d2718fdac87eb9c2330f75eca93dbaa94da Parents: 3e9cd9e Author: Marvin Humphrey <[email protected]> Authored: Mon Feb 1 16:43:49 2016 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Wed Feb 24 15:20:38 2016 -0800 ---------------------------------------------------------------------- compiler/src/CFCPython.c | 1 + runtime/core/Clownfish/Class.c | 4 ++++ runtime/core/Clownfish/Class.cfh | 8 ++++++++ runtime/python/cfext/CFBind.c | 33 +++++++++++++++++++++++++++++++++ runtime/python/cfext/CFBind.h | 3 +++ 5 files changed, 49 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/compiler/src/CFCPython.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c index 15f835f..7921fbe 100644 --- a/compiler/src/CFCPython.c +++ b/compiler/src/CFCPython.c @@ -491,6 +491,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) { "\n" "PyMODINIT_FUNC\n" "PyInit__%s(void) {\n" + " cfish_Class_bootstrap_hook1 = CFBind_class_bootstrap_hook1;\n" " S_link_py_types();\n" " PyObject *module = PyModule_Create(&module_def);\n" " return module;\n" http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c index ba83928..68258c6 100644 --- a/runtime/core/Clownfish/Class.c +++ b/runtime/core/Clownfish/Class.c @@ -54,6 +54,7 @@ static int32_t S_claim_parcel_id(void); static LockFreeRegistry *Class_registry; +cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1; void Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs, @@ -146,6 +147,9 @@ Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs, else { klass->obj_alloc_size = ivars_offset + spec->ivars_size; } + if (cfish_Class_bootstrap_hook1 != NULL) { + cfish_Class_bootstrap_hook1(klass); + } klass->flags = 0; if (klass == CLASS http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh index c87964f..a5c83ab 100644 --- a/runtime/core/Clownfish/Class.cfh +++ b/runtime/core/Clownfish/Class.cfh @@ -149,5 +149,13 @@ __C__ #define CFISH_ALLOCA_OBJ(class) \ cfish_alloca(CFISH_Class_Get_Obj_Alloc_Size(class)) +/** Bootstrapping hook/hack needed by the Python bindings. + * + * TODO: Refactor this away in favor of a more general solution. + */ +typedef void +(*cfish_Class_bootstrap_hook1_t)(cfish_Class *self); +extern cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1; + __END_C__ http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.c ---------------------------------------------------------------------- diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c index 99ad069..2471487 100644 --- a/runtime/python/cfext/CFBind.c +++ b/runtime/python/cfext/CFBind.c @@ -857,6 +857,39 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) { /**** Class ****************************************************************/ +/* Tell Python about the size of Clownfish objects, by copying + * `cfclass->obj_alloc_size` into `pytype->tp_basicsize`. + * **THIS MUST BE RUN BEFORE Class_Make_Obj IS CALLED** because under the + * Python bindings, Clownfish uses Python object allocation internally. + * Furthermore, `tp_basicsize` is supposed to be set before `PyType_Ready()` + * is called. + * + * Ideally we would set `tp_basicsize` from within `Class_register_with_host`, + * but it doesn't get called until too late. + */ +void +CFBind_class_bootstrap_hook1(cfish_Class *self) { + PyTypeObject *py_type = S_get_cached_py_type(self); + if (PyType_HasFeature(py_type, Py_TPFLAGS_READY)) { + if (py_type->tp_basicsize != (Py_ssize_t)self->obj_alloc_size) { + fprintf(stderr, "PyType for %s readied with wrong alloc size\n", + py_type->tp_name), + exit(1); + } + } + else { + if (self->parent) { + py_type->tp_base = S_get_cached_py_type(self->parent); + } + py_type->tp_basicsize = self->obj_alloc_size; + if (PyType_Ready(py_type) < 0) { + fprintf(stderr, "PyType_Ready failed for %s\n", + py_type->tp_name), + exit(1); + } + } +} + /* Check the Class object for its associated PyTypeObject, which is stored in * `klass->host_type`. If it is not there yet, search the class mapping and * cache it in the object. Return the PyTypeObject. http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.h ---------------------------------------------------------------------- diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h index 0064985..9c8d53f 100644 --- a/runtime/python/cfext/CFBind.h +++ b/runtime/python/cfext/CFBind.h @@ -219,6 +219,9 @@ CFBind_maybe_convert_float(PyObject *input, float *ptr); int CFBind_maybe_convert_double(PyObject *input, double *ptr); +void +CFBind_class_bootstrap_hook1(struct cfish_Class *self); + #ifdef __cplusplus } #endif
