[svn:parrot] r47820 - trunk/src/pmc
chromatic at svn.parrot.org
chromatic at svn.parrot.org
Fri Jun 25 03:16:10 UTC 2010
Author: chromatic
Date: Fri Jun 25 03:16:10 2010
New Revision: 47820
URL: https://trac.parrot.org/parrot/changeset/47820
Log:
[PMC] Added a cache to speed up Class's isa_pmc.
Rather than recursing upwards for positive and negative isa tests, each Class
now has a cache of Classes it is and isn't. This only works if the Class is
already instantiated, for obvious "don't pull the rug out from under me"
reasons. The result is a 1.5% performance improvement on the Rakudo startup
benchmark.
Modified:
trunk/src/pmc/class.pmc
Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc Fri Jun 25 03:15:41 2010 (r47819)
+++ trunk/src/pmc/class.pmc Fri Jun 25 03:16:10 2010 (r47820)
@@ -176,6 +176,21 @@
/* HEADERIZER END: static */
static int
+pointer_compare(SHIM_INTERP, ARGIN_NULLOK(const void *a),
+ ARGIN_NULLOK(const void *b))
+{
+ ASSERT_ARGS(pointer_compare)
+ return a != b;
+}
+
+static size_t
+key_hash_pointer(SHIM_INTERP, ARGIN(const void *value), size_t seed)
+{
+ ASSERT_ARGS(key_hash_pointer)
+ return ((size_t) value ^ seed);
+}
+
+static int
cache_class_attribs(PARROT_INTERP,
ARGIN(PMC *cur_class), ARGIN(PMC *attrib_index),
ARGIN(PMC *cache), int cur_index)
@@ -559,8 +574,9 @@
ATTR PMC *attrib_cache; /* Cache of visible attrib names to indexes. */
ATTR PMC *resolve_method; /* List of method names the class provides to resolve
* conflicts with methods from roles. */
- ATTR PMC *parent_overrides;
- ATTR PMC *meth_cache;
+ ATTR PMC *parent_overrides;
+ ATTR PMC *meth_cache;
+ ATTR Hash *isa_cache;
/*
@@ -600,6 +616,9 @@
_class->vtable_overrides = Parrot_pmc_new(INTERP, enum_class_Hash);
_class->parent_overrides = Parrot_pmc_new(INTERP, enum_class_Hash);
+ _class->isa_cache = parrot_create_hash(INTERP,
+ enum_type_INTVAL, Hash_key_type_PMC,
+ (hash_comp_fn)pointer_compare, (hash_hash_key_fn)key_hash_pointer);
/* We put ourself on the all parents list. */
VTABLE_push_pmc(INTERP, _class->all_parents, SELF);
@@ -657,6 +676,11 @@
init_class_from_hash(INTERP, SELF, arg);
}
+ void destroy() {
+ Parrot_Class_attributes * const _class = PARROT_CLASS(SELF);
+ parrot_hash_destroy(INTERP, _class->isa_cache);
+ }
+
/*
=item C<STRING *get_string()>
@@ -697,6 +721,8 @@
Parrot_gc_mark_PMC_alive(INTERP, _class->attrib_cache);
Parrot_gc_mark_PMC_alive(INTERP, _class->resolve_method);
Parrot_gc_mark_PMC_alive(INTERP, _class->meth_cache);
+ if (_class->isa_cache)
+ parrot_mark_hash(INTERP, _class->isa_cache);
}
@@ -922,6 +948,7 @@
/* Add to the lists of our immediate parents and all parents. */
VTABLE_push_pmc(INTERP, _class->parents, parent);
+ parrot_hash_put(INTERP, _class->isa_cache, (void *)parent, (void *)1);
calculate_mro(INTERP, SELF, parent_count + 1);
}
@@ -969,6 +996,7 @@
"Can't remove_parent: is not a parent.");
VTABLE_delete_keyed_int(INTERP, _class->parents, index);
+ parrot_hash_put(INTERP, _class->isa_cache, (void *)parent, (void *)0);
calculate_mro(INTERP, SELF, parent_count - 1);
}
@@ -1329,7 +1357,8 @@
VTABLE INTVAL isa_pmc(PMC *lookup) {
Parrot_Class_attributes * const _class = PARROT_CLASS(SELF);
PMC *classobj;
- INTVAL i, num_classes;
+ HashBucket *b;
+ INTVAL i, num_classes, retval = 0;
if (PMC_IS_NULL(lookup))
return 0;
@@ -1344,7 +1373,14 @@
/* Check if the class object is the same as self's class object */
if (VTABLE_is_same(INTERP, SELF, classobj))
- return 1;
+ goto found;
+
+ if (_class->instantiated) {
+ b = parrot_hash_get_bucket(INTERP, _class->isa_cache,
+ (void *)classobj);
+ if (b)
+ return (INTVAL)b->value;
+ }
/* this is effectively what the default PMC's isa_pmc does
* ... but this can cheat and avoid COW STRINGs for the classobj
@@ -1354,7 +1390,7 @@
STRING *classname = make_class_name(INTERP, classobj);
PARROT_ASSERT(SELF->vtable->isa_hash);
if (parrot_hash_exists(INTERP, SELF->vtable->isa_hash, classname))
- return 1;
+ goto found;
}
/* Iterate over all the parents and check if they respond true
@@ -1366,10 +1402,18 @@
_class->parents, i);
if (VTABLE_isa_pmc(INTERP, cur_class, lookup))
- return 1;
+ goto found;
}
- return 0;
+ cache_and_return:
+ if (_class->instantiated)
+ parrot_hash_put(INTERP, _class->isa_cache, (void *)classobj,
+ (void *)retval);
+ return retval;
+
+ found:
+ retval = 1;
+ goto cache_and_return;
}
/*
More information about the parrot-commits
mailing list