Perl_gv_name_set(pTHX_ GV *gv, const char *name, U32 len, U32 flags)
{
dVAR;
+ U32 hash;
PERL_UNUSED_ARG(flags);
- GvXPVGV(gv)->xgv_name = name ? savepvn(name, len) : NULL;
- GvXPVGV(gv)->xgv_namelen = len;
+ if (len > I32_MAX)
+ Perl_croak(aTHX_ "panic: gv name too long (%"UVuf")", (UV) len);
+
+ PERL_HASH(hash, name, len);
+ GvXPVGV(gv)->xgv_namehek = name ? share_hek(name, len, hash) : 0;
}
/*
assert(SvTYPE(_gv) == SVt_PVGV || SvTYPE(_gv) >= SVt_PVLV); \
&(GvXPVGV(_gv)->xnv_u.xgv_stash); \
}))
-# define GvNAME_get(gv) \
- ({ GV * const zzzz = (GV *) (gv); \
+# define GvNAME_HEK(gv) \
+ (*({ GV * const zzzz = (GV *) (gv); \
assert(isGV_with_GP(zzzz)); \
assert(SvTYPE(zzzz) == SVt_PVGV || SvTYPE(zzzz) >= SVt_PVLV); \
- 0 + (GvXPVGV(zzzz)->xgv_name); \
- })
-# define GvNAMELEN_get(gv) \
- ({ GV * const glank = (GV *) (gv); \
- assert(isGV_with_GP(glank)); \
- assert(SvTYPE(glank) == SVt_PVGV || SvTYPE(glank) >= SVt_PVLV); \
- 0 + (GvXPVGV(glank)->xgv_namelen); \
- })
+ &(GvXPVGV(zzzz)->xgv_namehek); \
+ }))
#else
# define GvGP(gv) ((gv)->sv_u.svu_gp)
# define GvFLAGS(gv) (GvXPVGV(gv)->xpv_cur)
# define GvSTASH(gv) (GvXPVGV(gv)->xnv_u.xgv_stash)
-# define GvNAME_get(gv) (0 + GvXPVGV(gv)->xgv_name)
-# define GvNAMELEN_get(gv) (0 + GvXPVGV(gv)->xgv_namelen)
+# define GvNAME_HEK(gv) (GvXPVGV(gv)->xgv_namehek)
#endif
+#define GvNAME_get(gv) (GvNAME_HEK(gv) ? HEK_KEY(GvNAME_HEK(gv)) : 0)
+#define GvNAMELEN_get(gv) (GvNAME_HEK(gv) ? HEK_LEN(GvNAME_HEK(gv)) : 0)
+
#define GvNAME(gv) GvNAME_get(gv)
#define GvNAMELEN(gv) GvNAMELEN_get(gv)
GvSTASH(dstr) = GvSTASH(sstr);
if (GvSTASH(dstr))
Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
- gv_name_set(dstr, name, len, 0);
+ gv_name_set((GV *)dstr, name, len, 0);
SvFAKE_on(dstr); /* can coerce to non-glob */
}
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))
GvSTASH(sv) = NULL;
}
GvMULTI_off(sv);
- Safefree(GvNAME(sv));
+ if (GvNAME_HEK(sv)) {
+ unshare_hek(GvNAME_HEK(sv));
+ }
SvSCREAM_off(sv);
/* need to keep SvANY(sv) in the right arena */
LvTARG(dstr) = sv_dup_inc(LvTARG(dstr), param);
break;
case SVt_PVGV:
- GvXPVGV(dstr)->xgv_name = SAVEPVN(GvNAME(dstr), GvNAMELEN(dstr));
+ 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. */
HV* xmg_stash; /* class package */
/* a full glob fits into this */
- char* xgv_name;
- STRLEN xgv_namelen;
+ HEK * xgv_namehek;
STRLEN xlv_targoff;
STRLEN xlv_targlen;
} xmg_u;
HV* xmg_stash; /* class package */
- char* xgv_name;
- STRLEN xgv_namelen;
+ HEK * xgv_namehek;
};
struct xpvbm {