diff options
author | David Mitchell <davem@iabyn.com> | 2011-11-01 16:50:16 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2011-12-19 15:06:03 +0000 |
commit | 1cd372981299d0b40c75b9146dd7542e4a8b8a48 (patch) | |
tree | 65d4aedec3ac8c47933bb0a5fc5e13e0f91077ed | |
parent | 91e4b22f1b3f748831962a9fcef822e30495e274 (diff) | |
download | perl-1cd372981299d0b40c75b9146dd7542e4a8b8a48.tar.gz |
add PMf_CODELIST_PRIVATE flag
This indicates that the op_code_list field in a PMOP is "private";
that is, it points to a list of DO blocks that we don't own, and
shouldn't free, and whose pad may not match ours.
This will allow us to use the op_code_list field in the runtime case of
literal code, e.g. /$runtime(?{...})/ and qr/$runtime(?{...})/. Here, at
compile-time, we need to make the pre-compiled (?{..}) blocks available to
pp_regcomp, but the list containing those blocks is also the list that is
executed in the lead-up to executing pp_regcomp (while skipping the DO
blocks), so the code is already embedded, and doesn't need freeing.
Furthermore, in the qr// case, the code blocks are actually within a
different sub (an anon one) than the PMOP, so the pads won't match.
-rw-r--r-- | dump.c | 10 | ||||
-rw-r--r-- | op.c | 9 | ||||
-rw-r--r-- | op.h | 6 |
3 files changed, 21 insertions, 4 deletions
@@ -614,8 +614,13 @@ Perl_do_pmop_dump(pTHX_ I32 level, PerlIO *file, const PMOP *pm) op_dump(pm->op_pmreplrootu.op_pmreplroot); } if (pm->op_code_list) { - Perl_dump_indent(aTHX_ level, file, "CODE_LIST =\n"); - do_op_dump(level, file, pm->op_code_list); + if (pm->op_pmflags & PMf_CODELIST_PRIVATE) { + Perl_dump_indent(aTHX_ level, file, "CODE_LIST =\n"); + do_op_dump(level, file, pm->op_code_list); + } + else + Perl_dump_indent(aTHX_ level, file, "CODE_LIST = 0x%"UVxf"\n", + PTR2UV(pm->op_code_list)); } if (pm->op_pmflags || (PM_GETRE(pm) && RX_CHECK_SUBSTR(PM_GETRE(pm)))) { SV * const tmpsv = pm_description(pm); @@ -635,6 +640,7 @@ const struct flag_to_name pmflags_flags_names[] = { {PMf_EVAL, ",EVAL"}, {PMf_NONDESTRUCT, ",NONDESTRUCT"}, {PMf_HAS_CV, ",HAS_CV"}, + {PMf_CODELIST_PRIVATE, "PMf_CODELIST_PRIVATE"} }; static SV * @@ -677,7 +677,8 @@ Perl_op_clear(pTHX_ OP *o) case OP_MATCH: case OP_QR: clear_pmop: - op_free(cPMOPo->op_code_list); + if (!(cPMOPo->op_pmflags & PMf_CODELIST_PRIVATE)) + op_free(cPMOPo->op_code_list); cPMOPo->op_code_list = NULL; forget_pmop(cPMOPo, 1); cPMOPo->op_pmreplrootu.op_pmreplroot = NULL; @@ -4405,6 +4406,12 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor) if (reglist) op_null(expr); + if (has_code) { + pm->op_code_list = expr; + /* don't free op_code_list; its ops are embedded elsewhere too */ + pm->op_pmflags |= PMf_CODELIST_PRIVATE; + } + if (pm->op_pmflags & PMf_KEEP || !(PL_hints & HINT_RE_EVAL)) expr = newUNOP((!(PL_hints & HINT_RE_EVAL) ? OP_REGCRESET @@ -434,7 +434,11 @@ struct pmop { /* the pattern has a CV attached (currently only under qr/...(?{}).../) */ #define PMf_HAS_CV (1<<(PMf_BASE_SHIFT+10)) -#if PMf_BASE_SHIFT+10 > 31 +/* op_code_list is private; don't free it etc. It may well point to + * code within another sub, with different pad etc */ +#define PMf_CODELIST_PRIVATE (1<<(PMf_BASE_SHIFT+11)) + +#if PMf_BASE_SHIFT+11 > 31 # error Too many PMf_ bits used. See above and regnodes.h for any spare in middle #endif |