summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2008-09-12 09:25:55 +0000
committerNicholas Clark <nick@ccl4.org>2008-09-12 09:25:55 +0000
commit6e4aef591331d48363634d9ad4a01d6c6b5f5577 (patch)
tree05af6b3137bd0f80e535f9f3f2a468126ef514b2
parent5782d502273e5b6d06607ebe625248c4c102d93b (diff)
downloadperl-6e4aef591331d48363634d9ad4a01d6c6b5f5577.tar.gz
Build the isa cache from any linear ISA, rather than forcing the use
of dfs. This avoids calling dfs on a C3 class (and all its parents), which won't break anything, but is more work than is needed. p4raw-id: //depot/perl@34356
-rw-r--r--mro.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/mro.c b/mro.c
index 4d7ade5747..b15ec3a69c 100644
--- a/mro.c
+++ b/mro.c
@@ -105,9 +105,28 @@ Perl_get_isa_hash(pTHX_ HV *const stash)
PERL_ARGS_ASSERT_GET_ISA_HASH;
- if (!meta->isa)
- mro_get_linear_isa_dfs(stash, 0);
- assert(meta->isa);
+ if (!meta->isa) {
+ AV *const isa = mro_get_linear_isa(stash);
+ if (!meta->isa) {
+ HV *const isa_hash = newHV();
+ /* Linearisation didn't build it for us, so do it here. */
+ SV *const *svp = AvARRAY(isa);
+ SV *const *const svp_end = svp + AvFILLp(isa) + 1;
+ const HEK *const canon_name = HvNAME_HEK(stash);
+
+ while (svp < svp_end) {
+ (void) hv_store_ent(isa_hash, *svp++, &PL_sv_undef, 0);
+ }
+
+ (void) hv_common(isa_hash, NULL, HEK_KEY(canon_name),
+ HEK_LEN(canon_name), HEK_FLAGS(canon_name),
+ HV_FETCH_ISSTORE, &PL_sv_undef,
+ HEK_HASH(canon_name));
+ (void) hv_store(isa_hash, "UNIVERSAL", 9, &PL_sv_undef, 0);
+
+ meta->isa = isa_hash;
+ }
+ }
return meta->isa;
}