Hi,

Currently, whenever we instantiate an object (e.g. from a Class PMC), we get an Object PMC. This process also allocates a ResizablePMCArray to hold the attributes. The first of the attached patches - which passes all but one test file in Parrot - switches us to malloc'ing a C array to store the attributes. The second needs to be applied to Rakudo to get it to build with these changes (it has a dynop that plays with the object guts).

There's one test failure in Parrot and some various ones in Rakudo (we get through all of the sanity tests though), but I'm only really inclined to spend time debugging these if there's a sense that this patch is worthwhile and actually an improvement. I'm not really set up to benchmark stuff so well and lack experience in this, so I'm posting the patch here in hope that:

1) Someone will benchmark it and see if it actually helps and is worthwhile spending more time on

2) Somebody might be able to spot, how I screwed up freeze/thaw.

3) I might get some other bits of review on it.

Thanks,

Jonathan
Index: src/pmc/class.pmc
===================================================================
--- src/pmc/class.pmc   (revision 39081)
+++ src/pmc/class.pmc   (working copy)
@@ -150,6 +150,7 @@
     /* Store built attribute index and invalidate cache. */
     _class->attrib_index = attrib_index;
     _class->attrib_cache = cache;
+    _class->num_attrs    = cur_index;
 }
 
 /* Takes a hash and initializes the class based on it. */
@@ -458,6 +459,7 @@
     ATTR PMC *resolve_method;   /* List of method names the class provides to 
resolve
                                  * conflicts with methods from roles. */
     ATTR PMC *parent_overrides;
+    ATTR INTVAL num_attrs;      /* The number of attributes this class has. */
 
 /*
 
@@ -1169,6 +1171,7 @@
 
         Parrot_Object_attributes *obj_guts;
         PMC                      *object;
+        int                      i;
 
         /* If we've not been instantiated before... */
         if (!_class->instantiated) {
@@ -1178,7 +1181,6 @@
             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;
@@ -1239,7 +1241,9 @@
         obj_guts               = 
mem_allocate_zeroed_typed(Parrot_Object_attributes);
         obj_guts->_class       = SELF;
         PMC_data(object)       = obj_guts;
-        obj_guts->attrib_store = pmc_new(interp, enum_class_ResizablePMCArray);
+        obj_guts->attrib_store = mem_allocate_n_typed(_class->num_attrs, PMC 
*);
+        for (i = 0; i < _class->num_attrs; i++)
+            obj_guts->attrib_store[i] = PMCNULL;
 
         if (!PMC_IS_NULL(init)) {
             /* Initialize attributes with the supplied values. */
Index: src/pmc/object.pmc
===================================================================
--- src/pmc/object.pmc  (revision 39081)
+++ src/pmc/object.pmc  (working copy)
@@ -104,8 +104,8 @@
 }
 
 pmclass Object need_ext {
-    ATTR PMC *_class;       /* The class this is an instance of. */
-    ATTR PMC *attrib_store; /* The attributes store - a resizable PMC array. */
+    ATTR PMC *_class;        /* The class this is an instance of. */
+    ATTR PMC **attrib_store; /* The attributes store - an array of PMCs. */
 
 /*
 
@@ -148,6 +148,9 @@
 
 */
     VTABLE void destroy() {
+        Parrot_Object_attributes * const obj = PARROT_OBJECT(SELF);
+        if (obj->attrib_store)
+            mem_sys_free(obj->attrib_store);
         mem_sys_free(PMC_data(SELF));
     }
 
@@ -187,10 +190,15 @@
         if (PARROT_OBJECT(SELF)) {
             Parrot_Object_attributes * const obj = PARROT_OBJECT(SELF);
 
-            if (obj->_class)
+            if (obj->_class) {
+                Parrot_Class_attributes * const _class = 
PARROT_CLASS(obj->_class);
                 Parrot_gc_mark_PObj_alive(interp, (PObj*)obj->_class);
-            if (obj->attrib_store)
-                Parrot_gc_mark_PObj_alive(interp, (PObj*)obj->attrib_store);
+                if (obj->attrib_store) {
+                    int i;
+                    for (i = 0; i < _class->num_attrs; i++)
+                        Parrot_gc_mark_PObj_alive(interp, 
(PObj*)obj->attrib_store[i]);
+                }
+            }
         }
     }
 
@@ -225,7 +233,7 @@
             Parrot_ex_throw_from_c_args(interp, NULL, 
EXCEPTION_ATTRIB_NOT_FOUND,
                 "No such attribute '%S'", name);
 
-        return VTABLE_get_pmc_keyed_int(interp, obj->attrib_store, index);
+        return obj->attrib_store[index];
     }
 
 /*
@@ -250,7 +258,7 @@
                 "No such attribute '%S' in class '%S'", name,
                 VTABLE_get_string(interp, key));
 
-        return VTABLE_get_pmc_keyed_int(interp, obj->attrib_store, index);
+        return obj->attrib_store[index];
     }
 
 /*
@@ -285,7 +293,7 @@
             Parrot_ex_throw_from_c_args(interp, NULL, 
EXCEPTION_ATTRIB_NOT_FOUND,
                 "No such attribute '%S'", name);
 
-        VTABLE_set_pmc_keyed_int(interp, obj->attrib_store, index, value);
+        obj->attrib_store[index] = value;
     }
 
 /*
@@ -308,7 +316,7 @@
                 "No such attribute '%S' in class '%S'", name,
                 VTABLE_get_string(interp, key));
 
-        VTABLE_set_pmc_keyed_int(interp, obj->attrib_store, index, value);
+        obj->attrib_store[index] = value;
     }
 
 /*
@@ -647,7 +655,7 @@
 
         /* See if we have a custom override of the method first. */
         const int num_classes = VTABLE_elements(interp, _class->all_parents);
