We can speed up PGE by 40%, if not more, by removing the great hate that is 
Parrot_get_vtable_index(), which performs a binary search of all of the 
vtable names with a strcmp for each one.  This function gets called every 
time something wonders "Hey, am I about to call a vtable entry?"

That happens a lot.

Instead, I prefer to store the vtable entries in the appropriate namespace 
*when they get added to the namespace*.  Okay, we already do that... but we 
first resolve the name to the entry index number, then store the Sub PMC in 
the cache indexed off of the number.

That's all well and good, but it means that whenever we want to look up an 
entry, we take the name (yes, we look them up pretty much all the time by 
name, why are you looking at me funny), perform the binary search with all of 
the strcmps, find the index, then look in the cache.

I managed to get this to work in a really ugly way that I don't want to talk 
about in order to prove that the speed gain really was about 40%.  Here's a 
cleaner patch that respects actual encapsulation.

Unfortunately, I don't have the hang of calling methods (real methods, not 
vtable entries) on PMCs from C yet, so it's fast... on the way to segfault 
town, riding the SIGBUS.  Jonathan?

-- c

=== src/objects.c
==================================================================
--- src/objects.c	(revision 4835)
+++ src/objects.c	(local)
@@ -204,12 +204,6 @@
     PMC   *ns, *mro;
     PMC   *_class       = pmc;
 
-    /* Get index in Parrot_vtable_slot_names[]. */
-    const INTVAL vtable_index = Parrot_get_vtable_index(interp, meth);
-
-    if (vtable_index == -1)
-        return PMCNULL;
-
     /* Get class. */
     if (PObj_is_object_TEST(pmc))
         _class = GET_CLASS(PMC_data_typed(pmc, Buffer), pmc);
@@ -224,7 +218,8 @@
         ns     = VTABLE_pmc_namespace(interp, _class);
 
         if (!PMC_IS_NULL(ns)) {
-            PMC * const res = find_vtable_meth_ns(interp, ns, vtable_index);
+            PMC * const res = Parrot_call_method(interp, PMCNULL, ns,
+                string_from_literal(interp, "get_vtable_entry"), "P->S", meth);
 
             if (!PMC_IS_NULL(res))
                 return res;
=== src/pmc/namespace.pmc
==================================================================
--- src/pmc/namespace.pmc	(revision 4847)
+++ src/pmc/namespace.pmc	(local)
@@ -54,7 +54,7 @@
 typedef struct Parrot_NSInfo {
     STRING *name;     /* Name of this namespace part. */
     PMC    *_class;   /* The class or role attached to this namespace. */
-    PMC    *vtable;   /* A Hash of vtable subs, keyed on the vtable index */
+    PMC    *vtable;   /* A Hash of vtable subs, keyed on the vtable name */
 } Parrot_NSInfo;
 
 /* Macro for easy access to the namespace info. */
@@ -229,25 +229,22 @@
             Parrot_NSInfo *nsinfo    = PARROT_NSINFO(SELF);
             PMC           *vtable    = nsinfo->vtable;
             Parrot_sub    *sub       = PMC_sub(value);
+            STRING        *meth_name = key;
 
             if (PMC_IS_NULL(vtable))
                 nsinfo->vtable = vtable = pmc_new(interp, enum_class_Hash);
 
-            if (sub->vtable_index == -1) {
-                STRING *meth_name = key;
+             if (string_str_index(interp, key,
+                CONST_STRING(interp, "__"), 0) == 0)
+                meth_name = string_substr(interp, key, 2,
+                    string_length(interp, key) - 2, NULL, 0);
 
-                if (string_str_index(interp, key,
-                    CONST_STRING(interp, "__"), 0 == 0)) {
-                    meth_name = string_substr(interp, key, 2,
-                        string_length(interp, key) - 2, NULL, 0);
-                }
+             if (sub->vtable_index == -1)
+                sub->vtable_index = Parrot_get_vtable_index(interp, meth_name);
 
-                sub->vtable_index = Parrot_get_vtable_index(interp, meth_name);
+             if (sub->vtable_index != -1) 
+                VTABLE_set_pmc_keyed_str(INTERP, vtable, key, meth_name);
             }
-
-            if (sub->vtable_index != -1)
-                VTABLE_set_pmc_keyed_int(INTERP, vtable,
-                    sub->vtable_index, value);
         }
     }
 
@@ -318,6 +315,7 @@
         Parrot_NSInfo *nsinfo = PARROT_NSINFO(SELF);
         PMC           *vtable = nsinfo->vtable;
 
+        assert(0);
         if (PMC_IS_NULL(vtable))
             return PMCNULL;
 
@@ -415,6 +413,8 @@
 Stores the given namespace under this namespace, with the given name.  Throws
 an invalid type exception if C<namespace> is not a NameSpace PMC or subclass.
 
+=cut
+
 */
 
     METHOD void add_namespace(STRING *name, PMC *_namespace) {
@@ -437,6 +437,8 @@
 Stores the given sub under this namespace, with the given name.  Throws an
 invalid type exception if C<sub> is not a Sub PMC or subclass.
 
+=cut
+
 */
 
     METHOD void add_sub(STRING *name, PMC *sub) {
@@ -449,14 +451,24 @@
         return;
     }
 
-/*
+    PCCMETHOD void get_vtable_entry(STRING *name) {
+        PMC *entries = PARROT_NSINFO(SELF)->vtable;
+        PMC *entry   = PMCNULL;
 
+        if (!PMC_IS_NULL(entries))
+            entry   = VTABLE_get_pmc_keyed_str(INTERP, entries, name);
+
+        PCCRETURN(PMC *entry);
+    }
+
 /*
 
 =item C<METHOD void PMC* add_var(STRING *name, PMC *var)>
 
 Stores the given sub under this namespace, with the given name.
 
+=cut
+
 */
 
     METHOD void add_var(STRING *name, PMC *var) {

Reply via email to