*/
#include "EXTERN.h"
+#define PERL_IN_MRO_C
#include "perl.h"
struct mro_meta*
=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;
/* 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 */
}
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);
}
}
+ /* 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);
=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;
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");