Updated Branches: refs/heads/master bb466e09e -> 377630cf4
Rework bootstrapping of VTables Move all of the bootstrapping code to VTable.c. Simplify the bootstrapping process to use three passes without manual initialization of methods. Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/377630cf Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/377630cf Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/377630cf Branch: refs/heads/master Commit: 377630cf4de5aa484733b0bcf49bdaa7df33d72d Parents: bb466e0 Author: Nick Wellnhofer <[email protected]> Authored: Sun Dec 16 19:45:41 2012 +0100 Committer: Nick Wellnhofer <[email protected]> Committed: Sun Dec 16 19:51:19 2012 +0100 ---------------------------------------------------------------------- clownfish/compiler/src/CFCBindAliases.c | 9 +-- clownfish/compiler/src/CFCBindCore.c | 109 +++++----------------- clownfish/runtime/core/Clownfish/VTable.c | 104 ++++++++++++++------- clownfish/runtime/core/Clownfish/VTable.cfh | 10 +-- core/Clownfish/VTable.c | 104 ++++++++++++++------- core/Clownfish/VTable.cfh | 10 +-- 6 files changed, 168 insertions(+), 178 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/clownfish/compiler/src/CFCBindAliases.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCBindAliases.c b/clownfish/compiler/src/CFCBindAliases.c index 9a4fde6..d7f3813 100644 --- a/clownfish/compiler/src/CFCBindAliases.c +++ b/clownfish/compiler/src/CFCBindAliases.c @@ -86,9 +86,6 @@ struct alias aliases[] = { {"Cfish_Hash_Store_Str", "Lucy_Hash_Store_Str"}, {"Cfish_Hash_Store", "Lucy_Hash_Store"}, - {"cfish_Method", "lucy_Method"}, - {"CFISH_METHOD", "LUCY_METHOD"}, - {"cfish_VArray", "lucy_VArray"}, {"CFISH_VARRAY", "LUCY_VARRAY"}, {"cfish_VA_new", "lucy_VA_new"}, @@ -100,13 +97,9 @@ struct alias aliases[] = { {"cfish_VTable", "lucy_VTable"}, {"CFISH_VTABLE", "LUCY_VTABLE"}, - {"cfish_VTable_allocate", "lucy_VTable_allocate"}, - {"cfish_VTable_init", "lucy_VTable_init"}, - {"cfish_VTable_add_method", "lucy_VTable_add_method"}, - {"cfish_VTable_add_to_registry", "lucy_VTable_add_to_registry"}, + {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"}, {"cfish_VTable_add_alias_to_registry", "lucy_VTable_add_alias_to_registry"}, {"cfish_VTable_offset_of_parent", "lucy_VTable_offset_of_parent"}, - {"cfish_VTable_override", "lucy_VTable_override"}, {"cfish_VTable_singleton", "lucy_VTable_singleton"}, {"Cfish_VTable_Get_Name", "Lucy_VTable_Get_Name"}, {"Cfish_VTable_Make_Obj", "Lucy_VTable_Make_Obj"}, http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/clownfish/compiler/src/CFCBindCore.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCBindCore.c b/clownfish/compiler/src/CFCBindCore.c index 1309822..0cf7e30 100644 --- a/clownfish/compiler/src/CFCBindCore.c +++ b/clownfish/compiler/src/CFCBindCore.c @@ -206,10 +206,33 @@ S_write_parcel_h(CFCBindCore *self) { " (cfish_method(*((cfish_VTable**)_self), _full_meth ## _OFFSET )\\\n" " != (cfish_method_t)_full_func)\n" "\n" + "/* Structs for VTable initialization.\n" + " */\n" + "\n" + "typedef struct cfish_MethodSpec {\n" + " int is_novel;\n" + " const char *name;\n" + " cfish_method_t func;\n" + " cfish_method_t callback_func;\n" + " size_t *offset;\n" + "} cfish_MethodSpec;\n" + "\n" + "typedef struct cfish_VTableSpec {\n" + " cfish_VTable **vtable;\n" + " cfish_VTable **parent;\n" + " const char *name;\n" + " size_t obj_alloc_size;\n" + " size_t num_fresh;\n" + " size_t num_novel;\n" + " cfish_MethodSpec *method_specs;\n" + "} cfish_VTableSpec;\n" + "\n" "#ifdef CFISH_USE_SHORT_NAMES\n" " #define METHOD_PTR CFISH_METHOD_PTR\n" " #define SUPER_METHOD_PTR CFISH_SUPER_METHOD_PTR\n" " #define OVERRIDDEN CFISH_OVERRIDDEN\n" + " #define MethodSpec cfish_MethodSpec\n" + " #define VTableSpec cfish_VTableSpec\n" "#endif\n" "\n" "void\n" @@ -303,28 +326,6 @@ S_write_parcel_c(CFCBindCore *self) { vt_specs = CFCUtil_cat(vt_specs, "\n};\n", NULL); FREEMEM(ordered); - const char *vt_bootstrap = ""; - if (strcmp(prefix, "lucy_") == 0) { - vt_bootstrap = - " /* Bootstrap VTables.\n" - " */\n" - " cfish_VTable_override(CFISH_OBJ, (cfish_method_t)lucy_Obj_destroy, Lucy_Obj_Destroy_OFFSET);\n" - " cfish_VTable_override(CFISH_VTABLE, (cfish_method_t)lucy_VTable_make_obj, Lucy_VTable_Make_Obj_OFFSET);\n" - " CFISH_CHARBUF->vtable = CFISH_VTABLE;\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_Obj_dec_refcount, Lucy_Obj_Dec_RefCount_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_Obj_inc_refcount, Lucy_Obj_Inc_RefCount_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_CB_cat_trusted_str, Lucy_CB_Cat_Trusted_Str_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_CB_clone, Lucy_CB_Clone_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_CB_destroy, Lucy_CB_Destroy_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_CB_grow, Lucy_CB_Grow_OFFSET);\n" - " cfish_VTable_override(CFISH_CHARBUF, (cfish_method_t)lucy_CB_vcatf, Lucy_CB_VCatF_OFFSET);\n" - " CFISH_VARRAY->vtable = CFISH_VTABLE;\n" - " cfish_VTable_override(CFISH_VARRAY, (cfish_method_t)lucy_VA_grow, Lucy_VA_Grow_OFFSET);\n" - " cfish_VTable_override(CFISH_VARRAY, (cfish_method_t)lucy_VA_push, Lucy_VA_Push_OFFSET);\n" - " CFISH_METHOD->vtable = CFISH_VTABLE;\n" - "\n"; - } - char pattern[] = "%s\n" "\n" @@ -334,24 +335,6 @@ S_write_parcel_c(CFCBindCore *self) { "#include \"Clownfish/VTable.h\"\n" "%s\n" "\n" - "typedef struct cfish_MethodSpec {\n" - " int is_novel;\n" - " const char *name;\n" - " cfish_method_t func;\n" - " cfish_method_t callback_func;\n" - " size_t *offset;\n" - "} cfish_MethodSpec;\n" - "\n" - "typedef struct cfish_VTableSpec {\n" - " cfish_VTable **vtable;\n" - " cfish_VTable **parent;\n" - " const char *name;\n" - " size_t obj_alloc_size;\n" - " size_t num_fresh;\n" - " size_t num_novel;\n" - " cfish_MethodSpec *method_specs;\n" - "} cfish_VTableSpec;\n" - "\n" "%s\n" "\n" "/* VTableSpec structs for initialization.\n" @@ -360,47 +343,7 @@ S_write_parcel_c(CFCBindCore *self) { "\n" "void\n" "%sbootstrap_parcel() {\n" - " int num_vtable_specs = %d;\n" - "\n" - " /* Allocate memory for VTables.\n" - " */\n" - " for (int i = 0; i < num_vtable_specs; ++i) {\n" - " cfish_VTableSpec *spec = &vtable_specs[i];\n" - " cfish_VTable *parent = spec->parent ? *spec->parent : NULL;\n" - " *spec->vtable = cfish_VTable_allocate(parent, 0,\n" - " spec->obj_alloc_size,\n" - " spec->num_novel);\n" - " }\n" - "\n" - "%s" - " /* Initialize VTables.\n" - " */\n" - " for (int i = 0; i < num_vtable_specs; ++i) {\n" - " cfish_VTableSpec *spec = &vtable_specs[i];\n" - " cfish_CharBuf *cb = cfish_CB_newf(\"%%s\", spec->name);\n" - " cfish_VTable_init(*spec->vtable, cb);\n" - " CFISH_DECREF(cb);\n" - " for (int i = 0; i < spec->num_fresh; ++i) {\n" - " cfish_MethodSpec *mspec = &spec->method_specs[i];\n" - " if (mspec->is_novel) {\n" - " cb = cfish_CB_newf(\"%%s\", mspec->name);\n" - " cfish_VTable_add_method(*spec->vtable, cb,\n" - " mspec->callback_func,\n" - " *mspec->offset);\n" - " CFISH_DECREF(cb);\n" - " }\n" - " cfish_VTable_override(*spec->vtable, mspec->func,\n" - " *mspec->offset);\n" - " }\n" - " }\n" - "\n" - " /* Register VTables.\n" - " */\n" - " for (int i = 0; i < num_vtable_specs; ++i) {\n" - " cfish_VTableSpec *spec = &vtable_specs[i];\n" - " cfish_VTable_add_to_registry(*spec->vtable);\n" - " }\n" - "\n" + " cfish_VTable_bootstrap(vtable_specs, %d);\n" " %sinit_parcel();\n" "}\n" "\n" @@ -413,14 +356,12 @@ S_write_parcel_c(CFCBindCore *self) { + strlen(vt_specs) + strlen(prefix) + 10 // for num_specs - + strlen(vt_bootstrap) + strlen(prefix) + strlen(self->footer) + 100; char *file_content = (char*)MALLOCATE(size); sprintf(file_content, pattern, self->header, privacy_syms, includes, - c_data, vt_specs, prefix, num_specs, vt_bootstrap, prefix, - self->footer); + c_data, vt_specs, prefix, num_specs, prefix, self->footer); // Unlink then open file. const char *src_dest = CFCHierarchy_get_source_dest(hierarchy); http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/clownfish/runtime/core/Clownfish/VTable.c ---------------------------------------------------------------------- diff --git a/clownfish/runtime/core/Clownfish/VTable.c b/clownfish/runtime/core/Clownfish/VTable.c index 1946a96..0ff58e2 100644 --- a/clownfish/runtime/core/Clownfish/VTable.c +++ b/clownfish/runtime/core/Clownfish/VTable.c @@ -43,44 +43,80 @@ S_scrunch_charbuf(CharBuf *source, CharBuf *target); LockFreeRegistry *VTable_registry = NULL; -VTable* -VTable_allocate(VTable *parent, int flags, size_t obj_alloc_size, - size_t num_novel) { - size_t vt_alloc_size = parent - ? parent->vt_alloc_size - : offsetof(cfish_VTable, method_ptrs); - vt_alloc_size += num_novel * sizeof(cfish_method_t); - VTable *self = (VTable*)Memory_wrapped_calloc(vt_alloc_size, 1); - self->ref.count = 1; - self->parent = parent; - self->flags = flags; - self->obj_alloc_size = obj_alloc_size; - self->vt_alloc_size = vt_alloc_size; - - return self; -} +void +VTable_bootstrap(VTableSpec *specs, size_t num_specs) +{ + /* Pass 1: + * - Allocate memory. + * - Initialize refcount, parent, flags, obj_alloc_size, vt_alloc_size. + * - Initialize method pointers. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *parent = spec->parent ? *spec->parent : NULL; + + size_t vt_alloc_size = parent + ? parent->vt_alloc_size + : offsetof(VTable, method_ptrs); + vt_alloc_size += spec->num_novel * sizeof(cfish_method_t); + VTable *vtable = (VTable*)Memory_wrapped_calloc(vt_alloc_size, 1); + + vtable->ref.count = 1; + vtable->parent = parent; + vtable->flags = 0; + vtable->obj_alloc_size = spec->obj_alloc_size; + vtable->vt_alloc_size = vt_alloc_size; + + if (parent) { + size_t parent_ptrs_size = parent->vt_alloc_size + - offsetof(VTable, method_ptrs); + memcpy(vtable->method_ptrs, parent->method_ptrs, parent_ptrs_size); + } -VTable* -VTable_init(VTable *self, const CharBuf *name) { - self->vtable = CFISH_VTABLE; - self->name = CB_Clone(name); - self->methods = VA_new(0); - - VTable *parent = self->parent; - if (parent) { - size_t parent_ptrs_size = parent->vt_alloc_size - - offsetof(cfish_VTable, method_ptrs); - memcpy(self->method_ptrs, parent->method_ptrs, parent_ptrs_size); + for (int i = 0; i < spec->num_fresh; ++i) { + MethodSpec *mspec = &spec->method_specs[i]; + VTable_override(vtable, mspec->func, *mspec->offset); + } + + *spec->vtable = vtable; } - return self; -} + /* Pass 2: + * - Initialize 'vtable' instance variable. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *vtable = *spec->vtable; -void -VTable_add_method(VTable *self, const CharBuf *name, - lucy_method_t callback_func, size_t offset) { - Method *method = Method_new(name, callback_func, offset); - VA_Push(self->methods, (Obj*)method); + vtable->vtable = VTABLE; + } + + /* Now it's safe to call methods. + * + * Pass 3: + * - Inititalize name and method array. + * - Register vtable. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *vtable = *spec->vtable; + + vtable->name = CB_newf("%s", spec->name); + vtable->methods = VA_new(0); + + for (int i = 0; i < spec->num_fresh; ++i) { + MethodSpec *mspec = &spec->method_specs[i]; + if (mspec->is_novel) { + CharBuf *name = CB_newf("%s", mspec->name); + Method *method = Method_new(name, mspec->callback_func, + *mspec->offset); + VA_Push(vtable->methods, (Obj*)method); + DECREF(name); + } + } + + VTable_add_to_registry(vtable); + } } void http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/clownfish/runtime/core/Clownfish/VTable.cfh ---------------------------------------------------------------------- diff --git a/clownfish/runtime/core/Clownfish/VTable.cfh b/clownfish/runtime/core/Clownfish/VTable.cfh index fbd6bcf..ffcc07d 100644 --- a/clownfish/runtime/core/Clownfish/VTable.cfh +++ b/clownfish/runtime/core/Clownfish/VTable.cfh @@ -36,16 +36,8 @@ class Clownfish::VTable inherits Clownfish::Obj { inert LockFreeRegistry *registry; inert size_t offset_of_parent; - inert VTable* - allocate(VTable *parent, int flags, size_t obj_alloc_size, - size_t num_novel); - - inert VTable* - init(VTable *self, const CharBuf *name); - inert void - add_method(VTable *self, const CharBuf *name, lucy_method_t callback_func, - size_t offset); + bootstrap(cfish_VTableSpec *specs, size_t num_specs); /** Return a singleton. If a VTable can be found in the registry based on * the supplied class name, it will be returned. Otherwise, a new VTable http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/core/Clownfish/VTable.c ---------------------------------------------------------------------- diff --git a/core/Clownfish/VTable.c b/core/Clownfish/VTable.c index fc7afeb..e02bae2 100644 --- a/core/Clownfish/VTable.c +++ b/core/Clownfish/VTable.c @@ -43,44 +43,80 @@ S_scrunch_charbuf(CharBuf *source, CharBuf *target); LockFreeRegistry *VTable_registry = NULL; -VTable* -VTable_allocate(VTable *parent, int flags, size_t obj_alloc_size, - size_t num_novel) { - size_t vt_alloc_size = parent - ? parent->vt_alloc_size - : offsetof(cfish_VTable, method_ptrs); - vt_alloc_size += num_novel * sizeof(cfish_method_t); - VTable *self = (VTable*)Memory_wrapped_calloc(vt_alloc_size, 1); - self->ref.count = 1; - self->parent = parent; - self->flags = flags; - self->obj_alloc_size = obj_alloc_size; - self->vt_alloc_size = vt_alloc_size; - - return self; -} +void +VTable_bootstrap(VTableSpec *specs, size_t num_specs) +{ + /* Pass 1: + * - Allocate memory. + * - Initialize refcount, parent, flags, obj_alloc_size, vt_alloc_size. + * - Initialize method pointers. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *parent = spec->parent ? *spec->parent : NULL; + + size_t vt_alloc_size = parent + ? parent->vt_alloc_size + : offsetof(VTable, method_ptrs); + vt_alloc_size += spec->num_novel * sizeof(cfish_method_t); + VTable *vtable = (VTable*)Memory_wrapped_calloc(vt_alloc_size, 1); + + vtable->ref.count = 1; + vtable->parent = parent; + vtable->flags = 0; + vtable->obj_alloc_size = spec->obj_alloc_size; + vtable->vt_alloc_size = vt_alloc_size; + + if (parent) { + size_t parent_ptrs_size = parent->vt_alloc_size + - offsetof(VTable, method_ptrs); + memcpy(vtable->method_ptrs, parent->method_ptrs, parent_ptrs_size); + } -VTable* -VTable_init(VTable *self, const CharBuf *name) { - self->vtable = CFISH_VTABLE; - self->name = CB_Clone(name); - self->methods = VA_new(0); - - VTable *parent = self->parent; - if (parent) { - size_t parent_ptrs_size = parent->vt_alloc_size - - offsetof(cfish_VTable, method_ptrs); - memcpy(self->method_ptrs, parent->method_ptrs, parent_ptrs_size); + for (int i = 0; i < spec->num_fresh; ++i) { + MethodSpec *mspec = &spec->method_specs[i]; + VTable_override(vtable, mspec->func, *mspec->offset); + } + + *spec->vtable = vtable; } - return self; -} + /* Pass 2: + * - Initialize 'vtable' instance variable. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *vtable = *spec->vtable; -void -VTable_add_method(VTable *self, const CharBuf *name, - lucy_method_t callback_func, size_t offset) { - Method *method = Method_new(name, callback_func, offset); - VA_Push(self->methods, (Obj*)method); + vtable->vtable = VTABLE; + } + + /* Now it's safe to call methods. + * + * Pass 3: + * - Inititalize name and method array. + * - Register vtable. + */ + for (int i = 0; i < num_specs; ++i) { + VTableSpec *spec = &specs[i]; + VTable *vtable = *spec->vtable; + + vtable->name = CB_newf("%s", spec->name); + vtable->methods = VA_new(0); + + for (int i = 0; i < spec->num_fresh; ++i) { + MethodSpec *mspec = &spec->method_specs[i]; + if (mspec->is_novel) { + CharBuf *name = CB_newf("%s", mspec->name); + Method *method = Method_new(name, mspec->callback_func, + *mspec->offset); + VA_Push(vtable->methods, (Obj*)method); + DECREF(name); + } + } + + VTable_add_to_registry(vtable); + } } void http://git-wip-us.apache.org/repos/asf/lucy/blob/377630cf/core/Clownfish/VTable.cfh ---------------------------------------------------------------------- diff --git a/core/Clownfish/VTable.cfh b/core/Clownfish/VTable.cfh index d0a7e6c..0351082 100644 --- a/core/Clownfish/VTable.cfh +++ b/core/Clownfish/VTable.cfh @@ -36,16 +36,8 @@ class Clownfish::VTable inherits Clownfish::Obj { inert LockFreeRegistry *registry; inert size_t offset_of_parent; - inert VTable* - allocate(VTable *parent, int flags, size_t obj_alloc_size, - size_t num_novel); - - inert VTable* - init(VTable *self, const CharBuf *name); - inert void - add_method(VTable *self, const CharBuf *name, lucy_method_t callback_func, - size_t offset); + bootstrap(cfish_VTableSpec *specs, size_t num_specs); /** Return a singleton. If a VTable can be found in the registry based on * the supplied class name, it will be returned. Otherwise, a new VTable
