Front page | perl.perl5.porters |
Postings from July 2011
[perl #95342] [PATCH] Add finalize_optree function which can take over all the compile time checking/finalization now being done by the peephole optimizer.
Thread Next
From:
Gerard Goossen
Date:
July 21, 2011 14:32
Subject:
[perl #95342] [PATCH] Add finalize_optree function which can take over all the compile time checking/finalization now being done by the peephole optimizer.
Message ID:
rt-3.6.HEAD-7815-1311283949-485.95342-75-0@perl.org
# New Ticket Created by Gerard Goossen
# Please include the string: [perl #95342]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=95342 >
This is a bug report for perl from gerard@ggoossen.net,
generated with the help of perlbug 1.39 running under perl 5.15.1.
>From 05fd0b4bc00c0d593cccb150a2094b6ce1d1ee3a Mon Sep 17 00:00:00 2001
From: Gerard Goossen <gerard@ggoossen.net>
Date: Wed, 15 Jun 2011 11:32:53 +0200
Subject: [PATCH] Add finalize_optree function which can take over all the
compile time checking/finalization now being done by the
peephole optimizer.
This function takes the optree after it is finished building. It
takes over some of the checking and final conversions which are currently being
done by the peephole optimizer.
Add the moment this is an unnecessary extra step after the peephole optimizer, but with
a separate code generation step, the current peephole optimizer can't exists and
this function will take over all its essential compile time functions.
---
embed.fnc | 4 +
embed.h | 2 +
global.sym | 1 +
op.c | 456 ++++++++++++++++++++++++++++++++----------------------------
pp_ctl.c | 12 ++-
proto.h | 10 ++
6 files changed, 269 insertions(+), 216 deletions(-)
diff --git a/embed.fnc b/embed.fnc
index 077955f..b198c14 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -757,6 +757,10 @@ AMmd |OP* |op_lvalue |NULLOK OP* o|I32 type
poX |OP* |op_lvalue_flags|NULLOK OP* o|I32 type|U32 flags
: To be removed after 5.14 (see [perl #78908]):
EXp |OP* |mod |NULLOK OP* o|I32 type
+Xp |void |finalize_optree |NN OP* o
+#if defined(PERL_IN_OP_C)
+s |void |finalize_op |NN OP* o
+#endif
: Used in op.c and pp_sys.c
p |int |mode_from_discipline|NULLOK const char* s|STRLEN len
Ap |const char* |moreswitches |NN const char* s
diff --git a/embed.h b/embed.h
index fa1a2a9..718f66a 100644
--- a/embed.h
+++ b/embed.h
@@ -1032,6 +1032,7 @@
#define dump_all_perl(a) Perl_dump_all_perl(aTHX_ a)
#define dump_packsubs_perl(a,b) Perl_dump_packsubs_perl(aTHX_ a,b)
#define dump_sub_perl(a,b) Perl_dump_sub_perl(aTHX_ a,b)
+#define finalize_optree(a) Perl_finalize_optree(aTHX_ a)
#define find_script(a,b,c,d) Perl_find_script(aTHX_ a,b,c,d)
#define free_tied_hv_pool() Perl_free_tied_hv_pool(aTHX)
#define get_hash_seed() Perl_get_hash_seed(aTHX)
@@ -1333,6 +1334,7 @@
#define bad_type(a,b,c,d) S_bad_type(aTHX_ a,b,c,d)
#define cop_free(a) S_cop_free(aTHX_ a)
#define dup_attrlist(a) S_dup_attrlist(aTHX_ a)
+#define finalize_op(a) S_finalize_op(aTHX_ a)
#define find_and_forget_pmops(a) S_find_and_forget_pmops(aTHX_ a)
#define fold_constants(a) S_fold_constants(aTHX_ a)
#define force_list(a) S_force_list(aTHX_ a)
diff --git a/global.sym b/global.sym
index 4f01c7b..11cecbe 100644
--- a/global.sym
+++ b/global.sym
@@ -127,6 +127,7 @@ Perl_fbm_instr
Perl_filter_add
Perl_filter_del
Perl_filter_read
+Perl_finalize_optree
Perl_find_runcv
Perl_find_rundefsv
Perl_find_rundefsvoffset
diff --git a/op.c b/op.c
index 1ff086b..1252f40 100644
--- a/op.c
+++ b/op.c
@@ -1396,6 +1396,246 @@ S_modkids(pTHX_ OP *o, I32 type)
}
/*
+=for apidoc finalize_optree
+
+This function finalizes the optree. Should be called directly after
+the complete optree is built. It does some additional
+checking which can't be done in the normal ck_xxx functions and makes
+the tree thread-safe.
+
+=cut
+*/
+void
+Perl_finalize_optree(pTHX_ OP* o)
+{
+ COP* oldcop = PL_curcop;
+
+ PERL_ARGS_ASSERT_FINALIZE_OPTREE;
+
+ finalize_op(o);
+
+ PL_curcop = oldcop;
+}
+
+void
+S_finalize_op(pTHX_ OP* o)
+{
+ PERL_ARGS_ASSERT_FINALIZE_OP;
+
+#if defined(PERL_MAD) && defined(USE_ITHREADS)
+ {
+ /* Make sure mad ops are also thread-safe */
+ MADPROP *mp = o->op_madprop;
+ while (mp) {
+ if (mp->mad_type == MAD_OP && mp->mad_vlen) {
+ OP *prop_op = (OP *) mp->mad_val;
+ /* We only need "Relocate sv to the pad for thread safety.", but this
+ easiest way to make sure it traverses everything */
+ finalize_op(prop_op);
+ }
+ mp = mp->mad_next;
+ }
+ }
+#endif
+
+ switch (o->op_type) {
+ case OP_NEXTSTATE:
+ case OP_DBSTATE:
+ PL_curcop = ((COP*)o); /* for warnings */
+ break;
+ case OP_EXEC:
+ if (o->op_next && o->op_next->op_type == OP_NEXTSTATE
+ && ckWARN(WARN_SYNTAX))
+ {
+ if (o->op_next->op_sibling) {
+ const OPCODE type = o->op_next->op_sibling->op_type;
+ if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) {
+ const line_t oldline = CopLINE(PL_curcop);
+ CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next));
+ Perl_warner(aTHX_ packWARN(WARN_EXEC),
+ "Statement unlikely to be reached");
+ Perl_warner(aTHX_ packWARN(WARN_EXEC),
+ "\t(Maybe you meant system() when you said exec()?)\n");
+ CopLINE_set(PL_curcop, oldline);
+ }
+ }
+ }
+ break;
+
+ case OP_GV:
+ if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
+ GV * const gv = cGVOPo_gv;
+ if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) {
+ /* XXX could check prototype here instead of just carping */
+ SV * const sv = sv_newmortal();
+ gv_efullname3(sv, gv, NULL);
+ Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
+ "%"SVf"() called too early to check prototype",
+ SVfARG(sv));
+ }
+ }
+ break;
+
+ case OP_CONST:
+#ifdef USE_ITHREADS
+ case OP_HINTSEVAL:
+ case OP_METHOD_NAMED:
+ /* Relocate sv to the pad for thread safety.
+ * Despite being a "constant", the SV is written to,
+ * for reference counts, sv_upgrade() etc. */
+ if (cSVOPo->op_sv) {
+ const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
+ if (o->op_type != OP_METHOD_NAMED &&
+ (SvPADTMP(cSVOPo->op_sv) || SvPADMY(cSVOPo->op_sv)))
+ {
+ /* If op_sv is already a PADTMP/MY then it is being used by
+ * some pad, so make a copy. */
+ sv_setsv(PAD_SVl(ix),cSVOPo->op_sv);
+ SvREADONLY_on(PAD_SVl(ix));
+ SvREFCNT_dec(cSVOPo->op_sv);
+ }
+ else if (o->op_type != OP_METHOD_NAMED
+ && cSVOPo->op_sv == &PL_sv_undef) {
+ /* PL_sv_undef is hack - it's unsafe to store it in the
+ AV that is the pad, because av_fetch treats values of
+ PL_sv_undef as a "free" AV entry and will merrily
+ replace them with a new SV, causing pad_alloc to think
+ that this pad slot is free. (When, clearly, it is not)
+ */
+ SvOK_off(PAD_SVl(ix));
+ SvPADTMP_on(PAD_SVl(ix));
+ SvREADONLY_on(PAD_SVl(ix));
+ }
+ else {
+ SvREFCNT_dec(PAD_SVl(ix));
+ SvPADTMP_on(cSVOPo->op_sv);
+ PAD_SETSV(ix, cSVOPo->op_sv);
+ /* XXX I don't know how this isn't readonly already. */
+ SvREADONLY_on(PAD_SVl(ix));
+ }
+ cSVOPo->op_sv = NULL;
+ o->op_targ = ix;
+ }
+#endif
+ break;
+
+ case OP_HELEM: {
+ UNOP *rop;
+ SV *lexname;
+ GV **fields;
+ SV **svp, *sv;
+ const char *key = NULL;
+ STRLEN keylen;
+
+ if (((BINOP*)o)->op_last->op_type != OP_CONST)
+ break;
+
+ /* Make the CONST have a shared SV */
+ svp = cSVOPx_svp(((BINOP*)o)->op_last);
+ if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv))
+ && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) {
+ key = SvPV_const(sv, keylen);
+ lexname = newSVpvn_share(key,
+ SvUTF8(sv) ? -(I32)keylen : (I32)keylen,
+ 0);
+ SvREFCNT_dec(sv);
+ *svp = lexname;
+ }
+
+ if ((o->op_private & (OPpLVAL_INTRO)))
+ break;
+
+ rop = (UNOP*)((BINOP*)o)->op_first;
+ if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
+ break;
+ lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
+ if (!SvPAD_TYPED(lexname))
+ break;
+ fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
+ if (!fields || !GvHV(*fields))
+ break;
+ key = SvPV_const(*svp, keylen);
+ if (!hv_fetch(GvHV(*fields), key,
+ SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) {
+ Perl_croak(aTHX_ "No such class field \"%s\" "
+ "in variable %s of type %s",
+ key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname)));
+ }
+ break;
+ }
+
+ case OP_HSLICE: {
+ UNOP *rop;
+ SV *lexname;
+ GV **fields;
+ SV **svp;
+ const char *key;
+ STRLEN keylen;
+ SVOP *first_key_op, *key_op;
+
+ if ((o->op_private & (OPpLVAL_INTRO))
+ /* I bet there's always a pushmark... */
+ || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
+ /* hmmm, no optimization if list contains only one key. */
+ break;
+ rop = (UNOP*)((LISTOP*)o)->op_last;
+ if (rop->op_type != OP_RV2HV)
+ break;
+ if (rop->op_first->op_type == OP_PADSV)
+ /* @$hash{qw(keys here)} */
+ rop = (UNOP*)rop->op_first;
+ else {
+ /* @{$hash}{qw(keys here)} */
+ if (rop->op_first->op_type == OP_SCOPE
+ && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
+ {
+ rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
+ }
+ else
+ break;
+ }
+
+ lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE);
+ if (!SvPAD_TYPED(lexname))
+ break;
+ fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
+ if (!fields || !GvHV(*fields))
+ break;
+ /* Again guessing that the pushmark can be jumped over.... */
+ first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
+ ->op_first->op_sibling;
+ for (key_op = first_key_op; key_op;
+ key_op = (SVOP*)key_op->op_sibling) {
+ if (key_op->op_type != OP_CONST)
+ continue;
+ svp = cSVOPx_svp(key_op);
+ key = SvPV_const(*svp, keylen);
+ if (!hv_fetch(GvHV(*fields), key,
+ SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) {
+ Perl_croak(aTHX_ "No such class field \"%s\" "
+ "in variable %s of type %s",
+ key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname)));
+ }
+ }
+ break;
+ }
+ case OP_SUBST: {
+ if (cPMOPo->op_pmreplrootu.op_pmreplroot)
+ finalize_op(cPMOPo->op_pmreplrootu.op_pmreplroot);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (o->op_flags & OPf_KIDS) {
+ OP *kid;
+ for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling)
+ finalize_op(kid);
+ }
+}
+
+/*
=for apidoc Amx|OP *|op_lvalue|OP *o|I32 type
Propagate lvalue ("modifiable") context to an op and its children.
@@ -2498,6 +2738,7 @@ Perl_newPROG(pTHX_ OP *o)
OpREFCNT_set(PL_main_root, 1);
PL_main_root->op_next = 0;
CALL_PEEP(PL_main_start);
+ finalize_optree(PL_main_root);
PL_compcv = 0;
/* Register with debugger */
@@ -6400,6 +6641,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
CvSTART(cv) = LINKLIST(CvROOT(cv));
CvROOT(cv)->op_next = 0;
CALL_PEEP(CvSTART(cv));
+ finalize_optree(CvROOT(cv));
/* now that optimizer has done its work, adjust pad values */
@@ -9341,47 +9583,6 @@ Perl_rpeep(pTHX_ register OP *o)
break;
}
-#if defined(PERL_MAD) && defined(USE_ITHREADS)
- MADPROP *mp = o->op_madprop;
- while (mp) {
- if (mp->mad_type == MAD_OP && mp->mad_vlen) {
- OP *prop_op = (OP *) mp->mad_val;
- /* I *think* that this is roughly the right thing to do. It
- seems that sometimes the optree hooked into the madprops
- doesn't have its next pointers set, so it's not possible to
- use them to locate all the OPs needing a fixup. Possibly
- it's a bit overkill calling LINKLIST to do this, when we
- could instead iterate over the OPs (without changing them)
- the way op_linklist does internally. However, I'm not sure
- if there are corner cases where we have a chain of partially
- linked OPs. Or even if we do, does that matter? Or should
- we always iterate on op_first,op_next? */
- LINKLIST(prop_op);
- do {
- if (prop_op->op_opt)
- break;
- prop_op->op_opt = 1;
- switch (prop_op->op_type) {
- case OP_CONST:
- case OP_HINTSEVAL:
- case OP_METHOD_NAMED:
- /* Duplicate the "relocate sv to the pad for thread
- safety" code, as otherwise an opfree of this madprop
- in the wrong thread will free the SV to the wrong
- interpreter. */
- if (((SVOP *)prop_op)->op_sv) {
- const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
- sv_setsv(PAD_SVl(ix),((SVOP *)prop_op)->op_sv);
- SvREFCNT_dec(((SVOP *)prop_op)->op_sv);
- ((SVOP *)prop_op)->op_sv = NULL;
- }
- break;
- }
- } while ((prop_op = prop_op->op_next));
- }
- mp = mp->mad_next;
- }
-#endif
/* By default, this op has now been optimised. A couple of cases below
clear this again. */
o->op_opt = 1;
@@ -9447,46 +9648,6 @@ Perl_rpeep(pTHX_ register OP *o)
case OP_CONST:
if (cSVOPo->op_private & OPpCONST_STRICT)
no_bareword_allowed(o);
-#ifdef USE_ITHREADS
- case OP_HINTSEVAL:
- case OP_METHOD_NAMED:
- /* Relocate sv to the pad for thread safety.
- * Despite being a "constant", the SV is written to,
- * for reference counts, sv_upgrade() etc. */
- if (cSVOP->op_sv) {
- const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP);
- if (o->op_type != OP_METHOD_NAMED &&
- (SvPADTMP(cSVOPo->op_sv) || SvPADMY(cSVOPo->op_sv)))
- {
- /* If op_sv is already a PADTMP/MY then it is being used by
- * some pad, so make a copy. */
- sv_setsv(PAD_SVl(ix),cSVOPo->op_sv);
- SvREADONLY_on(PAD_SVl(ix));
- SvREFCNT_dec(cSVOPo->op_sv);
- }
- else if (o->op_type != OP_METHOD_NAMED
- && cSVOPo->op_sv == &PL_sv_undef) {
- /* PL_sv_undef is hack - it's unsafe to store it in the
- AV that is the pad, because av_fetch treats values of
- PL_sv_undef as a "free" AV entry and will merrily
- replace them with a new SV, causing pad_alloc to think
- that this pad slot is free. (When, clearly, it is not)
- */
- SvOK_off(PAD_SVl(ix));
- SvPADTMP_on(PAD_SVl(ix));
- SvREADONLY_on(PAD_SVl(ix));
- }
- else {
- SvREFCNT_dec(PAD_SVl(ix));
- SvPADTMP_on(cSVOPo->op_sv);
- PAD_SETSV(ix, cSVOPo->op_sv);
- /* XXX I don't know how this isn't readonly already. */
- SvREADONLY_on(PAD_SVl(ix));
- }
- cSVOPo->op_sv = NULL;
- o->op_targ = ix;
- }
-#endif
break;
case OP_CONCAT:
@@ -9580,17 +9741,6 @@ Perl_rpeep(pTHX_ register OP *o)
o->op_ppaddr = PL_ppaddr[OP_GVSV];
}
}
- else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
- GV * const gv = cGVOPo_gv;
- if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) {
- /* XXX could check prototype here instead of just carping */
- SV * const sv = sv_newmortal();
- gv_efullname3(sv, gv, NULL);
- Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
- "%"SVf"() called too early to check prototype",
- SVfARG(sv));
- }
- }
else if (o->op_next->op_type == OP_READLINE
&& o->op_next->op_next->op_type == OP_CONCAT
&& (o->op_next->op_next->op_flags & OPf_STACKED))
@@ -9702,128 +9852,6 @@ Perl_rpeep(pTHX_ register OP *o)
DEFER(cPMOP->op_pmstashstartu.op_pmreplstart);
break;
- case OP_EXEC:
- if (o->op_next && o->op_next->op_type == OP_NEXTSTATE
- && ckWARN(WARN_SYNTAX))
- {
- if (o->op_next->op_sibling) {
- const OPCODE type = o->op_next->op_sibling->op_type;
- if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) {
- const line_t oldline = CopLINE(PL_curcop);
- CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next));
- Perl_warner(aTHX_ packWARN(WARN_EXEC),
- "Statement unlikely to be reached");
- Perl_warner(aTHX_ packWARN(WARN_EXEC),
- "\t(Maybe you meant system() when you said exec()?)\n");
- CopLINE_set(PL_curcop, oldline);
- }
- }
- }
- break;
-
- case OP_HELEM: {
- UNOP *rop;
- SV *lexname;
- GV **fields;
- SV **svp, *sv;
- const char *key = NULL;
- STRLEN keylen;
-
- if (((BINOP*)o)->op_last->op_type != OP_CONST)
- break;
-
- /* Make the CONST have a shared SV */
- svp = cSVOPx_svp(((BINOP*)o)->op_last);
- if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv))
- && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) {
- key = SvPV_const(sv, keylen);
- lexname = newSVpvn_share(key,
- SvUTF8(sv) ? -(I32)keylen : (I32)keylen,
- 0);
- SvREFCNT_dec(sv);
- *svp = lexname;
- }
-
- if ((o->op_private & (OPpLVAL_INTRO)))
- break;
-
- rop = (UNOP*)((BINOP*)o)->op_first;
- if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV)
- break;
- lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE);
- if (!SvPAD_TYPED(lexname))
- break;
- fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
- if (!fields || !GvHV(*fields))
- break;
- key = SvPV_const(*svp, keylen);
- if (!hv_fetch(GvHV(*fields), key,
- SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
- {
- Perl_croak(aTHX_ "No such class field \"%s\" "
- "in variable %s of type %s",
- key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname)));
- }
-
- break;
- }
-
- case OP_HSLICE: {
- UNOP *rop;
- SV *lexname;
- GV **fields;
- SV **svp;
- const char *key;
- STRLEN keylen;
- SVOP *first_key_op, *key_op;
-
- if ((o->op_private & (OPpLVAL_INTRO))
- /* I bet there's always a pushmark... */
- || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST)
- /* hmmm, no optimization if list contains only one key. */
- break;
- rop = (UNOP*)((LISTOP*)o)->op_last;
- if (rop->op_type != OP_RV2HV)
- break;
- if (rop->op_first->op_type == OP_PADSV)
- /* @$hash{qw(keys here)} */
- rop = (UNOP*)rop->op_first;
- else {
- /* @{$hash}{qw(keys here)} */
- if (rop->op_first->op_type == OP_SCOPE
- && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
- {
- rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
- }
- else
- break;
- }
-
- lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE);
- if (!SvPAD_TYPED(lexname))
- break;
- fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE);
- if (!fields || !GvHV(*fields))
- break;
- /* Again guessing that the pushmark can be jumped over.... */
- first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling)
- ->op_first->op_sibling;
- for (key_op = first_key_op; key_op;
- key_op = (SVOP*)key_op->op_sibling) {
- if (key_op->op_type != OP_CONST)
- continue;
- svp = cSVOPx_svp(key_op);
- key = SvPV_const(*svp, keylen);
- if (!hv_fetch(GvHV(*fields), key,
- SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE))
- {
- Perl_croak(aTHX_ "No such class field \"%s\" "
- "in variable %s of type %s",
- key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname)));
- }
- }
- break;
- }
case OP_RV2SV:
case OP_RV2AV:
case OP_RV2HV:
diff --git a/pp_ctl.c b/pp_ctl.c
index 533ff5f..7092c62 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3522,11 +3522,14 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
if (yystatus || PL_parser->error_count || !PL_eval_root) {
SV **newsp; /* Used by POPBLOCK. */
- PERL_CONTEXT *cx = NULL;
+ PERL_CONTEXT *cx;
I32 optype; /* Used by POPEVAL. */
- SV *namesv = NULL;
+ SV *namesv;
const char *msg;
+ parse_error:
+ cx = NULL;
+ namesv = NULL;
PERL_UNUSED_VAR(newsp);
PERL_UNUSED_VAR(optype);
@@ -3595,6 +3598,11 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
else
scalar(PL_eval_root);
+ finalize_optree(PL_eval_root);
+
+ if (PL_parser->error_count) /* finalize_optree might have generated new error */
+ goto parse_error;
+
DEBUG_x(dump_eval());
/* Register with debugger: */
diff --git a/proto.h b/proto.h
index 27788b5..e6174d4 100644
--- a/proto.h
+++ b/proto.h
@@ -960,6 +960,11 @@ PERL_CALLCONV I32 Perl_filter_read(pTHX_ int idx, SV *buf_sv, int maxlen)
#define PERL_ARGS_ASSERT_FILTER_READ \
assert(buf_sv)
+PERL_CALLCONV void Perl_finalize_optree(pTHX_ OP* o)
+ __attribute__nonnull__(pTHX_1);
+#define PERL_ARGS_ASSERT_FINALIZE_OPTREE \
+ assert(o)
+
PERL_CALLCONV CV* Perl_find_runcv(pTHX_ U32 *db_seqp)
__attribute__warn_unused_result__;
@@ -5479,6 +5484,11 @@ STATIC OP * S_dup_attrlist(pTHX_ OP *o)
#define PERL_ARGS_ASSERT_DUP_ATTRLIST \
assert(o)
+STATIC void S_finalize_op(pTHX_ OP* o)
+ __attribute__nonnull__(pTHX_1);
+#define PERL_ARGS_ASSERT_FINALIZE_OP \
+ assert(o)
+
STATIC void S_find_and_forget_pmops(pTHX_ OP *o)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_FIND_AND_FORGET_PMOPS \
--
1.7.5.4
---
Flags:
category=core
severity=low
---
Site configuration information for perl 5.15.1:
Configured by gerard at Thu Jul 21 20:57:45 CEST 2011.
Summary of my perl5 (revision 5 version 15 subversion 1) configuration:
Derived from: 0783a81c78cc5a9cae090ac4e335818cc65f640c
Platform:
osname=linux, osvers=2.6.39-2-686-pae, archname=i686-linux-thread-multi
uname='linux zeus 2.6.39-2-686-pae #1 smp wed jun 8 11:33:14 utc 2011 i686 gnulinux '
config_args='-des -DDEBUGGING -Dusethreads -Dusedevel -Doptimize=-O0 -g3 -Dprefix=/home/gerard/perl/inst/madperl'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O0 -g3',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
ccversion='', gccversion='4.6.1', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib /usr/lib/i386-linux-gnu /usr/lib64
libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.13'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -O0 -g3 -L/usr/local/lib -fstack-protector'
Locally applied patches:
---
@INC for perl 5.15.1:
lib
/home/gerard/perl/inst/madperl/lib/site_perl/5.15.1/i686-linux-thread-multi
/home/gerard/perl/inst/madperl/lib/site_perl/5.15.1
/home/gerard/perl/inst/madperl/lib/5.15.1/i686-linux-thread-multi
/home/gerard/perl/inst/madperl/lib/5.15.1
/home/gerard/perl/inst/madperl/lib/site_perl
.
---
Environment for perl 5.15.1:
HOME=/home/gerard
LANG=en_US.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/gerard/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
PERL_BADLANG (unset)
SHELL=/bin/bash
Thread Next
-
[perl #95342] [PATCH] Add finalize_optree function which can take over all the compile time checking/finalization now being done by the peephole optimizer.
by Gerard Goossen