In perl.git, the branch smueller/hash_vtable has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/cbcc509d6cd1a435393639fdd1cf0514f998a554?hp=9e821d0e5999fd089de04633c8d62a610b5d9e60>

- Log -----------------------------------------------------------------
commit cbcc509d6cd1a435393639fdd1cf0514f998a554
Author: Steffen Mueller <smuel...@cpan.org>
Date:   Thu Feb 2 18:04:39 2017 +0100

    Hash vtavbles: hv_store and friends

M       hv.c
M       hv_vtbl.c
M       hv_vtbl.h

commit edf3cb43b67f05b0f11bcb6e0ac4306ae4a122ba
Author: Steffen Mueller <smuel...@cpan.org>
Date:   Thu Feb 2 18:03:35 2017 +0100

    Hash vtables: Expose the damned flag on hv_undef

M       hv.c
M       hv_vtbl.c
M       hv_vtbl.h
-----------------------------------------------------------------------

Summary of changes:
 hv.c      | 15 ++++++++++-----
 hv_vtbl.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 hv_vtbl.h |  7 +++++--
 3 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/hv.c b/hv.c
index 4f68f92794..f65c93e83c 100644
--- a/hv.c
+++ b/hv.c
@@ -401,7 +401,13 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, 
STRLEN klen,
                                              flags, hash);
         }
         else if (action & HV_FETCH_ISSTORE) {
-            /* TODO - until then fall through */
+            assert((action & ~(HV_FETCH_ISSTORE|HV_FETCH_JUST_SV)) == 0);
+            if (action & HV_FETCH_JUST_SV) {
+                return (void *)vtable->hvt_store(hv, keysv, key, klen, flags, 
val, hash);
+            }
+            else {
+                return (void *)vtable->hvt_store_ent(hv, keysv, key, klen, 
flags, val, hash);
+            }
         }
         else if (action & HV_FETCH_JUST_SV) {
             assert((action & ~(HV_FETCH_JUST_SV|HV_FETCH_LVALUE)) == 0);
@@ -1777,9 +1783,8 @@ Perl_hv_clear(pTHX_ HV *hv)
 
     xhv = (XPVHV*)SvANY(hv);
 
-    if (HvBODYHASVTBL(xhv)) {
-        HvBODYVTBL(xhv)->hvt_clear(aTHX_ hv);
-    }
+    if (HvBODYHASVTBL(xhv))
+        return HvBODYVTBL(xhv)->hvt_clear(aTHX_ hv);
 
     /* avoid hv being freed when calling destructors below */
     EXTEND_MORTAL(1);
@@ -2018,7 +2023,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
     DEBUG_A(Perl_hv_assert(aTHX_ hv));
     xhv = (XPVHV*)SvANY(hv);
     if (HvBODYHASVTBL(xhv)) {
-        return HvBODYVTBL(xhv)->hvt_undef(aTHX_ hv);
+        return HvBODYVTBL(xhv)->hvt_undef(aTHX_ hv, flags);
     }
 
     save = cBOOL(SvREFCNT(hv));
diff --git a/hv_vtbl.c b/hv_vtbl.c
index 1d4b40ef3e..5a98ffb1f4 100644
--- a/hv_vtbl.c
+++ b/hv_vtbl.c
@@ -69,7 +69,7 @@ S_hv_mock_std_vtable_clear(pTHX_ HV *hv)
 }
 
 STATIC void
-S_hv_mock_std_vtable_undef(pTHX_ HV *hv)
+S_hv_mock_std_vtable_undef(pTHX_ HV *hv, U32 flags)
 {
     /* THIS IS PURELY FOR TESTING! */
     XPVHV* xhv = (XPVHV *)SvANY(hv);
@@ -80,7 +80,8 @@ S_hv_mock_std_vtable_undef(pTHX_ HV *hv)
     SAVEPPTR(vtable);
 
     xhv->xhv_vtbl = NULL;
-    hv_undef(hv);
+    /* FIXME find a way to ditch "flags"... */
+    Perl_hv_undef_flags(pTHX_ hv, flags);
 
     LEAVE;
 }
@@ -161,6 +162,65 @@ S_hv_mock_std_vtable_fetch_ent(pTHX_ HV *hv, SV *keysv, 
const char *key,
     return retval;
 }
 
