+=for apidoc newPADNAMELIST
+
+Creates a new pad name list. C<max> is the highest index for which space
+is allocated.
+
+=cut
+*/
+
+PADNAMELIST *
+Perl_newPADNAMELIST(pTHX_ size_t max)
+{
+ PADNAMELIST *pnl;
+ Newx(pnl, 1, PADNAMELIST);
+ Newxz(PadnamelistARRAY(pnl), max+1, PADNAME *);
+ PadnamelistMAX(pnl) = -1;
+ PadnamelistREFCNT(pnl) = 1;
+ PadnamelistMAXNAMED(pnl) = 0;
+ pnl->xpadnl_max = max;
+ return pnl;
+}
+
+/*
+=for apidoc padnamelist_store
+
+Stores the pad name (which may be null) at the given index, freeing any
+existing pad name in that slot.
+
+=cut
+*/
+
+PADNAME **
+Perl_padnamelist_store(pTHX_ PADNAMELIST *pnl, SSize_t key, PADNAME *val)
+{
+ PADNAME **ary;
+
+ PERL_ARGS_ASSERT_PADNAMELIST_STORE;
+
+ assert(key >= 0);
+
+ if (key > pnl->xpadnl_max)
+ av_extend_guts(NULL,key,&pnl->xpadnl_max,
+ (SV ***)&PadnamelistARRAY(pnl),
+ (SV ***)&PadnamelistARRAY(pnl));
+ if (PadnamelistMAX(pnl) < key) {
+ Zero(PadnamelistARRAY(pnl)+PadnamelistMAX(pnl)+1,
+ key-PadnamelistMAX(pnl), PADNAME *);
+ PadnamelistMAX(pnl) = key;
+ }
+ ary = PadnamelistARRAY(pnl);
+ if (ary[key])
+ PadnameREFCNT_dec(ary[key]);
+ ary[key] = val;
+ return &ary[key];
+}
+
+/*
+=for apidoc padnamelist_fetch
+
+Fetches the pad name from the given index.
+
+=cut
+*/
+
+PADNAME *
+Perl_padnamelist_fetch(pTHX_ PADNAMELIST *pnl, SSize_t key)
+{
+ PERL_ARGS_ASSERT_PADNAMELIST_FETCH;
+ ASSUME(key >= 0);
+
+ return key > PadnamelistMAX(pnl) ? NULL : PadnamelistARRAY(pnl)[key];
+}
+
+void
+Perl_padnamelist_free(pTHX_ PADNAMELIST *pnl)
+{
+ PERL_ARGS_ASSERT_PADNAMELIST_FREE;
+ if (!--PadnamelistREFCNT(pnl)) {
+ while(PadnamelistMAX(pnl) >= 0)
+ {
+ PADNAME * const pn =
+ PadnamelistARRAY(pnl)[PadnamelistMAX(pnl)--];
+ if (pn)
+ PadnameREFCNT_dec(pn);
+ }
+ Safefree(PadnamelistARRAY(pnl));
+ Safefree(pnl);
+ }
+}
+
+#if defined(USE_ITHREADS)
+
+/*
+=for apidoc padnamelist_dup
+
+Duplicates a pad name list.
+
+=cut
+*/
+
+PADNAMELIST *
+Perl_padnamelist_dup(pTHX_ PADNAMELIST *srcpad, CLONE_PARAMS *param)
+{
+ PADNAMELIST *dstpad;
+ SSize_t max = PadnamelistMAX(srcpad);
+
+ PERL_ARGS_ASSERT_PADNAMELIST_DUP;
+
+ /* look for it in the table first */
+ dstpad = (PADNAMELIST *)ptr_table_fetch(PL_ptr_table, srcpad);
+ if (dstpad)
+ return dstpad;
+
+ dstpad = newPADNAMELIST(max);
+ PadnamelistREFCNT(dstpad) = 0; /* The caller will increment it. */
+ PadnamelistMAXNAMED(dstpad) = PadnamelistMAXNAMED(srcpad);
+ PadnamelistMAX(dstpad) = max;
+
+ ptr_table_store(PL_ptr_table, srcpad, dstpad);
+ for (; max >= 0; max--)
+ if (PadnamelistARRAY(srcpad)[max]) {
+ PadnamelistARRAY(dstpad)[max] =
+ padname_dup(PadnamelistARRAY(srcpad)[max], param);
+ PadnameREFCNT(PadnamelistARRAY(dstpad)[max])++;
+ }
+
+ return dstpad;
+}
+
+#endif /* USE_ITHREADS */
+
+/*
+=for apidoc newPADNAMEpvn
+
+Constructs and returns a new pad name. I<s> must be a UTF8 string. Do not
+use this for pad names that point to outer lexicals. See
+L</newPADNAMEouter>.
+
+=cut
+*/
+
+PADNAME *
+Perl_newPADNAMEpvn(pTHX_ const char *s, STRLEN len)
+{
+ struct padname_with_str *alloc;
+ char *alloc2; /* for Newxz */
+ PADNAME *pn;
+ PERL_ARGS_ASSERT_NEWPADNAMEPVN;
+ Newxz(alloc2,
+ STRUCT_OFFSET(struct padname_with_str, xpadn_str[0]) + len + 1,
+ char);
+ alloc = (struct padname_with_str *)alloc2;
+ pn = (PADNAME *)alloc;
+ PadnameREFCNT(pn) = 1;
+ PadnamePV(pn) = alloc->xpadn_str;
+ Copy(s, PadnamePV(pn), len, char);
+ *(PadnamePV(pn) + len) = '\0';
+ PadnameLEN(pn) = len;
+ return pn;
+}
+
+/*
+=for apidoc newPADNAMEouter
+
+Constructs and returns a new pad name. Only use this function for names
+that refer to outer lexicals. (See also L</newPADNAMEpvn>.) I<outer> is
+the outer pad name that this one mirrors. The returned pad name has the
+PADNAMEt_OUTER flag already set.
+
+=cut
+*/
+
+PADNAME *
+Perl_newPADNAMEouter(pTHX_ PADNAME *outer)
+{
+ PADNAME *pn;
+ PERL_ARGS_ASSERT_NEWPADNAMEOUTER;
+ Newxz(pn, 1, PADNAME);
+ PadnameREFCNT(pn) = 1;
+ PadnamePV(pn) = PadnamePV(outer);
+ /* Not PadnameREFCNT(outer), because ‘outer’ may itself close over
+ another entry. The original pad name owns the buffer. */
+ PadnameREFCNT(PADNAME_FROM_PV(PadnamePV(outer)))++;
+ PadnameFLAGS(pn) = PADNAMEt_OUTER;
+ PadnameLEN(pn) = PadnameLEN(outer);
+ return pn;
+}
+
+void
+Perl_padname_free(pTHX_ PADNAME *pn)
+{
+ PERL_ARGS_ASSERT_PADNAME_FREE;
+ if (!--PadnameREFCNT(pn)) {
+ if (UNLIKELY(pn == &PL_padname_undef || pn == &PL_padname_const)) {
+ PadnameREFCNT(pn) = SvREFCNT_IMMORTAL;
+ return;
+ }
+ SvREFCNT_dec(PadnameTYPE(pn)); /* Takes care of protocv, too. */
+ SvREFCNT_dec(PadnameOURSTASH(pn));
+ if (PadnameOUTER(pn))
+ PadnameREFCNT_dec(PADNAME_FROM_PV(PadnamePV(pn)));
+ Safefree(pn);
+ }
+}
+
+#if defined(USE_ITHREADS)
+
+/*
+=for apidoc padname_dup
+
+Duplicates a pad name.
+
+=cut
+*/
+
+PADNAME *
+Perl_padname_dup(pTHX_ PADNAME *src, CLONE_PARAMS *param)
+{
+ PADNAME *dst;
+
+ PERL_ARGS_ASSERT_PADNAME_DUP;
+
+ /* look for it in the table first */
+ dst = (PADNAME *)ptr_table_fetch(PL_ptr_table, src);
+ if (dst)
+ return dst;
+
+ if (!PadnamePV(src)) {
+ dst = &PL_padname_undef;
+ ptr_table_store(PL_ptr_table, src, dst);
+ return dst;
+ }
+
+ dst = PadnameOUTER(src)
+ ? newPADNAMEouter(padname_dup(PADNAME_FROM_PV(PadnamePV(src)), param))
+ : newPADNAMEpvn(PadnamePV(src), PadnameLEN(src));
+ ptr_table_store(PL_ptr_table, src, dst);
+ PadnameLEN(dst) = PadnameLEN(src);
+ PadnameFLAGS(dst) = PadnameFLAGS(src);
+ PadnameREFCNT(dst) = 0; /* The caller will increment it. */
+ PadnameTYPE (dst) = (HV *)sv_dup_inc((SV *)PadnameTYPE(src), param);
+ PadnameOURSTASH(dst) = (HV *)sv_dup_inc((SV *)PadnameOURSTASH(src),
+ param);
+ dst->xpadn_low = src->xpadn_low;
+ dst->xpadn_high = src->xpadn_high;
+ dst->xpadn_gen = src->xpadn_gen;
+ return dst;
+}
+
+#endif /* USE_ITHREADS */
+
+/*