Rework Class bootstrapping process Adjust Class_bootstrap to the upcoming change that makes Init_Obj zero the object struct. Call Init_Obj before setting ivars. Allocate Class structs and initialize global class pointers in pass 1. Be extra careful about `obj_alloc_size` for Classes.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/12c46534 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/12c46534 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/12c46534 Branch: refs/heads/master Commit: 12c4653443b5fa445ac0663cf94bf5060c7a6c94 Parents: 50fed28 Author: Nick Wellnhofer <[email protected]> Authored: Tue May 12 00:24:36 2015 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Tue May 12 18:34:59 2015 +0200 ---------------------------------------------------------------------- runtime/core/Clownfish/Class.c | 72 ++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/12c46534/runtime/core/Clownfish/Class.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c index 6752135..e0a3ab5 100644 --- a/runtime/core/Clownfish/Class.c +++ b/runtime/core/Clownfish/Class.c @@ -58,14 +58,47 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs) int32_t parcel_id = S_claim_parcel_id(); /* Pass 1: - * - Initialize IVARS_OFFSET. * - Allocate memory. + * - Initialize global Class pointers. + */ + for (size_t i = 0; i < num_specs; ++i) { + const ClassSpec *spec = &specs[i]; + Class *parent = spec->parent ? *spec->parent : NULL; + + size_t novel_offset = parent + ? parent->class_alloc_size + : offsetof(Class, vtable); + size_t class_alloc_size = novel_offset + + spec->num_novel_meths + * sizeof(cfish_method_t); + + Class *klass = (Class*)Memory_wrapped_calloc(class_alloc_size, 1); + + // Needed to calculate size of subclasses. + klass->class_alloc_size = class_alloc_size; + + if (spec->klass == &CLASS) { + // `obj_alloc_size` is used by Init_Obj to zero the object. In the + // next pass, this method is called to initialize the Class + // objects. The Class struct is zeroed already, so this isn't + // crucial, but let's set the correct value here. + klass->obj_alloc_size = offsetof(Class, vtable); + } + + // Initialize the global pointer to the Class. + *spec->klass = klass; + } + + /* Pass 2: + * - Initialize IVARS_OFFSET. + * - Initialize 'klass' ivar and refcount by calling Init_Obj. * - Initialize parent, flags, obj_alloc_size, class_alloc_size. * - Assign parcel_id. - * - Initialize method pointers. + * - Initialize method pointers and offsets. */ for (size_t i = 0; i < num_specs; ++i) { const ClassSpec *spec = &specs[i]; + Class *klass = *spec->klass; Class *parent = spec->parent ? *spec->parent : NULL; size_t ivars_offset = 0; @@ -83,24 +116,34 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs) } } + // Init_Obj clears all klass ivars, so `class_alloc_size` must be + // recalculated. + Class_Init_Obj_IMP(CLASS, klass); + size_t novel_offset = parent ? parent->class_alloc_size : offsetof(Class, vtable); size_t class_alloc_size = novel_offset + spec->num_novel_meths * sizeof(cfish_method_t); - Class *klass = (Class*)Memory_wrapped_calloc(class_alloc_size, 1); klass->parent = parent; klass->parcel_id = parcel_id; - klass->obj_alloc_size = ivars_offset + spec->ivars_size; klass->class_alloc_size = class_alloc_size; + if (klass == CLASS) { + // Don't account for vtable array. + klass->obj_alloc_size = offsetof(Class, vtable); + } + else { + klass->obj_alloc_size = ivars_offset + spec->ivars_size; + } + klass->flags = 0; - if (spec->klass == &CLASS - || spec->klass == &METHOD - || spec->klass == &BOOLNUM - || spec->klass == &STRING + if (klass == CLASS + || klass == METHOD + || klass == BOOLNUM + || klass == STRING ) { klass->flags |= CFISH_fREFCOUNTSPECIAL; } @@ -129,19 +172,6 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs) novel_offset += sizeof(cfish_method_t); Class_Override_IMP(klass, mspec->func, *mspec->offset); } - - *spec->klass = klass; - } - - /* Pass 2: - * - Initialize 'klass' instance variable. - * - Initialize refcount. - */ - for (size_t i = 0; i < num_specs; ++i) { - const ClassSpec *spec = &specs[i]; - Class *klass = *spec->klass; - - Class_Init_Obj_IMP(CLASS, klass); } /* Now it's safe to call methods.
