This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Further conversion of overload.t
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index c8ad602..e5e997c 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -42,7 +42,7 @@
  * --jhi
  */
 #define ASSERT_UTF8_CACHE(cache) \
-       STMT_START { if (cache) { assert((cache)[0] <= (cache)[1]); } } STMT_END
+    STMT_START { if (cache) { assert((cache)[0] <= (cache)[1]); } } STMT_END
 #else
 #define ASSERT_UTF8_CACHE(cache) NOOP
 #endif
 
 =head1 Allocation and deallocation of SVs.
 
-An SV (or AV, HV, etc.) is allocated in two parts: the head (struct sv,
-av, hv...) contains type and reference count information, as well as a
-pointer to the body (struct xrv, xpv, xpviv...), which contains fields
-specific to each type.
+An SV (or AV, HV, etc.) is allocated in two parts: the head (struct
+sv, av, hv...) contains type and reference count information, and for
+many types, a pointer to the body (struct xrv, xpv, xpviv...), which
+contains fields specific to each type.  Some types store all they need
+in the head, so don't have a body.
 
-In all but the most memory-paranoid configuations (ex: PURIFY), this
-allocation is done using arenas, which by default are approximately 4K
-chunks of memory parcelled up into N heads or bodies (of same size).
+In all but the most memory-paranoid configuations (ex: PURIFY), heads
+and bodies are allocated out of arenas, which by default are
+approximately 4K chunks of memory parcelled up into N heads or bodies.
 Sv-bodies are allocated by their sv-type, guaranteeing size
 consistency needed to allocate safely from arrays.
 
-The first slot in each arena is reserved, and is used to hold a link
-to the next arena.  In the case of heads, the unused first slot also
-contains some flags and a note of the number of slots.  Snaked through
-each arena chain is a linked list of free items; when this becomes
-empty, an extra arena is allocated and divided up into N items which
-are threaded into the free list.
+For SV-heads, the first slot in each arena is reserved, and holds a
+link to the next arena, some flags, and a note of the number of slots.
+Snaked through each arena chain is a linked list of free items; when
+this becomes empty, an extra arena is allocated and divided up into N
+items which are threaded into the free list.
+
+SV-bodies are similar, but they use arena-sets by default, which
+separate the link and info from the arena itself, and reclaim the 1st
+slot in the arena.  SV-bodies are further described later.
 
 The following global variables are associated with arenas:
 
     PL_sv_arenaroot    pointer to list of SV arenas
     PL_sv_root         pointer to list of free SV structures
 
-    PL_body_arenaroots[]  array of pointers to list of arenas, 1 per svtype
-    PL_body_roots[]      array of pointers to list of free bodies of svtype
-                         arrays are indexed by the svtype needed
-
-Note that some of the larger and more rarely used body types (eg
-xpvio) are not allocated using arenas, but are instead just
-malloc()/free()ed as required.
+    PL_body_arenas     head of linked-list of body arenas
+    PL_body_roots[]    array of pointers to list of free bodies of svtype
+                       arrays are indexed by the svtype needed
 
-In addition, a few SV heads are not allocated from an arena, but are
-instead directly created as static or auto variables, eg PL_sv_undef.
+A few special SV heads are not allocated from an arena, but are
+instead directly created in the interpreter structure, eg PL_sv_undef.
 The size of arenas can be changed from the default by setting
 PERL_ARENA_SIZE appropriately at compile time.
 
@@ -103,13 +103,6 @@ to return the SV to the free list with error checking.) new_SV() calls
 more_sv() / sv_add_arena() to add an extra arena if the free list is empty.
 SVs in the free list have their SvTYPE field set to all ones.
 
-Similarly, there are macros new_XIV()/del_XIV(), new_XNV()/del_XNV() etc
-that allocate and return individual body types. Normally these are mapped
-to the arena-manipulating functions new_xiv()/del_xiv() etc, but may be
-instead mapped directly to malloc()/free() if PURIFY is defined. The
-new/del functions remove from, or add to, the appropriate PL_foo_root
-list, and call more_xiv() etc to add a new arena if the list is empty.
-
 At the time of very final cleanup, sv_free_arenas() is called from
 perl_destruct() to physically free all the arenas allocated since the
 start of the interpreter.
@@ -159,13 +152,10 @@ Public API:
 
     sv_report_used(), sv_clean_objs(), sv_clean_all(), sv_free_arenas()
 
-
 =cut
 
 ============================================================================ */
 
-
-
 /*
  * "A time to plant, and a time to uproot what was planted..."
  */
@@ -226,7 +216,7 @@ Perl_offer_nice_chunk(pTHX_ void *chunk, U32 chunk_size)
 #define uproot_SV(p) \
     STMT_START {                                       \
        (p) = PL_sv_root;                               \
-       PL_sv_root = (SV*)SvARENA_CHAIN(p);                     \
+       PL_sv_root = (SV*)SvARENA_CHAIN(p);             \
        ++PL_sv_count;                                  \
     } STMT_END
 
@@ -242,12 +232,12 @@ S_more_sv(pTHX)
 
     if (PL_nice_chunk) {
        sv_add_arena(PL_nice_chunk, PL_nice_chunk_size, 0);
-       PL_nice_chunk = Nullch;
+       PL_nice_chunk = NULL;
         PL_nice_chunk_size = 0;
     }
     else {
        char *chunk;                /* must use New here to match call to */
-       Newx(chunk,PERL_ARENA_SIZE,char);   /* Safefree() in sv_free_arenas()     */
+       Newx(chunk,PERL_ARENA_SIZE,char);  /* Safefree() in sv_free_arenas() */
        sv_add_arena(chunk, PERL_ARENA_SIZE, 0);
     }
     uproot_SV(sv);
@@ -445,6 +435,8 @@ Perl_sv_report_used(pTHX)
 {
 #ifdef DEBUGGING
     visit(do_report_used, 0, 0);
+#else
+    PERL_UNUSED_CONTEXT;
 #endif
 }
 
