Author: nwellnhof
Date: Sat Jul 14 13:49:21 2012
New Revision: 1361546

URL: http://svn.apache.org/viewvc?rev=1361546&view=rev
Log:
LUCY-233 Autogenerate array with class initialization data

A new struct cfish_VTableSpec that holds initialization data for a class is
defined in parcel.c. Then an array of these structs for all classes is
autogenerated, so the bootstrapping code that allocates, inits and registers
the VTables can iterate over this array and be made static.

The MethodSpec arrays are flattened.

Some VTable initialization code is moved from VTable_init to VTable_allocate
to simplify bootstrapping.

Modified:
    lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs
    lucy/trunk/clownfish/src/CFCBindClass.c
    lucy/trunk/clownfish/src/CFCBindClass.h
    lucy/trunk/clownfish/src/CFCBindCore.c
    lucy/trunk/clownfish/src/CFCBindMethod.c
    lucy/trunk/clownfish/src/CFCMethod.c
    lucy/trunk/clownfish/src/CFCMethod.h
    lucy/trunk/core/Lucy/Object/VTable.c
    lucy/trunk/core/Lucy/Object/VTable.cfh

Modified: lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs (original)
+++ lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs Sat Jul 14 13:49:21 2012
@@ -934,7 +934,6 @@ _set_or_get(self, ...)
     CFCMethod *self;
 ALIAS:
     get_macro_sym     = 2
-    full_spec_sym     = 8
     full_override_sym = 10
     abstract          = 12
     novel             = 14
@@ -948,11 +947,6 @@ PPCODE:
                 retval = newSVpvn(macro_sym, strlen(macro_sym));
             }
             break;
