Author: chromatic
Date: Sun Aug 17 14:49:39 2008
New Revision: 30286
Modified:
trunk/src/pmc/namespace.pmc
trunk/t/pmc/namespace.t
Log:
[PMC] Fixed co-recursion bug in NameSpace, when iterating through its contents.
The problem is that, when the key is a Key and not a String, sometimes there's
an infinite loop when the Key isn't a string, integer, or PMC key -- the
default path for the switch in key_string() calls the get_string() vtable entry
on the key, which calls key_string(), which....
The short-term solution is to call the parent PMC (Hash) implementation of
get_pmc_keyed() and return the results, if they're accurate. This fixes the
crash and keeps Rakudo working. Replacing the body of the vtable entry with
the SUPER() call breaks Rakudo.
The long-term solution is to fix the Key PMC, which is poorly designed and
poorly implemented.
See RT #57668 and RT #58040, for starters.
Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Sun Aug 17 14:49:39 2008
@@ -382,26 +382,26 @@
}
VTABLE PMC *get_pmc_keyed(PMC *key) {
- PMC *ns = SELF;
+ PMC *ns = SUPER(key);
- if (key->vtable->base_type == enum_class_String)
- return SELF.get_pmc_keyed_str(VTABLE_get_string(INTERP, key));
+ if (!PMC_IS_NULL(ns))
+ return ns;
+
+ ns = SELF;
if (key->vtable->base_type == enum_class_Key) {
- while (key) {
- STRING * const part = key_string(INTERP, key);
- key = key_next(INTERP, key);
+ STRING * const part = key_string(INTERP, key);
+ key = key_next(INTERP, key);
- if (!key)
- return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+ if (!key)
+ return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
- ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
+ ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
- if (PMC_IS_NULL(ns))
- return PMCNULL;
- }
+ if (PMC_IS_NULL(ns))
+ return PMCNULL;
- return ns;
+ return VTABLE_get_pmc_keyed(INTERP, ns, key);
}
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
Modified: trunk/t/pmc/namespace.t
==============================================================================
--- trunk/t/pmc/namespace.t (original)
+++ trunk/t/pmc/namespace.t Sun Aug 17 14:49:39 2008
@@ -1736,7 +1736,7 @@
/Null PMC access in get_string()/
OUT
-pir_output_is( <<'CODE', <<OUT, "RT #57668", todo => "iterate through a
NameSpace PMC, RT #57668" );
+pir_output_is( <<'CODE', <<OUT, "iterate through a NameSpace PMC" );
.namespace [ 'bar' ]
.sub 'main' :main