B-C
view release on metacpan or search on metacpan
dSP;
dVAR;
HV* stash;
#if PERL_VERSION > 7
assert(SvOBJECT(sv));
do {
stash = SvSTASH(sv);
assert(SvTYPE(stash) == SVt_PVHV);
if (HvNAME(stash)) {
CV* destructor = NULL;
if (!SvOBJECT(stash)) destructor = (CV *)SvSTASH(stash);
if (!destructor
#if (PERL_VERSION > 18) || (PERL_VERSION == 18 && PERL_SUBVERSION > 1)
|| HvMROMETA(stash)->destroy_gen != PL_sub_generation
#endif
) {
GV * const gv = gv_fetchmeth_autoload(stash, "DESTROY", 7, 0);
if (gv) {
destructor = GvCV(gv);
if (!SvOBJECT(stash)) {
SvSTASH(stash) =
destructor ? (HV *)destructor : ((HV *)0)+1;
#if (PERL_VERSION > 18) || (PERL_VERSION == 18 && PERL_SUBVERSION > 1)
HvAUX(stash)->xhv_mro_meta->destroy_gen = PL_sub_generation;
#endif
}
}
}
assert(!destructor || destructor == ((CV *)0)+1
|| SvTYPE(destructor) == SVt_PVCV);
if (destructor && destructor != ((CV *)0)+1
/* A constant subroutine can have no side effects, so
don't bother calling it. */
&& !CvCONST(destructor)
/* Don't bother calling an empty destructor or one that
returns immediately. */
&& (CvISXSUB(destructor)
|| (CvSTART(destructor)
&& (CvSTART(destructor)->op_next->op_type != OP_LEAVESUB)
&& (CvSTART(destructor)->op_next->op_type != OP_PUSHMARK
|| CvSTART(destructor)->op_next->op_next->op_type != OP_RETURN
)
))
)
{
SV* const tmpref = newRV(sv);
DEBUG_D(PerlIO_printf(Perl_debug_log, "Calling %s::DESTROY\n", HvNAME(stash)));
SvREADONLY_on(tmpref); /* DESTROY() could be naughty */
ENTER;
PUSHSTACKi(PERLSI_DESTROY);
EXTEND(SP, 2);
PUSHMARK(SP);
PUSHs(tmpref);
PUTBACK;
call_sv((SV*)destructor, G_DISCARD|G_EVAL|G_KEEPERR|G_VOID);
POPSTACK;
SPAGAIN;
LEAVE;
if(SvREFCNT(tmpref) < 2) {
/* tmpref is not kept alive! */
SvREFCNT(sv)--;
SvRV_set(tmpref, NULL);
SvROK_off(tmpref);
}
SvREFCNT_dec(tmpref);
}
}
} while (SvOBJECT(sv) && SvSTASH(sv) != stash);
if (SvOBJECT(sv)) {
/* Curse before freeing the stash, as freeing the stash could cause
a recursive call into S_curse. */
SvOBJECT_off(sv); /* Curse the object. */
SvSTASH_set(sv,0); /* SvREFCNT_dec may try to read this */
}
#endif
}
static int fast_perl_destruct( PerlInterpreter *my_perl ) {
dVAR;
volatile signed char destruct_level; /* see possible values in intrpvar.h */
HV *hv;
#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
pid_t child;
#endif
#ifndef MULTIPLICITY
# ifndef PERL_UNUSED_ARG
# define PERL_UNUSED_ARG(x) ((void)x)
# endif
PERL_UNUSED_ARG(my_perl);
#endif
assert(PL_scopestack_ix == 1);
/* wait for all pseudo-forked children to finish */
#if !defined(WIN32) || (defined(USE_CPERL) && PERL_VERSION >= 24)
PERL_WAIT_FOR_CHILDREN;
#endif
destruct_level = PL_perl_destruct_level;
#ifdef DEBUGGING
{
const char * const s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL");
if (s) {
const int i = atoi(s);
#ifdef DEBUGGING
if (destruct_level < i) destruct_level = i;
#endif
#ifdef PERL_TRACK_MEMPOOL
/* RT #114496, for perl_free */
PL_perl_destruct_level = i;
#endif
}
}
#endif
if (PL_exit_flags & PERL_EXIT_DESTRUCT_END) {
int x = 0;
( run in 1.492 second using v1.01-cache-2.11-cpan-df04353d9ac )