summaryrefslogtreecommitdiff
path: root/op.c
Commit message (Collapse)AuthorAgeFilesLines
* Revert "[perl #79908] Stop sub inlining from breaking closures"Ævar Arnfjörð Bjarmason2014-05-121-3/+54
| | | | | | | | | | | | | | | | | | | | | | | | This reverts commit 137da2b05b4b7628115049f343163bdaf2c30dbb. See the "How about having a recommended way to add constant subs dynamically?" thread on perl5-porters, specifically while it sucks that we have this bug, it's been documented to work this way since 5.003 in "Constant Functions" in perlsub: If the result after optimization and constant folding is either a constant or a lexically-scoped scalar which has no other references, then it will be used in place of function calls made without C<&> -- http://perldoc.perl.org/perlsub.html#Constant-Functions Since we've had this documented bug for a long time we should introduce this fix in a deprecation cycle rather than silently slowing down code that assumes it's going to be optimized by constant folding. I didn't revert the tests it t/op/sub.t, but turned them into TODO tests instead. Conflicts: t/op/sub.t
* elide "empty" ops at the head of op_next chainsDavid Mitchell2014-03-161-6/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently all OP_NULL/OP_SCOPE/OP_SCALAR/OP_LINESEQ ops (which all map at run time to pp_null()) are eliminated from op_next chains *except* ones at the head of a chain (e.g. pointed to by o->op_other). The API of peep()/rpeep() makes it difficult to directly do this within the function itself, as it has no return value - and thus RPEEP(o->op_other) has no way to update op_other to skip the first op if it happens to be a null or whatever. Instead, we add a small helper function, S_prune_chain_head(), and always call it after we call peep, e.g. CALL_PEEP(PL_main_start); finalize_optree(PL_main_root); +S_prune_chain_head(aTHX_ &PL_main_start); rpeep() is also complicated by its recursion reduction mechanism, where it saves the addresses of several ops before recursing on them. I had to change this so that it saves the addresses of the addresses of the ops instead, so they can be updated: i.e. rather than saving o->op_other, it saves &(o->op_other). With this commit, nothing in the test suite triggers executing pp_null(), execpt OP_REGCMAYBE and S_fold_constants(). I verified this with the following hacky diff: >>>>diff --git a/op.c b/op.c >>>>index 716c684..819a717 100644 >>>>--- a/op.c >>>>+++ b/op.c >>>>@@ -3489,6 +3489,7 @@ S_op_integerize(pTHX_ OP *o) >>>> return o; >>>> } >>>> >>>>+int XXX_folding = 0; >>>> static OP * >>>> S_fold_constants(pTHX_ OP *o) >>>> { >>>>@@ -3504,6 +3505,7 @@ S_fold_constants(pTHX_ OP *o) >>>> SV * const olddiehook = PL_diehook; >>>> COP not_compiling; >>>> dJMPENV; >>>>+ int XXX_folding_old = XXX_folding; >>>> >>>> PERL_ARGS_ASSERT_FOLD_CONSTANTS; >>>> >>>>@@ -3583,11 +3585,13 @@ S_fold_constants(pTHX_ OP *o) >>>> assert(IN_PERL_RUNTIME); >>>> PL_warnhook = PERL_WARNHOOK_FATAL; >>>> PL_diehook = NULL; >>>>+ XXX_folding = 1; >>>> JMPENV_PUSH(ret); >>>> >>>> switch (ret) { >>>> case 0: >>>> CALLRUNOPS(aTHX); >>>>+ XXX_folding = XXX_folding_old; >>>> sv = *(PL_stack_sp--); >>>> if (o->op_targ && sv == PAD_SV(o->op_targ)) { /* grab pad temp? */ >>>> #ifdef PERL_MAD >>>>@@ -3608,10 +3612,12 @@ S_fold_constants(pTHX_ OP *o) >>>> case 3: >>>> /* Something tried to die. Abandon constant folding. */ >>>> /* Pretend the error never happened. */ >>>>+ XXX_folding = XXX_folding_old; >>>> CLEAR_ERRSV(); >>>> o->op_next = old_next; >>>> break; >>>> default: >>>>+ XXX_folding = XXX_folding_old; >>>> JMPENV_POP; >>>> /* Don't expect 1 (setjmp failed) or 2 (something called my_exit) */ >>>> PL_warnhook = oldwarnhook; >>>>diff --git a/pp_hot.c b/pp_hot.c >>>>index 36eac2b..ccb582f 100644 >>>>--- a/pp_hot.c >>>>+++ b/pp_hot.c >>>>@@ -68,9 +68,16 @@ PP(pp_gvsv) >>>> RETURN; >>>> } >>>> >>>>+extern int XXX_folding; >>>> PP(pp_null) >>>> { >>>> dVAR; >>>>+ if (!XXX_folding && PL_op->op_type != OP_REGCMAYBE) { >>>>+ sv_dump((SV*)find_runcv(0)); >>>>+ op_dump(PL_op); >>>>+ op_dump((OP*)PL_curcop); >>>>+ assert(0); >>>>+ } >>>> return NORMAL; >>>> } >>>>
* rpeep(): elide just-nulled opsDavid Mitchell2014-03-161-2/+27
| | | | | | | | | | | | Perl_rpeep() currently spots "empty" ops like OP_NULL, OP_SCOPE and elides them from the op_next chain (by setting oldop->op_next to point to the op following the current op). However, if rpeep() itself op_null()'s the current op, then when the main loop is re-entered, that mechanism is bypassed. Modify re-entry to the loop in this case so that the just nulled op re-processed and thus elided. (Also document what the OP_SASSIGN/OP_SUBSTR optimisation is doing; studying that was what originally led me to this general fix.)
* rpeep(): remove trailing OP_NULLs etcDavid Mitchell2014-03-161-1/+1
| | | | | | | | Perl_rpeep() elides OP_NULLs etc in the middle of an op_next chain, but not at the start or end. Doing it at the start is hard (and not addressed here); doing it at the end is trivial, and it just looks like a mistake in the original code (there since 1994) that was (incorrectly) worried about following through a null pointer.
* code following eval {} not always optimisedDavid Mitchell2014-03-161-0/+5
| | | | | | | | | | | | | | | | | In something like this eval { 1 while 1 }; $x = $a[0]; The optimising of the while loop makes Perl_rpeep() miss processing the chain of ops from the OP_LEAVETRY onwards. So in the code above for example, the alem wont be optimised into an alemfast. Fix this by explicitly recursing into the entertry->op_other branch (which actually points at the leavetry). The infinite loop above can be broken by, for example, a signal handler calling die.
* OP_SORT: store start of block in null->op_nextDavid Mitchell2014-03-161-2/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | When a sort with a code block, like sort { BLOCK } arg, ... is compiled, it comes out like sort pushmark null scope BLOCK arg ... (The 'scope' may be instead be 'ex-leave' depending on circumstances). At run time, pp_sort() navigates its way down from the sort op to find the start op of the BLOCK. We can shorten this process slightly by storing the start of BLOCK in the otherwise unused op_next field of the OP_NULL. Effectively we are using the null->op_next field as a surrogate op_other field for the op_sort (which doesn't have a spare field we could store the pointer in). The main point of this commit however is not the slight speed up from skipping a couple of pointer follows at run-time; rather that it will shortly allow us to trim any null ops from the beginning of the BLOCK. We can't do this directly, as that would involve changing the scope->op_first pointer, which might confuse B:: type modules.
* rpeep(): OP_SORT with code block has OPf_SPECIALDavid Mitchell2014-03-161-6/+21
| | | | | | | | | | | In rpeep(), we check whether the OP_SORT has a code block as the first arg (e.g. sort {BLOCK} ...) by testing for OPf_STACKED, then looking for an OP_SCOPE or ex-OP_LEAVE. However, ck_sort() has already checked for this situation and set the OPf_SPECIAL flag. So just just check for this flag in rpeep(); leave in the OP_SCOPE/ex-OP_LEAVE checks as just assertions. Also, add some commentary to ck_sort() and S_simplify_sort().
* make OP_AELEMFAST work with negative indicesDavid Mitchell2014-02-281-1/+1
| | | | | | | | | | Use aelemfast for literal index array access where the index is in the range -128..127, rather than 0..255. You'd expect something like $a[-1] or $a[-2] to be a lot more common than $a[100] say. In fact a quick CPAN grep shows 66 distributions matching /\$\w+\[\d{3,}\]/, but "at least" 1000 matching /\$\w+\[\-\d\]/. And most of the former appear to be table initialisations.
* don't set SvPADTMP() on PADGV'sDavid Mitchell2014-02-271-1/+0
| | | | | | | | | | | | | | | | | | | | | | | Under threaded builds, GVs for OPs are stored in the pad rather than being directly attached to the op. For some reason, all such GV's were getting the SvPADTMP flag set. There seems to be be no good reason for this, and after skipping setting the flag, all tests still pass. The advantage of not setting this flag is that there are quite a few hot places in the code that do if (SvPADTMP(sv) && !IS_PADGV(sv)) { ... I've replaced them all with if (SvPADTMP(sv)) { assert(!IS_PADGV(sv)); ... Since the IS_PADGV() macro expands to something quite heavyweight, this is quite a saving: for example this commit reduces the size of pp_entersub by 111 bytes.
* Remove spurious assertSteffen Mueller2014-02-271-3/+1
| | | | kid is always dereferenced before the assert.
* List-OP removal: Fix compile fail on C90Steffen Mueller2014-02-261-1/+3
| | | | | | Apologies. I'd applied Reini's patch to my optimization branch. I think it got lost when I switched to Dave's variant my original code (which didn't have Reini's C90 fix). Sorry!
* Optimization: Remove needless list/pushmark pairs from the OP executionSteffen Mueller2014-02-261-5/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is an optimization for OP trees that involve list OPs in list context. In list context, the list OP's first child, a pushmark, will do what its name claims and push a mark to the mark stack, indicating the start of a list of parameters to another OP. Then the list's other child OPs will do their stack pushing. Finally, the list OP will be executed and do nothing but undo what the pushmark has done. This is because the main effect of the list OP only really kicks in if it's not in array context (actually, it should probably only kick in if it's in scalar context, but I don't know of any valid examples of list OPs in void contexts). This optimization is quite a measurable speed-up for array or hash slicing and some other situations. Another (contrived) example is that (1,2,(3,4)) now actually is the same, performance-wise as (1,2,3,4), albeit that's rarely relevant. The price to pay for this is a slightly convoluted (by standards other than the perl core) bit of optimization logic that has to do minor look-ahead on certain OPs in the peephole optimizer. A number of tests failed after the first attack on this problem. The failures were in two categories: a) Tests that are sensitive to details of the OP tree structure and did verbatim text comparisons of B::Concise output (ouch). These are just patched according to the new red in this commit. b) Test that validly failed because certain conditions in op.c were expecting OP_LISTs where there are now OP_NULLs (with op_targ=OP_LIST). For these, the respective conditions in op.c were adjusted. The change includes modifying B::Deparse to handle the new OP tree structure in the face of nulled OP_LISTs.
* Macro for common OP checks: "is this X or was it before NULLing?"Steffen Mueller2014-02-261-2/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | For example, if (OP_TYPE_IS_OR_WAS(o, OP_LIST)) ... is now available instead of either of the following: if ( o && ( o->op_type == OP_LIST || (o->op_type == OP_NULL && o->op_targ == OP_LIST) ) ) ... if ( o && (o->op_type == OP_NULL ? o->op_targ ? o->op_type) == OP_LIST ) ... In case the above logic is a bit unclear: It checks whether that OP is an OP_LIST or used to be one before being NULLed using op_null. (FTR, the resulting OP_NULLs have their op_targ set to the old OP type). This sort of check (and it's reverse "isn't and didn't use to be") are a relatively common pattern in the part of op.c that tries to intuit structures from optimization-mangled OP trees. Hopefully, using these macros will make some code a fair amount clearer.
* [perl #120939] at least fix the leak in const_av_xsubTony Cook2014-02-211-1/+1
|
* Change av_len calls to av_tindex for clarityKarl Williamson2014-02-201-1/+1
| | | | | | av_tindex is a more clearly named synonym for av_len, available starting in v5.18. This changes the core uses to it, including modules in /ext, which are not dual-lifed.
* bump to version 5.19.10 and fix the version number reference in op.cTony Cook2014-02-201-1/+1
|
* Add some examples to cv_set_call_checker and wrap_op_checkerMatthew Horsfall2014-02-111-2/+17
|
* [perl #120374] Stop for($h{k}||'') from vivifyingFather Chrysostomos2014-02-091-2/+21
| | | | | | | | | | | | | | | | | | Commit 2e73d70e52 broke this (made it vivify) by propagating lvalue context to the branches of || and && (to fix another bug). It broke App::JobLog as a result. Because foreach does not do defelem magic (i.e., it vivifies), this ends up extending vivification to happen where it did not before. Fixing foreach to do defelem magic (create ‘deferred element’ scalars, the way sub calls do, to avoid vivifying immediately) would be another way to fix this, but it is controversial. See ticket #2166. So, if either argument to || (or &&) is a vivifying op, don’t propa- gate the lvalue context, unless this is the return value of an lvalue sub (necessary for if/else with implicit return to work correctly in lvalue subs).
* Don't pull state vars into padrange opsMatthew Horsfall (alh)2014-02-031-0/+1
|
* op.c: Consistent spaces after dots in apidocsFather Chrysostomos2014-01-291-1/+2
|
* Optimisation for 'my $x; my $y;' -> 'my ($x, $y)'.Matthew Horsfall2014-01-301-0/+65
| | | | | | | | | | Brings: sub { my $x; my $y; return 1; } Up to speed with: sub { my ($x, $y); return 1; }
* Clarify op_free documentationMatthew Horsfall (alh)2014-01-301-1/+1
|
* op.c: fix grammar in apidocsFather Chrysostomos2014-01-281-1/+1
|
* document op_free and op_nullDaniel Dragan2014-01-291-0/+17
| | | | | | from https://rt.perl.org/Public/Bug/Display.html?id=121077#txn-1277679 Tony Cook: s/Neutralized/Neutralizes/
* bump version to 5.19.9!Ricardo Signes2014-01-201-1/+1
|
* Use ASSUME in op.c:newBINOPFather Chrysostomos2014-01-181-1/+1
| | | | This causes op.o to drop by 56 bytes for me under clang.
* PERL_DEBUG_READONLY_COWFather Chrysostomos2014-01-161-0/+3
| | | | | | | | | | | | | | | | | | | | | | Make perls compiled with -Accflags=-DPERL_DEBUG_READONLY_COW to turn COW buffer violations into crashes. We do this using mmap to allocate memory and then mprotect to mark memory as read-only when buffers are shared. We have to do this at the safesysmalloc level, because some code does SvPV_set with buffers it allocates on its own via safemalloc(). Unfortunately this means many things are allocated using mmap that will never be marked read-only, slowing things down considerably, but I see no other way. Because munmap and mprotect need to know the length, we use the existing sTHX/perl_memory_debug_header mechanism used already by PERL_TRACK_MEMPOOL and store the size there (as PERL_POISON already does when PERL_TRACK_MEMPOOL is enabled). perl_memory_debug_header is a struct positioned at the beginning of every allocated buffer, for tracking things.
* fix a typo in a commentRicardo Signes2014-01-151-1/+1
| | | | Spotted by Matthew Horsfall
* rename aggref warnings to autoderefRicardo Signes2014-01-141-2/+2
|
* Make key/push $scalar experimentalFather Chrysostomos2014-01-141-2/+15
| | | | | We need a better name for the experimental category, but I have not thought of one, even after sleeping on it.
* Use NOT_REACHED in one more place in op.cFather Chrysostomos2014-01-121-1/+1
| | | | | | | | | Under clang, this reduces the size of op.o by 16 bytes. $ clang -v Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) Target: x86_64-apple-darwin12.5.0 Thread model: posix
* perlapi: Consistent spaces after dotsFather Chrysostomos2013-12-291-10/+12
| | | | plus some typo fixes. I probably changed some things in perlintern, too.
* Revert "[perl #119801] Stop @DB::dbline modifications from crashing"Father Chrysostomos2013-12-251-19/+3
| | | | | | This reverts commit c1cec775e9019cc8ae244d4db239a7ea5c0b343e. See ticket #120864.
* op.c: newLOOPOP: Remove code supporting do-subFather Chrysostomos2013-12-231-1/+1
|
* [perl #115736] fix undocumented param from newATTRSUB_flagsDaniel Dragan2013-12-231-9/+3
| | | | | flags param was poorly designed and didn't have a formal api. Replace it with the bool it really is. See #115736 for details.
* [perl #119801] Stop @DB::dbline modifications from crashingFather Chrysostomos2013-12-211-3/+19
| | | | | | | | | | | | | | | | | | | | | The cop address for each breakable line was being stored in the IVX slot of ${"_<$file"}[$line]. This value itself, writable from Perl space, was being used as the address of the op to be flagged, whenever a breakpoint was set. This meant writing to ${"_<$file"}[$line] and assigning a number (like 42) would cause perl to use 42 as an op address, and crash when trying to flag the op. Furthermore, since the array holding the lines could outlive the ops, setting a breakpoint on the op could write to freed memory or to an unrelated op (even a different type), potentially changing the beha- viour of unrelated code. This commit solves those pitfalls by moving breakpoints into a global breakpoint bitfield. Dbstate ops now have an extra field on the end holding a sequence number, representing which bit holds the breakpoint for that op.
* Bump version number from 5.19.7 to 5.19.8.Abigail2013-12-201-1/+1
|
* [perl #72406] Bad read with do{} until CONSTFather Chrysostomos2013-12-151-1/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | According to the original bug report, ‘do{print("foobar");}until(1)}’ crashes. In recent perls it doesn’t, partly because of the slab allo- cator, partly because such crashes are naturally fleeting. ‘foo while bar’ and ‘foo until bar’ make their way through newLOOPOP, which then usually calls S_new_logop, to create and AND or OR op with special pointers that turn it into a loop. Because S_new_logop knows about folding ‘$x if 1’ down to a simple $x, and because ‘do{foo()} while 0’ should still execute the do block, newLOOPOP skips the call to S_new_logop in that case. Hence, it assumes that if it has seen a do block on its lhs, then S_new_logop must return an AND or OR op. ‘foo until bar’ is actually changed early on (in perly.y) to ‘foo while !bar’, before it reaches newLOOPOP. Constant folding usually folds !1 down to a simple ""/0 (actually &PL_sv_no), so newLOOPOP sees ‘foo while 0’ for ‘foo until 1’. If constant folding fails (e.g., because the parser has seen an unmatched } and constant folding is skipped after such errors), then newLOOPOP will see the unfolded !1. S_new_logop has a special optimisation that changes ‘!foo && bar’ to ‘foo || bar’, etc. That optimisation allows it to ‘see through’ the unoptimised !1 (a NOT with a CONST kid) and get to the constant, folding the resulting op and returning something that newLOOPOP is not expecting to be folded. In the case of ‘do{print("foobar");}until(1)}’, it optimises the do block away, which is wrong. So newLOOPOP reads past the end of the op in this line: o->op_next = ((LOGOP*)cUNOPo->op_first)->op_other; because it is treating an SVOP as a LOGOP. I can trigger this condition by defeating constant folding some other way. Croaking in boolean overloading, but just the first time, will do that, and crashes with blead: { package o; use overload bool => sub { die unless $::ok++; return 1 } } use constant OK => bless [], o::; do{print("foobar");}until OK; __END__ Bus error: 10 My reading of the source code leads me to believe that this bad read has been present since perl 5.000. But back then it was not possible to trigger it with this particular test case involving fatal overload- ing (as of b7f7fd0bb it seems*), but ‘do{print("foobar");}until(1)}’ would have triggered it. * Thanks to Matthew Horsfall for finding it.
* Also optimise returning lists: 'return ($one, $two);'Matthew Horsfall2013-12-141-5/+13
|
* Fix ‘Can't declare null operation in "my"’Father Chrysostomos2013-12-131-1/+7
| | | | | This message is very unhelpful. This was brought up in ticket #115688.
* op.c: Factor out two identical yyerror callsFather Chrysostomos2013-12-131-10/+12
|
* Optimise out PUSHMARK/RETURN if return is the last statement in a sub.Matthew Horsfall2013-12-131-0/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This makes: sub baz { return $cat; } Behave like: sub baz { $cat; } Which is notably faster. Unpatched: ./perl -Ilib/ ~/stuff/bench.pl Benchmark: timing 40000000 iterations of normal, ret... normal: 3 wallclock secs ( 1.60 usr + 0.01 sys = 1.61 CPU) @ 24844720.50/s (n=40000000) ret: 3 wallclock secs ( 2.08 usr + 0.00 sys = 2.08 CPU) @ 19230769.23/s (n=40000000) Patched: ./perl -Ilib ~/stuff/bench.pl Benchmark: timing 40000000 iterations of aret, normal... normal: 2 wallclock secs ( 1.72 usr + 0.00 sys = 1.72 CPU) @ 23255813.95/s (n=40000000) ret: 2 wallclock secs ( 1.72 usr + 0.00 sys = 1.72 CPU) @ 23255813.95/s (n=40000000) The difference in OP trees can be seen here: Unpatched: $ perl -MO=Concise,baz -e 'sub baz { return $cat }' main::baz: 5 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq KP ->5 1 <;> nextstate(main 1 -e:1) v ->2 4 <@> return K ->5 2 <0> pushmark s ->3 - <1> ex-rv2sv sK/1 ->4 3 <#> gvsv[*cat] s ->4 -e syntax OK Patched: $ ./perl -Ilib -MO=Concise,baz -e 'sub baz { return $cat }' main::baz: 3 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq KP ->3 1 <;> nextstate(main 1 -e:1) v ->2 - <@> return K ->- - <0> pushmark s ->2 - <1> ex-rv2sv sK/1 ->- 2 <$> gvsv(*cat) s ->3 -e syntax OK (Includes some modifications from Steffen)
* op.c: Turn on read-only flag for folded constantsFather Chrysostomos2013-11-301-1/+7
| | | | | | | They are marked PADTMP, which causes them to be copied in any contexts where readonliness makes a difference, so marking them as read-only does not change the behaviour. What it does is allow a future commit to implement string swiping for PADTMPs.
* No need to wrap calls to Perl_load_module() in ENTER/LEAVENicholas Clark2013-11-221-5/+2
| | | | | | As of commit 53a7735b62aee146 (May 2007) Perl_vload_module() wraps its call to Perl_utilize() with ENTER/LEAVE, so there's no longer a need for callers of Perl_load_module() to also wrap with ENTER/LEAVE.
* S_process_special_blocks() should use a new stack for BEGIN blocks.Nicholas Clark2013-11-221-0/+3
| | | | | | | | | | | | | | | | | | | | This avoids the stack moving underneath anything that directly or indirectly calls Perl_load_module(). [Committer’s note: This fixes bug #119993. Furthermore, under STRESS_REALLOC, t/io/layers.t was crashing like this: $ ./perl -Ilib -e ' open(UTF, "<:raw:encoding(utf8)", 'tmp75851B') or die $!; ref #blahblahblahblahblahblahblahblahblah' Segmentation fault: 11 (The comment seems to be necessary to make it crash.) It was happening because open() was causing a module to be loaded while the arguments to open() were still on the stack. ]
* Bump the perl version in various places for v5.19.7Chris 'BinGOs' Williams2013-11-201-1/+1
|
* S_already_defined no longer uses its gv parameter, remove itTony Cook2013-11-191-4/+3
|
* Optimise 'if ($a || $b)' and 'unless ($a && $b)' early exitMatthew Horsfall (alh)2013-11-191-0/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An OP_AND/OP_OR in void context provides a short circuit through ->op_other that can be used if AND/OR ops contained within it jump out early. Use that short circuit. Previously: $ ./perl -Ilib -MO=Concise -e 'if ($aa || $bb) {}' 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 3 -e:1) v:{ ->3 - <1> null vK/1 ->8 6 <|> and(other->7) vK/1 ->8 - <1> null sK/1 ->6 4 <|> or(other->5) sK/1 ->6 <-- Not optimised - <1> ex-rv2sv sK/1 ->4 3 <$> gvsv(*aa) s ->4 - <1> ex-rv2sv sK/1 ->- 5 <$> gvsv(*bb) s ->6 - <@> scope vK ->- 7 <0> stub v ->8 Now: $ ./perl -Ilib -MO=Concise -e 'if ($aa || $bb) {}' 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 3 -e:1) v:{ ->3 - <1> null vK/1 ->8 6 <|> and(other->7) vK/1 ->8 - <1> null sK/1 ->6 4 <|> or(other->5) sK/1 ->7 <-- Short circuited - <1> ex-rv2sv sK/1 ->4 3 <$> gvsv(*aa) s ->4 - <1> ex-rv2sv sK/1 ->- 5 <$> gvsv(*bb) s ->6 - <@> scope vK ->- 7 <0> stub v ->8
* op.c: diag_listed_as for Using !~ with %sFather Chrysostomos2013-11-171-0/+2
|
* Fix memory leak with recursive sub redefinitionFather Chrysostomos2013-11-161-4/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | See the thread starting at <20131115042923.7514.qmail@lists-nntp.develooper.com>. Commits 7004ee4937 and a61818571 changed subroutine redefinition to null the GvCV slot before freeing the CV, so that destructors won’t see GvCV without a reference count. That turns a double free into a memory leak. Kent Fredric explains it nice and clearly: > sub foo{} # A > bless \&foo; > DESTROY { *foo = sub {} # C } > eval "sub foo{} "; # B > > Previous behaviour was: > > B replaces A, triggers DESTROY, which triggers C replacing A, and this > invoked a double free, because C , triggering the removal of A, > happened while A still existed ( ?? ) > > So the change fixes this, so that A is removed from the symbol table > before DESTROY triggers , so that C is creating a "new" symbol, > effectively, and the problem is that C is then clobbered by the B > replacing the slot, after the DESTROY. So C leaks. This commit fixes it by changing the SvREFCNT_dec into SAVEFREESV, essentially delaying the DESTROY until after the subroutine redefini- tion is complete. This does mean that C is what ends up in the glob afterwards; but as long as perl’s own bookkeeping is thrown off, we can leave it to the user (the Perl programmer) to handle the consequences of naughty destructors.