@@ -480,7 +472,7 @@ static void
 do_clean_named_objs(pTHX_ SV *sv)
 {
     dVAR;
-    if (SvTYPE(sv) == SVt_PVGV && GvGP(sv)) {
+    if (SvTYPE(sv) == SVt_PVGV && isGV_with_GP(sv) && GvGP(sv)) {
        if ((
 #ifdef PERL_DONT_CREATE_GVSV
             GvSV(sv) &&
@@ -530,7 +522,7 @@ do_clean_all(pTHX_ SV *sv)
     SvFLAGS(sv) |= SVf_BREAK;
     if (PL_comppad == (AV*)sv) {
        PL_comppad = NULL;
-       PL_curpad = Null(SV**);
+       PL_curpad = NULL;
     }
     SvREFCNT_dec(sv);
 }
@@ -556,15 +548,45 @@ Perl_sv_clean_all(pTHX)
     return cleaned;
 }
 
-static void 
-S_free_arena(pTHX_ void **root) {
-    while (root) {
-       void ** const next = *(void **)root;
-       Safefree(root);
-       root = next;
-    }
-}
-    
+/*
+  ARENASETS: a meta-arena implementation which separates arena-info
+  into struct arena_set, which contains an array of struct
+  arena_descs, each holding info for a single arena.  By separating
+  the meta-info from the arena, we recover the 1st slot, formerly
+  borrowed for list management.  The arena_set is about the size of an
+  arena, avoiding the needless malloc overhead of a naive linked-list
+
+  The cost is 1 arena-set malloc per ~320 arena-mallocs, + the unused
+  memory in the last arena-set (1/2 on average).  In trade, we get
+  back the 1st slot in each arena (ie 1.7% of a CV-arena, less for
+  smaller types).  The recovery of the wasted space allows use of
+  small arenas for large, rare body types,
+*/
+struct arena_desc {
+    char       *arena;         /* the raw storage, allocated aligned */
+    size_t      size;          /* its size ~4k typ */
+    int         unit_type;     /* useful for arena audits */
+    /* info for sv-heads (eventually)
+       int count, flags;
+    */
+};
+
+struct arena_set;
+
+/* Get the maximum number of elements in set[] such that struct arena_set
+   will fit within PERL_ARENA_SIZE, which is probabably just under 4K, and
+   therefore likely to be 1 aligned memory page.  */
+
+#define ARENAS_PER_SET  ((PERL_ARENA_SIZE - sizeof(struct arena_set*) \
+                         - 2 * sizeof(int)) / sizeof (struct arena_desc))
+
+struct arena_set {
+    struct arena_set* next;
+    int   set_size;            /* ie ARENAS_PER_SET */
+    int   curr;                        /* index of next available arena-desc */
+    struct arena_desc set[ARENAS_PER_SET];
+};
+
 /*
 =for apidoc sv_free_arenas
 
@@ -573,13 +595,6 @@ heads and bodies within the arenas must already have been freed.
 
 =cut
 */
-#define free_arena(name)                                       \
-    STMT_START {                                               \
-       S_free_arena(aTHX_ (void**) PL_ ## name ## _arenaroot); \
-       PL_ ## name ## _arenaroot = 0;                          \
-       PL_ ## name ## _root = 0;                               \
-    } STMT_END
-
 void
 Perl_sv_free_arenas(pTHX)
 {
@@ -600,14 +615,26 @@ Perl_sv_free_arenas(pTHX)
            Safefree(sva);
     }
 
-    for (i=0; i<SVt_LAST; i++) {
-       S_free_arena(aTHX_ (void**) PL_body_arenaroots[i]);
-       PL_body_arenaroots[i] = 0;
-       PL_body_roots[i] = 0;
+    {
+       struct arena_set *next, *aroot = (struct arena_set*) PL_body_arenas;
+       
+       for (; aroot; aroot = next) {
+           const int max = aroot->curr;
+           for (i=0; i<max; i++) {
+               assert(aroot->set[i].arena);
+               Safefree(aroot->set[i].arena);
+           }
+           next = aroot->next;
+           Safefree(aroot);
+       }
     }
+    PL_body_arenas = 0;
+
+    for (i=0; i<PERL_ARENA_ROOTS_SIZE; i++)
+       PL_body_roots[i] = 0;
 
     Safefree(PL_nice_chunk);
-    PL_nice_chunk = Nullch;
+    PL_nice_chunk = NULL;
     PL_nice_chunk_size = 0;
     PL_sv_arenaroot = 0;
     PL_sv_root = 0;
@@ -648,70 +675,42 @@ Perl_sv_free_arenas(pTHX)
   contexts below (line ~10k)
 */
 
-STATIC void *
-S_more_bodies (pTHX_ size_t size, svtype sv_type)
+/* get_arena(size): this creates custom-sized arenas
+   TBD: export properly for hv.c: S_more_he().
+*/
+void*
+Perl_get_arena(pTHX_ int arena_size)
 {
-    dVAR;
-    void ** const arena_root   = &PL_body_arenaroots[sv_type];
-    void ** const root         = &PL_body_roots[sv_type];
-    char *start;
-    const char *end;
-    const size_t count = PERL_ARENA_SIZE / size;
-
-    Newx(start, count*size, char);
-    *((void **) start) = *arena_root;
-    *arena_root = (void *)start;
-
-    end = start + (count-1) * size;
+    struct arena_desc* adesc;
+    struct arena_set *newroot, **aroot = (struct arena_set**) &PL_body_arenas;
+    int curr;
 
-    /* The initial slot is used to link the arenas together, so it isn't to be
-       linked into the list of ready-to-use bodies.  */
-
-    start += size;
-
-    *root = (void *)start;
+    /* shouldnt need this
+    if (!arena_size)   arena_size = PERL_ARENA_SIZE;
+    */
 
-    while (start < end) {
-       char * const next = start + size;
-       *(void**) start = (void *)next;
-       start = next;
+    /* may need new arena-set to hold new arena */
+    if (!*aroot || (*aroot)->curr >= (*aroot)->set_size) {
+       Newxz(newroot, 1, struct arena_set);
+       newroot->set_size = ARENAS_PER_SET;
+       newroot->next = *aroot;
+       *aroot = newroot;
+       DEBUG_m(PerlIO_printf(Perl_debug_log, "new arenaset %p\n", *aroot));
     }
-    *(void **)start = 0;
-
-    return *root;
-}
 
-/* grab a new thing from the free list, allocating more if necessary */
-
-/* 1st, the inline version  */
-
-#define new_body_inline(xpv, size, sv_type) \
-    STMT_START { \
-       void ** const r3wt = &PL_body_roots[sv_type]; \
-       LOCK_SV_MUTEX; \
-       xpv = *((void **)(r3wt)) \
-         ? *((void **)(r3wt)) : S_more_bodies(aTHX_ size, sv_type); \
-       *(r3wt) = *(void**)(xpv); \
-       UNLOCK_SV_MUTEX; \
-    } STMT_END
-
-/* now use the inline version in the proper function */
-
-#ifndef PURIFY
-
-/* This isn't being used with -DPURIFY, so don't declare it. Otherwise
-   compilers issue warnings.  */
+    /* ok, now have arena-set with at least 1 empty/available arena-desc */
+    curr = (*aroot)->curr++;
+    adesc = &((*aroot)->set[curr]);
+    assert(!adesc->arena);
+    
+    Newxz(adesc->arena, arena_size, char);
+    adesc->size = arena_size;
+    DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p size %d\n", 
+                         curr, adesc->arena, arena_size));
 
-STATIC void *
-S_new_body(pTHX_ size_t size, svtype sv_type)
-{
-    dVAR;
-    void *xpv;
-    new_body_inline(xpv, size, sv_type);
-    return xpv;
+    return adesc->arena;
 }
 
-#endif
 
 /* return a thing to the free list */
 
@@ -725,54 +724,111 @@ S_new_body(pTHX_ size_t size, svtype sv_type)
     } STMT_END
 
 /* 
-   Revisiting type 3 arenas, there are 4 body-types which have some
-   members that are never accessed.  They are XPV, XPVIV, XPVAV,
-   XPVHV, which have corresponding types: xpv_allocated,
-   xpviv_allocated, xpvav_allocated, xpvhv_allocated,
-
-   For these types, the arenas are carved up into *_allocated size
-   chunks, we thus avoid wasted memory for those unaccessed members.
-   When bodies are allocated, we adjust the pointer back in memory by
-   the size of the bit not allocated, so it's as if we allocated the
-   full structure.  (But things will all go boom if you write to the
-   part that is "not there", because you'll be overwriting the last
-   members of the preceding structure in memory.)
-
-   We calculate the correction using the STRUCT_OFFSET macro. For example, if
-   xpv_allocated is the same structure as XPV then the two OFFSETs sum to zero,
-   and the pointer is unchanged. If the allocated structure is smaller (no
-   initial NV actually allocated) then the net effect is to subtract the size
-   of the NV from the pointer, to return a new pointer as if an initial NV were
-   actually allocated.
-
-   This is the same trick as was used for NV and IV bodies. Ironically it
-   doesn't need to be used for NV bodies any more, because NV is now at the
-   start of the structure. IV bodies don't need it either, because they are
-   no longer allocated.  */
-
-/* The following 2 arrays hide the above details in a pair of
-   lookup-tables, allowing us to be body-type agnostic.
-
-   size maps svtype to its body's allocated size.
-   offset maps svtype to the body-pointer adjustment needed
-
-   NB: elements in latter are 0 or <0, and are added during
-   allocation, and subtracted during deallocation.  It may be clearer
-   to invert the values, and call it shrinkage_by_svtype.
+
+=head1 SV-Body Allocation
+
+Allocation of SV-bodies is similar to SV-heads, differing as follows;
+the allocation mechanism is used for many body types, so is somewhat
+more complicated, it uses arena-sets, and has no need for still-live
+SV detection.
+
+At the outermost level, (new|del)_X*V macros return bodies of the
+appropriate type.  These macros call either (new|del)_body_type or
+(new|del)_body_allocated macro pairs, depending on specifics of the
+type.  Most body types use the former pair, the latter pair is used to
+allocate body types with "ghost fields".
+
+"ghost fields" are fields that are unused in certain types, and
+consequently dont need to actually exist.  They are declared because
+they're part of a "base type", which allows use of functions as
+methods.  The simplest examples are AVs and HVs, 2 aggregate types
+which don't use the fields which support SCALAR semantics.
+
+For these types, the arenas are carved up into *_allocated size
+chunks, we thus avoid wasted memory for those unaccessed members.
+When bodies are allocated, we adjust the pointer back in memory by the
+size of the bit not allocated, so it's as if we allocated the full
+structure.  (But things will all go boom if you write to the part that
+is "not there", because you'll be overwriting the last members of the
+preceding structure in memory.)
+
+We calculate the correction using the STRUCT_OFFSET macro. For
+example, if xpv_allocated is the same structure as XPV then the two
+OFFSETs sum to zero, and the pointer is unchanged. If the allocated
+structure is smaller (no initial NV actually allocated) then the net
+effect is to subtract the size of the NV from the pointer, to return a
+new pointer as if an initial NV were actually allocated.
+
+This is the same trick as was used for NV and IV bodies. Ironically it
+doesn't need to be used for NV bodies any more, because NV is now at
+the start of the structure. IV bodies don't need it either, because
+they are no longer allocated.
+
+In turn, the new_body_* allocators call S_new_body(), which invokes
+new_body_inline macro, which takes a lock, and takes a body off the
+linked list at PL_body_roots[sv_type], calling S_more_bodies() if
+necessary to refresh an empty list.  Then the lock is released, and
+the body is returned.
+
+S_more_bodies calls get_arena(), and carves it up into an array of N
+bodies, which it strings into a linked list.  It looks up arena-size
+and body-size from the body_details table described below, thus
+supporting the multiple body-types.
+
+If PURIFY is defined, or PERL_ARENA_SIZE=0, arenas are not used, and
+the (new|del)_X*V macros are mapped directly to malloc/free.
+
+*/
+
+/* 
+
+For each sv-type, struct body_details bodies_by_type[] carries
+parameters which control these aspects of SV handling:
+
+Arena_size determines whether arenas are used for this body type, and if
+so, how big they are.  PURIFY or PERL_ARENA_SIZE=0 set this field to
+zero, forcing individual mallocs and frees.
+
+Body_size determines how big a body is, and therefore how many fit into
+each arena.  Offset carries the body-pointer adjustment needed for
+*_allocated body types, and is used in *_allocated macros.
+
+But its main purpose is to parameterize info needed in
+Perl_sv_upgrade().  The info here dramatically simplifies the function
+vs the implementation in 5.8.7, making it table-driven.  All fields
+are used for this, except for arena_size.
+
+For the sv-types that have no bodies, arenas are not used, so those
+PL_body_roots[sv_type] are unused, and can be overloaded.  In
+something of a special case, SVt_NULL is borrowed for HE arenas;
+PL_body_roots[SVt_NULL] is filled by S_more_he, but the
+bodies_by_type[SVt_NULL] slot is not used, as the table is not
+available in hv.c,
+
+PTEs also use arenas, but are never seen in Perl_sv_upgrade.
+Nonetheless, they get their own slot in bodies_by_type[SVt_NULL], so
+they can just use the same allocation semantics.  At first, PTEs were
+also overloaded to a non-body sv-type, but this yielded hard-to-find
+malloc bugs, so was simplified by claiming a new slot.  This choice
+has no consequence at this time.
+
 */
 
 struct body_details {
-    size_t size;       /* Size to allocate  */
-    size_t copy;       /* Size of structure to copy (may be shorter)  */
-    size_t offset;
-    bool cant_upgrade; /* Can upgrade this type */
-    bool zero_nv;      /* zero the NV when upgrading from this */
-    bool arena;                /* Allocated from an arena */
+    U8 body_size;      /* Size to allocate  */
+    U8 copy;           /* Size of structure to copy (may be shorter)  */
+    U8 offset;
+    unsigned int type : 4;         /* We have space for a sanity check.  */
+    unsigned int cant_upgrade : 1;  /* Cannot upgrade this type */
+    unsigned int zero_nv : 1;      /* zero the NV when upgrading from this */
+    unsigned int arena : 1;        /* Allocated from an arena */
+    size_t arena_size;             /* Size of arena to allocate */
 };
 
 #define HADNV FALSE
 #define NONV TRUE
 
+
 #ifdef PURIFY
 /* With -DPURFIY we allocate everything directly, and don't use arenas.
    This seems a rather elegant way to simplify some of the code below.  */
@@ -782,6 +838,25 @@ struct body_details {
 #endif
 #define NOARENA FALSE
 
+/* Size the arenas to exactly fit a given number of bodies.  A count
+   of 0 fits the max number bodies into a PERL_ARENA_SIZE.block,
+   simplifying the default.  If count > 0, the arena is sized to fit
+   only that many bodies, allowing arenas to be used for large, rare
+   bodies (XPVFM, XPVIO) without undue waste.  The arena size is
+   limited by PERL_ARENA_SIZE, so we can safely oversize the
+   declarations.
+ */
+#define FIT_ARENA0(body_size)                          \
+    ((size_t)(PERL_ARENA_SIZE / body_size) * body_size)
+#define FIT_ARENAn(count,body_size)                    \
+    ( count * body_size <= PERL_ARENA_SIZE)            \
+    ? count * body_size                                        \
+    : FIT_ARENA0 (body_size)
+#define FIT_ARENA(count,body_size)                     \
+    count                                              \
+    ? FIT_ARENAn (count, body_size)                    \
+    : FIT_ARENA0 (body_size)
+
 /* A macro to work out the offset needed to subtract from a pointer to (say)
 
 typedef struct {
@@ -811,66 +886,95 @@ struct xpv {
        + sizeof (((type*)SvANY((SV*)0))->last_member)
 
 static const struct body_details bodies_by_type[] = {
-    {0, 0, 0, FALSE, NONV, NOARENA},
-    /* IVs are in the head, so the allocation size is 0  */
-    {0, sizeof(IV), STRUCT_OFFSET(XPVIV, xiv_iv), FALSE, NONV, NOARENA},
+    { sizeof(HE), 0, 0, SVt_NULL,
+      FALSE, NONV, NOARENA, FIT_ARENA(0, sizeof(HE)) },
+
+    /* IVs are in the head, so the allocation size is 0.
+       However, the slot is overloaded for PTEs.  */
+    { sizeof(struct ptr_tbl_ent), /* This is used for PTEs.  */
+      sizeof(IV), /* This is used to copy out the IV body.  */
+      STRUCT_OFFSET(XPVIV, xiv_iv), SVt_IV, FALSE, NONV,
+      NOARENA /* IVS don't need an arena  */,
+      /* But PTEs need to know the size of their arena  */
+      FIT_ARENA(0, sizeof(struct ptr_tbl_ent))
+    },
+
     /* 8 bytes on most ILP32 with IEEE doubles */
-    {sizeof(NV), sizeof(NV), 0, FALSE, HADNV, HASARENA},
-    /* RVs are in the head now */
-    /* However, this slot is overloaded and used by the pte  */
-    {0, 0, 0, FALSE, NONV, NOARENA},
+    { sizeof(NV), sizeof(NV), 0, SVt_NV, FALSE, HADNV, HASARENA,
+      FIT_ARENA(0, sizeof(NV)) },
+
+    /* RVs are in the head now.  */
+    { 0, 0, 0, SVt_RV, FALSE, NONV, NOARENA, 0 },
+
     /* 8 bytes on most ILP32 with IEEE doubles */
-    {sizeof(xpv_allocated),
-     copy_length(XPV, xpv_len)
-     - relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
-     + relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
-     FALSE, NONV, HASARENA},
+    { sizeof(xpv_allocated),
+      copy_length(XPV, xpv_len)
+      - relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
+      + relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
+      SVt_PV, FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpv_allocated)) },
+
     /* 12 */
-    {sizeof(xpviv_allocated),
-     copy_length(XPVIV, xiv_u)
-     - relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
-     + relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
-     FALSE, NONV, HASARENA},
+    { sizeof(xpviv_allocated),
+      copy_length(XPVIV, xiv_u)
+      - relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
+      + relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
+      SVt_PVIV, FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpviv_allocated)) },
+
     /* 20 */
-    {sizeof(XPVNV), copy_length(XPVNV, xiv_u), 0, FALSE, HADNV, HASARENA},
+    { sizeof(XPVNV), copy_length(XPVNV, xiv_u), 0, SVt_PVNV, FALSE, HADNV,
+      HASARENA, FIT_ARENA(0, sizeof(XPVNV)) },
+
     /* 28 */
-    {sizeof(XPVMG), copy_length(XPVMG, xmg_stash), 0, FALSE, HADNV, HASARENA},
+    { sizeof(XPVMG), copy_length(XPVMG, xmg_stash), 0, SVt_PVMG, FALSE, HADNV,
+      HASARENA, FIT_ARENA(0, sizeof(XPVMG)) },
+    
     /* 36 */
-    {sizeof(XPVBM), sizeof(XPVBM), 0, TRUE, HADNV, HASARENA},
+    { sizeof(XPVBM), sizeof(XPVBM), 0, SVt_PVBM, TRUE, HADNV,
+      HASARENA, FIT_ARENA(0, sizeof(XPVBM)) },
+
     /* 48 */
-    {sizeof(XPVGV), sizeof(XPVGV), 0, TRUE, HADNV, HASARENA},
+    { sizeof(XPVGV), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV,
+      HASARENA, FIT_ARENA(0, sizeof(XPVGV)) },
+    
     /* 64 */
-    {sizeof(XPVLV), sizeof(XPVLV), 0, TRUE, HADNV, HASARENA},
-    /* 20 */
-    {sizeof(xpvav_allocated),
-     copy_length(XPVAV, xmg_stash)
-     - relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
-     + relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
-     TRUE, HADNV, HASARENA},
-    /* 20 */
-    {sizeof(xpvhv_allocated),
-     copy_length(XPVHV, xmg_stash)
-     - relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
-     + relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
-     TRUE, HADNV, HASARENA},
-    /* 76 */
-    {sizeof(XPVCV), sizeof(XPVCV), 0, TRUE, HADNV, HASARENA},
-    /* 80 */
-    {sizeof(XPVFM), sizeof(XPVFM), 0, TRUE, HADNV, NOARENA},
-    /* 84 */
-    {sizeof(XPVIO), sizeof(XPVIO), 0, TRUE, HADNV, NOARENA}
+    { sizeof(XPVLV), sizeof(XPVLV), 0, SVt_PVLV, TRUE, HADNV,
+      HASARENA, FIT_ARENA(0, sizeof(XPVLV)) },
+
+    { sizeof(xpvav_allocated),
+      copy_length(XPVAV, xmg_stash)
+      - relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
+      + relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
+      SVt_PVAV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvav_allocated)) },
+
+    { sizeof(xpvhv_allocated),
+      copy_length(XPVHV, xmg_stash)
+      - relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
+      + relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
+      SVt_PVHV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvhv_allocated)) },
+
+    /* 56 */
+    { sizeof(xpvcv_allocated), sizeof(xpvcv_allocated),
+      + relative_STRUCT_OFFSET(xpvcv_allocated, XPVCV, xpv_cur),
+      SVt_PVCV, TRUE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpvcv_allocated)) },
+
+    { sizeof(xpvfm_allocated), sizeof(xpvfm_allocated),
+      + relative_STRUCT_OFFSET(xpvfm_allocated, XPVFM, xpv_cur),
+      SVt_PVFM, TRUE, NONV, NOARENA, FIT_ARENA(20, sizeof(xpvfm_allocated)) },
+
+    /* XPVIO is 84 bytes, fits 48x */
+    { sizeof(XPVIO), sizeof(XPVIO), 0, SVt_PVIO, TRUE, HADNV,
+      HASARENA, FIT_ARENA(24, sizeof(XPVIO)) },
 };
 
-#define new_body_type(sv_type)                 \
-    (void *)((char *)S_new_body(aTHX_ bodies_by_type[sv_type].size, sv_type)\
-            - bodies_by_type[sv_type].offset)
+#define new_body_type(sv_type)         \
+    (void *)((char *)S_new_body(aTHX_ sv_type))
 
 #define del_body_type(p, sv_type)      \
     del_body(p, &PL_body_roots[sv_type])
 
 
 #define new_body_allocated(sv_type)            \
