diff options
author | Søren Sandmann Pedersen <soren.sandmann@gmail.com> | 2016-04-07 18:24:14 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <soren.sandmann@gmail.com> | 2016-04-07 18:24:14 -0400 |
commit | 7e9675f322ffe287570b2aa1fcfc92fc08f6d9bb (patch) | |
tree | d4483317c2e32f8c7f7782ded6de30f9efe6f92f | |
parent | 1699c4210ee0912866801303544bb20191df1b64 (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.c | 41 | ||||
-rw-r--r-- | pixman/pixman-jit-x86-asm.h | 17 |
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: |