#define HV_MAX_LENGTH_BEFORE_SPLIT 14
+static const char *const S_strtab_error
+ = "Cannot modify shared string table in hv_%s";
+
STATIC void
S_more_he(pTHX)
{
HEK *
Perl_hek_dup(pTHX_ HEK *source, CLONE_PARAMS* param)
{
- HE *shared = (HE*)ptr_table_fetch(PL_shared_hek_table, source);
+ HEK *shared = (HEK*)ptr_table_fetch(PL_ptr_table, source);
(void)param;
if (shared) {
/* We already shared this hash key. */
- ++HeVAL(shared);
+ (void)share_hek_hek(shared);
}
else {
- shared = share_hek_flags(HEK_KEY(source), HEK_LEN(source),
- HEK_HASH(source), HEK_FLAGS(source));
- ptr_table_store(PL_shared_hek_table, source, shared);
+ shared
+ = share_hek_flags(HEK_KEY(source), HEK_LEN(source),
+ HEK_HASH(source), HEK_FLAGS(source));
+ ptr_table_store(PL_ptr_table, source, shared);
}
- return HeKEY_hek(shared);
+ return shared;
}
HE *
else if (shared) {
/* This is hek_dup inlined, which seems to be important for speed
reasons. */
- HEK *source = HeKEY_hek(e);
- HE *shared = (HE*)ptr_table_fetch(PL_shared_hek_table, source);
+ HEK * const source = HeKEY_hek(e);
+ HEK *shared = (HEK*)ptr_table_fetch(PL_ptr_table, source);
if (shared) {
/* We already shared this hash key. */
- ++HeVAL(shared);
+ (void)share_hek_hek(shared);
}
else {
- shared = share_hek_flags(HEK_KEY(source), HEK_LEN(source),
- HEK_HASH(source), HEK_FLAGS(source));
- ptr_table_store(PL_shared_hek_table, source, shared);
+ shared
+ = share_hek_flags(HEK_KEY(source), HEK_LEN(source),
+ HEK_HASH(source), HEK_FLAGS(source));
+ ptr_table_store(PL_ptr_table, source, shared);
}
- HeKEY_hek(ret) = HeKEY_hek(shared);
+ HeKEY_hek(ret) = shared;
}
else
HeKEY_hek(ret) = save_hek_flags(HeKEY(e), HeKLEN(e), HeHASH(e),
S_hv_notallowed(pTHX_ int flags, const char *key, I32 klen,
const char *msg)
{
- SV *sv = sv_newmortal();
+ SV * const sv = sv_newmortal();
if (!(flags & HVhek_FREEKEY)) {
sv_setpvn(sv, key, klen);
}
/* Need to swap the key we have for a key with the flags we
need. As keys are shared we can't just write to the
flag, so we share the new one, unshare the old one. */
- HEK *new_hek = HeKEY_hek(share_hek_flags(key, klen, hash,
- masked_flags));
+ HEK *new_hek = share_hek_flags(key, klen, hash,
+ masked_flags);
unshare_hek (HeKEY_hek(entry));
HeKEY_hek(entry) = new_hek;
}
+ else if (hv == PL_strtab) {
+ /* PL_strtab is usually the only hash without HvSHAREKEYS,
+ so putting this test here is cheap */
+ if (flags & HVhek_FREEKEY)
+ Safefree(key);
+ Perl_croak(aTHX_ S_strtab_error,
+ action & HV_FETCH_LVALUE ? "fetch" : "store");
+ }
else
HeKFLAGS(entry) = masked_flags;
if (masked_flags & HVhek_ENABLEHVKFLAGS)
/* share_hek_flags will do the free for us. This might be considered
bad API design. */
if (HvSHAREKEYS(hv))
- HeKEY_hek(entry) = HeKEY_hek(share_hek_flags(key, klen, hash, flags));
+ HeKEY_hek(entry) = share_hek_flags(key, klen, hash, flags);
+ else if (hv == PL_strtab) {
+ /* PL_strtab is usually the only hash without HvSHAREKEYS, so putting
+ this test here is cheap */
+ if (flags & HVhek_FREEKEY)
+ Safefree(key);
+ Perl_croak(aTHX_ S_strtab_error,
+ action & HV_FETCH_LVALUE ? "fetch" : "store");
+ }
else /* gotta do the real thing */
HeKEY_hek(entry) = save_hek_flags(key, klen, hash, flags);
HeVAL(entry) = val;
if ((HeKFLAGS(entry) ^ masked_flags) & HVhek_UTF8)
continue;
+ if (hv == PL_strtab) {
+ if (k_flags & HVhek_FREEKEY)
+ Safefree(key);
+ Perl_croak(aTHX_ S_strtab_error, "delete");
+ }
+
/* if placeholder is here, it's already been deleted.... */
if (HeVAL(entry) == &PL_sv_placeholder)
{
ent = new_HE();
HeVAL(ent) = newSVsv(HeVAL(oent));
HeKEY_hek(ent)
- = shared ? HeKEY_hek(share_hek_flags(key, len, hash, flags))
+ = shared ? share_hek_flags(key, len, hash, flags)
: save_hek_flags(key, len, hash, flags);
if (prev)
HeNEXT(prev) = ent;
/* assert(xhv_array != 0) */
LOCK_STRTAB_MUTEX;
first = oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)];
- if (hek) {
+ if (he) {
+ const HE *const he_he = &(he->shared_he_he);
for (entry = *oentry; entry; oentry = &HeNEXT(entry), entry = *oentry) {
- if (HeKEY_hek(entry) != hek)
+ if (entry != he_he)
continue;
found = 1;
break;
flags |= HVhek_WASUTF8 | HVhek_FREEKEY;
}
- return HeKEY_hek(share_hek_flags (str, len, hash, flags));
+ return share_hek_flags (str, len, hash, flags);
}
-STATIC HE *
+STATIC HEK *
S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags)
{
- register XPVHV* xhv;
register HE *entry;
register HE **oentry;
I32 found = 0;
Can't rehash the shared string table, so not sure if it's worth
counting the number of entries in the linked list
*/
- xhv = (XPVHV*)SvANY(PL_strtab);
+ register XPVHV * const xhv = (XPVHV*)SvANY(PL_strtab);
/* assert(xhv_array != 0) */
LOCK_STRTAB_MUTEX;
oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)];
if (flags & HVhek_FREEKEY)
Safefree(str);
- return entry;
+ return HeKEY_hek(entry);
}
I32 *