+ *spot = name ? share_hek(name, len, hash) : NULL;
+ iter->xhv_name_count = 0;
+}
+
+/*
+=for apidoc hv_ename_add
+
+Adds a name to a stash's internal list of effective names. See
+C<hv_ename_delete>.
+
+This is called when a stash is assigned to a new location in the symbol
+table.
+
+=cut
+*/
+
+void
+Perl_hv_ename_add(pTHX_ HV *hv, const char *name, U32 len)
+{
+ dVAR;
+ struct xpvhv_aux *aux = SvOOK(hv) ? HvAUX(hv) : hv_auxinit(hv);
+ U32 hash;
+
+ PERL_ARGS_ASSERT_HV_ENAME_ADD;
+
+ if (len > I32_MAX)
+ Perl_croak(aTHX_ "panic: hv name too long (%"UVuf")", (UV) len);
+
+ PERL_HASH(hash, name, len);
+
+ if (aux->xhv_name_count) {
+ HEK ** const xhv_name = (HEK **)aux->xhv_name;
+ I32 count = aux->xhv_name_count;
+ HEK **hekp = xhv_name + (count < 0 ? -count : count);
+ while (hekp-- > xhv_name)
+ if (
+ HEK_LEN(*hekp) == (I32)len && memEQ(HEK_KEY(*hekp), name, len)
+ ) {
+ if (hekp == xhv_name && count < 0)
+ aux->xhv_name_count = -count;
+ return;
+ }
+ if (count < 0) aux->xhv_name_count--, count = -count;
+ else aux->xhv_name_count++;
+ Renewc(aux->xhv_name, count + 1, HEK *, HEK);
+ ((HEK **)aux->xhv_name)[count] = share_hek(name, len, hash);
+ }
+ else {
+ HEK *existing_name = aux->xhv_name;
+ if (
+ existing_name && HEK_LEN(existing_name) == (I32)len
+ && memEQ(HEK_KEY(existing_name), name, len)
+ ) return;
+ Newxc(aux->xhv_name, 2, HEK *, HEK);
+ aux->xhv_name_count = existing_name ? 2 : -2;
+ *(HEK **)aux->xhv_name = existing_name;
+ ((HEK **)aux->xhv_name)[1] = share_hek(name, len, hash);
+ }
+}
+
+/*
+=for apidoc hv_ename_delete
+
+Removes a name from a stash's internal list of effective names. If this is
+the name returned by C<HvENAME>, then another name in the list will take
+its place (C<HvENAME> will use it).
+
+This is called when a stash is deleted from the symbol table.
+
+=cut
+*/
+
+void
+Perl_hv_ename_delete(pTHX_ HV *hv, const char *name, U32 len)
+{
+ dVAR;
+ struct xpvhv_aux *aux;
+
+ PERL_ARGS_ASSERT_HV_ENAME_DELETE;
+
+ if (len > I32_MAX)
+ Perl_croak(aTHX_ "panic: hv name too long (%"UVuf")", (UV) len);
+
+ if (!SvOOK(hv)) return;
+
+ aux = HvAUX(hv);
+ if (!aux->xhv_name) return;
+
+ if (aux->xhv_name_count) {
+ HEK ** const namep = (HEK **)aux->xhv_name;
+ I32 const count = aux->xhv_name_count;
+ HEK **victim = namep + (count < 0 ? -count : count);
+ while (victim-- > namep + 1)
+ if (
+ HEK_LEN(*victim) == (I32)len
+ && memEQ(HEK_KEY(*victim), name, len)
+ ) {
+ unshare_hek_or_pvn(*victim, 0, 0, 0);
+ if (count < 0) ++aux->xhv_name_count;
+ else --aux->xhv_name_count;
+ if (
+ (aux->xhv_name_count == 1 || aux->xhv_name_count == -1)
+ && !*namep
+ ) { /* if there are none left */
+ Safefree(namep);
+ aux->xhv_name = NULL;
+ aux->xhv_name_count = 0;
+ }
+ else {
+ /* Move the last one back to fill the empty slot. It
+ does not matter what order they are in. */
+ *victim = *(namep + (count < 0 ? -count : count) - 1);
+ }
+ return;
+ }
+ if (
+ count > 0 && HEK_LEN(*namep) == (I32)len
+ && memEQ(HEK_KEY(*namep),name,len)
+ ) {
+ aux->xhv_name_count = -count;
+ }
+ }
+ else if(
+ HEK_LEN(aux->xhv_name) == (I32)len
+ && memEQ(HEK_KEY(aux->xhv_name), name, len)
+ ) {
+ const HEK * const namehek = aux->xhv_name;
+ Newxc(aux->xhv_name, 1, HEK *, HEK);
+ *(const HEK **)aux->xhv_name = namehek;
+ aux->xhv_name_count = -1;
+ }