X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2Fautovivification.git;a=blobdiff_plain;f=autovivification.xs;h=e36b8f50dfc6f1ed7bdfec6f3c6d3a0b1df5a339;hp=98140687672dd2512a136a8f79186ea472d2b87a;hb=0b4ae66b743ee623cdfdb7cdbea5c84338f9e3d9;hpb=46e0ea48eeda37d558ae27bfc983da47245c9777 diff --git a/autovivification.xs b/autovivification.xs index 9814068..e36b8f5 100644 --- a/autovivification.xs +++ b/autovivification.xs @@ -21,22 +21,6 @@ #define A_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) -#define A_HAS_PERL_EXACT(R, V, S) ((PERL_REVISION == (R)) && (PERL_VERSION == (V)) && (PERL_SUBVERSION == (S))) - -#undef ENTERn -#if defined(ENTER_with_name) && !A_HAS_PERL(5, 11, 4) -# define ENTERn(N) ENTER_with_name(N) -#else -# define ENTERn(N) ENTER -#endif - -#undef LEAVEn -#if defined(LEAVE_with_name) && !A_HAS_PERL(5, 11, 4) -# define LEAVEn(N) LEAVE_with_name(N) -#else -# define LEAVEn(N) LEAVE -#endif - #ifndef A_WORKAROUND_REQUIRE_PROPAGATION # define A_WORKAROUND_REQUIRE_PROPAGATION !A_HAS_PERL(5, 10, 1) #endif @@ -123,18 +107,15 @@ typedef struct { #endif /* A_WORKAROUND_REQUIRE_PROPAGATION */ -#if !A_HAS_RPEEP - #define PTABLE_NAME ptable_seen #define PTABLE_VAL_FREE(V) NOOP #include "ptable.h" -#endif /* !A_HAS_RPEEP */ - -#define A_NEED_CXT ((A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION) || !A_HAS_RPEEP) - -#if A_NEED_CXT +/* PerlMemShared_free() needs the [ap]PTBLMS_? default values */ +#define ptable_seen_store(T, K, V) ptable_seen_store(aPTBLMS_ (T), (K), (V)) +#define ptable_seen_clear(T) ptable_seen_clear(aPTBLMS_ (T)) +#define ptable_seen_free(T) ptable_seen_free(aPTBLMS_ (T)) #define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION @@ -143,9 +124,7 @@ typedef struct { ptable *tbl; /* It really is a ptable_hints */ tTHX owner; #endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */ -#if !A_HAS_RPEEP ptable *seen; /* It really is a ptable_seen */ -#endif /* !A_HAS_RPEEP */ } my_cxt_t; START_MY_CXT @@ -155,11 +134,11 @@ START_MY_CXT #if A_WORKAROUND_REQUIRE_PROPAGATION typedef struct { - ptable *tbl; + ptable *tbl; #if A_HAS_PERL(5, 13, 2) CLONE_PARAMS *params; #else - CLONE_PARAMS params; + CLONE_PARAMS params; #endif } a_ptable_clone_ud; @@ -201,15 +180,11 @@ STATIC void a_thread_cleanup(pTHX_ void *ud) { #if A_WORKAROUND_REQUIRE_PROPAGATION ptable_hints_free(MY_CXT.tbl); #endif /* A_WORKAROUND_REQUIRE_PROPAGATION */ -#if !A_HAS_RPEEP ptable_seen_free(MY_CXT.seen); -#endif /* !A_HAS_RPEEP */ } #endif /* A_THREADSAFE */ -#endif /* A_NEED_CXT */ - #if A_WORKAROUND_REQUIRE_PROPAGATION STATIC IV a_require_tag(pTHX) { @@ -259,19 +234,19 @@ get_enclosing_cv: STATIC SV *a_tag(pTHX_ UV bits) { #define a_tag(B) a_tag(aTHX_ (B)) a_hint_t *h; -#if A_THREADSAFE - dMY_CXT; -#endif h = PerlMemShared_malloc(sizeof *h); h->bits = bits; h->require_tag = a_require_tag(); #if A_THREADSAFE - /* We only need for the key to be an unique tag for looking up the value later. - * Allocated memory provides convenient unique identifiers, so that's why we - * use the hint as the key itself. */ - ptable_hints_store(MY_CXT.tbl, h, h); + { + dMY_CXT; + /* We only need for the key to be an unique tag for looking up the value later + * Allocated memory provides convenient unique identifiers, so that's why we + * use the hint as the key itself. */ + ptable_hints_store(MY_CXT.tbl, h, h); + } #endif /* A_THREADSAFE */ return newSViv(PTR2IV(h)); @@ -280,16 +255,16 @@ STATIC SV *a_tag(pTHX_ UV bits) { STATIC UV a_detag(pTHX_ const SV *hint) { #define a_detag(H) a_detag(aTHX_ (H)) a_hint_t *h; -#if A_THREADSAFE - dMY_CXT; -#endif if (!(hint && SvIOK(hint))) return 0; h = INT2PTR(a_hint_t *, SvIVX(hint)); #if A_THREADSAFE - h = ptable_fetch(MY_CXT.tbl, h); + { + dMY_CXT; + h = ptable_fetch(MY_CXT.tbl, h); + } #endif /* A_THREADSAFE */ if (a_require_tag() != h->require_tag) @@ -309,7 +284,7 @@ STATIC UV a_detag(pTHX_ const SV *hint) { ? SvUVX(H) \ : (SvPOK(H) \ ? sv_2uv(SvLEN(H) ? (H) : sv_mortalcopy(H)) \ - : 0 \ + : 0 \ ) \ ) \ : 0) @@ -345,7 +320,7 @@ STATIC UV a_hint(pTHX) { 0, a_hash); #else - SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, a_hash); + SV **val = hv_fetch(GvHV(PL_hintgv), __PACKAGE__, __PACKAGE_LEN__, 0); if (!val) return 0; hint = *val; @@ -356,9 +331,9 @@ STATIC UV a_hint(pTHX) { /* ... op => info map ...................................................... */ typedef struct { - OP *(*old_pp)(pTHX); - UV flags; - void *next; + OP *(*old_pp)(pTHX); + void *next; + UV flags; } a_op_info; #define PTABLE_NAME ptable_map @@ -368,6 +343,7 @@ typedef struct { /* 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)) STATIC ptable *a_op_map = NULL; @@ -615,8 +591,6 @@ STATIC OP *a_pp_rv2av(pTHX) { PUSHs(av); RETURN; } - } else { - PL_op->op_ppaddr = oi->old_pp; } return oi->old_pp(aTHX); @@ -634,8 +608,6 @@ STATIC OP *a_pp_rv2hv_simple(pTHX) { if (oi->flags & A_HINT_DEREF) { if (a_undef(TOPs)) RETURN; - } else { - PL_op->op_ppaddr = oi->old_pp; } return oi->old_pp(aTHX); @@ -656,8 +628,6 @@ STATIC OP *a_pp_rv2hv(pTHX) { PUSHs(hv); RETURN; } - } else { - PL_op->op_ppaddr = oi->old_pp; } return oi->old_pp(aTHX); @@ -672,17 +642,12 @@ STATIC OP *a_pp_deref(pTHX) { dSP; oi = a_map_fetch(PL_op); - flags = oi->flags; + flags = oi->flags; if (flags & A_HINT_DEREF) { OP *o; - U8 old_private; -deref: - old_private = PL_op->op_private; - PL_op->op_private = ((old_private & ~OPpDEREF) | OPpLVAL_DEFER); o = oi->old_pp(aTHX); - PL_op->op_private = old_private; if (flags & (A_HINT_NOTIFY|A_HINT_STORE)) { SPAGAIN; @@ -697,21 +662,8 @@ deref: } return o; - } else if ((flags & ~A_HINT_ROOT) - && (PL_op->op_private & OPpDEREF || flags & A_HINT_ROOT)) { - /* Decide if the expression must autovivify or not. - * This branch should be called only once by expression. */ - flags = a_map_resolve(PL_op, oi); - - /* We need the updated flags value in the deref branch. */ - if (flags & A_HINT_DEREF) - goto deref; } - /* This op doesn't need to skip autovivification, so restore the original - * state. */ - PL_op->op_ppaddr = oi->old_pp; - return oi->old_pp(aTHX); } @@ -981,31 +933,19 @@ STATIC OP *a_ck_root(pTHX_ OP *o) { STATIC peep_t a_old_peep = 0; /* This is actually the rpeep past 5.13.5 */ -#if !A_HAS_RPEEP -# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen) -#else /* !A_HAS_RPEEP */ -# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o) -#endif /* A_HAS_RPEEP */ - -A_PEEP_REC_PROTO; -A_PEEP_REC_PROTO { -#if !A_HAS_RPEEP -# define a_peep_rec(O) a_peep_rec(aTHX_ (O), seen) -#else /* !A_HAS_RPEEP */ -# define a_peep_rec(O) a_peep_rec(aTHX_ (O)) -#endif /* A_HAS_RPEEP */ - dA_MAP_THX; - const a_op_info *oi; - -#if !A_HAS_RPEEP - if (ptable_fetch(seen, o)) - return; -#endif +STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen); +STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen) { +#define a_peep_rec(O) a_peep_rec(aTHX_ (O), seen) for (; o; o = o->op_next) { -#if !A_HAS_RPEEP + dA_MAP_THX; + const a_op_info *oi = NULL; + UV flags = 0; + + if (ptable_fetch(seen, o)) + break; ptable_seen_store(seen, o, o); -#endif + switch (o->op_type) { case OP_PADSV: if (o->op_ppaddr != a_pp_deref) { @@ -1015,6 +955,39 @@ A_PEEP_REC_PROTO { o->op_ppaddr = a_pp_deref; } } + /* FALLTHROUGH */ + case OP_AELEM: + case OP_AELEMFAST: + case OP_HELEM: + case OP_RV2SV: + if (o->op_ppaddr != a_pp_deref) + break; + oi = a_map_fetch(o); + if (!oi) + break; + flags = oi->flags; + if (!(flags & A_HINT_DEREF) + && (flags & A_HINT_DO) + && (o->op_private & OPpDEREF || flags & A_HINT_ROOT)) { + /* Decide if the expression must autovivify or not. */ + flags = a_map_resolve(o, oi); + } + if (flags & A_HINT_DEREF) + o->op_private = ((o->op_private & ~OPpDEREF) | OPpLVAL_DEFER); + else + o->op_ppaddr = oi->old_pp; + break; + case OP_RV2AV: + case OP_RV2HV: + if ( o->op_ppaddr != a_pp_rv2av + && o->op_ppaddr != a_pp_rv2hv + && o->op_ppaddr != a_pp_rv2hv_simple) + break; + oi = a_map_fetch(o); + if (!oi) + break; + if (!(oi->flags & A_HINT_DEREF)) + o->op_ppaddr = oi->old_pp; break; #if !A_HAS_RPEEP case OP_MAPWHILE: @@ -1057,22 +1030,14 @@ A_PEEP_REC_PROTO { } STATIC void a_peep(pTHX_ OP *o) { -#if !A_HAS_RPEEP dMY_CXT; ptable *seen = MY_CXT.seen; - ptable_seen_clear(seen); -#endif /* !A_HAS_RPEEP */ - -#if A_HAS_PERL_EXACT(5, 8, 2) - /* 5.8.2's peephole optimizer has a naughty bug with stub ops coming from - * sub { }. */ - a_peep_rec(o); - a_old_peep(aTHX_ o); -#else a_old_peep(aTHX_ o); + + ptable_seen_clear(seen); a_peep_rec(o); -#endif + ptable_seen_clear(seen); } /* --- Interpreter setup/teardown ------------------------------------------ */ @@ -1089,17 +1054,13 @@ STATIC void a_teardown(pTHX_ void *root) { return; #endif -#if A_NEED_CXT { dMY_CXT; # if A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION ptable_hints_free(MY_CXT.tbl); # endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */ -# if !A_HAS_RPEEP ptable_seen_free(MY_CXT.seen); -# endif /* !A_HAS_RPEEP */ } -#endif /* A_NEED_CXT */ PL_check[OP_PADANY] = MEMBER_TO_FPTR(a_old_ck_padany); a_old_ck_padany = 0; @@ -1147,18 +1108,14 @@ STATIC void a_setup(pTHX) { if (a_initialized) return; -#if A_NEED_CXT { MY_CXT_INIT; # if A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION MY_CXT.tbl = ptable_new(); MY_CXT.owner = aTHX; # endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */ -# if !A_HAS_RPEEP MY_CXT.seen = ptable_new(); -# endif /* !A_RPEEP */ } -#endif /* A_NEED_CXT */ a_old_ck_padany = PL_check[OP_PADANY]; PL_check[OP_PADANY] = MEMBER_TO_FPTR(a_ck_padany); @@ -1243,7 +1200,7 @@ BOOT: a_setup(); } -#if A_THREADSAFE && (A_WORKAROUND_REQUIRE_PROPAGATION || !A_HAS_RPEEP) +#if A_THREADSAFE void CLONE(...) @@ -1252,9 +1209,7 @@ PREINIT: #if A_WORKAROUND_REQUIRE_PROPAGATION ptable *t; #endif -#if !A_HAS_RPEEP ptable *s; -#endif PPCODE: { dMY_CXT; @@ -1268,9 +1223,7 @@ PPCODE: a_ptable_clone_ud_deinit(ud); } #endif -#if !A_HAS_RPEEP s = ptable_new(); -#endif } { MY_CXT_CLONE; @@ -1278,14 +1231,12 @@ PPCODE: MY_CXT.tbl = t; MY_CXT.owner = aTHX; #endif -#if !A_HAS_RPEEP MY_CXT.seen = s; -#endif } reap(3, a_thread_cleanup, NULL); XSRETURN(0); -#endif +#endif /* A_THREADSAFE */ SV * _tag(SV *hint)