This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Documentation typo fix
[perl5.git] / av.c
diff --git a/av.c b/av.c
index 18fa3c3..0029191 100644 (file)
--- a/av.c
+++ b/av.c
@@ -26,8 +26,7 @@
 void
 Perl_av_reify(pTHX_ AV *av)
 {
-    dVAR;
-    I32 key;
+    SSize_t key;
 
     PERL_ARGS_ASSERT_AV_REIFY;
     assert(SvTYPE(av) == SVt_PVAV);
@@ -40,16 +39,15 @@ Perl_av_reify(pTHX_ AV *av)
 #endif
     key = AvMAX(av) + 1;
     while (key > AvFILLp(av) + 1)
-       AvARRAY(av)[--key] = &PL_sv_undef;
+       AvARRAY(av)[--key] = NULL;
     while (key) {
        SV * const sv = AvARRAY(av)[--key];
-       assert(sv);
        if (sv != &PL_sv_undef)
-           SvREFCNT_inc_simple_void_NN(sv);
+           SvREFCNT_inc_simple_void(sv);
     }
     key = AvARRAY(av) - AvALLOC(av);
     while (key)
-       AvALLOC(av)[--key] = &PL_sv_undef;
+       AvALLOC(av)[--key] = NULL;
     AvREIFY_off(av);
     AvREAL_on(av);
 }
@@ -64,9 +62,8 @@ extended.
 */
 
 void
-Perl_av_extend(pTHX_ AV *av, I32 key)
+Perl_av_extend(pTHX_ AV *av, SSize_t key)
 {
-    dVAR;
     MAGIC *mg;
 
     PERL_ARGS_ASSERT_AV_EXTEND;
@@ -76,7 +73,7 @@ Perl_av_extend(pTHX_ AV *av, I32 key)
     if (mg) {
        SV *arg1 = sv_newmortal();
        sv_setiv(arg1, (IV)(key + 1));
-       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "EXTEND", G_DISCARD, 1,
+       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(EXTEND), G_DISCARD, 1,
                            arg1);
        return;
     }
@@ -85,17 +82,15 @@ Perl_av_extend(pTHX_ AV *av, I32 key)
 
 /* The guts of av_extend.  *Not* for general use! */
 void
-Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
+Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp,
                          SV ***arrayp)
 {
-    dVAR;
-
     PERL_ARGS_ASSERT_AV_EXTEND_GUTS;
 
     if (key > *maxp) {
        SV** ary;
-       I32 tmp;
-       I32 newmax;
+       SSize_t tmp;
+       SSize_t newmax;
 
        if (av && *allocp != *arrayp) {
            ary = *allocp + AvFILLp(av) + 1;
@@ -105,7 +100,7 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
            *arrayp = *allocp;
            if (AvREAL(av)) {
                while (tmp)
-                   ary[--tmp] = &PL_sv_undef;
+                   ary[--tmp] = NULL;
            }
            if (key > *maxp - 10) {
                newmax = key + *maxp;
@@ -113,16 +108,7 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
            }
        }
        else {
-#ifdef PERL_MALLOC_WRAP
-           static const char oom_array_extend[] =
-             "Out of memory during array extend"; /* Duplicated in pp_hot.c */
-#endif
-
            if (*allocp) {
-#if !defined(STRANGE_MALLOC) && !defined(MYMALLOC)
-               MEM_SIZE bytes;
-               IV itmp;
-#endif
 
 #ifdef Perl_safesysmalloc_size
                /* Whilst it would be quite possible to move this logic around
@@ -130,7 +116,7 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
                   based on calling Perl_safesysmalloc_size() immediately after
                   allocation, I'm not convinced that it is a great idea here.
                   In an array we have to loop round setting everything to
-                  &PL_sv_undef, which means writing to memory, potentially lots
+                  NULL, which means writing to memory, potentially lots
                   of it, whereas for the SV buffer case we don't touch the
                   "bonus" memory. So there there is no cost in telling the
                   world about it, whereas here we have to do work before we can
@@ -146,24 +132,22 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
 #endif 
                newmax = key + *maxp / 5;
              resize:
-               MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
-#if defined(STRANGE_MALLOC) || defined(MYMALLOC)
-               Renew(*allocp,newmax+1, SV*);
+               {
+#ifdef PERL_MALLOC_WRAP /* Duplicated in pp_hot.c */
+                   static const char oom_array_extend[] =
+                       "Out of memory during array extend";
+#endif
+                   MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
+               }
+#ifdef STRESS_REALLOC
+               {
+                   SV ** const old_alloc = *allocp;
+                   Newx(*allocp, newmax+1, SV*);
+                   Copy(old_alloc, *allocp, *maxp + 1, SV*);
+                   Safefree(old_alloc);
+               }
 #else
-               bytes = (newmax + 1) * sizeof(const SV *);
-#define MALLOC_OVERHEAD 16
-               itmp = MALLOC_OVERHEAD;
-               while ((MEM_SIZE)(itmp - MALLOC_OVERHEAD) < bytes)
-                   itmp += itmp;
-               itmp -= MALLOC_OVERHEAD;
-               itmp /= sizeof(const SV *);
-               assert(itmp > newmax);
-               newmax = itmp - 1;
-               assert(newmax >= *maxp);
-               Newx(ary, newmax+1, SV*);
-               Copy(*allocp, ary, *maxp+1, SV*);
-               Safefree(*allocp);
-               *allocp = ary;
+               Renew(*allocp,newmax+1, SV*);
 #endif
 #ifdef Perl_safesysmalloc_size
              resized:
@@ -178,15 +162,21 @@ Perl_av_extend_guts(pTHX_ AV *av, I32 key, SSize_t *maxp, SV ***allocp,
            }
            else {
                newmax = key < 3 ? 3 : key;
-               MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
+               {
+#ifdef PERL_MALLOC_WRAP /* Duplicated in pp_hot.c */
+                   static const char oom_array_extend[] =
+                       "Out of memory during array extend";
+#endif
+                   MEM_WRAP_CHECK_1(newmax+1, SV*, oom_array_extend);
+               }
                Newx(*allocp, newmax+1, SV*);
                ary = *allocp + 1;
                tmp = newmax;
-               *allocp[0] = &PL_sv_undef;      /* For the stacks */
+               *allocp[0] = NULL;      /* For the stacks */
            }
            if (av && AvREAL(av)) {
                while (tmp)
-                   ary[--tmp] = &PL_sv_undef;
+                   ary[--tmp] = NULL;
            }
            
            *arrayp = *allocp;
@@ -212,7 +202,7 @@ The rough perl equivalent is C<$myarray[$idx]>.
 */
 
 static bool
-S_adjust_index(pTHX_ AV *av, const MAGIC *mg, I32 *keyp)
+S_adjust_index(pTHX_ AV *av, const MAGIC *mg, SSize_t *keyp)
 {
     bool adjust_index = 1;
     if (mg) {
@@ -223,7 +213,8 @@ S_adjust_index(pTHX_ AV *av, const MAGIC *mg, I32 *keyp)
            SV * const * const negative_indices_glob =
                hv_fetchs(SvSTASH(SvRV(ref)), NEGATIVE_INDICES_VAR, 0);
 
-           if (negative_indices_glob && SvTRUE(GvSV(*negative_indices_glob)))
+           if (negative_indices_glob && isGV(*negative_indices_glob)
+            && SvTRUE(GvSV(*negative_indices_glob)))
                adjust_index = 0;
        }
     }
@@ -237,10 +228,8 @@ S_adjust_index(pTHX_ AV *av, const MAGIC *mg, I32 *keyp)
 }
 
 SV**
-Perl_av_fetch(pTHX_ AV *av, I32 key, I32 lval)
+Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval)
 {
-    dVAR;
-
     PERL_ARGS_ASSERT_AV_FETCH;
     assert(SvTYPE(av) == SVt_PVAV);
 
@@ -271,7 +260,7 @@ Perl_av_fetch(pTHX_ AV *av, I32 key, I32 lval)
            return NULL;
     }
 
-    if (key > AvFILLp(av) || AvARRAY(av)[key] == &PL_sv_undef) {
+    if (key > AvFILLp(av) || !AvARRAY(av)[key]) {
       emptyness:
        return lval ? av_store(av,key,newSV(0)) : NULL;
     }
@@ -279,7 +268,7 @@ Perl_av_fetch(pTHX_ AV *av, I32 key, I32 lval)
     if (AvREIFY(av)
             && (!AvARRAY(av)[key]      /* eg. @_ could have freed elts */
                 || SvIS_FREED(AvARRAY(av)[key]))) {
-       AvARRAY(av)[key] = &PL_sv_undef;        /* 1/2 reify */
+       AvARRAY(av)[key] = NULL;        /* 1/2 reify */
        goto emptyness;
     }
     return &AvARRAY(av)[key];
@@ -291,7 +280,7 @@ Perl_av_fetch(pTHX_ AV *av, I32 key, I32 lval)
 Stores an SV in an array.  The array index is specified as C<key>.  The
 return value will be NULL if the operation failed or if the value did not
 need to be actually stored within the array (as in the case of tied
-arrays). Otherwise, it can be dereferenced
+arrays).  Otherwise, it can be dereferenced
 to get the C<SV*> that was stored
 there (= C<val>)).
 
