summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-07-17 17:51:57 +0100
committerDavid Mitchell <davem@iabyn.com>2017-07-27 11:30:24 +0100
commitaf3b1cba4fa1f9302496ccf5135bf61703227009 (patch)
treed84ea620b9bf30b1356fc690e4d1313f94ba0cfa /hv.c
parente84e4286916d8a219c8a63468807b41df9cde7fe (diff)
downloadperl-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.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/hv.c b/hv.c
index 1c339d5c73..37518c4ff4 100644
--- a/hv.c
+++ b/hv.c
@@ -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