diff options
author | Vincent Pit <perl@profvince.com> | 2008-12-28 15:08:05 +0100 |
---|---|---|
committer | Vincent Pit <perl@profvince.com> | 2008-12-28 15:46:41 +0100 |
commit | 4ad10a0b60fb728d1be0a9eeb1970166a3846d38 (patch) | |
tree | 1d837e46785bb215c2744c7becf85e3c71bcc8e3 /pp_hot.c | |
parent | c68ec7a9f950f968bb39608a47e0228e03511a18 (diff) | |
download | perl-4ad10a0b60fb728d1be0a9eeb1970166a3846d38.tar.gz |
On scope end, delete localized array elements that should not exist anymore, so that the array recovers its previous length. Honour EXISTS and DELETE for tied arrays.
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 23 |
1 files changed, 21 insertions, 2 deletions
@@ -2913,6 +2913,8 @@ PP(pp_aelem) AV *const av = MUTABLE_AV(POPs); const U32 lval = PL_op->op_flags & OPf_MOD || LVRET; const U32 defer = (PL_op->op_private & OPpLVAL_DEFER) && (elem > av_len(av)); + const bool localizing = PL_op->op_private & OPpLVAL_INTRO; + bool preeminent = TRUE; SV *sv; if (SvROK(elemsv) && !SvGAMAGIC(elemsv) && ckWARN(WARN_MISC)) @@ -2923,6 +2925,19 @@ PP(pp_aelem) elem -= CopARYBASE_get(PL_curcop); if (SvTYPE(av) != SVt_PVAV) RETPUSHUNDEF; + + if (localizing) { + MAGIC *mg; + HV *stash; + + /* If we can determine whether the element exist, + * Try to preserve the existenceness of a tied array + * element by using EXISTS and DELETE if possible. + * Fallback to FETCH and STORE otherwise. */ + if (SvCANEXISTDELETE(av)) + preeminent = av_exists(av, elem); + } + svp = av_fetch(av, elem, lval && !defer); if (lval) { #ifdef PERL_MALLOC_WRAP @@ -2952,8 +2967,12 @@ PP(pp_aelem) PUSHs(lv); RETURN; } - if (PL_op->op_private & OPpLVAL_INTRO) - save_aelem(av, elem, svp); + if (localizing) { + if (preeminent) + save_aelem(av, elem, svp); + else + SAVEADELETE(av, elem); + } else if (PL_op->op_private & OPpDEREF) vivify_ref(*svp, PL_op->op_private & OPpDEREF); } |