@@ -308,9 +297,8 @@ more information on how to use this function on tied arrays.
 */
 
 SV**
-Perl_av_store(pTHX_ AV *av, I32 key, SV *val)
+Perl_av_store(pTHX_ AV *av, SSize_t key, SV *val)
 {
-    dVAR;
     SV** ary;
 
     PERL_ARGS_ASSERT_AV_STORE;
@@ -320,9 +308,6 @@ Perl_av_store(pTHX_ AV *av, I32 key, SV *val)
        (unicode_alternate may be NULL).
     */
 
-    if (!val)
-       val = &PL_sv_undef;
-
     if (SvRMAGICAL(av)) {
         const MAGIC * const tied_magic = mg_find((const SV *)av, PERL_MAGIC_tied);
         if (tied_magic) {
@@ -330,7 +315,7 @@ Perl_av_store(pTHX_ AV *av, I32 key, SV *val)
                if (!S_adjust_index(aTHX_ av, tied_magic, &key))
                         return 0;
             }
-           if (val != &PL_sv_undef) {
+           if (val) {
                mg_copy(MUTABLE_SV(av), val, 0, key);
            }
            return NULL;
@@ -357,7 +342,7 @@ Perl_av_store(pTHX_ AV *av, I32 key, SV *val)
            if (av == PL_curstack && key > PL_stack_sp - PL_stack_base)
                PL_stack_sp = PL_stack_base + key;      /* XPUSH in disguise */
            do {
-               ary[++AvFILLp(av)] = &PL_sv_undef;
+               ary[++AvFILLp(av)] = NULL;
            } while (AvFILLp(av) < key);
        }
        AvFILLp(av) = key;
@@ -370,7 +355,7 @@ Perl_av_store(pTHX_ AV *av, I32 key, SV *val)
        bool set = TRUE;
        for (; mg; mg = mg->mg_moremagic) {
          if (!isUPPER(mg->mg_type)) continue;
-         if (val != &PL_sv_undef) {
+         if (val) {
            sv_magic(val, MUTABLE_SV(av), toLOWER(mg->mg_type), 0, key);
          }
          if (PL_delaymagic && mg->mg_type == PERL_MAGIC_isa) {
@@ -397,7 +382,7 @@ Perl equivalent: C<my @new_array = ($scalar1, $scalar2, $scalar3...);>
 */
 
 AV *
-Perl_av_make(pTHX_ I32 size, SV **strp)
+Perl_av_make(pTHX_ SSize_t size, SV **strp)
 {
     AV * const av = MUTABLE_AV(newSV_type(SVt_PVAV));
     /* sv_upgrade does AvREAL_only()  */
@@ -406,7 +391,7 @@ Perl_av_make(pTHX_ I32 size, SV **strp)
 
     if (size) {                /* "defined" was returning undef for size==0 anyway. */
         SV** ary;
-        I32 i;
+        SSize_t i;
        Newx(ary,size,SV*);
        AvALLOC(av) = ary;
        AvARRAY(av) = ary;
@@ -449,8 +434,7 @@ Perl equivalent: C<@myarray = ();>.
 void
 Perl_av_clear(pTHX_ AV *av)
 {
-    dVAR;
-    I32 extra;
+    SSize_t extra;
     bool real;
 
     PERL_ARGS_ASSERT_AV_CLEAR;
@@ -479,14 +463,14 @@ Perl_av_clear(pTHX_ AV *av)
 
     if ((real = !!AvREAL(av))) {
        SV** const ary = AvARRAY(av);
-       I32 index = AvFILLp(av) + 1;
+       SSize_t index = AvFILLp(av) + 1;
        ENTER;
        SAVEFREESV(SvREFCNT_inc_simple_NN(av));
        while (index) {
            SV * const sv = ary[--index];
            /* undef the slot before freeing the value, because a
             * destructor might try to modify this array */
-           ary[index] = &PL_sv_undef;
+           ary[index] = NULL;
            SvREFCNT_dec(sv);
        }
     }
@@ -522,7 +506,7 @@ Perl_av_undef(pTHX_ AV *av)
        av_fill(av, -1);
 
     if ((real = !!AvREAL(av))) {
-       I32 key = AvFILLp(av) + 1;
+       SSize_t key = AvFILLp(av) + 1;
        ENTER;
        SAVEFREESV(SvREFCNT_inc_simple_NN(av));
        while (key)
@@ -572,7 +556,6 @@ Perl equivalent: C<push @myarray, $elem;>.
 void
 Perl_av_push(pTHX_ AV *av, SV *val)
 {             
-    dVAR;
     MAGIC *mg;
 
     PERL_ARGS_ASSERT_AV_PUSH;
@@ -582,7 +565,7 @@ Perl_av_push(pTHX_ AV *av, SV *val)
        Perl_croak_no_modify();
 
     if ((mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied))) {
-       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "PUSH", G_DISCARD, 1,
+       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(PUSH), G_DISCARD, 1,
                            val);
        return;
     }
@@ -604,7 +587,6 @@ Perl equivalent: C<pop(@myarray);>
 SV *
 Perl_av_pop(pTHX_ AV *av)
 {
-    dVAR;
     SV *retval;
     MAGIC* mg;
 
@@ -614,7 +596,7 @@ Perl_av_pop(pTHX_ AV *av)
     if (SvREADONLY(av))
        Perl_croak_no_modify();
     if ((mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied))) {
-       retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "POP", 0, 0);
+       retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(POP), 0, 0);
        if (retval)
            retval = newSVsv(retval);
        return retval;
@@ -622,10 +604,10 @@ Perl_av_pop(pTHX_ AV *av)
     if (AvFILL(av) < 0)
        return &PL_sv_undef;
     retval = AvARRAY(av)[AvFILLp(av)];
-    AvARRAY(av)[AvFILLp(av)--] = &PL_sv_undef;
+    AvARRAY(av)[AvFILLp(av)--] = NULL;
     if (SvSMAGICAL(av))
        mg_set(MUTABLE_SV(av));
-    return retval;
+    return retval ? retval : &PL_sv_undef;
 }
 
 /*
@@ -663,10 +645,9 @@ Perl equivalent: C<unshift @myarray, ( (undef) x $n );>
 */
 
 void
-Perl_av_unshift(pTHX_ AV *av, I32 num)
+Perl_av_unshift(pTHX_ AV *av, SSize_t num)
 {
-    dVAR;
-    I32 i;
+    SSize_t i;
     MAGIC* mg;
 
     PERL_ARGS_ASSERT_AV_UNSHIFT;
@@ -676,7 +657,7 @@ Perl_av_unshift(pTHX_ AV *av, I32 num)
        Perl_croak_no_modify();
 
     if ((mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied))) {
-       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "UNSHIFT",
+       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(UNSHIFT),
                            G_DISCARD | G_UNDEF_FILL, num);
        return;
     }
@@ -697,16 +678,16 @@ Perl_av_unshift(pTHX_ AV *av, I32 num)
     }
     if (num) {
        SV **ary;
-       const I32 i = AvFILLp(av);
+       const SSize_t i = AvFILLp(av);
        /* Create extra elements */
-       const I32 slide = i > 0 ? i : 0;
+       const SSize_t slide = i > 0 ? i : 0;
        num += slide;
        av_extend(av, i + num);
        AvFILLp(av) += num;
        ary = AvARRAY(av);
        Move(ary, ary + num, i + 1, SV*);
        do {
-           ary[--num] = &PL_sv_undef;
+           ary[--num] = NULL;
        } while (num);
        /* Make extra elements into a buffer */
        AvMAX(av) -= slide;
@@ -718,9 +699,9 @@ Perl_av_unshift(pTHX_ AV *av, I32 num)
 /*
 =for apidoc av_shift
 
-Shifts an SV off the beginning of the
-array.  Returns C<&PL_sv_undef> if the 
-array is empty.
+Removes one SV from the start of the array, reducing its size by one and
+returning the SV (transferring control of one reference count) to the
+caller.  Returns C<&PL_sv_undef> if the array is empty.
 
 Perl equivalent: C<shift(@myarray);>
 
@@ -730,7 +711,6 @@ Perl equivalent: C<shift(@myarray);>
 SV *
 Perl_av_shift(pTHX_ AV *av)
 {
-    dVAR;
     SV *retval;
     MAGIC* mg;
 
@@ -740,7 +720,7 @@ Perl_av_shift(pTHX_ AV *av)
     if (SvREADONLY(av))
        Perl_croak_no_modify();
     if ((mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied))) {
-       retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "SHIFT", 0, 0);
+       retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(SHIFT), 0, 0);
        if (retval)
            retval = newSVsv(retval);
        return retval;
@@ -749,13 +729,13 @@ Perl_av_shift(pTHX_ AV *av)
       return &PL_sv_undef;
     retval = *AvARRAY(av);
     if (AvREAL(av))
-       *AvARRAY(av) = &PL_sv_undef;
+       *AvARRAY(av) = NULL;
     AvARRAY(av) = AvARRAY(av) + 1;
     AvMAX(av)--;
     AvFILLp(av)--;
     if (SvSMAGICAL(av))
        mg_set(MUTABLE_SV(av));
-    return retval;
+    return retval ? retval : &PL_sv_undef;
 }
 
 /*
@@ -766,36 +746,28 @@ array is C<av_top_index(av) + 1>.  Returns -1 if the array is empty.
 
 The Perl equivalent for this is C<$#myarray>.
 
+(A slightly shorter form is C<av_tindex>.)
+
+=for apidoc av_tindex
+
+Same as L</av_top_index>.
+
 =for apidoc av_len
 
-Same as L</av_top_index>.  Returns the highest index in the array.  Note that the
-return value is +1 what its name implies it returns; and hence differs in
-meaning from what the similarly named L</sv_len> returns.
+Same as L</av_top_index>.  Note that, unlike what the name implies, it returns
+the highest index in the array, so to get the size of the array you need to use
+S<C<av_len(av) + 1>>.  This is unlike L</sv_len>, which returns what you would
+expect.
 
 =cut
 */
 
-I32
+SSize_t
 Perl_av_len(pTHX_ AV *av)
 {
-    /* If change this, must change identical Perl_av_top_index() just below */
-
     PERL_ARGS_ASSERT_AV_LEN;
-    assert(SvTYPE(av) == SVt_PVAV);
-
-    return AvFILL(av);
-}
 
-I32
-Perl_av_top_index(pTHX_ AV *av)
-{
-    /* So short, that it is just a duplicate of Perl_av_len().  Must keep them
-     * in sync */
-
-    PERL_ARGS_ASSERT_AV_TOP_INDEX;
-    assert(SvTYPE(av) == SVt_PVAV);
-
-    return AvFILL(av);
+    return av_top_index(av);
 }
 
 /*
@@ -804,18 +776,17 @@ Perl_av_top_index(pTHX_ AV *av)
 Set the highest index in the array to the given number, equivalent to
 Perl's C<$#array = $fill;>.
 
-The number of elements in the an array will be C<fill + 1> after
+The number of elements in the array will be C<fill + 1> after
 av_fill() returns.  If the array was previously shorter, then the
-additional elements appended are set to C<PL_sv_undef>.  If the array
+additional elements appended are set to NULL.  If the array
 was longer, then the excess elements are freed.  C<av_fill(av, -1)> is
 the same as C<av_clear(av)>.
 
 =cut
 */
 void
-Perl_av_fill(pTHX_ AV *av, I32 fill)
+Perl_av_fill(pTHX_ AV *av, SSize_t fill)
 {
-    dVAR;
     MAGIC *mg;
 
     PERL_ARGS_ASSERT_AV_FILL;
@@ -826,23 +797,23 @@ Perl_av_fill(pTHX_ AV *av, I32 fill)
     if ((mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied))) {
        SV *arg1 = sv_newmortal();
        sv_setiv(arg1, (IV)(fill + 1));
-       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, "STORESIZE", G_DISCARD,
+       Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(STORESIZE), G_DISCARD,
                            1, arg1);
        return;
     }
     if (fill <= AvMAX(av)) {
-       I32 key = AvFILLp(av);
+       SSize_t key = AvFILLp(av);
        SV** const ary = AvARRAY(av);
 
        if (AvREAL(av)) {
            while (key > fill) {
                SvREFCNT_dec(ary[key]);
-               ary[key--] = &PL_sv_undef;
+               ary[key--] = NULL;
            }
        }
        else {
            while (key < fill)
-               ary[++key] = &PL_sv_undef;
+               ary[++key] = NULL;
        }
            
        AvFILLp(av) = fill;
@@ -850,7 +821,7 @@ Perl_av_fill(pTHX_ AV *av, I32 fill)
            mg_set(MUTABLE_SV(av));
     }
     else
-       (void)av_store(av,fill,&PL_sv_undef);
+       (void)av_store(av,fill,NULL);
 }
 
 /*
@@ -865,9 +836,8 @@ C<G_DISCARD> version.
 =cut
 */
 SV *
-Perl_av_delete(pTHX_ AV *av, I32 key, I32 flags)
+Perl_av_delete(pTHX_ AV *av, SSize_t key, I32 flags)
 {
-    dVAR;
     SV *sv;
 
     PERL_ARGS_ASSERT_AV_DELETE;
@@ -910,23 +880,23 @@ Perl_av_delete(pTHX_ AV *av, I32 key, I32 flags)
        if (!AvREAL(av) && AvREIFY(av))
            av_reify(av);
        sv = AvARRAY(av)[key];
+       AvARRAY(av)[key] = NULL;
        if (key == AvFILLp(av)) {
-           AvARRAY(av)[key] = &PL_sv_undef;
            do {
                AvFILLp(av)--;
-           } while (--key >= 0 && AvARRAY(av)[key] == &PL_sv_undef);
+           } while (--key >= 0 && !AvARRAY(av)[key]);
        }
-       else
-           AvARRAY(av)[key] = &PL_sv_undef;
        if (SvSMAGICAL(av))
            mg_set(MUTABLE_SV(av));
     }
-    if (flags & G_DISCARD) {
-       SvREFCNT_dec(sv);
-       sv = NULL;
+    if(sv != NULL) {
+       if (flags & G_DISCARD) {
+           SvREFCNT_dec_NN(sv);
+           return NULL;
+       }
+       else if (AvREAL(av))
+           sv_2mortal(sv);
     }
-    else if (AvREAL(av))
-       sv = sv_2mortal(sv);
     return sv;
 }
 
@@ -936,16 +906,15 @@ Perl_av_delete(pTHX_ AV *av, I32 key, I32 flags)
 Returns true if the element indexed by C<key> has been initialized.
 
 This relies on the fact that uninitialized array elements are set to
-C<&PL_sv_undef>.
+NULL.
 
 Perl equivalent: C<exists($myarray[$key])>.
 
 =cut
 */
 bool
-Perl_av_exists(pTHX_ AV *av, I32 key)
+Perl_av_exists(pTHX_ AV *av, SSize_t key)
 {
-    dVAR;
     PERL_ARGS_ASSERT_AV_EXISTS;
     assert(SvTYPE(av) == SVt_PVAV);
 
@@ -989,8 +958,7 @@ Perl_av_exists(pTHX_ AV *av, I32 key)
            return FALSE;
     }
 
-    if (key <= AvFILLp(av) && AvARRAY(av)[key] != &PL_sv_undef
-       && AvARRAY(av)[key])
+    if (key <= AvFILLp(av) && AvARRAY(av)[key])
     {
        return TRUE;
     }
@@ -1000,7 +968,6 @@ Perl_av_exists(pTHX_ AV *av, I32 key)
 
 static MAGIC *
 S_get_aux_mg(pTHX_ AV *av) {
-    dVAR;
     MAGIC *mg;
 
     PERL_ARGS_ASSERT_GET_AUX_MG;