aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-07-21 23:55:05 +0200
committerMike Pall <mike>2010-07-21 23:55:05 +0200
commitc5feda2d532495e64a468f0a1cf549e1760dbc6d (patch)
treee352a67c09341c4de1c43d3961749a9533c5c40e /src
parent420124372b7643410a1cdd6f80b9cc8aa6ec1302 (diff)
downloadluajit-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.supp10
-rw-r--r--src/lj_str.c47
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! */
47static 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). */
47void lj_str_resize(lua_State *L, MSize newmask) 68void 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. */