+STATIC SV **
+S_hv_mock_std_vtable_store(pTHX_ HV *hv, SV *keysv,
+                            const char *key, STRLEN klen, int key_flags,
+                            SV *val, U32 hash)
+{
+    /* THIS IS PURELY FOR TESTING! */
+    SV **retval;
+    XPVHV* xhv = (XPVHV *)SvANY(hv);
+    HV_VTBL *vtable = xhv->xhv_vtbl;
+
+    ENTER;
+    /* localize vtable such that hv_common takes the normal code path */
+    SAVEPPTR(vtable);
+    xhv->xhv_vtbl = NULL;
+
+    {
+        retval = (SV **)hv_common(hv, keysv, key, klen, key_flags,
+                                  HV_FETCH_ISSTORE|HV_FETCH_JUST_SV,
+                                  val, hash);
+    }
+
+    LEAVE;
+
+    return retval;
+}
+
+
+
+/* TODO Returning a HE* is problematic for a pluggable hash implementation
+ *      since HE's are specific to perl's default implementation. So a wildly
+ *      different hash implementation would have to fake up HE's here. Sigh.
+ *      Options? Slowly try to move all uses to use the SV-fetching variant
+ *      instead? (But I assume there's some very good reasons why many places
+ *      would fetch HE's.)
+ */
+STATIC HE *
+S_hv_mock_std_vtable_store_ent(pTHX_ HV *hv, SV *keysv,
+                               const char *key, STRLEN klen, int key_flags,
+                               SV *val, U32 hash)
+{
+    /* THIS IS PURELY FOR TESTING! */
+    HE *retval;
+    XPVHV* xhv = (XPVHV *)SvANY(hv);
+    HV_VTBL *vtable = xhv->xhv_vtbl;
+
+    ENTER;
+    /* localize vtable such that hv_common takes the normal code path */
+    SAVEPPTR(vtable);
+    xhv->xhv_vtbl = NULL;
+
+    retval = (HE *)hv_common(hv, keysv, key, klen, key_flags,
+                             HV_FETCH_ISSTORE, val, hash);
+
+    LEAVE;
+
+    return retval;
+}
+
+
 STATIC bool
 S_hv_mock_std_vtable_exists(pTHX_ HV *hv, SV *keysv, const char *key,
                             STRLEN klen, int key_flags, U32 hash)
@@ -187,6 +247,8 @@ HV_VTBL PL_mock_std_vtable = {
         S_hv_mock_std_vtable_destroy,
         S_hv_mock_std_vtable_fetch,
         S_hv_mock_std_vtable_fetch_ent,
+        S_hv_mock_std_vtable_store,
+        S_hv_mock_std_vtable_store_ent,
         S_hv_mock_std_vtable_exists,
        S_hv_mock_std_vtable_delete,
        S_hv_mock_std_vtable_clear,
diff --git a/hv_vtbl.h b/hv_vtbl.h
index 71f8b44382..a0158a150a 100644
--- a/hv_vtbl.h
+++ b/hv_vtbl.h
@@ -19,7 +19,10 @@ struct hv_vtbl {
     /* fetch_flags can contain at least HV_FETCH_LVALUE and HV_FETCH_EMPTY_HE 
*/
     HE *       (*hvt_fetch_ent)(pTHX_ HV *hv, SV *keysv, const char *key, 
STRLEN klen, int key_flags, I32 fetch_flags, U32 hash);
 
-    /* TODO store */
+    /* Implements hv_store (and hv_stores) */
+    SV **      (*hvt_store)(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN 
klen, int key_flags, SV *val, U32 hash);
+    /* Implements hv_store_ent */
+    HE *       (*hvt_store_ent)(pTHX_ HV *hv, SV *keysv, const char *key, 
STRLEN klen, int key_flags, SV *val, U32 hash);
 
     /* Implements the equivalent of hv_exists(_ent) */
     bool       (*hvt_exists)(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN 
klen, int key_flags, U32 hash);
@@ -33,7 +36,7 @@ struct hv_vtbl {
      *       seems to be a "no, really do away with everything" sort of corner 
case. Need to understand
      *       significance for this much better. Is that just for stashes? But 
really, I'd hate to expose
      *       some internal hack. Needs more thinking! */
-    void       (*hvt_undef)(pTHX_ HV *hv);
+    void       (*hvt_undef)(pTHX_ HV *hv, U32 flags);
 
     /* TODO also wrap all the iteration primitives! */
     /* TODO research what other primitives are missing! */

--
Perl5 Master Repository

Reply via email to