X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mro.c;h=8634ccb3eb7e4f67ea3497e3fa675125088c4605;hb=53c40a8fd46e24a1d1e4bce188f973172eb1a279;hp=01461b145ae369ffbf09b5a64cff368df760f2a5;hpb=5be5c7a687aa37f2ea9dec7988eb57cad1f1ec24;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mro.c b/mro.c index 01461b1..8634ccb 100644 --- a/mro.c +++ b/mro.c @@ -21,6 +21,7 @@ These functions are related to the method resolution order of perl classes */ #include "EXTERN.h" +#define PERL_IN_MRO_C #include "perl.h" struct mro_meta* @@ -83,8 +84,8 @@ invalidated). =cut */ -AV* -Perl_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level) +static AV* +S_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level) { AV* retval; GV** gvp; @@ -113,7 +114,7 @@ Perl_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level) /* not in cache, make a new one */ - retval = newAV(); + retval = (AV*)sv_2mortal((SV *)newAV()); av_push(retval, newSVpv(stashname, 0)); /* add ourselves at the top */ /* fetch our @ISA */ @@ -146,7 +147,10 @@ Perl_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level) } else { /* otherwise, recurse into ourselves for the MRO - of this @ISA member, and append their MRO to ours */ + of this @ISA member, and append their MRO to ours. + The recursive call could throw an exception, which + has memory management implications here, hence the use of + the mortal. */ const AV *const subrv = mro_get_linear_isa_dfs(basestash, level + 1); @@ -163,6 +167,12 @@ Perl_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level) } } + /* now that we're past the exception dangers, grab our own reference to + the AV we're about to use for the result. The reference owned by the + mortals' stack will be released soon, so everything will balance. */ + SvREFCNT_inc_simple_void_NN(retval); + SvTEMP_off(retval); + /* we don't want anyone modifying the cache entry but us, and we do so by replacing it completely */ SvREADONLY_on(retval); @@ -188,8 +198,8 @@ invalidated). =cut */ -AV* -Perl_mro_get_linear_isa_c3(pTHX_ HV* stash, I32 level) +static AV* +S_mro_get_linear_isa_c3(pTHX_ HV* stash, I32 level) { AV* retval; GV** gvp; @@ -448,10 +458,8 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash) bool is_universal; struct mro_meta * meta; - const char * const stashname = stash ? HvNAME_get(stash) : NULL; - const STRLEN stashname_len = stash ? HvNAMELEN_get(stash) : 0; - - if(!stash) return; + const char * const stashname = HvNAME_get(stash); + const STRLEN stashname_len = HvNAMELEN_get(stash); if(!stashname) Perl_croak(aTHX_ "Can't call mro_isa_changed_in() on anonymous symbol table");