From: Gerard Goossen Date: Tue, 8 Dec 2009 19:41:28 +0000 (+0100) Subject: Store the PL_compcv instead of the the PL_comppad in parser stack, and make it refere... X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8c63ea58497f2deb05596f96547d19395545a0ee;p=p5sagit%2Fp5-mst-13.2.git Store the PL_compcv instead of the the PL_comppad in parser stack, and make it reference counted. Properly solves [perl #66094] --- diff --git a/pad.h b/pad.h index 986f7c2..8602eda 100644 --- a/pad.h +++ b/pad.h @@ -249,7 +249,8 @@ Restore the old pad saved into the local variable opad by PAD_SAVE_LOCAL() PTR2UV(PL_comppad), PTR2UV(PL_curpad))); #define PAD_RESTORE_LOCAL(opad) \ - PL_comppad = opad && SvIS_FREED(opad) ? NULL : opad; \ + assert(!opad || !SvIS_FREED(opad)); \ + PL_comppad = opad; \ PL_curpad = PL_comppad ? AvARRAY(PL_comppad) : NULL; \ DEBUG_Xv(PerlIO_printf(Perl_debug_log, \ "Pad 0x%"UVxf"[0x%"UVxf"] restore_local\n", \ diff --git a/parser.h b/parser.h index 462dcfd..4ef4608 100644 --- a/parser.h +++ b/parser.h @@ -15,7 +15,7 @@ typedef struct { YYSTYPE val; /* semantic value */ short state; I32 savestack_ix; /* size of savestack at this state */ - AV *comppad; /* value of PL_comppad when this value was created */ + CV *compcv; /* value of PL_compcv when this value was created */ #ifdef DEBUGGING const char *name; /* token/rule name for -Dpv */ #endif diff --git a/perly.c b/perly.c index eff36d1..ac87b8e 100644 --- a/perly.c +++ b/perly.c @@ -266,8 +266,10 @@ S_clear_yystack(pTHX_ const yy_parser *parser) #ifdef DISABLE_STACK_FREE + for (i=0; i< parser->yylen; i++) { + SvREFCNT_dec(ps[-i].compcv); + } ps -= parser->yylen; - PERL_UNUSED_VAR(i); #else /* clear any reducing ops (1st pass) */ @@ -278,8 +280,9 @@ S_clear_yystack(pTHX_ const yy_parser *parser) if ( ! (ps[-i].val.opval->op_attached && !ps[-i].val.opval->op_latefreed)) { - if (ps[-i].comppad != PL_comppad) { - PAD_RESTORE_LOCAL(ps[-i].comppad); + if (ps[-i].compcv != PL_compcv) { + PL_compcv = ps[-i].compcv; + PAD_SET_CUR_NOSAVE(CvPADLIST(PL_compcv), 1); } op_free(ps[-i].val.opval); } @@ -294,8 +297,9 @@ S_clear_yystack(pTHX_ const yy_parser *parser) if (yy_type_tab[yystos[ps->state]] == toketype_opval && ps->val.opval) { - if (ps->comppad != PL_comppad) { - PAD_RESTORE_LOCAL(ps->comppad); + if (ps->compcv != PL_compcv) { + PL_compcv = ps->compcv; + PAD_SET_CUR_NOSAVE(CvPADLIST(PL_compcv), 1); } YYDPRINTF ((Perl_debug_log, "(freeing op)\n")); #ifndef DISABLE_STACK_FREE @@ -304,6 +308,7 @@ S_clear_yystack(pTHX_ const yy_parser *parser) #endif op_free(ps->val.opval); } + SvREFCNT_dec(ps->compcv); ps--; } } @@ -451,7 +456,7 @@ Perl_yyparse (pTHX) YYPUSHSTACK; ps->state = yyn; ps->val = parser->yylval; - ps->comppad = PL_comppad; + ps->compcv = SvREFCNT_inc(PL_compcv); ps->savestack_ix = PL_savestack_ix; #ifdef DEBUGGING ps->name = (const char *)(yytname[yytoken]); @@ -525,12 +530,12 @@ Perl_yyparse (pTHX) } -#ifndef DISABLE_STACK_FREE /* any just-reduced ops with the op_latefreed flag cleared need to be * freed; the rest need the flag resetting */ { int i; for (i=0; i< parser->yylen; i++) { +#ifndef DISABLE_STACK_FREE if (yy_type_tab[yystos[ps[-i].state]] == toketype_opval && ps[-i].val.opval) { @@ -538,9 +543,10 @@ Perl_yyparse (pTHX) if (ps[-i].val.opval->op_latefreed) op_free(ps[-i].val.opval); } +#endif + SvREFCNT_dec(ps[-i].compcv); } } -#endif parser->ps = ps -= (parser->yylen-1); @@ -549,7 +555,7 @@ Perl_yyparse (pTHX) number reduced by. */ ps->val = yyval; - ps->comppad = PL_comppad; + ps->compcv = SvREFCNT_inc(PL_compcv); ps->savestack_ix = PL_savestack_ix; #ifdef DEBUGGING ps->name = (const char *)(yytname [yyr1[yyn]]); @@ -584,6 +590,7 @@ Perl_yyparse (pTHX) /* Return failure if at end of input. */ if (parser->yychar == YYEOF) { /* Pop the error token. */ + SvREFCNT_dec(ps->compcv); YYPOPSTACK; /* Pop the rest of the stack. */ while (ps > parser->stack) { @@ -593,12 +600,14 @@ Perl_yyparse (pTHX) && ps->val.opval) { YYDPRINTF ((Perl_debug_log, "(freeing op)\n")); - if (ps->comppad != PL_comppad) { - PAD_RESTORE_LOCAL(ps->comppad); + if (ps->compcv != PL_compcv) { + PL_compcv = ps->compcv; + PAD_SET_CUR_NOSAVE(CvPADLIST(PL_compcv), 1); } ps->val.opval->op_latefree = 0; op_free(ps->val.opval); } + SvREFCNT_dec(ps->compcv); YYPOPSTACK; } YYABORT; @@ -639,12 +648,14 @@ Perl_yyparse (pTHX) LEAVE_SCOPE(ps->savestack_ix); if (yy_type_tab[yystos[ps->state]] == toketype_opval && ps->val.opval) { YYDPRINTF ((Perl_debug_log, "(freeing op)\n")); - if (ps->comppad != PL_comppad) { - PAD_RESTORE_LOCAL(ps->comppad); + if (ps->compcv != PL_compcv) { + PL_compcv = ps->compcv; + PAD_SET_CUR_NOSAVE(CvPADLIST(PL_compcv), 1); } ps->val.opval->op_latefree = 0; op_free(ps->val.opval); } + SvREFCNT_dec(ps->compcv); YYPOPSTACK; yystate = ps->state; @@ -659,7 +670,7 @@ Perl_yyparse (pTHX) YYPUSHSTACK; ps->state = yyn; ps->val = parser->yylval; - ps->comppad = PL_comppad; + ps->compcv = SvREFCNT_inc(PL_compcv); ps->savestack_ix = PL_savestack_ix; #ifdef DEBUGGING ps->name =""; @@ -673,6 +684,9 @@ Perl_yyparse (pTHX) `-------------------------------------*/ yyacceptlab: yyresult = 0; + for (ps=parser->ps; ps > parser->stack; ps--) { + SvREFCNT_dec(ps->compcv); + } parser->ps = parser->stack; /* disable cleanup */ goto yyreturn;