diff options
author | David Mitchell <davem@iabyn.com> | 2017-07-17 17:51:57 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-07-27 11:30:24 +0100 |
commit | af3b1cba4fa1f9302496ccf5135bf61703227009 (patch) | |
tree | d84ea620b9bf30b1356fc690e4d1313f94ba0cfa /hv.c | |
parent | e84e4286916d8a219c8a63468807b41df9cde7fe (diff) | |
download | perl-af3b1cba4fa1f9302496ccf5135bf61703227009.tar.gz |
create Perl_hv_pushkv() function
...and make pp_padhv(), pp_rv2hv() use it rather than using Perl_do_kv()
Both pp_padhv() and pp_rv2hv() (via S_padhv_rv2hv_common()), outsource to
Perl_do_kv(), the list-context pushing/flattening of a hash onto the
stack.
Perl_do_kv() is a big function that handles all the actions of
keys, values etc. Instead, create a new function which does just the
pushing of a hash onto the stack.
At the same time, split it out into two loops, one for tied, one for
normal: the untied one can skip extending the stack on each iteration,
and use a cheaper HeVAL() instead of calling hv_iterval().
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -967,6 +967,50 @@ Perl_hv_scalar(pTHX_ HV *hv) return sv; } + +/* +Pushes all the keys and values of a hash onto the stack. +Resets the hash's iterator. +The rough Perl equivalent: C< () = %hash; > +XXX this may at some point be extended to push 'keys %h' and 'values %h' +too. I might also unroll hv_iternext() - DAPM +*/ + +void +Perl_hv_pushkv(pTHX_ HV *hv) +{ + HE *entry; + bool tied = SvRMAGICAL(hv) && mg_find(MUTABLE_SV(hv), PERL_MAGIC_tied); + dSP; + + PERL_ARGS_ASSERT_HV_PUSHKV; + + (void)hv_iterinit(hv); + + if (tied) { + while ((entry = hv_iternext(hv))) { + EXTEND(SP, 2); + PUSHs(hv_iterkeysv(entry)); + PUSHs(hv_iterval(hv, entry)); + } + } + else { + SSize_t extend_size; + /* 2*HvUSEDKEYS() should never be big enough to truncate or wrap */ + assert(HvUSEDKEYS(hv) <= (SSize_t_MAX >> 1)); + extend_size = (SSize_t)HvUSEDKEYS(hv) * 2; + EXTEND(SP, extend_size); + + while ((entry = hv_iternext(hv))) { + PUSHs(hv_iterkeysv(entry)); + PUSHs(HeVAL(entry)); + } + } + + PUTBACK; +} + + /* =for apidoc hv_bucket_ratio |