internals.
*/
-/* This is %next::METHOD_CACHE */
-STATIC HV* nmcache;
-
AV*
__mro_linear_isa_c3(pTHX_ HV* stash, HV* cache, I32 level)
{
STRLEN stashname_len;
assert(stash);
- assert(HvAUX(stash));
stashname = HvNAME(stash);
stashname_len = strlen(stashname);
/* not in cache, make a new one */
- retval = (AV*)sv_2mortal((SV*)newAV());
+ retval = newAV();
av_push(retval, newSVpvn(stashname, stashname_len)); /* us first */
gvp = (GV**)hv_fetch(stash, "ISA", 3, FALSE);
}
}
if(!cand) break;
- if(!winner)
+ if(!winner) {
+ SvREFCNT_dec(retval);
Perl_croak(aTHX_ "Inconsistent hierarchy during C3 merge of class '%s': "
"merging failed on parent '%s'", stashname, SvPV_nolen(cand));
+ }
}
}
SvREADONLY_on(retval);
- SvREFCNT_inc(retval); /* for cache storage */
- SvREFCNT_inc(retval); /* for return */
hv_store(cache, stashname, stashname_len, (SV*)retval, 0);
- return retval;
+ return (AV*)SvREFCNT_inc(retval);
}
STATIC I32
CV* cand_cv = NULL;
const char *hvname;
I32 items;
+ HV* nmcache;
HE* cache_entry;
SV* cachekey;
sv_catpvn(cachekey, "|", 1);
sv_catsv(cachekey, sv);
+ nmcache = get_hv("next::METHOD_CACHE", 1);
if((cache_entry = hv_fetch_ent(nmcache, cachekey, 0, 0))) {
SV* val = HeVAL(cache_entry);
if(val == &PL_sv_undef) {
stashname_len = subname - fq_subname - 2;
stashname = sv_2mortal(newSVpvn(fq_subname, stashname_len));
- linear_av = (AV*)sv_2mortal((SV*)__mro_linear_isa_c3(aTHX_ selfstash, NULL, 0));
+ linear_av = __mro_linear_isa_c3(aTHX_ selfstash, NULL, 0);
linear_svp = AvARRAY(linear_av);
items = AvFILLp(linear_av) + 1;
if(cc3_mro) {
HE* he_cc3_mro_class = hv_fetch_ent(cc3_mro, linear_sv, 0, 0);
if(he_cc3_mro_class) {
- HV* cc3_mro_class = (HV*)SvRV(HeVAL(he_cc3_mro_class));
- SV** svp_cc3_mro_class_methods = hv_fetch(cc3_mro_class, "methods", 7, 0);
- if(svp_cc3_mro_class_methods) {
- HV* cc3_mro_class_methods = (HV*)SvRV(*svp_cc3_mro_class_methods);
- if(hv_exists_ent(cc3_mro_class_methods, sub_sv, 0))
- continue;
+ SV* cc3_mro_class_sv = HeVAL(he_cc3_mro_class);
+ if(SvROK(cc3_mro_class_sv)) {
+ HV* cc3_mro_class = (HV*)SvRV(cc3_mro_class_sv);
+ SV** svp_cc3_mro_class_methods = hv_fetch(cc3_mro_class, "methods", 7, 0);
+ if(svp_cc3_mro_class_methods) {
+ SV* cc3_mro_class_methods_sv = *svp_cc3_mro_class_methods;
+ if(SvROK(cc3_mro_class_methods_sv)) {
+ HV* cc3_mro_class_methods = (HV*)SvRV(cc3_mro_class_methods_sv);
+ if(hv_exists_ent(cc3_mro_class_methods, sub_sv, 0))
+ continue;
+ }
+ }
}
}
}
if (SvTYPE(candidate) != SVt_PVGV)
gv_init(candidate, cstash, subname, subname_len, TRUE);
if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
+ SvREFCNT_dec(linear_av);
SvREFCNT_inc((SV*)cand_cv);
hv_store_ent(nmcache, newSVsv(cachekey), (SV*)cand_cv, 0);
return (SV*)cand_cv;
}
}
+ SvREFCNT_dec(linear_av);
hv_store_ent(nmcache, newSVsv(cachekey), &PL_sv_undef, 0);
if(throw_nomethod)
croak("No next::method '%s' found for %s", subname, hvname);
class_stash = gv_stashsv(classname, 0);
if(!class_stash) croak("No such class: '%s'!", SvPV_nolen(classname));
- res = (AV*)sv_2mortal((SV*)__mro_linear_isa_c3(aTHX_ class_stash, cache, 0));
+ res = __mro_linear_isa_c3(aTHX_ class_stash, cache, 0);
res_items = ret_items = AvFILLp(res) + 1;
res_ptr = AvARRAY(res);
while(res_items--) {
SV* res_item = *res_ptr++;
- XPUSHs(res_item);
+ XPUSHs(sv_2mortal(newSVsv(res_item)));
}
+ SvREFCNT_dec(res);
PUTBACK;
MODULE = Class::C3::XS PACKAGE = Class::C3::XS
BOOT:
- nmcache = get_hv("next::METHOD_CACHE", 1);
newXS("Class::C3::XS::calculateMRO", XS_Class_C3_XS_calculateMRO, __FILE__);
newXS("next::can", XS_next_can, __FILE__);
newXS("next::method", XS_next_method, __FILE__);