-        case 8: {
-                const char *value = CFCMethod_full_spec_sym(self);
-                retval = newSVpvn(value, strlen(value));
-            }
-            break;
         case 10: {
                 const char *value = CFCMethod_full_override_sym(self);
                 retval = newSVpvn(value, strlen(value));

Modified: lucy/trunk/clownfish/src/CFCBindClass.c
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindClass.c?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindClass.c (original)
+++ lucy/trunk/clownfish/src/CFCBindClass.c Sat Jul 14 13:49:21 2012
@@ -281,19 +281,17 @@ CFCBindClass_to_c_data(CFCBindClass *sel
 
     char *offsets  = CFCUtil_strdup("");
     char *cb_funcs = CFCUtil_strdup("");
-    char *ms_defs  = CFCUtil_strdup("");
 
-    /* Start a NULL-terminated array of cfish_MethodSpec vars.  Since C89
-     * doesn't allow us to initialize a pointer to an anonymous array inside a
-     * global struct, we have to give it a real symbol and then store a pointer
-     * to that symbol inside the VTable struct. */
+    /* Start an array of cfish_MethodSpec structs.  Since C89 doesn't allow us
+     * to initialize a pointer to an anonymous array inside a global struct,
+     * we have to give it a real symbol and then store a pointer to that
+     * symbol inside the VTableSpec struct. */
     char *ms_var = CFCUtil_strdup("");
-    ms_var = CFCUtil_cat(ms_var, "static cfish_MethodSpec *",
-                         self->method_specs_var, "[] = {\n    ", NULL);
+    ms_var = CFCUtil_cat(ms_var, "static cfish_MethodSpec ",
+                         self->method_specs_var, "[] = {\n", NULL);
 
     for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
         CFCMethod *method = methods[meth_num];
-        int method_is_fresh = S_method_is_fresh(method, fresh_methods);
         size_t off_sym_size 
             = CFCMethod_full_offset_sym(method, client, NULL, 0);
         char *full_offset_sym = (char*)MALLOCATE(off_sym_size);
@@ -304,41 +302,42 @@ CFCBindClass_to_c_data(CFCBindClass *sel
 
         // Create offset in bytes for the method from the top of the VTable
         // object.
-        char *offset_str = CFCUtil_cat(CFCUtil_strdup(""),
-                                       "(offsetof(cfish_VTable, method_ptrs) + 
",
-                                       meth_num_str,
-                                       " * sizeof(cfish_method_t))", NULL);
         offsets = CFCUtil_cat(offsets, "size_t ", full_offset_sym, " = ",
-                              offset_str, ";\n", NULL);
+                              "offsetof(cfish_VTable, method_ptrs) + ",
+                              meth_num_str, " * sizeof(cfish_method_t);\n",
+                              NULL);
         FREEMEM(full_offset_sym);
+    }
+
+    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
+        CFCMethod *method = fresh_methods[meth_num];
 
         // Create a default implementation for abstract methods.
-        if (method_is_fresh && CFCMethod_abstract(method)) {
+        if (CFCMethod_abstract(method)) {
             char *method_def = CFCBindMeth_abstract_method_def(method);
             cb_funcs = CFCUtil_cat(cb_funcs, method_def, "\n", NULL);
             FREEMEM(method_def);
         }
 
-        // Define method metadata for initialization and callbacks.
-        if (method_is_fresh) {
-            if ((CFCMethod_public(method) || CFCMethod_abstract(method))
-                && CFCMethod_novel(method)) {
-                char *cb_def = CFCBindMeth_callback_def(method);
-                cb_funcs = CFCUtil_cat(cb_funcs, cb_def, "\n", NULL);
-                FREEMEM(cb_def);
-            }
-            char *ms_def = CFCBindMeth_spec_def(method);
-            ms_defs = CFCUtil_cat(ms_defs, ms_def, NULL);
-            FREEMEM(ms_def);
-            const char *full_md_sym = CFCMethod_full_spec_sym(method);
-            ms_var = CFCUtil_cat(ms_var, "&", full_md_sym, ",\n    ", NULL);
+        // Define callback.
+        if ((CFCMethod_public(method) || CFCMethod_abstract(method))
+            && CFCMethod_novel(method)) {
+            char *cb_def = CFCBindMeth_callback_def(method);
+            cb_funcs = CFCUtil_cat(cb_funcs, cb_def, "\n", NULL);
+            FREEMEM(cb_def);
         }
 
-        FREEMEM(offset_str);
+        // Define MethodSpec struct.
+        if (meth_num != 0) {
+            ms_var = CFCUtil_cat(ms_var, ",\n", NULL);
+        }
+        char *ms_def = CFCBindMeth_spec_def(method);
+        ms_var = CFCUtil_cat(ms_var, ms_def, NULL);
+        FREEMEM(ms_def);
     }
 
-    // Close method metadata variable definition.
-    ms_var =  CFCUtil_cat(ms_var, "NULL\n};\n", NULL);
+    // Close MethodSpec array definition.
+    ms_var =  CFCUtil_cat(ms_var, "\n};\n", NULL);
 
     const char pattern[] =
         "#include \"%s\"\n"
@@ -361,11 +360,6 @@ CFCBindClass_to_c_data(CFCBindClass *sel
         "\n"
         "%s\n"
         "\n"
-        "/* Assemble all the cfish_MethodSpec structs for this class.\n"
-        " */\n"
-        "\n"
-        "%s\n"
-        "\n"
         "/* Define this class's VTable.\n"
         " */\n"
         "\n"
@@ -380,19 +374,17 @@ CFCBindClass_to_c_data(CFCBindClass *sel
                   + strlen(include_h)
                   + strlen(offsets)
                   + strlen(cb_funcs)
-                  + strlen(ms_defs)
                   + strlen(ms_var)
                   + strlen(vt_var)
                   + strlen(autocode)
                   + 100;
     char *code = (char*)MALLOCATE(size);
-    sprintf(code, pattern, include_h, offsets, cb_funcs, ms_defs, ms_var,
-            vt_var, autocode);
+    sprintf(code, pattern, include_h, offsets, cb_funcs, ms_var, vt_var,
+            autocode);
 
     FREEMEM(fresh_methods);
     FREEMEM(offsets);
     FREEMEM(cb_funcs);
-    FREEMEM(ms_defs);
     FREEMEM(ms_var);
     return code;
 }
@@ -424,96 +416,62 @@ S_struct_definition(CFCBindClass *self) 
     return struct_def;
 }
 
-// Return C code allocating the class's VTable.
+// Return C definition of the class's VTableSpec.
 char*
-CFCBindClass_to_vtable_allocate(CFCBindClass *self) {
+CFCBindClass_spec_def(CFCBindClass *self) {
     CFCClass *client = self->client;
 
-    if (CFCClass_inert(client)) {
-        return CFCUtil_strdup("");
-    }
-
-    const char *vt_var      = CFCClass_full_vtable_var(client);
-    size_t      num_methods = CFCClass_num_methods(client);
-
-    char pattern[] =
-        "    %s = cfish_VTable_allocate(%d);\n";
-
-    size_t size = sizeof(pattern)
-                  + strlen(vt_var)
-                  + 20  // for num_methods
-                  + 20;
-    char *code = (char*)MALLOCATE(size);
-    sprintf(code, pattern, vt_var, num_methods);
-
-    return code;
-}
-
-// Return C code initializing the class's VTable.
-char*
-CFCBindClass_to_vtable_init(CFCBindClass *self) {
-    CFCClass *client = self->client;
-
-    if (CFCClass_inert(client)) {
-        return CFCUtil_strdup("");
-    }
-
     CFCClass    *parent     = CFCClass_get_parent(client);
     const char  *class_name = CFCClass_get_class_name(client);
     const char  *vt_var     = CFCClass_full_vtable_var(client);
     const char  *struct_sym = CFCClass_full_struct_sym(client);
 
     // Create a pointer to the parent class's vtable.
-    const char *parent_ref = parent
-                             ? CFCClass_full_vtable_var(parent)
-                             : "NULL"; // No parent, e.g. Obj or inert classes.
+    char *parent_ref;
+    if (parent) {
+        parent_ref = CFCUtil_cat(CFCUtil_strdup("&"),
+                                 CFCClass_full_vtable_var(parent), NULL);
+    }
+    else {
+        // No parent, e.g. Obj or inert classes.
+        parent_ref = CFCUtil_strdup("NULL");
+    }
+
+    int num_fresh = 0;
+    int num_novel = 0;
+    CFCMethod **fresh_methods = CFCClass_fresh_methods(client);
+    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
+        CFCMethod *method = fresh_methods[meth_num];
+        ++num_fresh;
+        if (CFCMethod_novel(method)) { ++num_novel; }
+    }
+    FREEMEM(fresh_methods);
 
     char pattern[] =
-        "    S_init_vtable(\n"
-        "        %s, /* vtable */\n"
+        "    {\n"
+        "        &%s, /* vtable */\n"
         "        %s, /* parent */\n"
         "        \"%s\", /* name */\n"
         "        sizeof(%s), /* obj_alloc_size */\n"
+        "        %d, /* num_fresh */\n"
+        "        %d, /* num_novel */\n"
         "        %s /* method_specs */\n"
-        "    );\n";
+        "    }";
 
     size_t size = sizeof(pattern)
                   + strlen(vt_var)
                   + strlen(parent_ref)
                   + strlen(class_name)
                   + strlen(struct_sym)
+                  + 10 // for num_fresh
+                  + 10 // for num_novel
                   + strlen(self->method_specs_var)
-                  + 40;
+                  + 100;
     char *code = (char*)MALLOCATE(size);
     sprintf(code, pattern, vt_var, parent_ref, class_name, struct_sym,
-            self->method_specs_var);
-
-    return code;
-}
-
-// Return C code registering the class's VTable.
-char*
-CFCBindClass_to_vtable_register(CFCBindClass *self) {
-    CFCClass    *client     = self->client;
-
-    if (CFCClass_inert(client)) {
-        return CFCUtil_strdup("");
-    }
-
-    const char  *vt_var     = CFCClass_full_vtable_var(client);
-
-    // Ignore return value from VTable_add_to_registry, since it's OK if
-    // multiple threads contend for adding these permanent VTables and some
-    // fail.
-    char pattern[] =
-        "    cfish_VTable_add_to_registry(%s);\n";
-
-    size_t size = sizeof(pattern)
-                  + strlen(vt_var)
-                  + 20;
-    char *code = (char*)MALLOCATE(size);
-    sprintf(code, pattern, vt_var);
+            num_fresh, num_novel, self->method_specs_var);
 
+    FREEMEM(parent_ref);
     return code;
 }
 

Modified: lucy/trunk/clownfish/src/CFCBindClass.h
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindClass.h?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindClass.h (original)
+++ lucy/trunk/clownfish/src/CFCBindClass.h Sat Jul 14 13:49:21 2012
@@ -54,20 +54,10 @@ CFCBindClass_to_c_header(CFCBindClass *s
 char*
 CFCBindClass_to_c_data(CFCBindClass *self);
 
-/** Return the autogenerated C code necessary to allocate the class's VTable.
+/** Return the autogenerated C definition of class's VTableSpec.
  */
 char*
-CFCBindClass_to_vtable_allocate(CFCBindClass *self);
-
-/** Return the autogenerated C code necessary to initialize the class's VTable.
- */
-char*
-CFCBindClass_to_vtable_init(CFCBindClass *self);
-
-/** Return the autogenerated C code necessary to register the class's VTable.
- */
-char*
-CFCBindClass_to_vtable_register(CFCBindClass *self);
+CFCBindClass_spec_def(CFCBindClass *self);
 
 #ifdef __cplusplus
 }

Modified: lucy/trunk/clownfish/src/CFCBindCore.c
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindCore.c?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindCore.c (original)
+++ lucy/trunk/clownfish/src/CFCBindCore.c Sat Jul 14 13:49:21 2012
@@ -258,12 +258,12 @@ S_write_parcel_c(CFCBindCore *self) {
 
     // Aggregate C code from all files.
     // Obtain parcel prefix for use in bootstrap function name.
-    char *privacy_syms  = CFCUtil_strdup("");
-    char *includes      = CFCUtil_strdup("");
-    char *c_data        = CFCUtil_strdup("");
-    char *vt_allocate   = CFCUtil_strdup("");
-    char *vt_initialize = CFCUtil_strdup("");
-    char *vt_register   = CFCUtil_strdup("");
+    char *privacy_syms = CFCUtil_strdup("");
+    char *includes     = CFCUtil_strdup("");
+    char *c_data       = CFCUtil_strdup("");
+    char *vt_specs = CFCUtil_strdup(
+        "static cfish_VTableSpec vtable_specs[] = {\n");
+    int num_specs = 0;
     CFCClass **ordered  = CFCHierarchy_ordered_classes(hierarchy);
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -273,15 +273,15 @@ S_write_parcel_c(CFCBindCore *self) {
         char *class_c_data = CFCBindClass_to_c_data(class_binding);
         c_data = CFCUtil_cat(c_data, class_c_data, "\n", NULL);
         FREEMEM(class_c_data);
-        char *vt_alloc = CFCBindClass_to_vtable_allocate(class_binding);
-        vt_allocate = CFCUtil_cat(vt_allocate, vt_alloc, NULL);
-        FREEMEM(vt_alloc);
-        char *vt_init = CFCBindClass_to_vtable_init(class_binding);
-        vt_initialize = CFCUtil_cat(vt_initialize, vt_init, NULL);
-        FREEMEM(vt_init);
-        char *vt_reg = CFCBindClass_to_vtable_register(class_binding);
-        vt_register = CFCUtil_cat(vt_register, vt_reg, NULL);
-        FREEMEM(vt_reg);
+        if (!CFCClass_inert(klass)) {
+            if (num_specs != 0) {
+                vt_specs = CFCUtil_cat(vt_specs, ",\n", NULL);
+            }
+            char *vt_spec = CFCBindClass_spec_def(class_binding);
+            vt_specs = CFCUtil_cat(vt_specs, vt_spec, NULL);
+            FREEMEM(vt_spec);
+            ++num_specs;
+        }
         CFCBase_decref((CFCBase*)class_binding);
         const char *privacy_sym = CFCClass_privacy_symbol(klass);
         privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
@@ -300,6 +300,7 @@ S_write_parcel_c(CFCBindCore *self) {
         CFCUtil_die("No source classes found.");
     }
     const char *prefix = CFCParcel_get_prefix(parcel);
+    vt_specs = CFCUtil_cat(vt_specs, "\n};\n", NULL);
     FREEMEM(ordered);
 
     const char *vt_bootstrap = "";
@@ -307,11 +308,9 @@ S_write_parcel_c(CFCBindCore *self) {
         vt_bootstrap =
             "    /* Bootstrap VTables.\n"
             "     */\n"
-            "    cfish_VTable_override(CFISH_VTABLE, 
(cfish_method_t)lucy_VTable_make_obj, Lucy_VTable_Make_Obj_OFFSET);\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_CHARBUF->parent = CFISH_OBJ;\n"
-            "    CFISH_CHARBUF->obj_alloc_size = sizeof(cfish_CharBuf);\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"
@@ -320,11 +319,9 @@ S_write_parcel_c(CFCBindCore *self) {
             "    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_VARRAY->obj_alloc_size = sizeof(cfish_VArray);\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"
-            "    CFISH_METHOD->obj_alloc_size = sizeof(cfish_Method);\n"
             "\n";
     }
 
@@ -345,42 +342,64 @@ S_write_parcel_c(CFCBindCore *self) {
         "    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"
-        "static void\n"
-        "S_init_vtable(cfish_VTable *vtable, cfish_VTable *parent,\n"
-        "              const char *name, size_t obj_alloc_size,\n"
-        "              cfish_MethodSpec **method_specs) {\n"
-        "    cfish_CharBuf *cb = cfish_CB_newf(\"%%s\", name);\n"
-        "    cfish_VTable_init(vtable, parent, cb, 0, obj_alloc_size);\n"
-        "    CFISH_DECREF(cb);\n"
-        "    for (int i = 0; method_specs[i]; ++i) {\n"
-        "        cfish_MethodSpec *spec = method_specs[i];\n"
-        "        if (spec->is_novel) {\n"
-        "            cb = cfish_CB_newf(\"%%s\", spec->name);\n"
-        "            cfish_VTable_add_method(vtable, cb,\n"
-        "                                    spec->callback_func,\n"
-        "                                    *spec->offset);\n"
-        "            CFISH_DECREF(cb);\n"
-        "        }\n"
-        "        cfish_VTable_override(vtable, spec->func, *spec->offset);\n"
-        "    }\n"
-        "}\n"
+        "/* VTableSpec structs for initialization.\n"
+        " */\n"
+        "%s\n"
         "\n"
         "void\n"
         "%sbootstrap_parcel() {\n"
+        "    int num_vtable_specs = %d;\n"
+        "\n"
         "    /* Allocate memory for VTables.\n"
         "     */\n"
-        "%s"
+        "    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"
-        "%s"
+        "    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"
-        "%s"
+        "    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"
         "    %sinit_parcel();\n"
         "}\n"
@@ -391,18 +410,17 @@ S_write_parcel_c(CFCBindCore *self) {
                   + strlen(privacy_syms)
                   + strlen(includes)
                   + strlen(c_data)
+                  + strlen(vt_specs)
                   + strlen(prefix)
-                  + strlen(vt_allocate)
+                  + 10 // for num_specs
                   + strlen(vt_bootstrap)
-                  + strlen(vt_initialize)
-                  + strlen(vt_register)
                   + strlen(prefix)
                   + strlen(self->footer)
                   + 100;
     char *file_content = (char*)MALLOCATE(size);
     sprintf(file_content, pattern, self->header, privacy_syms, includes,
-            c_data, prefix, vt_allocate, vt_bootstrap, vt_initialize,
-            vt_register, prefix, self->footer);
+            c_data, vt_specs, prefix, num_specs, vt_bootstrap, prefix,
+            self->footer);
 
     // Unlink then open file.
     const char *src_dest = CFCHierarchy_get_source_dest(hierarchy);
@@ -415,8 +433,6 @@ S_write_parcel_c(CFCBindCore *self) {
     FREEMEM(privacy_syms);
     FREEMEM(includes);
     FREEMEM(c_data);
-    FREEMEM(vt_allocate);
-    FREEMEM(vt_initialize);
-    FREEMEM(vt_register);
+    FREEMEM(vt_specs);
 }
 

Modified: lucy/trunk/clownfish/src/CFCBindMethod.c
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindMethod.c?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindMethod.c (original)
+++ lucy/trunk/clownfish/src/CFCBindMethod.c Sat Jul 14 13:49:21 2012
@@ -228,7 +228,6 @@ CFCBindMeth_typedef_dec(struct CFCMethod
 
 char*
 CFCBindMeth_spec_def(CFCMethod *method) {
-    const char *full_ms_sym = CFCMethod_full_spec_sym(method);
     const char *macro_sym   = CFCMethod_get_macro_sym(method);
     const char *impl_sym    = CFCMethod_implementing_func_sym(method);
     int         is_novel    = CFCMethod_novel(method);
@@ -243,15 +242,14 @@ CFCBindMeth_spec_def(CFCMethod *method) 
     CFCMethod_full_offset_sym(method, NULL, full_offset_sym, offset_sym_size);
 
     char pattern[] =
-        "static cfish_MethodSpec %s = {\n"
-        "    %d, /* is_novel */\n"
-        "    \"%s\", /* name */\n"
-        "    (cfish_method_t)%s, /* func */\n"
-        "    (cfish_method_t)%s, /* callback_func */\n"
-        "    &%s /* offset */\n"
-        "};\n";
+        "    {\n"
+        "        %d, /* is_novel */\n"
+        "        \"%s\", /* name */\n"
+        "        (cfish_method_t)%s, /* func */\n"
+        "        (cfish_method_t)%s, /* callback_func */\n"
+        "        &%s /* offset */\n"
+        "    }";
     size_t size = sizeof(pattern)
-                  + strlen(full_ms_sym)
                   + 10 /* for is_novel */
                   + strlen(macro_sym)
                   + strlen(impl_sym)
@@ -259,8 +257,8 @@ CFCBindMeth_spec_def(CFCMethod *method) 
                   + strlen(full_offset_sym)
                   + 30;
     char *def = (char*)MALLOCATE(size);
-    sprintf(def, pattern, full_ms_sym, is_novel, macro_sym, impl_sym,
-            full_override_sym, full_offset_sym);
+    sprintf(def, pattern, is_novel, macro_sym, impl_sym, full_override_sym,
+            full_offset_sym);
 
     FREEMEM(full_offset_sym);
     return def;

Modified: lucy/trunk/clownfish/src/CFCMethod.c
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCMethod.c?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCMethod.c (original)
+++ lucy/trunk/clownfish/src/CFCMethod.c Sat Jul 14 13:49:21 2012
@@ -37,7 +37,6 @@
 struct CFCMethod {
     CFCFunction function;
     char *macro_sym;
-    char *full_spec_sym;
     char *full_override_sym;
     int is_final;
     int is_abstract;
@@ -130,9 +129,7 @@ CFCMethod_init(CFCMethod *self, CFCParce
     // Derive more symbols.
     const char *full_func_sym = CFCMethod_implementing_func_sym(self);
     size_t amount = strlen(full_func_sym) + sizeof("_OVERRIDE") + 1;
-    self->full_spec_sym     = (char*)MALLOCATE(amount);
     self->full_override_sym = (char*)MALLOCATE(amount);
-    sprintf(self->full_spec_sym, "%s_SPEC", full_func_sym);
     sprintf(self->full_override_sym, "%s_OVERRIDE", full_func_sym);
 
     // Assume that this method is novel until we discover when applying
@@ -145,7 +142,6 @@ CFCMethod_init(CFCMethod *self, CFCParce
 void
 CFCMethod_destroy(CFCMethod *self) {
     FREEMEM(self->macro_sym);
-    FREEMEM(self->full_spec_sym);
     FREEMEM(self->full_override_sym);
     CFCFunction_destroy((CFCFunction*)self);
 }
@@ -319,11 +315,6 @@ CFCMethod_full_typedef(CFCMethod *self, 
 }
 
 const char*
-CFCMethod_full_spec_sym(CFCMethod *self) {
-    return self->full_spec_sym;
-}
-
-const char*
 CFCMethod_full_override_sym(CFCMethod *self) {
     return self->full_override_sym;
 }

Modified: lucy/trunk/clownfish/src/CFCMethod.h
URL: 
http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCMethod.h?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCMethod.h (original)
+++ lucy/trunk/clownfish/src/CFCMethod.h Sat Jul 14 13:49:21 2012
@@ -165,12 +165,6 @@ size_t
 CFCMethod_full_typedef(CFCMethod *self, struct CFCClass *invoker, char *buf,
                        size_t buf_size);
 
-/** Returns the fully qualified name of the variable which stores the method's
- * initialization data.
- */
-const char*
-CFCMethod_full_spec_sym(CFCMethod *self);
-
 /** Returns the fully qualified name of the function which implements the
  * callback to the host in the event that a host method has been defined which
  * overrides this method, e.g. "crust_LobClaw_pinch_OVERRIDE".

Modified: lucy/trunk/core/Lucy/Object/VTable.c
URL: 
http://svn.apache.org/viewvc/lucy/trunk/core/Lucy/Object/VTable.c?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/core/Lucy/Object/VTable.c (original)
+++ lucy/trunk/core/Lucy/Object/VTable.c Sat Jul 14 13:49:21 2012
@@ -44,30 +44,36 @@ S_scrunch_charbuf(CharBuf *source, CharB
 LockFreeRegistry *VTable_registry = NULL;
 
 VTable*
-VTable_allocate(size_t num_methods) {
-    size_t vt_alloc_size = offsetof(cfish_VTable, method_ptrs)
-                           + num_methods * sizeof(cfish_method_t);
+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->vt_alloc_size = vt_alloc_size;
-    return self;
-}
-
-VTable*
-VTable_init(VTable *self, VTable *parent, const CharBuf *name, int flags,
-            size_t obj_alloc_size) {
-    self->vtable         = CFISH_VTABLE;
     self->ref.count      = 1;
     self->parent         = parent;
-    self->name           = CB_Clone(name);
     self->flags          = flags;
     self->obj_alloc_size = obj_alloc_size;
-    self->methods        = VA_new(0);
+    self->vt_alloc_size  = vt_alloc_size;
 
+    return self;
+}
+
+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);
     }
+
+    return self;
 }
 
 void

Modified: lucy/trunk/core/Lucy/Object/VTable.cfh
URL: 
http://svn.apache.org/viewvc/lucy/trunk/core/Lucy/Object/VTable.cfh?rev=1361546&r1=1361545&r2=1361546&view=diff
==============================================================================
--- lucy/trunk/core/Lucy/Object/VTable.cfh (original)
+++ lucy/trunk/core/Lucy/Object/VTable.cfh Sat Jul 14 13:49:21 2012
@@ -37,11 +37,11 @@ class Lucy::Object::VTable inherits Lucy
     inert size_t offset_of_parent;
 
     inert VTable*
-    allocate(size_t num_methods);
+    allocate(VTable *parent, int flags, size_t obj_alloc_size,
+             size_t num_novel);
 
     inert VTable*
-    init(VTable *self, VTable *parent, const CharBuf *name, int flags,
-         size_t obj_alloc_size);
+    init(VTable *self, const CharBuf *name);
 
     inert void
     add_method(VTable *self, const CharBuf *name, lucy_method_t callback_func,


Reply via email to