summaryrefslogtreecommitdiff
path: root/mro.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-30 09:38:24 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-30 09:39:34 -0700
commit7311f41d6a3262c063a74d2b53124a5345407512 (patch)
treea16f438f0ad6dcd26368c59f5cfe12760f7ae048 /mro.c
parentf1f1936442c5bdb04e4ce83479e97319d753cb3b (diff)
downloadperl-7311f41d6a3262c063a74d2b53124a5345407512.tar.gz
Move the meta->isa code from UNIVERSAL::isa to mro_get_linear_isa
This is so that it can be used for PL_isarev bookkeeping as well. This will have no effect on the speed of DFS classes. C3 classes on which ->isa is never called will have a slight slowdown. (We could always add an API for setting meta->isa if we want to avoid that.)
Diffstat (limited to 'mro.c')
-rw-r--r--mro.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/mro.c b/mro.c
index ca38a76f59..509e9d8f9c 100644
--- a/mro.c
+++ b/mro.c
@@ -397,6 +397,7 @@ AV*
Perl_mro_get_linear_isa(pTHX_ HV *stash)
{
struct mro_meta* meta;
+ AV *isa;
PERL_ARGS_ASSERT_MRO_GET_LINEAR_ISA;
if(!SvOOK(stash))
@@ -405,7 +406,32 @@ Perl_mro_get_linear_isa(pTHX_ HV *stash)
meta = HvMROMETA(stash);
if (!meta->mro_which)
Perl_croak(aTHX_ "panic: invalid MRO!");
- return meta->mro_which->resolve(aTHX_ stash, 0);
+ isa = meta->mro_which->resolve(aTHX_ stash, 0);
+
+ 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 *canon_name = HvENAME_HEK(stash);
+ if (!canon_name) 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);
+
+ SvREADONLY_on(isa_hash);
+
+ meta->isa = isa_hash;
+ }
+
+ return isa;
}
/*