HEK *
Perl_hek_dup(pTHX_ HEK *source, CLONE_PARAMS* param)
{
- HEK *shared = (HEK*)ptr_table_fetch(PL_ptr_table, source);
+ HEK *shared;
PERL_ARGS_ASSERT_HEK_DUP;
PERL_UNUSED_ARG(param);
+ if (!source)
+ return NULL;
+
+ shared = (HEK*)ptr_table_fetch(PL_ptr_table, source);
if (shared) {
/* We already shared this hash key. */
(void)share_hek_hek(shared);
if (flags & HVhek_FREEKEY)
Safefree(key);
key = SvPV_const(keysv, klen);
- flags = 0;
is_utf8 = (SvUTF8(keysv) != 0);
+ if (SvIsCOW_shared_hash(keysv)) {
+ flags = HVhek_KEYCANONICAL | (is_utf8 ? HVhek_UTF8 : 0);
+ } else {
+ flags = 0;
+ }
} else {
is_utf8 = ((flags & HVhek_UTF8) ? TRUE : FALSE);
}
}
}
- if (is_utf8) {
+ if (is_utf8 & !(flags & HVhek_KEYCANONICAL)) {
char * const keysave = (char *)key;
key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8);
if (is_utf8)
if (flags & HVhek_FREEKEY)
Safefree(keysave);
flags |= HVhek_WASUTF8 | HVhek_FREEKEY;
+ /* If the caller calculated a hash, it was on the sequence of
+ octets that are the UTF-8 form. We've now changed the sequence
+ of octets stored to that of the equivalent byte representation,
+ so the hash we need is different. */
+ hash = 0;
}
}
hv_iterinit(ohv);
while ((entry = hv_iternext_flags(ohv, 0))) {
SV *const sv = newSVsv(HeVAL(entry));
+ SV *heksv = newSVhek(HeKEY_hek(entry));
sv_magic(sv, NULL, PERL_MAGIC_hintselem,
- (char *)newSVhek (HeKEY_hek(entry)), HEf_SVKEY);
+ (char *)heksv, HEf_SVKEY);
+ SvREFCNT_dec(heksv);
(void)hv_store_flags(hv, HeKEY(entry), HeKLEN(entry),
sv, HeHASH(entry), HeKFLAGS(entry));
}
iter->xhv_eiter = NULL; /* HvEITER(hv) = NULL */
if((meta = iter->xhv_mro_meta)) {
- if (meta->mro_linear_dfs) {
- SvREFCNT_dec(MUTABLE_SV(meta->mro_linear_dfs));
- meta->mro_linear_dfs = NULL;
+ if (meta->mro_linear_all) {
+ SvREFCNT_dec(MUTABLE_SV(meta->mro_linear_all));
+ meta->mro_linear_all = NULL;
/* This is just acting as a shortcut pointer. */
- meta->mro_linear_c3 = NULL;
- } else if (meta->mro_linear_c3) {
+ meta->mro_linear_current = NULL;
+ } else if (meta->mro_linear_current) {
/* Only the current MRO is stored, so this owns the data.
*/
- SvREFCNT_dec(MUTABLE_SV(meta->mro_linear_c3));
- meta->mro_linear_c3 = NULL;
+ SvREFCNT_dec(meta->mro_linear_current);
+ meta->mro_linear_current = NULL;
}
if(meta->mro_nextmethod) SvREFCNT_dec(meta->mro_nextmethod);
SvREFCNT_dec(meta->isa);
}
}
}
- while (!entry) {
- /* OK. Come to the end of the current list. Grab the next one. */
- iter->xhv_riter++; /* HvRITER(hv)++ */
- if (iter->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) {
- /* There is no next one. End of the hash. */
- iter->xhv_riter = -1; /* HvRITER(hv) = -1 */
- break;
- }
- entry = (HvARRAY(hv))[iter->xhv_riter];
+ /* Skip the entire loop if the hash is empty. */
+ if ((flags & HV_ITERNEXT_WANTPLACEHOLDERS)
+ ? HvTOTALKEYS(hv) : HvUSEDKEYS(hv)) {
+ while (!entry) {
+ /* OK. Come to the end of the current list. Grab the next one. */
- if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
- /* If we have an entry, but it's a placeholder, don't count it.
- Try the next. */
- while (entry && HeVAL(entry) == &PL_sv_placeholder)
- entry = HeNEXT(entry);
+ iter->xhv_riter++; /* HvRITER(hv)++ */
+ if (iter->xhv_riter > (I32)xhv->xhv_max /* HvRITER(hv) > HvMAX(hv) */) {
+ /* There is no next one. End of the hash. */
+ iter->xhv_riter = -1; /* HvRITER(hv) = -1 */
+ break;
+ }
+ entry = (HvARRAY(hv))[iter->xhv_riter];
+
+ if (!(flags & HV_ITERNEXT_WANTPLACEHOLDERS)) {
+ /* If we have an entry, but it's a placeholder, don't count it.
+ Try the next. */
+ while (entry && HeVAL(entry) == &PL_sv_placeholder)
+ entry = HeNEXT(entry);
+ }
+ /* Will loop again if this linked list starts NULL
+ (for HV_ITERNEXT_WANTPLACEHOLDERS)
+ or if we run through it and find only placeholders. */
}
- /* Will loop again if this linked list starts NULL
- (for HV_ITERNEXT_WANTPLACEHOLDERS)
- or if we run through it and find only placeholders. */
}
if (oldentry && HvLAZYDEL(hv)) { /* was deleted earlier? */
shared hek */
assert (he->shared_he_he.hent_hek == hek);
- LOCK_STRTAB_MUTEX;
if (he->shared_he_he.he_valu.hent_refcount - 1) {
--he->shared_he_he.he_valu.hent_refcount;
- UNLOCK_STRTAB_MUTEX;
return;
}
- UNLOCK_STRTAB_MUTEX;
hash = HEK_HASH(hek);
} else if (len < 0) {
} */
xhv = (XPVHV*)SvANY(PL_strtab);
/* assert(xhv_array != 0) */
- LOCK_STRTAB_MUTEX;
first = oentry = &(HvARRAY(PL_strtab))[hash & (I32) HvMAX(PL_strtab)];
if (he) {
const HE *const he_he = &(he->shared_he_he);
}
}
- UNLOCK_STRTAB_MUTEX;
if (!entry && ckWARN_d(WARN_INTERNAL))
Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
"Attempt to free non-existent shared string '%s'%s"
*/
/* assert(xhv_array != 0) */
- LOCK_STRTAB_MUTEX;
entry = (HvARRAY(PL_strtab))[hindex];
for (;entry; entry = HeNEXT(entry)) {
if (HeHASH(entry) != hash) /* strings can't be equal */
}
++entry->he_valu.hent_refcount;
- UNLOCK_STRTAB_MUTEX;
if (flags & HVhek_FREEKEY)
Safefree(str);