summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2005-06-12 20:00:18 +0000
committerNicholas Clark <nick@ccl4.org>2005-06-12 20:00:18 +0000
commitcbae396092f5aa3ab7374d8414eb06704dfb41d6 (patch)
treeb6df14e133cfcdd478b8fb8f9ea0a3f4ac36fa48
parent3341d187a8c660dcdef29c6ff668870f1d944ae1 (diff)
downloadperl-cbae396092f5aa3ab7374d8414eb06704dfb41d6.tar.gz
In the shared string table, store the HE and HEK next to each other
in one malloc()ed block. p4raw-id: //depot/perl@24808
-rw-r--r--hv.c40
-rw-r--r--hv.h4
2 files changed, 40 insertions, 4 deletions
diff --git a/hv.c b/hv.c
index 556996e8c0..ae67070954 100644
--- a/hv.c
+++ b/hv.c
@@ -2159,8 +2159,17 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
bool is_utf8 = FALSE;
int k_flags = 0;
const char *save = str;
+ struct shared_he *he = 0;
if (hek) {
+ /* Find the shared he which is just before us in memory. */
+ he = (struct shared_he *)(((char *)hek)
+ - STRUCT_OFFSET(struct shared_he,
+ shared_he_hek));
+
+ /* Assert that the caller passed us a genuine (or at least consistent)
+ shared hek */
+ assert (he->shared_he_he.hent_hek == hek);
hash = HEK_HASH(hek);
} else if (len < 0) {
STRLEN tmplen = -len;
@@ -2213,8 +2222,7 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
/* There are now no entries in our slot. */
xhv->xhv_fill--; /* HvFILL(hv)-- */
}
- Safefree(HeKEY_hek(entry));
- del_HE(entry);
+ Safefree(entry);
xhv->xhv_keys--; /* HvKEYS(hv)-- */
}
}
@@ -2299,11 +2307,35 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags)
If this is NULL, then we're the first entry for this slot, which
means we need to increate fill. */
const HE *old_first = *oentry;
- entry = new_HE();
- HeKEY_hek(entry) = save_hek_flags(str, len, hash, flags_masked);
+ struct shared_he *new_entry;
+ HEK *hek;
+ char *k;
+
+ /* We don't actually store a HE from the arena and a regular HEK.
+ Instead we allocate one chunk of memory big enough for both,
+ and put the HEK straight after the HE. This way we can find the
+ HEK directly from the HE.
+ */
+
+ New(0, k, STRUCT_OFFSET(struct shared_he,
+ shared_he_hek.hek_key[0]) + len + 2, char);
+ new_entry = (struct shared_he *)k;
+ entry = &(new_entry->shared_he_he);
+ hek = &(new_entry->shared_he_hek);
+
+ Copy(str, HEK_KEY(hek), len, char);
+ HEK_KEY(hek)[len] = 0;
+ HEK_LEN(hek) = len;
+ HEK_HASH(hek) = hash;
+ HEK_FLAGS(hek) = (unsigned char)flags_masked;
+
+ /* Still "point" to the HEK, so that other code need not know what
+ we're up to. */
+ HeKEY_hek(entry) = hek;
HeVAL(entry) = Nullsv;
HeNEXT(entry) = *oentry;
*oentry = entry;
+
xhv->xhv_keys++; /* HvKEYS(hv)++ */
if (!old_first) { /* initial entry? */
xhv->xhv_fill++; /* HvFILL(hv)++ */
diff --git a/hv.h b/hv.h
index 3115dba91c..ac4bdd33c8 100644
--- a/hv.h
+++ b/hv.h
@@ -29,6 +29,10 @@ struct hek {
is UTF-8 */
};
+struct shared_he {
+ struct he shared_he_he;
+ struct hek shared_he_hek;
+};
/* Subject to change.
Don't access this directly.