diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-11-25 23:04:22 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-11-26 14:33:47 -0800 |
commit | 24fcb59fcc2fac06ec8b42aeedb3a16987d87db4 (patch) | |
tree | c975ed9172a79e92712e3dcba8a279bb6972bbe1 /op.h | |
parent | a74fb2cdc8f2121774cc6d2b5e9ddd01a96db467 (diff) | |
download | perl-24fcb59fcc2fac06ec8b42aeedb3a16987d87db4.tar.gz |
Optimise substr assignment in void context
In void context we can optimise
substr($foo, $bar, $baz) = $replacement;
to something like
substr($foo, $bar, $baz, $replacement);
except that the execution order must be preserved. So what we actu-
ally do is
substr($replacement, $foo, $bar, $baz);
with a flag to indicate that the replacement comes first. This means
we can also optimise assignment to two-argument substr the same way.
Although optimisations are not supposed to change behaviour,
this one does.
• It stops substr assignment from calling get-magic twice, which means
the optimisation makes things less buggy than usual.
• It causes the uninitialized warning (for an undefined first argu-
ment) to mention the substr operator, as it did before the previous
commit, rather than the assignment operator. I think that sort of
detail is minor enough.
I had to make the warning about clobbering references apply whenever
substr does a replacement, and not only when used as an lvalue. So
four-argument substr now emits that warning. I would consider that a
bug fix, too.
Also, if the numeric arguments to four-argument substr and the
replacement string are undefined, the order of the uninitialized warn-
ings is slightly different, but is consistent regardless of whether
the optimisation is in effect.
I believe this will make 95% of substr assignments run faster. So
there is less incentive to use what I consider the less readable form
(the four-argument form, which is not self-documenting).
Since I like naïve benchmarks, here are Before and After:
$ time ./miniperl -le 'do{$x="hello"; substr ($x,0,0) = 34;0}for 1..1000000'
real 0m2.391s
user 0m2.381s
sys 0m0.005s
$ time ./miniperl -le 'do{$x="hello"; substr ($x,0,0) = 34;0}for 1..1000000'
real 0m0.936s
user 0m0.927s
sys 0m0.005s
Diffstat (limited to 'op.h')
-rw-r--r-- | op.h | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -229,6 +229,10 @@ Deprecated. Use C<GIMME_V> instead. /* OP_RV2[AGH]V, OP_PAD[AH]V, OP_[AH]ELEM, OP_[AH]SLICE OP_AV2ARYLEN, OP_R?KEYS, OP_SUBSTR, OP_POS, OP_VEC */ #define OPpMAYBE_LVSUB 8 /* We might be an lvalue to return */ + + /* OP_SUBSTR only */ +#define OPpSUBSTR_REPL_FIRST 16 /* 1st arg is replacement string */ + /* OP_PADSV only */ #define OPpPAD_STATE 16 /* is a "state" pad */ /* for OP_RV2?V, lower bits carry hints (currently only HINT_STRICT_REFS) */ |