summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <soren.sandmann@gmail.com>2016-04-07 18:24:14 -0400
committerSøren Sandmann Pedersen <soren.sandmann@gmail.com>2016-04-07 18:24:14 -0400
commit7e9675f322ffe287570b2aa1fcfc92fc08f6d9bb (patch)
treed4483317c2e32f8c7f7782ded6de30f9efe6f92f
parent1699c4210ee0912866801303544bb20191df1b64 (diff)
Use hashes of the labels instead of storing a pointerjit
Instead of storing a pointer in the 58 available bits of labels, just compute a hash and use that instead. This does come with a risk collisions, but the code is a nicer and probably slightly faster.
-rw-r--r--pixman/pixman-jit-x86-asm.c41
-rw-r--r--pixman/pixman-jit-x86-asm.h17
2 files changed, 25 insertions, 33 deletions
diff --git a/pixman/pixman-jit-x86-asm.c b/pixman/pixman-jit-x86-asm.c
index 7880c51c..a6040ce7 100644
--- a/pixman/pixman-jit-x86-asm.c
+++ b/pixman/pixman-jit-x86-asm.c
@@ -970,7 +970,7 @@ struct annotation_t
annotation_type_t type;
ssize_t offset;
size_t size;
- char name[32];
+ uint64_t hash;
annotation_t * label;
const uint8_t * fragment;
uint32_t opcode;
@@ -1235,11 +1235,11 @@ emit_imm8 (uint8_t *code, int32_t imm)
return code;
}
-static uint32_t
-hash (const char *str)
+uint64_t
+label_hash (const char *str)
{
const signed char *p = (const signed char *)str;
- uint32_t h = 5381;
+ uint64_t h = 5381;
signed char c;
while ((c = *p++))
@@ -1276,12 +1276,12 @@ gather_labels (array_t *a)
if (label->type == LABEL)
{
annotation_t *existing;
- uint32_t idx = hash (label->name);
+ uint32_t idx = label->hash;
while ((existing = hash_table[idx & mask]))
{
- if (strcmp (existing->name, label->name) == 0)
+ if (existing->hash == label->hash)
{
- printf ("Duplicate label %s\n", label->name);
+ printf ("Duplicate label with hash %lx\n", label->hash);
abort ();
}
idx++;
@@ -1299,14 +1299,14 @@ gather_labels (array_t *a)
if (ref->type == JCC || ref->type == RIP_REF || ref->type == JUMP || ref->type == CALL)
{
- idx = hash (ref->name);
+ idx = ref->hash;
while ((label = hash_table[idx++ & mask]))
{
- if (strcmp (ref->name, label->name) == 0)
+ if (ref->hash == label->hash)
goto found;
}
- printf ("Label \"%s\" does not exist\n", ref->name);
+ printf ("Label with hash %lx does not exist\n", ref->hash);
abort();
found:
@@ -1703,8 +1703,8 @@ oom_fragment:
#define GET_IMM(op) \
(((int64_t)(op)) >> 6)
-#define GET_LABEL(op) \
- ((const char *)(size_t)((op) >> 6))
+#define GET_LABEL_HASH(op) \
+ ((op) >> 6)
#define GET_REGNO(op) \
((op) >> 6)
@@ -1750,19 +1750,6 @@ emit_address_byte (uint8_t *code,
return code;
}
-static void
-copy_string (char *dst, const char *src, int size)
-{
- if (strlen (src) >= size)
- {
- assert (0);
- return;
- }
-
- strncpy (dst, src, size);
- dst[size - 1] = '\0';
-}
-
static uint8_t *
emit_reg_regm (uint8_t *c, op_t reg, op_t regm,
uint8_t *r, uint8_t *x, uint8_t *b,
@@ -1783,7 +1770,7 @@ emit_reg_regm (uint8_t *c, op_t reg, op_t regm,
ann->type = RIP_REF;
ann->offset = (size_t)c;
- copy_string (ann->name, GET_LABEL (regm), sizeof ann->name);
+ ann->hash = GET_LABEL_HASH (regm);
}
else if (is_reg (regm))
{
@@ -2054,7 +2041,7 @@ emit (fragment_t *frag, const variant_t *variant, const op_t ops[4])
ann.offset = (size_t)c;
if (variant->ops[0] == A_LABEL)
- copy_string (ann.name, GET_LABEL (ops[0]), sizeof ann.name);
+ ann.hash = GET_LABEL_HASH (ops[0]);
if (ann.type == ALIGN)
{
ann.align_mask = 1;
diff --git a/pixman/pixman-jit-x86-asm.h b/pixman/pixman-jit-x86-asm.h
index 0aa68727..739a1723 100644
--- a/pixman/pixman-jit-x86-asm.h
+++ b/pixman/pixman-jit-x86-asm.h
@@ -20,6 +20,7 @@ fragment_t *fragment_new (assembler_t *as);
void fragment_assemble (fragment_t *a,
const uint64_t *code);
size_t assembler_get_last_size (assembler_t *as);
+uint64_t label_hash (const char *str);
#define BEGIN_ASM(frag) \
{ \
@@ -211,15 +212,19 @@ typedef enum
ymm15 = (15 << 6) | OP_YMM,
} reg_t;
-/* Assume here that the string pointer will only make use of at most
- * 58 of the 64 bits. This is safe since a virtual pointer on x86-64
- * is currently at most 48 bits.
+/* We are assuming / hoping here that there will be no hash collisions
+ * of the labels within one linked piece of assembly. With 58 bits of hash,
+ * this assumption is probably fairly safe.
+ *
+ * If we do get a collision, the symptom will be the jit compiler
+ * reporting a spurious "duplicate label" error. If this happens, the
+ * user can simply tweak their labels until they no longer collide.
*/
-#define LABEL(l) \
- ((((uint64_t)(size_t)(l)) << 6) | OP_LABEL_REF)
+#define LABEL(label) \
+ ((label_hash (label) & ~0x3f) | OP_LABEL_REF)
#define RIP_REL(label) \
- ((((uint64_t)(size_t)(label)) << 6) | OP_RIP_REL)
+ ((label_hash (label) & ~0x3f) | OP_RIP_REL)
/* base_reg + (index_reg << shift) + disp */
/* Layout: