diff options
author | David Mitchell <davem@iabyn.com> | 2014-03-05 14:44:41 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-03-16 18:34:37 +0000 |
commit | 932bca295d64243e2ef2aeaacc779b68cc05e1b2 (patch) | |
tree | 8c5e02e3d9bd77cc733812159167425df1186b4f /pp_sort.c | |
parent | 22240f589eab50022218e3541b91a487c29a729b (diff) | |
download | perl-932bca295d64243e2ef2aeaacc779b68cc05e1b2.tar.gz |
OP_SORT: store start of block in null->op_next
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.
Diffstat (limited to 'pp_sort.c')
-rw-r--r-- | pp_sort.c | 7 |
1 files changed, 3 insertions, 4 deletions
@@ -1512,10 +1512,9 @@ PP(pp_sort) SAVEVPTR(PL_sortcop); if (flags & OPf_STACKED) { if (flags & OPf_SPECIAL) { - OP *kid = cLISTOP->op_first->op_sibling; /* pass pushmark */ - kid = kUNOP->op_first; /* pass rv2gv */ - kid = kUNOP->op_first; /* pass leave */ - PL_sortcop = kid->op_next; + OP *nullop = cLISTOP->op_first->op_sibling; /* pass pushmark */ + assert(nullop->op_type == OP_NULL); + PL_sortcop = nullop->op_next; } else { GV *autogv = NULL; |