[svn:parrot] r38477 - trunk/src/pmc

chromatic at svn.parrot.org chromatic at svn.parrot.org
Tue May 5 03:15:09 UTC 2009


Author: chromatic
Date: Tue May  5 03:15:02 2009
New Revision: 38477
URL: https://trac.parrot.org/parrot/changeset/38477

Log:
[PMC] Revised MRO generation so that the (relatively expensive C3) MRO
resolution only occurs when absolutely necessary -- that is, when it differs
substantially from any parent's MRO.  A class with no parents needs no MRO
calculation.  A class with one parent can borrow its parent's MRO calculation.

Modified:
   trunk/src/pmc/class.pmc

Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc	Tue May  5 02:20:48 2009	(r38476)
+++ trunk/src/pmc/class.pmc	Tue May  5 03:15:02 2009	(r38477)
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2001-2008, Parrot Foundation.
+Copyright (C) 2001-2009, Parrot Foundation.
 $Id$
 
 =head1 NAME
@@ -404,6 +404,30 @@
     return _class->name;
 }
 
+/* calculates the C3 method resolution order for this class --
+ * working hard *not* to recalculate MRO when unnecessary */
+static PMC *
+calculate_mro(PARROT_INTERP, PMC *SELF, INTVAL num_parents)
+{
+    Parrot_Class_attributes  * const _class = PARROT_CLASS(SELF);
+
+    /* SELF is already on the all_parents */
+    if (num_parents == 0)
+        return _class->all_parents;
+
+    if (num_parents == 1) {
+            const STRING *ap         = CONST_STRING(interp, "all_parents");
+            PMC          *parent     = VTABLE_get_pmc_keyed_int(interp,
+                                            _class->parents, 0);
+            PMC          *parent_mro = VTABLE_inspect_str(interp, parent, ap);
+            PMC          *mro        = VTABLE_clone(interp, parent_mro);
+            VTABLE_unshift_pmc(interp, mro, SELF);
+            return mro;
+    }
+
+    return Parrot_ComputeMRO_C3(interp, SELF);
+}
+
 /*
 
 =back
@@ -812,7 +836,7 @@
 
         /* Add to the lists of our immediate parents and all parents. */
         VTABLE_push_pmc(interp, _class->parents, parent);
-        _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF);
+        _class->all_parents = calculate_mro(interp, SELF, parent_count + 1);
 
         /* Anonymous classes have no entry in the vtable array */
         if (!CLASS_is_anon_TEST(SELF))
@@ -871,9 +895,9 @@
             VTABLE_set_pmc_keyed_int(interp, _class->parents,
                 index, current_parent);
         }
-        VTABLE_pop_pmc(interp, _class->parents);
 
-        _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF);
+        VTABLE_pop_pmc(interp, _class->parents);
+        _class->all_parents = calculate_mro(interp, SELF, parent_count - 1);
 
         /* Anonymous classes have no entry in the vtable array */
         if (!CLASS_is_anon_TEST(SELF))
@@ -988,19 +1012,23 @@
                 "Unknown introspection value '%S'", what);
 
         /* return found value */
-        if (PMC_IS_NULL(found)) { return PMCNULL; }
+        if (PMC_IS_NULL(found))
+            return PMCNULL;
+
         if (found->vtable->base_type == enum_class_Hash) {
             /* for Hash return values, create and return a shallow
              * clone because the VTABLE_clone does a deep clone */
-            PMC * const hash = pmc_new(interp, enum_class_Hash);
-            PMC * const iter = VTABLE_get_iter(interp, found);
+            PMC * const hash  = pmc_new(interp, enum_class_Hash);
+            PMC * const iter  = VTABLE_get_iter(interp, found);
             while (VTABLE_get_bool(interp, iter)) {
-                STRING * key = VTABLE_shift_string(interp, iter);
-                PMC * value  = VTABLE_get_pmc_keyed_str(interp, found, key);
+                STRING *key   = VTABLE_shift_string(interp, iter);
+                PMC    *value = VTABLE_get_pmc_keyed_str(interp, found, key);
                 VTABLE_set_pmc_keyed_str(interp, hash, key, value);
             }
+
             return hash;
         }
+
         return VTABLE_clone(interp, found);
     }
 
@@ -1125,7 +1153,7 @@
 */
 
     VTABLE PMC *instantiate(PMC *init) {
-        Parrot_Class_attributes  * const _class    = PARROT_CLASS(SELF);
+        Parrot_Class_attributes  * const _class = PARROT_CLASS(SELF);
 
         Parrot_Object_attributes *obj_guts;
         PMC                      *object;
@@ -1133,10 +1161,12 @@
         /* If we've not been instantiated before... */
         if (!_class->instantiated) {
             /* Check that we have all methods listed in resolve list. */
-            const int resolve_count = VTABLE_elements(interp, _class->resolve_method);
-            const INTVAL cur_hll    = CONTEXT(interp)->current_HLL;
-            INTVAL    mro_length;
-            int       i;
+            const int resolve_count  = VTABLE_elements(interp,
+                                                       _class->resolve_method);
+            const INTVAL cur_hll     = CONTEXT(interp)->current_HLL;
+            const INTVAL num_parents = VTABLE_elements(interp, _class->parents);
+            INTVAL       mro_length;
+            int          i;
 
             /* don't use HLL mappings for internal-only data */
             CONTEXT(interp)->current_HLL = 0;
@@ -1152,7 +1182,7 @@
 
             /* Build full parents list.
              * RT #46101 Need pluggable MRO, for now always do C3. */
-            _class->all_parents = Parrot_ComputeMRO_C3(interp, SELF);
+             _class->all_parents = calculate_mro(interp, SELF, num_parents);
 
             if (!CLASS_is_anon_TEST(SELF))
                 interp->vtables[VTABLE_type(interp, SELF)]->mro = _class->all_parents;


More information about the parrot-commits mailing list