-        int i, num_attrs;
+        int i;
         for (i = 0; i < num_classes; i++) {
             /* Get the class. */
             PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, 
_class->all_parents, i);
@@ -672,15 +680,16 @@
         /* Now create the underlying structure, and clone attributes 
list.class. */
         cloned_guts               = 
mem_allocate_zeroed_typed(Parrot_Object_attributes);
         cloned_guts->_class       = obj->_class;
-        cloned_guts->attrib_store = VTABLE_clone(INTERP, obj->attrib_store);
+        cloned_guts->attrib_store = mem_allocate_n_typed(_class->num_attrs, 
PMC *);
         PMC_data(cloned)          = cloned_guts;
-        num_attrs                 = VTABLE_elements(INTERP, 
cloned_guts->attrib_store);
-        for (i = 0; i < num_attrs; i++) {
-            PMC * const to_clone = VTABLE_get_pmc_keyed_int(INTERP, 
cloned_guts->attrib_store, i);
+        for (i = 0; i < _class->num_attrs; i++) {
+            PMC * const to_clone = obj->attrib_store[i];
             if (!PMC_IS_NULL(to_clone)) {
-                VTABLE_set_pmc_keyed_int(INTERP, cloned_guts->attrib_store, i,
-                        VTABLE_clone(INTERP, to_clone));
+                cloned_guts->attrib_store[i] = VTABLE_clone(INTERP, to_clone);
             }
+            else {
+                cloned_guts->attrib_store[i] = to_clone;
+            }
         }
 
         /* Some of the attributes may have been the PMCs providing storage for 
any
@@ -718,16 +727,26 @@
     VTABLE void visit(visit_info *info) {
         Parrot_Object_attributes * const obj_data = PARROT_OBJECT(SELF);
         PMC **pos;
+        INTVAL num_attrs, i;
 
         /* 1) visit class */
         pos            = &obj_data->_class;
         info->thaw_ptr = pos;
         (info->visit_pmc_now)(INTERP, *pos, info);
 
+        /* Now we have the class, and if we're thawing, we can allocate the
+         * attributes storage array for visiting. */
+        num_attrs = PARROT_CLASS(obj_data->_class)->num_attrs;
+        if (!obj_data->attrib_store) {
+            obj_data->attrib_store = mem_allocate_n_typed(num_attrs, PMC *);
+        }
+
         /* 2) visit the attributes */
-        pos      = &obj_data->attrib_store;
-        info->thaw_ptr = pos;
-        (info->visit_pmc_now)(INTERP, *pos, info);
+        for (i = 0; i < num_attrs; i++) {
+            pos      = &obj_data->attrib_store[i];
+            info->thaw_ptr = pos;
+            (info->visit_pmc_now)(INTERP, *pos, info);
+        }
     }
 
 /*
diff --git a/src/ops/perl6.ops b/src/ops/perl6.ops
index b797c23..efbfb2d 100644
--- a/src/ops/perl6.ops
+++ b/src/ops/perl6.ops
@@ -5,6 +5,7 @@
 
 #include "parrot/dynext.h"
 #include "pmc_object.h"
+#include "pmc_class.h"
 VERSION = PARROT_VERSION;
 
 #if PARROT_HAS_ICU
@@ -94,8 +95,7 @@ inline op rebless_subclass(in PMC, in PMC) :base_core {
 
         /* Now set any new attributes to be undef. */
         for (i = 0; i < new_attribs; i++)
-            VTABLE_set_pmc_keyed_int(interp, 
PARROT_OBJECT(value)->attrib_store,
-                i, pmc_new(interp, enum_class_Undef));
+            PARROT_OBJECT(value)->attrib_store[i] = pmc_new(interp, 
enum_class_Undef);
     }
     else if (value->vtable->base_type != enum_class_Object
             || current_class->vtable->base_type != enum_class_Class) {
@@ -110,13 +110,20 @@ inline op rebless_subclass(in PMC, in PMC) :base_core {
          * Shuffle up attributes to the point of the difference between the 
number
          * of attributes in the parent and the derived class. Yes, this is 
evil -
          * we're diddling the object's internals. */
+        INTVAL orig_attrs = PARROT_CLASS(current_class)->num_attrs;
+        PMC **new_attr_store = mem_allocate_n_typed(orig_attrs + new_attribs, 
PMC *);
+        Parrot_block_GC_mark(interp);
+        memmove(new_attr_store + new_attribs, 
PARROT_OBJECT(value)->attrib_store,
+                orig_attrs * sizeof(PMC *));
+        mem_sys_free(PARROT_OBJECT(value)->attrib_store);
+        PARROT_OBJECT(value)->attrib_store = new_attr_store;
         for (i = 0; i < new_attribs; i++)
-            VTABLE_unshift_pmc(interp, PARROT_OBJECT(value)->attrib_store,
-                pmc_new(interp, enum_class_Undef));
+            new_attr_store[i] = pmc_new(interp, enum_class_Undef);
 
         /* Now switch object's class pointer to point at the new class. This is
          * also evil. */
         PARROT_OBJECT(value)->_class = $2;
+        Parrot_unblock_GC_mark(interp);
     }
 
     goto NEXT();
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev

Reply via email to