diff options
| author | Mike Pall <mike> | 2010-07-21 23:55:05 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-07-21 23:55:05 +0200 |
| commit | c5feda2d532495e64a468f0a1cf549e1760dbc6d (patch) | |
| tree | e352a67c09341c4de1c43d3961749a9533c5c40e /src | |
| parent | 420124372b7643410a1cdd6f80b9cc8aa6ec1302 (diff) | |
| download | luajit-c5feda2d532495e64a468f0a1cf549e1760dbc6d.tar.gz luajit-c5feda2d532495e64a468f0a1cf549e1760dbc6d.tar.bz2 luajit-c5feda2d532495e64a468f0a1cf549e1760dbc6d.zip | |
Speed up string compares in string interning.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj.supp | 10 | ||||
| -rw-r--r-- | src/lj_str.c | 47 |
2 files changed, 51 insertions, 6 deletions
diff --git a/src/lj.supp b/src/lj.supp index 9a1379d7..f1126ad7 100644 --- a/src/lj.supp +++ b/src/lj.supp | |||
| @@ -4,3 +4,13 @@ | |||
| 4 | Memcheck:Addr4 | 4 | Memcheck:Addr4 |
| 5 | fun:lj_str_cmp | 5 | fun:lj_str_cmp |
| 6 | } | 6 | } |
| 7 | { | ||
| 8 | Optimized string compare | ||
| 9 | Memcheck:Addr4 | ||
| 10 | fun:lj_str_new | ||
| 11 | } | ||
| 12 | { | ||
| 13 | Optimized string compare | ||
| 14 | Memcheck:Cond | ||
| 15 | fun:lj_str_new | ||
| 16 | } | ||
diff --git a/src/lj_str.c b/src/lj_str.c index 5ba55bdd..1f31c615 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
| @@ -43,6 +43,27 @@ int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b) | |||
| 43 | return (int32_t)(a->len - b->len); | 43 | return (int32_t)(a->len - b->len); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | /* Fast string data comparison. Caveat: unaligned access to 1st string! */ | ||
| 47 | static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len) | ||
| 48 | { | ||
| 49 | MSize i = 0; | ||
| 50 | lua_assert(len > 0); | ||
| 51 | lua_assert((((uintptr_t)a + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4); | ||
| 52 | do { /* Note: innocuous access up to end of string + 3. */ | ||
| 53 | uint32_t v = *(const uint32_t *)(a+i) ^ *(const uint32_t *)(b+i); | ||
| 54 | if (v) { | ||
| 55 | i -= len; | ||
| 56 | #if LJ_ARCH_ENDIAN == LUAJIT_LE | ||
| 57 | return (int32_t)i >= -3 ? (v << (32+(i<<3))) : 1; | ||
| 58 | #else | ||
| 59 | return (int32_t)i >= -3 ? (v >> (32+(i<<3))) : 1; | ||
| 60 | #endif | ||
| 61 | } | ||
| 62 | i += 4; | ||
| 63 | } while (i < len); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 46 | /* Resize the string hash table (grow and shrink). */ | 67 | /* Resize the string hash table (grow and shrink). */ |
| 47 | void lj_str_resize(lua_State *L, MSize newmask) | 68 | void lj_str_resize(lua_State *L, MSize newmask) |
| 48 | { | 69 | { |
| @@ -99,12 +120,26 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx) | |||
| 99 | b ^= a; b -= lj_rol(a, 25); | 120 | b ^= a; b -= lj_rol(a, 25); |
| 100 | h ^= b; h -= lj_rol(b, 16); | 121 | h ^= b; h -= lj_rol(b, 16); |
| 101 | /* Check if the string has already been interned. */ | 122 | /* Check if the string has already been interned. */ |
| 102 | for (o = gcref(g->strhash[h & g->strmask]); o != NULL; o = gcnext(o)) { | 123 | o = gcref(g->strhash[h & g->strmask]); |
| 103 | GCstr *tso = gco2str(o); | 124 | if (LJ_LIKELY((((uintptr_t)str + len) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4)) { |
| 104 | if (tso->len == len && (memcmp(str, strdata(tso), len) == 0)) { | 125 | while (o != NULL) { |
| 105 | /* Resurrect if dead. Can only happen with fixstring() (keywords). */ | 126 | GCstr *sx = gco2str(o); |
| 106 | if (isdead(g, o)) flipwhite(o); | 127 | if (sx->len == len && str_fastcmp(str, strdata(sx), len) == 0) { |
| 107 | return tso; /* Return existing string. */ | 128 | /* Resurrect if dead. Can only happen with fixstring() (keywords). */ |
| 129 | if (isdead(g, o)) flipwhite(o); | ||
| 130 | return sx; /* Return existing string. */ | ||
| 131 | } | ||
| 132 | o = gcnext(o); | ||
| 133 | } | ||
| 134 | } else { /* Slow path: end of string is too close to a page boundary. */ | ||
| 135 | while (o != NULL) { | ||
| 136 | GCstr *sx = gco2str(o); | ||
| 137 | if (sx->len == len && memcmp(str, strdata(sx), len) == 0) { | ||
| 138 | /* Resurrect if dead. Can only happen with fixstring() (keywords). */ | ||
| 139 | if (isdead(g, o)) flipwhite(o); | ||
| 140 | return sx; /* Return existing string. */ | ||
| 141 | } | ||
| 142 | o = gcnext(o); | ||
| 108 | } | 143 | } |
| 109 | } | 144 | } |
| 110 | /* Nope, create a new string. */ | 145 | /* Nope, create a new string. */ |
