X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Fautovivification.git;a=blobdiff_plain;f=autovivification.xs;h=9884389bd99370dd398e8a812bfd88e6172d4bcf;hp=23e20729b5db4e3c8b78c08a42c00e219de3b56a;hb=aae04e46de5be0dc7e9abfc02035b6bb09aea6a7;hpb=73772795ebcb8df2c461e190ec0b90b02617144f diff --git a/autovivification.xs b/autovivification.xs index 23e2072..9884389 100644 --- a/autovivification.xs +++ b/autovivification.xs @@ -41,6 +41,49 @@ # endif #endif +/* ... Our vivify_ref() .................................................... */ + +/* Perl_vivify_ref() is not exported, so we have to reimplement it. */ + +#if A_HAS_MULTIDEREF + +static SV *a_vivify_ref(pTHX_ SV *sv, int to_hash) { +#define a_vivify_ref(S, TH) a_vivify_ref(aTHX_ (S), (TH)) + SvGETMAGIC(sv); + + if (!SvOK(sv)) { + SV *val; + + if (SvREADONLY(sv)) + Perl_croak_no_modify(); + + /* Inlined prepare_SV_for_RV() */ + if (SvTYPE(sv) < SVt_PV && SvTYPE(sv) != SVt_IV) { + sv_upgrade(sv, SVt_IV); + } else if (SvTYPE(sv) >= SVt_PV) { + SvPV_free(sv); + SvLEN_set(sv, 0); + SvCUR_set(sv, 0); + } + + val = to_hash ? MUTABLE_SV(newHV()) : MUTABLE_SV(newAV()); + SvRV_set(sv, val); + SvROK_on(sv); + SvSETMAGIC(sv); + SvGETMAGIC(sv); + } + + if (SvGMAGICAL(sv)) { + SV *msv = sv_newmortal(); + sv_setsv_nomg(msv, sv); + return msv; + } + + return sv; +} + +#endif /* A_HAS_MULTIDEREF */ + /* ... Thread safety and multiplicity ...................................... */ /* Always safe when the workaround isn't needed */ @@ -160,7 +203,8 @@ static I32 a_loaded = 0; #if A_THREADSAFE #define PTABLE_NAME ptable_loaded -#define PTABLE_VAL_FREE(V) NOOP +#define PTABLE_NEED_DELETE 1 +#define PTABLE_NEED_WALK 0 #include "ptable.h" @@ -241,6 +285,8 @@ typedef struct { #define PTABLE_NAME ptable_hints #define PTABLE_VAL_FREE(V) A_HINT_FREE(V) +#define PTABLE_NEED_DELETE 0 +#define PTABLE_NEED_WALK 1 #define pPTBL pTHX #define pPTBL_ pTHX_ @@ -257,7 +303,8 @@ typedef struct { #endif /* A_WORKAROUND_REQUIRE_PROPAGATION */ #define PTABLE_NAME ptable_seen -#define PTABLE_VAL_FREE(V) NOOP +#define PTABLE_NEED_DELETE 0 +#define PTABLE_NEED_WALK 0 #include "ptable.h" @@ -479,12 +526,15 @@ typedef struct { #define PTABLE_NAME ptable_map #define PTABLE_VAL_FREE(V) PerlMemShared_free(V) +#define PTABLE_NEED_DELETE 1 +#define PTABLE_NEED_WALK 0 #include "ptable.h" /* PerlMemShared_free() needs the [ap]PTBLMS_? default values */ #define ptable_map_store(T, K, V) ptable_map_store(aPTBLMS_ (T), (K), (V)) #define ptable_map_delete(T, K) ptable_map_delete(aPTBLMS_ (T), (K)) +#define ptable_map_free(T) ptable_map_free(aPTBLMS_ (T)) static ptable *a_op_map = NULL; @@ -1019,7 +1069,7 @@ static OP *a_pp_multideref(pTHX) { if (a_undef(sv)) goto ret_undef; do_AV_vivify_rv2av_aelem: - sv = Perl_vivify_ref(aTHX_ sv, OPpDEREF_AV); + sv = a_vivify_ref(sv, 0); do_AV_rv2av_aelem: sv = a_do_pp_rv2av(sv); do_AV_aelem: @@ -1098,7 +1148,7 @@ check_elem: if (a_undef(sv)) goto ret_undef; do_HV_vivify_rv2hv_helem: - sv = Perl_vivify_ref(aTHX_ sv, OPpDEREF_HV); + sv = a_vivify_ref(sv, 1); do_HV_rv2hv_helem: sv = a_do_pp_rv2hv(sv); do_HV_helem: @@ -1252,14 +1302,19 @@ static OP *a_ck_deref(pTHX_ OP *o) { } o = old_ck(aTHX_ o); - if (hint & A_HINT_DO) { #if A_HAS_MULTIDEREF - if (old_ck == a_old_ck_rv2sv && o->op_flags & OPf_KIDS) { - OP *kid = cUNOPo->op_first; - if (kid && kid->op_type == OP_GV) + if (old_ck == a_old_ck_rv2sv && o->op_flags & OPf_KIDS) { + OP *kid = cUNOPo->op_first; + if (kid && kid->op_type == OP_GV) { + if (hint & A_HINT_DO) a_map_store(kid, kid->op_ppaddr, NULL, hint); + else + a_map_delete(kid); } + } #endif + + if (hint & A_HINT_DO) { a_map_store_root(o, o->op_ppaddr, hint); o->op_ppaddr = a_pp_deref; } else @@ -1558,6 +1613,10 @@ static void a_teardown(pTHX_ void *root) { ptable_map_free(a_op_map); a_op_map = NULL; + +#ifdef USE_ITHREADS + MUTEX_DESTROY(&a_op_map_mutex); +#endif } A_LOADED_UNLOCK; @@ -1592,6 +1651,7 @@ static void a_setup(pTHX) { PERL_HASH(a_hash, __PACKAGE__, __PACKAGE_LEN__); a_op_map = ptable_new(); + #ifdef USE_ITHREADS MUTEX_INIT(&a_op_map_mutex); #endif