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

Reply via email to