-    (void *)((char *)S_new_body(aTHX_ bodies_by_type[sv_type].size, sv_type)\
+    (void *)((char *)S_new_body(aTHX_ sv_type) \
             - bodies_by_type[sv_type].offset)
 
 #define del_body_allocated(p, sv_type)         \
@@ -926,9 +1030,85 @@ static const struct body_details bodies_by_type[] = {
 /* no arena for you! */
 
 #define new_NOARENA(details) \
-       my_safemalloc((details)->size + (details)->offset)
+       my_safemalloc((details)->body_size + (details)->offset)
 #define new_NOARENAZ(details) \
-       my_safecalloc((details)->size + (details)->offset)
+       my_safecalloc((details)->body_size + (details)->offset)
+
+#ifdef DEBUGGING
+static bool done_sanity_check;
+#endif
+
+STATIC void *
+S_more_bodies (pTHX_ svtype sv_type)
+{
+    dVAR;
+    void ** const root = &PL_body_roots[sv_type];
+    const struct body_details * const bdp = &bodies_by_type[sv_type];
+    const size_t body_size = bdp->body_size;
+    char *start;
+    const char *end;
+
+    assert(bdp->arena_size);
+
+#ifdef DEBUGGING
+    if (!done_sanity_check) {
+       unsigned int i = SVt_LAST;
+
+       done_sanity_check = TRUE;
+
+       while (i--)
+           assert (bodies_by_type[i].type == i);
+    }
+#endif
+
+    start = (char*) Perl_get_arena(aTHX_ bdp->arena_size);
+
+    end = start + bdp->arena_size - body_size;
+
+    /* computed count doesnt reflect the 1st slot reservation */
+    DEBUG_m(PerlIO_printf(Perl_debug_log,
+                         "arena %p end %p arena-size %d type %d size %d ct %d\n",
+                         start, end, bdp->arena_size, sv_type, body_size,
+                         bdp->arena_size / body_size));
+
+    *root = (void *)start;
+
+    while (start < end) {
+       char * const next = start + body_size;
+       *(void**) start = (void *)next;
+       start = next;
+    }
+    *(void **)start = 0;
+
+    return *root;
+}
+
+/* grab a new thing from the free list, allocating more if necessary.
+   The inline version is used for speed in hot routines, and the
+   function using it serves the rest (unless PURIFY).
+*/
+#define new_body_inline(xpv, sv_type) \
+    STMT_START { \
+       void ** const r3wt = &PL_body_roots[sv_type]; \
+       LOCK_SV_MUTEX; \
+       xpv = *((void **)(r3wt)) \
+         ? *((void **)(r3wt)) : S_more_bodies(aTHX_ sv_type); \
+       *(r3wt) = *(void**)(xpv); \
+       UNLOCK_SV_MUTEX; \
+    } STMT_END
+
+#ifndef PURIFY
+
+STATIC void *
+S_new_body(pTHX_ svtype sv_type)
+{
+    dVAR;
+    void *xpv;
+    new_body_inline(xpv, sv_type);
+    return xpv;
+}
+
+#endif
 
 /*
 =for apidoc sv_upgrade
@@ -947,9 +1127,9 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
     void*      old_body;
     void*      new_body;
     const U32  old_type = SvTYPE(sv);
+    const struct body_details *new_type_details;
     const struct body_details *const old_type_details
        = bodies_by_type + old_type;
-    const struct body_details *new_type_details = bodies_by_type + new_type;
 
     if (new_type != SVt_PV && SvIsCOW(sv)) {
        sv_force_normal_flags(sv, 0);
@@ -1008,13 +1188,11 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        if (new_type < SVt_PVIV) {
            new_type = (new_type == SVt_NV)
                ? SVt_PVNV : SVt_PVIV;
-           new_type_details = bodies_by_type + new_type;
        }
        break;
     case SVt_NV:
        if (new_type < SVt_PVNV) {
            new_type = SVt_PVNV;
-           new_type_details = bodies_by_type + new_type;
        }
        break;
     case SVt_RV:
@@ -1036,19 +1214,22 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        /* This flag bit is used to mean other things in other scalar types.
           Given that it only has meaning inside the pad, it shouldn't be set
           on anything that can get upgraded.  */
-       assert((SvFLAGS(sv) & SVpad_TYPED) == 0);
+       assert(!SvPAD_TYPED(sv));
        break;
     default:
        if (old_type_details->cant_upgrade)
-           Perl_croak(aTHX_ "Can't upgrade that kind of scalar");
+           Perl_croak(aTHX_ "Can't upgrade %s (%" UVuf ") to %" UVuf,
+                      sv_reftype(sv, 0), (UV) old_type, (UV) new_type);
     }
+    new_type_details = bodies_by_type + new_type;
 
     SvFLAGS(sv) &= ~SVTYPEMASK;
     SvFLAGS(sv) |= new_type;
 
+    /* This can't happen, as SVt_NULL is <= all values of new_type, so one of
+       the return statements above will have triggered.  */
+    assert (new_type != SVt_NULL);
     switch (new_type) {
-    case SVt_NULL:
-       Perl_croak(aTHX_ "Can't upgrade to undef");
     case SVt_IV:
        assert(old_type == SVt_NULL);
        SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
@@ -1065,21 +1246,28 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        SvRV_set(sv, 0);
        return;
     case SVt_PVHV:
-       SvANY(sv) = new_XPVHV();
-       HvFILL(sv)      = 0;
-       HvMAX(sv)       = 0;
-       HvTOTALKEYS(sv) = 0;
-
-       goto hv_av_common;
-
     case SVt_PVAV:
-       SvANY(sv) = new_XPVAV();
-       AvMAX(sv)       = -1;
-       AvFILLp(sv)     = -1;
-       AvALLOC(sv)     = 0;
-       AvREAL_only(sv);
+       assert(new_type_details->body_size);
+
+#ifndef PURIFY 
+       assert(new_type_details->arena);
+       assert(new_type_details->arena_size);
+       /* This points to the start of the allocated area.  */
+       new_body_inline(new_body, new_type);
+       Zero(new_body, new_type_details->body_size, char);
+       new_body = ((char *)new_body) - new_type_details->offset;
+#else
+       /* We always allocated the full length item with PURIFY. To do this
+          we fake things so that arena is false for all 16 types..  */
+       new_body = new_NOARENAZ(new_type_details);
+#endif
+       SvANY(sv) = new_body;
+       if (new_type == SVt_PVAV) {
+           AvMAX(sv)   = -1;
+           AvFILLp(sv) = -1;
+           AvREAL_only(sv);
+       }
 
-    hv_av_common:
        /* SVt_NULL isn't the only thing upgraded to AV or HV.
           The target created by newSVrv also is, and it can have magic.
           However, it never has SvPVX set.
@@ -1093,11 +1281,8 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        SvPV_set(sv, NULL);
 
        if (old_type >= SVt_PVMG) {
-           SvMAGIC_set(sv, ((XPVMG*)old_body)->xmg_magic);
+           SvMAGIC_set(sv, ((XPVMG*)old_body)->xmg_u.xmg_magic);
            SvSTASH_set(sv, ((XPVMG*)old_body)->xmg_stash);
-       } else {
-           SvMAGIC_set(sv, NULL);
-           SvSTASH_set(sv, NULL);
        }
        break;
 
@@ -1117,13 +1302,13 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
     case SVt_PVNV:
     case SVt_PV:
 
-       assert(new_type_details->size);
+       assert(new_type_details->body_size);
        /* We always allocated the full length item with PURIFY. To do this
           we fake things so that arena is false for all 16 types..  */
        if(new_type_details->arena) {
            /* This points to the start of the allocated area.  */
-           new_body_inline(new_body, new_type_details->size, new_type);
-           Zero(new_body, new_type_details->size, char);
+           new_body_inline(new_body, new_type);
+           Zero(new_body, new_type_details->body_size, char);
            new_body = ((char *)new_body) - new_type_details->offset;
        } else {
            new_body = new_NOARENAZ(new_type_details);
@@ -1131,9 +1316,21 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        SvANY(sv) = new_body;
 
        if (old_type_details->copy) {
-           Copy((char *)old_body + old_type_details->offset,
-                (char *)new_body + old_type_details->offset,
-                old_type_details->copy, char);
+           /* There is now the potential for an upgrade from something without
+              an offset (PVNV or PVMG) to something with one (PVCV, PVFM)  */
+           int offset = old_type_details->offset;
+           int length = old_type_details->copy;
+
+           if (new_type_details->offset > old_type_details->offset) {
+               int difference
+                   = new_type_details->offset - old_type_details->offset;
+               offset += difference;
+               length -= difference;
+           }
+           assert (length >= 0);
+               
+           Copy((char *)old_body + offset, (char *)new_body + offset, length,
+                char);
        }
 
 #ifndef NV_ZERO_IS_ALLBITS_ZERO
@@ -1156,8 +1353,11 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
                   (unsigned long)new_type);
     }
 
-    if (old_type_details->size) {
-       /* If the old body had an allocated size, then we need to free it.  */
+    if (old_type_details->arena) {
+       /* If there was an old body, then we need to free it.
+          Note that there is an assumption that all bodies of types that
+          can be upgraded came from arenas. Only the more complex non-
+          upgradable types are allowed to be directly malloc()ed.  */
 #ifdef PURIFY
        my_safefree(old_body);
 #else
@@ -1179,6 +1379,7 @@ wrapper instead.
 int
 Perl_sv_backoff(pTHX_ register SV *sv)
 {
+    PERL_UNUSED_CONTEXT;
     assert(SvOOK(sv));
     assert(SvTYPE(sv) != SVt_PVHV);
     assert(SvTYPE(sv) != SVt_PVAV);
@@ -1208,6 +1409,10 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
 {
     register char *s;
 
+    if (PL_madskills && newlen >= 0x100000) {
+       PerlIO_printf(Perl_debug_log,
+                     "Allocation too large: %"UVxf"\n", (UV)newlen);
+    }
 #ifdef HAS_64K_LIMIT
     if (newlen >= 0x10000) {
        PerlIO_printf(Perl_debug_log,
@@ -1515,6 +1720,31 @@ Perl_looks_like_number(pTHX_ SV *sv)
     return grok_number(sbegin, len, NULL);
 }
 
+STATIC char *
+S_glob_2inpuv(pTHX_ GV *gv, STRLEN *len, bool want_number)
+{
+    const U32 wasfake = SvFLAGS(gv) & SVf_FAKE;
+    SV *const buffer = sv_newmortal();
+
+    /* FAKE globs can get coerced, so need to turn this off temporarily if it
+       is on.  */
+    SvFAKE_off(gv);
+    gv_efullname3(buffer, gv, "*");
+    SvFLAGS(gv) |= wasfake;
+
+    if (want_number) {
+       /* We know that all GVs stringify to something that is not-a-number,
+          so no need to test that.  */
+       if (ckWARN(WARN_NUMERIC))
+           not_a_number(buffer);
+       /* We just want something true to return, so that S_sv_2iuv_common
+          can tail call us and return true.  */
+       return (char *) 1;
+    } else {
+       return SvPV(buffer, *len);
+    }
+}
+
 /* Actually, ISO C leaves conversion of UV to IV undefined, but
    until proven guilty, assume that things are not that bad... */
 
@@ -1816,7 +2046,7 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
                 if ((NV)(SvIVX(sv)) == SvNVX(sv)) {
                     SvIOK_on(sv);
                 } else {
-                    /* Integer is imprecise. NOK, IOKp */
+                   /*EMPTY*/;  /* Integer is imprecise. NOK, IOKp */
                 }
                 /* UV will not work better than IV */
             } else {
@@ -1831,7 +2061,7 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
                     if ((NV)(SvUVX(sv)) == SvNVX(sv)) {
                         SvIOK_on(sv);
                     } else {
-                        /* Integer is imprecise. NOK, IOKp, is UV */
+                       /*EMPTY*/;   /* Integer is imprecise. NOK, IOKp, is UV */
                     }
                 }
                SvIsUV_on(sv);
@@ -1875,6 +2105,10 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
        }
     }
     else  {
+       if (isGV_with_GP(sv)) {
+           return (bool)PTR2IV(glob_2inpuv((GV *)sv, NULL, TRUE));
+       }
+
        if (!(SvFLAGS(sv) & SVs_PADTMP)) {
            if (!PL_localizing && ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
@@ -2063,7 +2297,7 @@ Perl_sv_2nv(pTHX_ register SV *sv)
        mg_get(sv);
        if (SvNOKp(sv))
            return SvNVX(sv);
-       if (SvPOKp(sv) && SvLEN(sv)) {
+       if ((SvPOKp(sv) && SvLEN(sv)) && !SvIOKp(sv)) {
            if (!SvIOKp(sv) && ckWARN(WARN_NUMERIC) &&
                !grok_number(SvPVX_const(sv), SvCUR(sv), NULL))
                not_a_number(sv);
@@ -2222,6 +2456,11 @@ Perl_sv_2nv(pTHX_ register SV *sv)
 #endif /* NV_PRESERVES_UV */
     }
     else  {
+       if (isGV_with_GP(sv)) {
+           glob_2inpuv((GV *)sv, NULL, TRUE);
+           return 0.0;
+       }
+
        if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        assert (SvTYPE(sv) >= SVt_NV);
@@ -2407,16 +2646,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
                Gconvert(SvNVX(sv), NV_DIG, 0, tbuf);
                len = strlen(tbuf);
            }
-           if (SvROK(sv)) {    /* XXX Skip this when sv_pvn_force calls */
-               /* Sneaky stuff here */
-               SV * const tsv = newSVpvn(tbuf, len);
-
-               sv_2mortal(tsv);
-               if (lp)
-                   *lp = SvCUR(tsv);
-               return SvPVX(tsv);
-           }
-           else {
+           assert(!SvROK(sv));
+           {
                dVAR;
 
 #ifdef FIXNEGATIVEZERO
@@ -2562,6 +2793,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 #endif
     }
     else {
+       if (isGV_with_GP(sv)) {
+           return glob_2inpuv((GV *)sv, lp, FALSE);
+       }
+
        if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        if (lp)
@@ -2692,8 +2927,12 @@ Perl_sv_2bool(pTHX_ register SV *sv)
        else {
            if (SvNOKp(sv))
                return SvNVX(sv) != 0.0;
-           else
-               return FALSE;
+           else {
+               if (isGV_with_GP(sv))
+                   return TRUE;
+               else
+                   return FALSE;
+           }
        }
     }
 }
@@ -2926,20 +3165,27 @@ copy-ish functions and macros use this underneath.
 */
 
 static void
-S_glob_assign(pTHX_ SV *dstr, SV *sstr, const int dtype)
+S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
 {
     if (dtype != SVt_PVGV) {
        const char * const name = GvNAME(sstr);
        const STRLEN len = GvNAMELEN(sstr);
        /* don't upgrade SVt_PVLV: it can hold a glob */
-       if (dtype != SVt_PVLV)
+       if (dtype != SVt_PVLV) {
+           if (dtype >= SVt_PV) {
+               SvPV_free(dstr);
+               SvPV_set(dstr, 0);
+               SvLEN_set(dstr, 0);
+               SvCUR_set(dstr, 0);
+           }
            sv_upgrade(dstr, SVt_PVGV);
-       sv_magic(dstr, dstr, PERL_MAGIC_glob, Nullch, 0);
+           (void)SvOK_off(dstr);
+           SvSCREAM_on(dstr);
+       }
        GvSTASH(dstr) = GvSTASH(sstr);
        if (GvSTASH(dstr))
            Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
-       GvNAME(dstr) = savepvn(name, len);
-       GvNAMELEN(dstr) = len;
+       gv_name_set((GV *)dstr, name, len, GV_ADD);
        SvFAKE_on(dstr);        /* can coerce to non-glob */
     }
 
@@ -2949,9 +3195,11 @@ S_glob_assign(pTHX_ SV *dstr, SV *sstr, const int dtype)
     }
 #endif
 
+    gp_free((GV*)dstr);
+    SvSCREAM_off(dstr);
     (void)SvOK_off(dstr);
+    SvSCREAM_on(dstr);
     GvINTRO_off(dstr);         /* one-shot flag */
-    gp_free((GV*)dstr);
     GvGP(dstr) = gp_ref(GvGP(sstr));
     if (SvTAINTED(sstr))
        SvTAINT(dstr);
@@ -2965,10 +3213,14 @@ S_glob_assign(pTHX_ SV *dstr, SV *sstr, const int dtype)
 }
 
 static void
-S_pvgv_assign(pTHX_ SV *dstr, SV *sstr) {
+S_glob_assign_ref(pTHX_ SV *dstr, SV *sstr) {
     SV * const sref = SvREFCNT_inc(SvRV(sstr));
     SV *dref = NULL;
     const int intro = GvINTRO(dstr);
+    SV **location;
+    U8 import_flag = 0;
+    const U32 stype = SvTYPE(sref);
+
 
 #ifdef GV_UNIQUE_CHECK
     if (GvUNIQUE((GV*)dstr)) {
@@ -2982,45 +3234,43 @@ S_pvgv_assign(pTHX_ SV *dstr, SV *sstr) {
        GvEGV(dstr) = (GV*)dstr;
     }
     GvMULTI_on(dstr);
-    switch (SvTYPE(sref)) {
-    case SVt_PVAV:
-       if (intro)
-           SAVEGENERICSV(GvAV(dstr));
-       else
-           dref = (SV*)GvAV(dstr);
-       GvAV(dstr) = (AV*)sref;
-       if (!GvIMPORTED_AV(dstr)
-           && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-           {
-               GvIMPORTED_AV_on(dstr);
-           }
-       break;
-    case SVt_PVHV:
-       if (intro)
-           SAVEGENERICSV(GvHV(dstr));
-       else
-           dref = (SV*)GvHV(dstr);
-       GvHV(dstr) = (HV*)sref;
-       if (!GvIMPORTED_HV(dstr)
-           && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-           {
-               GvIMPORTED_HV_on(dstr);
-           }
-       break;
+    switch (stype) {
     case SVt_PVCV:
+       location = (SV **) &GvCV(dstr);
+       import_flag = GVf_IMPORTED_CV;
+       goto common;
+    case SVt_PVHV:
+       location = (SV **) &GvHV(dstr);
+       import_flag = GVf_IMPORTED_HV;
+       goto common;
+    case SVt_PVAV:
+       location = (SV **) &GvAV(dstr);
+       import_flag = GVf_IMPORTED_AV;
+       goto common;
+    case SVt_PVIO:
+       location = (SV **) &GvIOp(dstr);
+       goto common;
+    case SVt_PVFM:
+       location = (SV **) &GvFORM(dstr);
+    default:
+       location = &GvSV(dstr);
+       import_flag = GVf_IMPORTED_SV;
+    common:
        if (intro) {
-           if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
-               SvREFCNT_dec(GvCV(dstr));
-               GvCV(dstr) = Nullcv;
-               GvCVGEN(dstr) = 0; /* Switch off cacheness. */
-               PL_sub_generation++;
+           if (stype == SVt_PVCV) {
+               if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
+                   SvREFCNT_dec(GvCV(dstr));
+                   GvCV(dstr) = NULL;
+                   GvCVGEN(dstr) = 0; /* Switch off cacheness. */
+                   PL_sub_generation++;
+               }
            }
-           SAVEGENERICSV(GvCV(dstr));
+           SAVEGENERICSV(*location);
        }
        else
-           dref = (SV*)GvCV(dstr);
-       if (GvCV(dstr) != (CV*)sref) {
-           CV* const cv = GvCV(dstr);
+           dref = *location;
+       if (stype == SVt_PVCV && *location != sref) {
+           CV* const cv = (CV*)*location;
            if (cv) {
                if (!GvCVGEN((GV*)dstr) &&
                    (CvROOT(cv) || CvXSUB(cv)))
@@ -3029,6 +3279,7 @@ S_pvgv_assign(pTHX_ SV *dstr, SV *sstr) {
                           it was a const and its value changed. */
                        if (CvCONST(cv) && CvCONST((CV*)sref)
                            && cv_const_sv(cv) == cv_const_sv((CV*)sref)) {
+                           /*EMPTY*/
                            /* They are 2 constant subroutines generated from
                               the same constant. This probably means that
                               they are really the "same" proxy subroutine
@@ -3051,44 +3302,20 @@ S_pvgv_assign(pTHX_ SV *dstr, SV *sstr) {
                    }
                if (!intro)
                    cv_ckproto(cv, (GV*)dstr,
-                              SvPOK(sref) ? SvPVX_const(sref) : Nullch);
+                              SvPOK(sref) ? SvPVX_const(sref) : NULL);
            }
-           GvCV(dstr) = (CV*)sref;
            GvCVGEN(dstr) = 0; /* Switch off cacheness. */
            GvASSUMECV_on(dstr);
            PL_sub_generation++;
        }
-       if (!GvIMPORTED_CV(dstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
-           GvIMPORTED_CV_on(dstr);
-       }
-       break;
-    case SVt_PVIO:
-       if (intro)
-           SAVEGENERICSV(GvIOp(dstr));
-       else
-           dref = (SV*)GvIOp(dstr);
-       GvIOp(dstr) = (IO*)sref;
-       break;
-    case SVt_PVFM:
-       if (intro)
-           SAVEGENERICSV(GvFORM(dstr));
-       else
-           dref = (SV*)GvFORM(dstr);
-       GvFORM(dstr) = (CV*)sref;
-       break;
-    default:
-       if (intro)
-           SAVEGENERICSV(GvSV(dstr));
-       else
-           dref = (SV*)GvSV(dstr);
-       GvSV(dstr) = sref;
-       if (!GvIMPORTED_SV(dstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
-           GvIMPORTED_SV_on(dstr);
+       *location = sref;
+       if (import_flag && !(GvFLAGS(dstr) & import_flag)
+           && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) {
+           GvFLAGS(dstr) |= import_flag;
        }
        break;
     }
-    if (dref)
-       SvREFCNT_dec(dref);
+    SvREFCNT_dec(dref);
     if (SvTAINTED(sstr))
        SvTAINT(dstr);
     return;
@@ -3135,8 +3362,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                sv_upgrade(dstr, SVt_IV);
                break;
            case SVt_NV:
-               sv_upgrade(dstr, SVt_PVNV);
-               break;
            case SVt_RV:
            case SVt_PV:
                sv_upgrade(dstr, SVt_PVIV);
@@ -3146,8 +3371,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvIV_set(dstr,  SvIVX(sstr));
            if (SvIsUV(sstr))
                SvIsUV_on(dstr);
-           if (SvTAINTED(sstr))
-               SvTAINT(dstr);
+           /* SvTAINTED can only be true if the SV has taint magic, which in
+              turn means that the SV type is PVMG (or greater). This is the
+              case statement for SVt_IV, so this cannot be true (whatever gcov
+              may say).  */
+           assert(!SvTAINTED(sstr));
            return;
        }
        goto undef_sstr;
@@ -3167,8 +3395,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            }
            SvNV_set(dstr, SvNVX(sstr));
            (void)SvNOK_only(dstr);
-           if (SvTAINTED(sstr))
-               SvTAINT(dstr);
+           /* SvTAINTED can only be true if the SV has taint magic, which in
+              turn means that the SV type is PVMG (or greater). This is the
+              case statement for SVt_NV, so this cannot be true (whatever gcov
+              may say).  */
+           assert(!SvTAINTED(sstr));
            return;
        }
        goto undef_sstr;
@@ -3176,20 +3407,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
     case SVt_RV:
        if (dtype < SVt_RV)
            sv_upgrade(dstr, SVt_RV);
-       else if (dtype == SVt_PVGV &&
-                SvROK(sstr) && SvTYPE(SvRV(sstr)) == SVt_PVGV) {
-           sstr = SvRV(sstr);
-           if (sstr == dstr) {
-               if (GvIMPORTED(dstr) != GVf_IMPORTED
-                   && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
-               {
-                   GvIMPORTED_on(dstr);
-               }
-               GvMULTI_on(dstr);
-               return;
-           }
-           return S_glob_assign(aTHX_ dstr, sstr, dtype);
-       }
        break;
     case SVt_PVFM:
 #ifdef PERL_OLD_COPY_ON_WRITE
@@ -3212,10 +3429,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        if (dtype < SVt_PVNV)
            sv_upgrade(dstr, SVt_PVNV);
        break;
-    case SVt_PVAV:
-    case SVt_PVHV:
-    case SVt_PVCV:
-    case SVt_PVIO:
+    default:
        {
        const char * const type = sv_reftype(sstr,0);
        if (PL_op)
@@ -3227,17 +3441,22 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
 
     case SVt_PVGV:
        if (dtype <= SVt_PVGV) {
-           return S_glob_assign(aTHX_ dstr, sstr, dtype);
+           S_glob_assign_glob(aTHX_ dstr, sstr, dtype);
+           return;
        }
-       /* FALL THROUGH */
+       /*FALLTHROUGH*/
 
-    default:
+    case SVt_PVMG:
+    case SVt_PVLV:
+    case SVt_PVBM:
        if (SvGMAGICAL(sstr) && (flags & SV_GMAGIC)) {
            mg_get(sstr);
            if ((int)SvTYPE(sstr) != stype) {
                stype = SvTYPE(sstr);
-               if (stype == SVt_PVGV && dtype <= SVt_PVGV)
-                   return S_glob_assign(aTHX_ dstr, sstr, dtype);
+               if (stype == SVt_PVGV && dtype <= SVt_PVGV) {
+                   S_glob_assign_glob(aTHX_ dstr, sstr, dtype);
+                   return;
+               }
            }
        }
        if (stype == SVt_PVLV)
@@ -3246,12 +3465,32 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvUPGRADE(dstr, (U32)stype);
     }
 
+    /* dstr may have been upgraded.  */
+    dtype = SvTYPE(dstr);
     sflags = SvFLAGS(sstr);
 
     if (sflags & SVf_ROK) {
+       if (dtype == SVt_PVGV &&
+           SvROK(sstr) && SvTYPE(SvRV(sstr)) == SVt_PVGV) {
+           sstr = SvRV(sstr);
+           if (sstr == dstr) {
+               if (GvIMPORTED(dstr) != GVf_IMPORTED
+                   && CopSTASH_ne(PL_curcop, GvSTASH(dstr)))
+               {
+                   GvIMPORTED_on(dstr);
+               }
+               GvMULTI_on(dstr);
+               return;
+           }
+           S_glob_assign_glob(aTHX_ dstr, sstr, dtype);
+           return;
+       }
+
        if (dtype >= SVt_PV) {
-           if (dtype == SVt_PVGV)
-               return S_pvgv_assign(aTHX_ dstr, sstr);
+           if (dtype == SVt_PVGV) {
+               S_glob_assign_ref(aTHX_ dstr, sstr);
+               return;
+           }
            if (SvPVX_const(dstr)) {
                SvPV_free(dstr);
                SvLEN_set(dstr, 0);
@@ -3260,24 +3499,25 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
        (void)SvOK_off(dstr);
        SvRV_set(dstr, SvREFCNT_inc(SvRV(sstr)));
-       SvROK_on(dstr);
-       if (sflags & SVp_NOK) {
-           SvNOKp_on(dstr);
-           /* Only set the public OK flag if the source has public OK.  */
-           if (sflags & SVf_NOK)
-               SvFLAGS(dstr) |= SVf_NOK;
-           SvNV_set(dstr, SvNVX(sstr));
-       }
-       if (sflags & SVp_IOK) {
-           (void)SvIOKp_on(dstr);
-           if (sflags & SVf_IOK)
-               SvFLAGS(dstr) |= SVf_IOK;
-           if (sflags & SVf_IVisUV)
-               SvIsUV_on(dstr);
-           SvIV_set(dstr, SvIVX(sstr));
+       SvFLAGS(dstr) |= sflags & (SVf_ROK|SVf_AMAGIC);
+       assert(!(sflags & SVp_NOK));
+       assert(!(sflags & SVp_IOK));
+       assert(!(sflags & SVf_NOK));
+       assert(!(sflags & SVf_IOK));
+    }
+    else if (dtype == SVt_PVGV) {
+       if (!(sflags & SVf_OK)) {
+           if (ckWARN(WARN_MISC))
+               Perl_warner(aTHX_ packWARN(WARN_MISC),
+                           "Undefined value assigned to typeglob");
        }
-       if (SvAMAGIC(sstr)) {
-           SvAMAGIC_on(dstr);
+       else {
+           GV *gv = gv_fetchsv(sstr, GV_ADD, SVt_PVGV);
+           if (dstr != (SV*)gv) {
+               if (GvGP(dstr))
+                   gp_free((GV*)dstr);
+               GvGP(dstr) = gp_ref(GvGP(gv));
+           }
        }
     }
     else if (sflags & SVp_POK) {
@@ -3401,22 +3641,18 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                 SvTEMP_off(sstr);
             }
         }
-       if (sflags & SVf_UTF8)
-           SvUTF8_on(dstr);
        if (sflags & SVp_NOK) {
-           SvNOKp_on(dstr);
-           if (sflags & SVf_NOK)
-               SvFLAGS(dstr) |= SVf_NOK;
            SvNV_set(dstr, SvNVX(sstr));
        }
        if (sflags & SVp_IOK) {
-           (void)SvIOKp_on(dstr);
-           if (sflags & SVf_IOK)
-               SvFLAGS(dstr) |= SVf_IOK;
+           SvRELEASE_IVX(dstr);
+           SvIV_set(dstr, SvIVX(sstr));
+           /* Must do this otherwise some other overloaded use of 0x80000000
+              gets confused. I guess SVpbm_VALID */
            if (sflags & SVf_IVisUV)
                SvIsUV_on(dstr);
-           SvIV_set(dstr, SvIVX(sstr));
        }
+       SvFLAGS(dstr) |= sflags & (SVf_IOK|SVp_IOK|SVf_NOK|SVp_NOK|SVf_UTF8);
        {
            const MAGIC * const smg = SvVOK(sstr);
            if (smg) {
@@ -3426,25 +3662,28 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            }
        }
     }
-    else if (sflags & SVp_IOK) {
+    else if (sflags & (SVp_IOK|SVp_NOK)) {
        (void)SvOK_off(dstr);
-       /* XXXX Do we want to set IsUV for IV(ROK)?  Be extra safe... */
-       SvFLAGS(dstr) |= sflags & (SVf_IOK|SVp_IOK|SVf_IVisUV);
-       SvIV_set(dstr, SvIVX(sstr));
+       SvFLAGS(dstr) |= sflags & (SVf_IOK|SVp_IOK|SVf_IVisUV|SVf_NOK|SVp_NOK);
+       if (sflags & SVp_IOK) {
+           /* XXXX Do we want to set IsUV for IV(ROK)?  Be extra safe... */
+           SvIV_set(dstr, SvIVX(sstr));
+       }
        if (sflags & SVp_NOK) {
-           SvFLAGS(dstr) |= sflags & (SVf_NOK|SVp_NOK);
            SvNV_set(dstr, SvNVX(sstr));
        }
     }
-    else if (sflags & SVp_NOK) {
-       (void)SvOK_off(dstr);
-       SvFLAGS(dstr) |= sflags & (SVf_NOK|SVp_NOK);
-       SvNV_set(dstr, SvNVX(sstr));
-    }
     else {
-       if (dtype == SVt_PVGV) {
-           if (ckWARN(WARN_MISC))
-               Perl_warner(aTHX_ packWARN(WARN_MISC), "Undefined value assigned to typeglob");
+       if (isGV_with_GP(sstr)) {
+           /* This stringification rule for globs is spread in 3 places.
+              This feels bad. FIXME.  */
+           const U32 wasfake = sflags & SVf_FAKE;
+
+           /* FAKE globs can get coerced, so need to turn this off
+              temporarily if it is on.  */
+           SvFAKE_off(sstr);
+           gv_efullname3(dstr, (GV *)sstr, "*");
+           SvFLAGS(sstr) |= wasfake;
        }
        else
            (void)SvOK_off(dstr);
@@ -3698,7 +3937,7 @@ S_sv_release_COW(pTHX_ register SV *sv, const char *pvx, STRLEN len, SV *after)
 {
     if (len) { /* this SV was SvIsCOW_normal(sv) */
          /* we need to find the SV pointing to us.  */
-        SV * const current = SV_COW_NEXT_SV(after);
+        SV *current = SV_COW_NEXT_SV(after);
 
         if (current == sv) {
             /* The SV we point to points back to us (there were only two of us
@@ -3798,7 +4037,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags)
            const STRLEN len = SvCUR(sv);
            SvFAKE_off(sv);
            SvREADONLY_off(sv);
-           SvPV_set(sv, Nullch);
+           SvPV_set(sv, NULL);
            SvLEN_set(sv, 0);
            SvGROW(sv, len + 1);
            Move(pvx,SvPVX(sv),len,char);
@@ -4084,7 +4323,7 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
        mg->mg_obj = obj;
     }
     else {
-       mg->mg_obj = SvREFCNT_inc(obj);
+       mg->mg_obj = SvREFCNT_inc_simple(obj);
        mg->mg_flags |= MGf_REFCOUNTED;
     }
 
@@ -4108,7 +4347,7 @@ Perl_sv_magicext(pTHX_ SV* sv, SV* obj, int how, MGVTBL *vtable,
        if (namlen > 0)
            mg->mg_ptr = savepvn(name, namlen);
        else if (namlen == HEf_SVKEY)
-           mg->mg_ptr = (char*)SvREFCNT_inc((SV*)name);
+           mg->mg_ptr = (char*)SvREFCNT_inc_simple_NN((SV*)name);
        else
            mg->mg_ptr = (char *) name;
     }
@@ -4168,8 +4407,13 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
            /* sv_magic() refuses to add a magic of the same 'how' as an
               existing one
             */
-           if (how == PERL_MAGIC_taint)
+           if (how == PERL_MAGIC_taint) {
                mg->mg_len |= 1;
+               /* Any scalar which already had taint magic on which someone
+                  (erroneously?) did SvIOK_on() or similar will now be
+                  incorrectly sporting public "OK" flags.  */
+               SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
+           }
            return;
        }
     }
@@ -4268,9 +4512,6 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
     case PERL_MAGIC_defelem:
        vtable = &PL_vtbl_defelem;
        break;
-    case PERL_MAGIC_glob:
-       vtable = &PL_vtbl_glob;
-       break;
     case PERL_MAGIC_arylen:
        vtable = &PL_vtbl_arylen;
        break;
@@ -4320,7 +4561,7 @@ Perl_sv_unmagic(pTHX_ SV *sv, int type)
     MAGIC** mgp;
     if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv))
        return 0;
-    mgp = &SvMAGIC(sv);
+    mgp = &(((XPVMG*) SvANY(sv))->xmg_u.xmg_magic);
     for (mg = *mgp; mg; mg = *mgp) {
        if (mg->mg_type == type) {
             const MGVTBL* const vtbl = mg->mg_virtual;
@@ -4344,7 +4585,7 @@ Perl_sv_unmagic(pTHX_ SV *sv, int type)
     }
     if (!SvMAGIC(sv)) {
        SvMAGICAL_off(sv);
-       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
        SvMAGIC_set(sv, NULL);
     }
 
@@ -4412,7 +4653,7 @@ Perl_sv_add_backref(pTHX_ SV *tsv, SV *sv)
            } else {
                av = newAV();
                AvREAL_off(av);
-               SvREFCNT_inc(av);
+               SvREFCNT_inc_simple_void(av);
            }
            *avp = av;
        }
@@ -4484,7 +4725,7 @@ S_sv_del_backref(pTHX_ SV *tsv, SV *sv)
                */
                svp[i] = svp[fill];
            }
-           svp[fill] = Nullsv;
+           svp[fill] = NULL;
            AvFILLp(av) = fill - 1;
        }
     }
@@ -4522,7 +4763,7 @@ Perl_sv_kill_backrefs(pTHX_ SV *sv, AV *av)
                               (UV)SvFLAGS(referrer));
                }
 
-               *svp = Nullsv;
+               *svp = NULL;
            }
            svp++;
        }
@@ -4732,8 +4973,12 @@ Perl_sv_clear(pTHX_ register SV *sv)
     assert(sv);
     assert(SvREFCNT(sv) == 0);
 
-    if (type <= SVt_IV)
+    if (type <= SVt_IV) {
+       /* See the comment in sv.h about the collusion between this early
+          return and the overloading of the NULL and IV slots in the size
+          table.  */
        return;
+    }
 
     if (SvOBJECT(sv)) {
        if (PL_defstash) {              /* Still have a symbol table? */
@@ -4786,9 +5031,13 @@ Perl_sv_clear(pTHX_ register SV *sv)
        }
     }
     if (type >= SVt_PVMG) {
-       if (SvMAGIC(sv))
+       HV *ourstash;
+       if ((type == SVt_PVMG || type == SVt_PVGV) &&
+           (ourstash = OURSTASH(sv))) {
+           SvREFCNT_dec(ourstash);
+       } else if (SvMAGIC(sv))
            mg_free(sv);
-       if (type == SVt_PVMG && SvFLAGS(sv) & SVpad_TYPED)
+       if (type == SVt_PVMG && SvPAD_TYPED(sv))
            SvREFCNT_dec(SvSTASH(sv));
     }
     switch (type) {
@@ -4831,7 +5080,9 @@ Perl_sv_clear(pTHX_ register SV *sv)
        goto freescalar;
     case SVt_PVGV:
        gp_free((GV*)sv);
-       Safefree(GvNAME(sv));
+       if (GvNAME_HEK(sv)) {
+           unshare_hek(GvNAME_HEK(sv));
+       }
        /* If we're in a stash, we don't own a reference to it. However it does
           have a back reference to us, which needs to be cleared.  */
        if (GvSTASH(sv))
@@ -4848,7 +5099,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
     case SVt_PV:
     case SVt_RV:
        if (SvROK(sv)) {
-           SV *target = SvRV(sv);
+           SV * const target = SvRV(sv);
            if (SvWEAKREF(sv))
                sv_del_backref(target, sv);
            else
@@ -4891,7 +5142,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
        del_body(((char *)SvANY(sv) + sv_type_details->offset),
                 &PL_body_roots[type]);
     }
-    else if (sv_type_details->size) {
+    else if (sv_type_details->body_size) {
        my_safefree(SvANY(sv));
     }
 }
@@ -4908,6 +5159,7 @@ instead.
 SV *
 Perl_sv_newref(pTHX_ SV *sv)
 {
+    PERL_UNUSED_CONTEXT;
     if (sv)
        (SvREFCNT(sv))++;
     return sv;
@@ -5434,8 +5686,8 @@ Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
     const char *pv2;
     STRLEN cur2;
     I32  eq     = 0;
-    char *tpv   = Nullch;
-    SV* svrecode = Nullsv;
+    char *tpv   = NULL;
+    SV* svrecode = NULL;
 
     if (!sv1) {
        pv1 = "";
@@ -5501,9 +5753,7 @@ Perl_sv_eq(pTHX_ register SV *sv1, register SV *sv2)
     if (cur1 == cur2)
        eq = (pv1 == pv2) || memEQ(pv1, pv2, cur1);
        
-    if (svrecode)
-        SvREFCNT_dec(svrecode);
-
+    SvREFCNT_dec(svrecode);
     if (tpv)
        Safefree(tpv);
 
@@ -5527,9 +5777,9 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
     dVAR;
     STRLEN cur1, cur2;
     const char *pv1, *pv2;
-    char *tpv = Nullch;
+    char *tpv = NULL;
     I32  cmp;
-    SV *svrecode = Nullsv;
+    SV *svrecode = NULL;
 
     if (!sv1) {
        pv1 = "";
@@ -5586,9 +5836,7 @@ Perl_sv_cmp(pTHX_ register SV *sv1, register SV *sv2)
        }
     }
 
-    if (svrecode)
-        SvREFCNT_dec(svrecode);
-
+    SvREFCNT_dec(svrecode);
     if (tpv)
        Safefree(tpv);
 
@@ -5647,7 +5895,7 @@ Perl_sv_cmp_locale(pTHX_ register SV *sv1, register SV *sv2)
      */
 
   raw_compare:
-    /* FALL THROUGH */
+    /*FALLTHROUGH*/
 
 #endif /* USE_LOCALE_COLLATE */
 
@@ -6071,7 +6319,7 @@ screamer2:
     }
 
 return_string_or_null:
-    return (SvCUR(sv) - append) ? SvPVX(sv) : Nullch;
+    return (SvCUR(sv) - append) ? SvPVX(sv) : NULL;
 }
 
 /*
@@ -6611,7 +6859,7 @@ Perl_vnewSVpvf(pTHX_ const char* pat, va_list* args)
     dVAR;
     register SV *sv;
     new_SV(sv);
-    sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+    sv_vsetpvfn(sv, pat, strlen(pat), args, NULL, 0, NULL);
     return sv;
 }
 
@@ -6703,10 +6951,10 @@ Perl_newRV_noinc(pTHX_ SV *tmpRef)
  */
 
 SV *
-Perl_newRV(pTHX_ SV *tmpRef)
+Perl_newRV(pTHX_ SV *sv)
 {
     dVAR;
-    return newRV_noinc(SvREFCNT_inc(tmpRef));
+    return newRV_noinc(SvREFCNT_inc_simple_NN(sv));
 }
 
 /*
@@ -6729,7 +6977,7 @@ Perl_newSVsv(pTHX_ register SV *old)
     if (SvTYPE(old) == SVTYPEMASK) {
         if (ckWARN_d(WARN_INTERNAL))
            Perl_warner(aTHX_ packWARN(WARN_INTERNAL), "semi-panic: attempt to dup freed string");
-       return Nullsv;
+       return NULL;
     }
     new_SV(sv);
     /* SV_GMAGIC is the default for sv_setv()
@@ -6809,7 +7057,7 @@ Perl_sv_reset(pTHX_ register const char *s, HV *stash)
                    SvOK_off(sv);
                    if (SvTYPE(sv) >= SVt_PV) {
                        SvCUR_set(sv, 0);
-                       if (SvPVX_const(sv) != Nullch)
+                       if (SvPVX_const(sv) != NULL)
                            *SvPVX(sv) = '\0';
                        SvTAINT(sv);
                    }
@@ -6890,21 +7138,24 @@ CV *
 Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
 {
     dVAR;
-    GV *gv = Nullgv;
-    CV *cv = Nullcv;
+    GV *gv = NULL;
+    CV *cv = NULL;
 
-    if (!sv)
-       return *st = NULL, *gvp = Nullgv, Nullcv;
+    if (!sv) {
+       *st = NULL;
+       *gvp = NULL;
+       return NULL;
+    }
     switch (SvTYPE(sv)) {
     case SVt_PVCV:
        *st = CvSTASH(sv);
-       *gvp = Nullgv;
+       *gvp = NULL;
        return (CV*)sv;
     case SVt_PVHV:
     case SVt_PVAV:
        *st = NULL;
-       *gvp = Nullgv;
-       return Nullcv;
+       *gvp = NULL;
+       return NULL;
     case SVt_PVGV:
        gv = (GV*)sv;
        *gvp = gv;
@@ -6920,7 +7171,7 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
            sv = SvRV(sv);
            if (SvTYPE(sv) == SVt_PVCV) {
                cv = (CV*)sv;
-               *gvp = Nullgv;
+               *gvp = NULL;
                *st = CvSTASH(cv);
                return cv;
            }
@@ -6936,7 +7187,7 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
        *gvp = gv;
        if (!gv) {
            *st = NULL;
-           return Nullcv;
+           return NULL;
        }
        /* Some flags to gv_fetchsv mean don't really create the GV  */
        if (SvTYPE(gv) != SVt_PVGV) {
@@ -6949,14 +7200,13 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **st, GV **gvp, I32 lref)
            SV *tmpsv;
            ENTER;
            tmpsv = newSV(0);
-           gv_efullname3(tmpsv, gv, Nullch);
+           gv_efullname3(tmpsv, gv, NULL);
            /* XXX this is probably not what they think they're getting.
             * It has the same effect as "sub name;", i.e. just a forward
             * declaration! */
            newSUB(start_subparse(FALSE, 0),
                   newSVOP(OP_CONST, 0, tmpsv),
-                  Nullop,
-                  Nullop);
+                  NULL, NULL);
            LEAVE;
            if (!GvCVu(gv))
                Perl_croak(aTHX_ "Unable to create sub named \"%"SVf"\"",
@@ -7264,7 +7514,7 @@ Copies a pointer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  If the C<pv> argument is NULL then C<PL_sv_undef> will be placed
 into the SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 Do not use with other Perl types such as HV, AV, SV, CV, because those
@@ -7294,7 +7544,7 @@ Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
 Copies an integer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7313,7 +7563,7 @@ Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv)
 Copies an unsigned integer into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7332,7 +7582,7 @@ Perl_sv_setref_uv(pTHX_ SV *rv, const char *classname, UV uv)
 Copies a double into a new SV, optionally blessing the SV.  The C<rv>
 argument will be upgraded to an RV.  That RV will be modified to point to
 the new SV.  The C<classname> argument indicates the package for the
-blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+blessing.  Set C<classname> to C<NULL> to avoid the blessing.  The new SV
 will have a reference count of 1, and the RV will be returned.
 
 =cut
@@ -7352,7 +7602,7 @@ Copies a string into a new SV, optionally blessing the SV.  The length of the
 string must be specified with C<n>.  The C<rv> argument will be upgraded to
 an RV.  That RV will be modified to point to the new SV.  The C<classname>
 argument indicates the package for the blessing.  Set C<classname> to
-C<Nullch> to avoid the blessing.  The new SV will have a reference count
+C<NULL> to avoid the blessing.  The new SV will have a reference count
 of 1, and the RV will be returned.
 
 Note that C<sv_setref_pv> copies the pointer while this copies the string.
@@ -7398,7 +7648,7 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
     if (SvTYPE(tmpRef) != SVt_PVIO)
        ++PL_sv_objcount;
     SvUPGRADE(tmpRef, SVt_PVMG);
-    SvSTASH_set(tmpRef, (HV*)SvREFCNT_inc(stash));
+    SvSTASH_set(tmpRef, (HV*)SvREFCNT_inc_simple(stash));
 
     if (Gv_AMG(stash))
        SvAMAGIC_on(sv);
@@ -7422,18 +7672,24 @@ S_sv_unglob(pTHX_ SV *sv)
 {
     dVAR;
     void *xpvmg;
+    SV * const temp = sv_newmortal();
 
     assert(SvTYPE(sv) == SVt_PVGV);
     SvFAKE_off(sv);
-    if (GvGP(sv))
+    gv_efullname3(temp, (GV *) sv, "*");
+
+    if (GvGP(sv)) {
        gp_free((GV*)sv);
+    }
     if (GvSTASH(sv)) {
        sv_del_backref((SV*)GvSTASH(sv), sv);
        GvSTASH(sv) = NULL;
     }
-    sv_unmagic(sv, PERL_MAGIC_glob);
-    Safefree(GvNAME(sv));
     GvMULTI_off(sv);
+    if (GvNAME_HEK(sv)) {
+       unshare_hek(GvNAME_HEK(sv));
+    }
+    SvSCREAM_off(sv);
 
     /* need to keep SvANY(sv) in the right arena */
     xpvmg = new_XPVMG();
@@ -7443,6 +7699,10 @@ S_sv_unglob(pTHX_ SV *sv)
 
     SvFLAGS(sv) &= ~SVTYPEMASK;
     SvFLAGS(sv) |= SVt_PVMG;
+
+    /* Intentionally not calling any local SET magic, as this isn't so much a
+       set operation as merely an internal storage change.  */
+    sv_setsv_flags(sv, temp, 0);
 }
 
 /*
@@ -7614,7 +7874,7 @@ Usually used via its frontend C<sv_setpvf>.
 void
 Perl_sv_vsetpvf(pTHX_ SV *sv, const char* pat, va_list* args)
 {
-    sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+    sv_vsetpvfn(sv, pat, strlen(pat), args, NULL, 0, NULL);
 }
 
 /*
@@ -7647,7 +7907,7 @@ Usually used via its frontend C<sv_setpvf_mg>.
 void
 Perl_sv_vsetpvf_mg(pTHX_ SV *sv, const char* pat, va_list* args)
 {
-    sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+    sv_vsetpvfn(sv, pat, strlen(pat), args, NULL, 0, NULL);
     SvSETMAGIC(sv);
 }
 
@@ -7720,7 +7980,7 @@ Usually used via its frontend C<sv_catpvf>.
 void
 Perl_sv_vcatpvf(pTHX_ SV *sv, const char* pat, va_list* args)
 {
-    sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+    sv_vcatpvfn(sv, pat, strlen(pat), args, NULL, 0, NULL);
 }
 
 /*
@@ -7753,7 +8013,7 @@ Usually used via its frontend C<sv_catpvf_mg>.
 void
 Perl_sv_vcatpvf_mg(pTHX_ SV *sv, const char* pat, va_list* args)
 {
-    sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+    sv_vcatpvfn(sv, pat, strlen(pat), args, NULL, 0, NULL);
     SvSETMAGIC(sv);
 }
 
@@ -7786,7 +8046,7 @@ S_expect_number(pTHX_ char** pattern)
     case '7': case '8': case '9':
        var = *(*pattern)++ - '0';
        while (isDIGIT(**pattern)) {
-           I32 tmp = var * 10 + (*(*pattern)++ - '0');
+           const I32 tmp = var * 10 + (*(*pattern)++ - '0');
            if (tmp < var)
                Perl_croak(aTHX_ "Integer overflow in format string for %s", (PL_op ? OP_NAME(PL_op) : "sv_vcatpvfn"));
            var = tmp;
@@ -7818,7 +8078,7 @@ S_F0convert(NV nv, char *endbuf, STRLEN *len)
        *len = endbuf - p;
        return p;
     }
-    return Nullch;
+    return NULL;
 }
 
 
@@ -7853,10 +8113,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     STRLEN origlen;
     I32 svix = 0;
     static const char nullstr[] = "(null)";
-    SV *argsv = Nullsv;
+    SV *argsv = NULL;
     bool has_utf8 = DO_UTF8(sv);    /* has the result utf8? */
     const bool pat_utf8 = has_utf8; /* the pattern is in utf8? */
-    SV *nsv = Nullsv;
+    SV *nsv = NULL;
     /* Times 4: a decimal digit takes more than 3 binary digits.
      * NV_DIG: mantissa takes than many decimal digits.
      * Plus 32: Playing safe. */
@@ -7958,10 +8218,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        U8 utf8buf[UTF8_MAXBYTES+1];
        STRLEN esignlen = 0;
 
-       const char *eptr = Nullch;
+       const char *eptr = NULL;
        STRLEN elen = 0;
-       SV *vecsv = Nullsv;
-       const U8 *vecstr = Null(U8*);
+       SV *vecsv = NULL;
+       const U8 *vecstr = NULL;
        STRLEN veclen = 0;
        char c = 0;
        int i;
@@ -8248,7 +8508,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #endif
 #if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE)
        case 'L':                       /* Ld */
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
 #ifdef HAS_QUAD
        case 'q':                       /* qd */
 #endif
@@ -8264,9 +8524,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                break;
             }
 #endif
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'h':
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'V':
            intsize = *q++;
            break;
@@ -8369,7 +8629,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #else
            intsize = 'l';
 #endif
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'd':
        case 'i':
 #if vdNUMBER
@@ -8435,7 +8695,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #else
            intsize = 'l';
 #endif
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'u':
            base = 10;
            goto uns_integer;
@@ -8450,7 +8710,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #else
            intsize = 'l';
 #endif
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'o':
            base = 8;
            goto uns_integer;
@@ -8560,7 +8820,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 
        case 'F':
            c = 'f';            /* maybe %F isn't supported here */
-           /* FALL THROUGH */
+           /*FALLTHROUGH*/
        case 'e': case 'E':
        case 'f':
        case 'g': case 'G':
@@ -8581,7 +8841,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                break;
 /* [perl #20339] - we should accept and ignore %lf rather than die */
            case 'l':
-               /* FALL THROUGH */
+               /*FALLTHROUGH*/
            default:
 #if defined(USE_LONG_DOUBLE)
                intsize = args ? 0 : 'q';
@@ -8591,7 +8851,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 #if defined(HAS_LONG_DOUBLE)
                break;
 #else
-               /* FALL THROUGH */
+               /*FALLTHROUGH*/
 #endif
            case 'h':
                goto unknown;
@@ -8926,6 +9186,7 @@ ptr_table_* functions.
 
 
 #define sv_dup_inc(s,t)        SvREFCNT_inc(sv_dup(s,t))
+#define sv_dup_inc_NN(s,t)     SvREFCNT_inc_NN(sv_dup(s,t))
 #define av_dup(s,t)    (AV*)sv_dup((SV*)s,t)
 #define av_dup_inc(s,t)        (AV*)SvREFCNT_inc(sv_dup((SV*)s,t))
 #define hv_dup(s,t)    (HV*)sv_dup((SV*)s,t)
@@ -9048,9 +9309,9 @@ Perl_re_dup(pTHX_ const REGEXP *r, CLONE_PARAMS *param)
     if (RX_MATCH_COPIED(ret))
        ret->subbeg  = SAVEPVN(r->subbeg, r->sublen);
     else
-       ret->subbeg = Nullch;
+       ret->subbeg = NULL;
 #ifdef PERL_OLD_COPY_ON_WRITE
-    ret->saved_copy = Nullsv;
+    ret->saved_copy = NULL;
 #endif
 
     ptr_table_store(PL_ptr_table, r, ret);
@@ -9085,6 +9346,7 @@ Perl_fp_dup(pTHX_ PerlIO *fp, char type, CLONE_PARAMS *param)
 DIR *
 Perl_dirp_dup(pTHX_ DIR *dp)
 {
+    PERL_UNUSED_CONTEXT;
     if (!dp)
        return (DIR*)NULL;
     /* XXX TODO */
@@ -9097,6 +9359,7 @@ GP *
 Perl_gp_dup(pTHX_ GP *gp, CLONE_PARAMS* param)
 {
     GP *ret;
+
     if (!gp)
        return (GP*)NULL;
     /* look for it in the table first */
@@ -9197,6 +9460,8 @@ PTR_TBL_t *
 Perl_ptr_table_new(pTHX)
 {
     PTR_TBL_t *tbl;
+    PERL_UNUSED_CONTEXT;
+
     Newxz(tbl, 1, PTR_TBL_t);
     tbl->tbl_max       = 511;
     tbl->tbl_items     = 0;
@@ -9218,7 +9483,7 @@ Perl_ptr_table_new(pTHX)
 /* map an existing pointer using a table */
 
 STATIC PTR_TBL_ENT_t *
-S_ptr_table_find(pTHX_ PTR_TBL_t *tbl, const void *sv) {
+S_ptr_table_find(PTR_TBL_t *tbl, const void *sv) {
     PTR_TBL_ENT_t *tblent;
     const UV hash = PTR_TABLE_HASH(sv);
     assert(tbl);
@@ -9233,7 +9498,8 @@ S_ptr_table_find(pTHX_ PTR_TBL_t *tbl, const void *sv) {
 void *
 Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, const void *sv)
 {
-    PTR_TBL_ENT_t const *const tblent = S_ptr_table_find(aTHX_ tbl, sv);
+    PTR_TBL_ENT_t const *const tblent = ptr_table_find(tbl, sv);
+    PERL_UNUSED_CONTEXT;
     return tblent ? tblent->newval : (void *) 0;
 }
 
@@ -9242,14 +9508,16 @@ Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, const void *sv)
 void
 Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, const void *oldsv, void *newsv)
 {
-    PTR_TBL_ENT_t *tblent = S_ptr_table_find(aTHX_ tbl, oldsv);
+    PTR_TBL_ENT_t *tblent = ptr_table_find(tbl, oldsv);
+    PERL_UNUSED_CONTEXT;
 
     if (tblent) {
        tblent->newval = newsv;
     } else {
        const UV entry = PTR_TABLE_HASH(oldsv) & tbl->tbl_max;
 
-       new_body_inline(tblent, sizeof(struct ptr_tbl_ent), PTE_SVSLOT);
+       new_body_inline(tblent, PTE_SVSLOT);
+
        tblent->oldval = oldsv;
        tblent->newval = newsv;
        tblent->next = tbl->tbl_ary[entry];
@@ -9269,6 +9537,7 @@ Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl)
     const UV oldsize = tbl->tbl_max + 1;
     UV newsize = oldsize * 2;
     UV i;
+    PERL_UNUSED_CONTEXT;
 
     Renew(ary, newsize, PTR_TBL_ENT_t*);
     Zero(&ary[oldsize], newsize-oldsize, PTR_TBL_ENT_t*);
@@ -9352,7 +9621,10 @@ Perl_rvpv_dup(pTHX_ SV *dstr, const SV *sstr, CLONE_PARAMS* param)
        }
        else {
            /* Special case - not normally malloced for some reason */
-           if ((SvREADONLY(sstr) && SvFAKE(sstr))) {
+           if (isGV_with_GP(sstr)) {
+               /* Don't need to do anything here.  */
+           }
+           else if ((SvREADONLY(sstr) && SvFAKE(sstr))) {
                /* A "shared" PV - clone it as "shared" PV */
                SvPV_set(dstr,
                         HEK_KEY(hek_dup(SvSHARED_HEK_FROM_PV(SvPVX_const(sstr)),
@@ -9365,7 +9637,7 @@ Perl_rvpv_dup(pTHX_ SV *dstr, const SV *sstr, CLONE_PARAMS* param)
        }
     }
     else {
-       /* Copy the Null */
+       /* Copy the NULL */
        if (SvTYPE(dstr) == SVt_RV)
            SvRV_set(dstr, NULL);
        else
@@ -9456,13 +9728,12 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
 
            switch (sv_type) {
            default:
-               Perl_croak(aTHX_ "Bizarre SvTYPE [%" IVdf "]",
-                          (IV)SvTYPE(sstr));
+               Perl_croak(aTHX_ "Bizarre SvTYPE [%" IVdf "]", (IV)SvTYPE(sstr));
                break;
 
            case SVt_PVGV:
                if (GvUNIQUE((GV*)sstr)) {
-                   /* Do sharing here, and fall through */
+                   /*EMPTY*/;   /* Do sharing here, and fall through */
                }
            case SVt_PVIO:
            case SVt_PVFM:
@@ -9475,9 +9746,9 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
            case SVt_PVNV:
            case SVt_PVIV:
            case SVt_PV:
-               assert(sv_type_details->size);
+               assert(sv_type_details->body_size);
                if (sv_type_details->arena) {
-                   new_body_inline(new_body, sv_type_details->size, sv_type);
+                   new_body_inline(new_body, sv_type);
                    new_body
                        = (void*)((char*)new_body - sv_type_details->offset);
                } else {
@@ -9494,10 +9765,11 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
 #else
            Copy(((char*)SvANY(sstr)),
                 ((char*)SvANY(dstr)),
-                sv_type_details->size + sv_type_details->offset, char);
+                sv_type_details->body_size + sv_type_details->offset, char);
 #endif
 
-           if (sv_type != SVt_PVAV && sv_type != SVt_PVHV)
+           if (sv_type != SVt_PVAV && sv_type != SVt_PVHV
+               && !isGV_with_GP(dstr))
                Perl_rvpv_dup(aTHX_ dstr, sstr, param);
 
            /* The Copy above means that all the source (unduplicated) pointers
@@ -9506,7 +9778,10 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
               missing by always going for the destination.
               FIXME - instrument and check that assumption  */
            if (sv_type >= SVt_PVMG) {
-               if (SvMAGIC(dstr))
+               HV *ourstash;
+               if ((sv_type == SVt_PVMG) && (ourstash = OURSTASH(dstr))) {
+                   OURSTASH_set(dstr, hv_dup_inc(ourstash, param));
+               } else if (SvMAGIC(dstr))
                    SvMAGIC_set(dstr, mg_dup(SvMAGIC(dstr), param));
                if (SvSTASH(dstr))
                    SvSTASH_set(dstr, hv_dup_inc(SvSTASH(dstr), param));
@@ -9534,12 +9809,19 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    LvTARG(dstr) = sv_dup_inc(LvTARG(dstr), param);
                break;
            case SVt_PVGV:
-               GvNAME(dstr)    = SAVEPVN(GvNAME(dstr), GvNAMELEN(dstr));
-               GvSTASH(dstr)   = hv_dup(GvSTASH(dstr), param);
+               if (GvNAME_HEK(dstr))
+                   GvNAME_HEK(dstr) = hek_dup(GvNAME_HEK(dstr), param);
+
                /* Don't call sv_add_backref here as it's going to be created
                   as part of the magic cloning of the symbol table.  */
-               GvGP(dstr)      = gp_dup(GvGP(dstr), param);
-               (void)GpREFCNT_inc(GvGP(dstr));
+               GvSTASH(dstr)   = hv_dup(GvSTASH(dstr), param);
+               if(isGV_with_GP(sstr)) {
+                   /* Danger Will Robinson - GvGP(dstr) isn't initialised
+                      at the point of this comment.  */
+                   GvGP(dstr)  = gp_dup(GvGP(sstr), param);
+                   (void)GpREFCNT_inc(GvGP(dstr));
+               } else
+                   Perl_rvpv_dup(aTHX_ dstr, sstr, param);
                break;
            case SVt_PVIO:
                IoIFP(dstr)     = fp_dup(IoIFP(dstr), IoTYPE(dstr), param);
@@ -9548,8 +9830,6 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                else
                    IoOFP(dstr) = fp_dup(IoOFP(dstr), IoTYPE(dstr), param);
                /* PL_rsfp_filters entries have fake IoDIRP() */
-               if (IoDIRP(dstr) && !(IoFLAGS(dstr) & IOf_FAKE_DIRP))
-                   IoDIRP(dstr)        = dirp_dup(IoDIRP(dstr));
                if(IoFLAGS(dstr) & IOf_FAKE_DIRP) {
                    /* I have no idea why fake dirp (rsfps)
                       should be treated differently but otherwise
@@ -9561,6 +9841,12 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    IoTOP_GV(dstr)      = gv_dup(IoTOP_GV(dstr), param);
                    IoFMT_GV(dstr)      = gv_dup(IoFMT_GV(dstr), param);
                    IoBOTTOM_GV(dstr)   = gv_dup(IoBOTTOM_GV(dstr), param);
+                   if (IoDIRP(dstr)) {
+                       IoDIRP(dstr)    = dirp_dup(IoDIRP(dstr));
+                   } else {
+                       /*EMPTY*/;
+                       /* IoDIRP(dstr) is already a copy of IoDIRP(sstr)  */
+                   }
                }
                IoTOP_NAME(dstr)        = SAVEPV(IoTOP_NAME(dstr));
                IoFMT_NAME(dstr)        = SAVEPV(IoFMT_NAME(dstr));
@@ -9590,7 +9876,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                    }
                }
                else {
-                   SvPV_set(dstr, Nullch);
+                   SvPV_set(dstr, NULL);
                    AvALLOC((AV*)dstr)  = (SV**)NULL;
                }
                break;
@@ -9638,21 +9924,25 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                        }
                    }
                    else {
-                       SvPV_set(dstr, Nullch);
+                       SvPV_set(dstr, NULL);
                    }
                    /* Record stashes for possible cloning in Perl_clone(). */
                    if(hvname)
                        av_push(param->stashes, dstr);
                }
                break;
-           case SVt_PVFM:
            case SVt_PVCV:
+               if (!(param->flags & CLONEf_COPY_STACKS)) {
+                   CvDEPTH(dstr) = 0;
+               }
+           case SVt_PVFM:
                /* NOTE: not refcounted */
                CvSTASH(dstr)   = hv_dup(CvSTASH(dstr), param);
                OP_REFCNT_LOCK;
-               CvROOT(dstr)    = OpREFCNT_inc(CvROOT(dstr));
+               if (!CvISXSUB(dstr))
+                   CvROOT(dstr) = OpREFCNT_inc(CvROOT(dstr));
                OP_REFCNT_UNLOCK;
-               if (CvCONST(dstr)) {
+               if (CvCONST(dstr) && CvISXSUB(dstr)) {
                    CvXSUBANY(dstr).any_ptr = GvUNIQUE(CvGV(dstr)) ?
                        SvREFCNT_inc(CvXSUBANY(dstr).any_ptr) :
                        sv_dup_inc((SV *)CvXSUBANY(dstr).any_ptr, param);
@@ -9660,16 +9950,13 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                /* don't dup if copying back - CvGV isn't refcounted, so the
                 * duped GV may never be freed. A bit of a hack! DAPM */
                CvGV(dstr)      = (param->flags & CLONEf_JOIN_IN) ?
-                   Nullgv : gv_dup(CvGV(dstr), param) ;
-               if (!(param->flags & CLONEf_COPY_STACKS)) {
-                   CvDEPTH(dstr) = 0;
-               }
+                   NULL : gv_dup(CvGV(dstr), param) ;
                PAD_DUP(CvPADLIST(dstr), CvPADLIST(sstr), param);
                CvOUTSIDE(dstr) =
                    CvWEAKOUTSIDE(sstr)
                    ? cv_dup(    CvOUTSIDE(dstr), param)
                    : cv_dup_inc(CvOUTSIDE(dstr), param);
-               if (!CvXSUB(dstr))
+               if (!CvISXSUB(dstr))
                    CvFILE(dstr) = SAVEPV(CvFILE(dstr));
                break;
            }
@@ -10016,12 +10303,12 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
                    OpREFCNT_inc(o);
                    break;
                default:
-                   TOPPTR(nss,ix) = Nullop;
+                   TOPPTR(nss,ix) = NULL;
                    break;
                }
            }
            else
-               TOPPTR(nss,ix) = Nullop;
+               TOPPTR(nss,ix) = NULL;
            break;
        case SAVEt_FREEPV:
            c = (char*)POPPTR(ss,ix);
@@ -10237,17 +10524,17 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     IV i;
     CLONE_PARAMS clone_params;
-    CLONE_PARAMS* param = &clone_params;
+    CLONE_PARAMS* const param = &clone_params;
 
-    PerlInterpreter *my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter));
+    PerlInterpreter * const my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter));
     /* for each stash, determine whether its objects should be cloned */
     S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK);
     PERL_SET_THX(my_perl);
 
 #  ifdef DEBUGGING
     Poison(my_perl, 1, PerlInterpreter);
-    PL_op = Nullop;
-    PL_curcop = (COP *)Nullop;
+    PL_op = NULL;
+    PL_curcop = NULL;
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
@@ -10273,15 +10560,15 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     IV i;
     CLONE_PARAMS clone_params;
     CLONE_PARAMS* param = &clone_params;
-    PerlInterpreter *my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
+    PerlInterpreter * const my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
     /* for each stash, determine whether its objects should be cloned */
     S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK);
     PERL_SET_THX(my_perl);
 
 #    ifdef DEBUGGING
     Poison(my_perl, 1, PerlInterpreter);
-    PL_op = Nullop;
-    PL_curcop = (COP *)Nullop;
+    PL_op = NULL;
+    PL_curcop = NULL;
     PL_markstack = 0;
     PL_scopestack = 0;
     PL_savestack = 0;
@@ -10296,15 +10583,17 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     param->flags = flags;
     param->proto_perl = proto_perl;
 
-    Zero(&PL_body_arenaroots, 1, PL_body_arenaroots);
+    INIT_TRACK_MEMPOOL(my_perl->Imemory_debug_header, my_perl);
+
+    PL_body_arenas = NULL;
     Zero(&PL_body_roots, 1, PL_body_roots);
     
     PL_nice_chunk      = NULL;
     PL_nice_chunk_size = 0;
     PL_sv_count                = 0;
     PL_sv_objcount     = 0;
-    PL_sv_root         = Nullsv;
-    PL_sv_arenaroot    = Nullsv;
+    PL_sv_root         = NULL;
+    PL_sv_arenaroot    = NULL;
 
     PL_debug           = proto_perl->Idebug;
 
@@ -10442,8 +10731,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        const I32 len = av_len((AV*)proto_perl->Iregex_padav);
        SV* const * const regexen = AvARRAY((AV*)proto_perl->Iregex_padav);
        IV i;
-       av_push(PL_regex_padav,
-               sv_dup_inc(regexen[0],param));
+       av_push(PL_regex_padav, sv_dup_inc_NN(regexen[0],param));
        for(i = 1; i <= len; i++) {
            const SV * const regex = regexen[i];
            SV * const sv =
@@ -10510,7 +10798,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     if (proto_perl->Iop_mask)
        PL_op_mask      = SAVEPVN(proto_perl->Iop_mask, PL_maxo);
     else
-       PL_op_mask      = Nullch;
+       PL_op_mask      = NULL;
     /* PL_asserting        = proto_perl->Iasserting; */
 
     /* current interpreter roots */
@@ -10528,13 +10816,13 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_lastfd          = proto_perl->Ilastfd;
     PL_oldname         = proto_perl->Ioldname;         /* XXX not quite right */
     PL_Argv            = NULL;
-    PL_Cmd             = Nullch;
+    PL_Cmd             = NULL;
     PL_gensym          = proto_perl->Igensym;
     PL_preambled       = proto_perl->Ipreambled;
     PL_preambleav      = av_dup_inc(proto_perl->Ipreambleav, param);
     PL_laststatval     = proto_perl->Ilaststatval;
     PL_laststype       = proto_perl->Ilaststype;
-    PL_mess_sv         = Nullsv;
+    PL_mess_sv         = NULL;
 
     PL_ors_sv          = sv_dup_inc(proto_perl->Iors_sv, param);
 
@@ -10620,9 +10908,26 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     i = (PL_lex_casemods < 12 ? 12 : PL_lex_casemods);
     PL_lex_casestack   = SAVEPVN(proto_perl->Ilex_casestack,i);
 
+#ifdef PERL_MAD
+    Copy(proto_perl->Inexttoke, PL_nexttoke, 5, NEXTTOKE);
+    PL_lasttoke                = proto_perl->Ilasttoke;
+    PL_realtokenstart  = proto_perl->Irealtokenstart;
+    PL_faketokens      = proto_perl->Ifaketokens;
+    PL_thismad         = proto_perl->Ithismad;
+    PL_thistoken       = proto_perl->Ithistoken;
+    PL_thisopen                = proto_perl->Ithisopen;
+    PL_thisstuff       = proto_perl->Ithisstuff;
+    PL_thisclose       = proto_perl->Ithisclose;
+    PL_thiswhite       = proto_perl->Ithiswhite;
+    PL_nextwhite       = proto_perl->Inextwhite;
+    PL_skipwhite       = proto_perl->Iskipwhite;
+    PL_endwhite                = proto_perl->Iendwhite;
+    PL_curforce                = proto_perl->Icurforce;
+#else
     Copy(proto_perl->Inextval, PL_nextval, 5, YYSTYPE);
     Copy(proto_perl->Inexttype, PL_nexttype, 5,        I32);
     PL_nexttoke                = proto_perl->Inexttoke;
+#endif
 
     /* XXX This is probably masking the deeper issue of why
      * SvANY(proto_perl->Ilinestr) can be NULL at this point. For test case:
@@ -10765,7 +11070,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
     PL_uudmap['M']     = 0;            /* reinits on demand */
-    PL_bitcount                = Nullch;       /* reinits on demand */
+    PL_bitcount                = NULL; /* reinits on demand */
 
     if (proto_perl->Ipsig_pend) {
        Newxz(PL_psig_pend, SIG_SIZE, int);
@@ -10852,7 +11157,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
                    proto_perl->Ttmps_stack[i]);
            if (nsv && !SvREFCNT(nsv)) {
                EXTEND_MORTAL(1);
-               PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc(nsv);
+               PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc_simple(nsv);
            }
        }
     }
@@ -10862,7 +11167,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_op              = proto_perl->Top;
 
-    PL_Sv              = Nullsv;
+    PL_Sv              = NULL;
     PL_Xpv             = (XPV*)NULL;
     PL_na              = proto_perl->Tna;
 
@@ -10892,16 +11197,16 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_localizing      = proto_perl->Tlocalizing;
 
     PL_errors          = sv_dup_inc(proto_perl->Terrors, param);
-    PL_hv_fetch_ent_mh = Nullhe;
+    PL_hv_fetch_ent_mh = NULL;
     PL_modcount                = proto_perl->Tmodcount;
-    PL_lastgotoprobe   = Nullop;
+    PL_lastgotoprobe   = NULL;
     PL_dumpindent      = proto_perl->Tdumpindent;
 
     PL_sortcop         = (OP*)any_dup(proto_perl->Tsortcop, proto_perl);
     PL_sortstash       = hv_dup(proto_perl->Tsortstash, param);
     PL_firstgv         = gv_dup(proto_perl->Tfirstgv, param);
     PL_secondgv                = gv_dup(proto_perl->Tsecondgv, param);
-    PL_efloatbuf       = Nullch;               /* reinits on demand */
+    PL_efloatbuf       = NULL;         /* reinits on demand */
     PL_efloatsize      = 0;                    /* reinits on demand */
 
     /* regex stuff */
@@ -10909,29 +11214,29 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_screamfirst     = NULL;
     PL_screamnext      = NULL;
     PL_maxscream       = -1;                   /* reinits on demand */
-    PL_lastscream      = Nullsv;
+    PL_lastscream      = NULL;
 
     PL_watchaddr       = NULL;
-    PL_watchok         = Nullch;
+    PL_watchok         = NULL;
 
     PL_regdummy                = proto_perl->Tregdummy;
-    PL_regprecomp      = Nullch;
+    PL_regprecomp      = NULL;
     PL_regnpar         = 0;
     PL_regsize         = 0;
     PL_colorset                = 0;            /* reinits PL_colors[] */
     /*PL_colors[6]     = {0,0,0,0,0,0};*/
-    PL_reginput                = Nullch;
-    PL_regbol          = Nullch;
-    PL_regeol          = Nullch;
+    PL_reginput                = NULL;
+    PL_regbol          = NULL;
+    PL_regeol          = NULL;
     PL_regstartp       = (I32*)NULL;
     PL_regendp         = (I32*)NULL;
     PL_reglastparen    = (U32*)NULL;
     PL_reglastcloseparen       = (U32*)NULL;
-    PL_regtill         = Nullch;
+    PL_regtill         = NULL;
     PL_reg_start_tmp   = (char**)NULL;
     PL_reg_start_tmpl  = 0;
     PL_regdata         = (struct reg_data*)NULL;
-    PL_bostr           = Nullch;
+    PL_bostr           = NULL;
     PL_reg_flags       = 0;
     PL_reg_eval_set    = 0;
     PL_regnarrate      = 0;
@@ -10940,21 +11245,21 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_regcc           = (CURCUR*)NULL;
     PL_reg_call_cc     = (struct re_cc_state*)NULL;
     PL_reg_re          = (regexp*)NULL;
-    PL_reg_ganch       = Nullch;
-    PL_reg_sv          = Nullsv;
+    PL_reg_ganch       = NULL;
+    PL_reg_sv          = NULL;
     PL_reg_match_utf8  = FALSE;
     PL_reg_magic       = (MAGIC*)NULL;
     PL_reg_oldpos      = 0;
     PL_reg_oldcurpm    = (PMOP*)NULL;
     PL_reg_curpm       = (PMOP*)NULL;
-    PL_reg_oldsaved    = Nullch;
+    PL_reg_oldsaved    = NULL;
     PL_reg_oldsavedlen = 0;
 #ifdef PERL_OLD_COPY_ON_WRITE
-    PL_nrs             = Nullsv;
+    PL_nrs             = NULL;
 #endif
     PL_reg_maxiter     = 0;
     PL_reg_leftiter    = 0;
-    PL_reg_poscache    = Nullch;
+    PL_reg_poscache    = NULL;
     PL_reg_poscache_size= 0;
 
     /* RE engine - function pointers */
@@ -11000,7 +11305,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* orphaned? eg threads->new inside BEGIN or use */
     if (PL_compcv && ! SvREFCNT(PL_compcv)) {
-       (void)SvREFCNT_inc(PL_compcv);
+       SvREFCNT_inc_simple_void(PL_compcv);
        SAVEFREESV(PL_compcv);
     }
 
@@ -11143,7 +11448,7 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
 
     if (!hv || SvMAGICAL(hv) || !HvARRAY(hv) ||
                        (HvTOTALKEYS(hv) > FUV_MAX_SEARCH_SIZE))
-       return Nullsv;
+       return NULL;
 
     array = HvARRAY(hv);
 
@@ -11156,13 +11461,13 @@ S_find_hash_subscript(pTHX_ HV *hv, SV* val)
                    HeVAL(entry) == &PL_sv_placeholder)
                continue;
            if (!HeKEY(entry))
-               return Nullsv;
+               return NULL;
            if (HeKLEN(entry) == HEf_SVKEY)
                return sv_mortalcopy(HeKEY_sv(entry));
            return sv_2mortal(newSVpvn(HeKEY(entry), HeKLEN(entry)));
        }
     }
-    return Nullsv;
+    return NULL;
 }
 
 /* Look for an entry in the array whose value has the same SV as val;
@@ -11228,7 +11533,7 @@ S_varname(pTHX_ GV *gv, const char gvtype, PADOFFSET targ,
        AV *av;
 
        if (!cv || !CvPADLIST(cv))
-           return Nullsv;
+           return NULL;
        av = (AV*)(*av_fetch(CvPADLIST(cv), 0, FALSE));
        sv = *av_fetch(av, targ, FALSE);
        /* SvLEN in a pad name is not to be trusted */
@@ -11284,7 +11589,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 
     if (!obase || (match && (!uninit_sv || uninit_sv == &PL_sv_undef ||
                            uninit_sv == &PL_sv_placeholder)))
-       return Nullsv;
+       return NULL;
 
     switch (obase->op_type) {
 
@@ -11296,12 +11601,12 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
        const bool pad  = (obase->op_type == OP_PADAV || obase->op_type == OP_PADHV);
        const bool hash = (obase->op_type == OP_PADHV || obase->op_type == OP_RV2HV);
        I32 index = 0;
-       SV *keysv = Nullsv;
+       SV *keysv = NULL;
        int subscript_type = FUV_SUBSCRIPT_WITHIN;
 
        if (pad) { /* @lex, %lex */
            sv = PAD_SVl(obase->op_targ);
-           gv = Nullgv;
+           gv = NULL;
        }
        else {
            if (cUNOPx(obase)->op_first->op_type == OP_GV) {
@@ -11338,14 +11643,14 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
     case OP_PADSV:
        if (match && PAD_SVl(obase->op_targ) != uninit_sv)
            break;
-       return varname(Nullgv, '$', obase->op_targ,
-                                   Nullsv, 0, FUV_SUBSCRIPT_NONE);
+       return varname(NULL, '$', obase->op_targ,
+                                   NULL, 0, FUV_SUBSCRIPT_NONE);
 
     case OP_GVSV:
        gv = cGVOPx_gv(obase);
        if (!gv || (match && GvSV(gv) != uninit_sv))
            break;
-       return varname(gv, '$', 0, Nullsv, 0, FUV_SUBSCRIPT_NONE);
+       return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE);
 
     case OP_AELEMFAST:
        if (obase->op_flags & OPf_SPECIAL) { /* lexical array */
@@ -11358,8 +11663,8 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                if (!svp || *svp != uninit_sv)
                    break;
            }
-           return varname(Nullgv, '$', obase->op_targ,
-                   Nullsv, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+           return varname(NULL, '$', obase->op_targ,
+                   NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
        }
        else {
            gv = cGVOPx_gv(obase);
@@ -11375,7 +11680,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                    break;
            }
            return varname(gv, '$', 0,
-                   Nullsv, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
+                   NULL, (I32)obase->op_private, FUV_SUBSCRIPT_ARRAY);
        }
        break;
 
@@ -11392,12 +11697,12 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
            /* $a[uninit_expr] or $h{uninit_expr} */
            return find_uninit_var(cBINOPx(obase)->op_last, uninit_sv, match);
 
-       gv = Nullgv;
+       gv = NULL;
        o = cBINOPx(obase)->op_first;
        kid = cBINOPx(obase)->op_last;
 
        /* get the av or hv, and optionally the gv */
-       sv = Nullsv;
+       sv = NULL;
        if  (o->op_type == OP_PADAV || o->op_type == OP_PADHV) {
            sv = PAD_SV(o->op_targ);
        }
@@ -11432,7 +11737,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                return varname(gv, '%', o->op_targ,
                            cSVOPx_sv(kid), 0, FUV_SUBSCRIPT_HASH);
            else
-               return varname(gv, '@', o->op_targ, Nullsv,
+               return varname(gv, '@', o->op_targ, NULL,
                            SvIV(cSVOPx_sv(kid)), FUV_SUBSCRIPT_ARRAY);
        }
        else  {
@@ -11448,16 +11753,15 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                const I32 index = S_find_array_subscript(aTHX_ (AV*)sv, uninit_sv);
                if (index >= 0)
                    return varname(gv, '@', o->op_targ,
-                                       Nullsv, index, FUV_SUBSCRIPT_ARRAY);
+                                       NULL, index, FUV_SUBSCRIPT_ARRAY);
            }
            if (match)
                break;
            return varname(gv,
                (o->op_type == OP_PADAV || o->op_type == OP_RV2AV)
                ? '@' : '%',
-               o->op_targ, Nullsv, 0, FUV_SUBSCRIPT_WITHIN);
+               o->op_targ, NULL, 0, FUV_SUBSCRIPT_WITHIN);
        }
-
        break;
 
     case OP_AASSIGN:
@@ -11477,7 +11781,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
                if (match && GvSV(gv) != uninit_sv)
                    break;
                return varname(gv, '$', 0,
-                           Nullsv, 0, FUV_SUBSCRIPT_NONE);
+                           NULL, 0, FUV_SUBSCRIPT_NONE);
            }
            /* other possibilities not handled are:
             * open $x; or open my $x;  should return '${*$x}'
@@ -11522,7 +11826,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
     case OP_CHOMP:
        if (SvROK(PL_rs) && uninit_sv == SvRV(PL_rs))
            return sv_2mortal(newSVpvs("${$/}"));
-       /* FALL THROUGH */
+       /*FALLTHROUGH*/
 
     default:
     do_op:
@@ -11536,7 +11840,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
 
        /* if all except one arg are constant, or have no side-effects,
         * or are optimized away, then it's unambiguous */
-       o2 = Nullop;
+       o2 = NULL;
        for (kid=o; kid; kid = kid->op_sibling) {
            if (kid &&
                (    (kid->op_type == OP_CONST && SvOK(cSVOPx_sv(kid)))
@@ -11546,7 +11850,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
            )
                continue;
            if (o2) { /* more than one found */
-               o2 = Nullop;
+               o2 = NULL;
                break;
            }
            o2 = kid;
@@ -11563,7 +11867,7 @@ S_find_uninit_var(pTHX_ OP* obase, SV* uninit_sv, bool match)
        }
        break;
     }
-    return Nullsv;
+    return NULL;
 }
 
 
@@ -11580,7 +11884,7 @@ Perl_report_uninit(pTHX_ SV* uninit_sv)
 {
     dVAR;
     if (PL_op) {
-       SV* varname = Nullsv;
+       SV* varname = NULL;
        if (uninit_sv) {
            varname = find_uninit_var(PL_op, uninit_sv,0);
            if (varname)