aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib_buffer.c60
-rw-r--r--src/lj_buf.h16
-rw-r--r--src/lj_errmsg.h2
-rw-r--r--src/lj_gc.c5
-rw-r--r--src/lj_obj.h2
-rw-r--r--src/lj_serialize.c77
-rw-r--r--src/lj_serialize.h1
-rw-r--r--src/lj_tab.c23
-rw-r--r--src/lj_tab.h23
9 files changed, 151 insertions, 58 deletions
diff --git a/src/lib_buffer.c b/src/lib_buffer.c
index 78c4eeb9..f13320c4 100644
--- a/src/lib_buffer.c
+++ b/src/lib_buffer.c
@@ -29,9 +29,7 @@
29#include "lj_serialize.h" 29#include "lj_serialize.h"
30#include "lj_lib.h" 30#include "lj_lib.h"
31 31
32/* ------------------------------------------------------------------------ */ 32/* -- Helper functions ---------------------------------------------------- */
33
34#define LJLIB_MODULE_buffer_method
35 33
36/* Check that the first argument is a string buffer. */ 34/* Check that the first argument is a string buffer. */
37static SBufExt *buffer_tobuf(lua_State *L) 35static SBufExt *buffer_tobuf(lua_State *L)
@@ -49,11 +47,16 @@ static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L)
49 return sbx; 47 return sbx;
50} 48}
51 49
50#define buffer_toudata(sbx) ((GCudata *)(sbx)-1)
51
52/* -- Buffer methods ------------------------------------------------------ */
53
54#define LJLIB_MODULE_buffer_method
55
52LJLIB_CF(buffer_method_free) 56LJLIB_CF(buffer_method_free)
53{ 57{
54 SBufExt *sbx = buffer_tobuf(L); 58 SBufExt *sbx = buffer_tobuf(L);
55 lj_bufx_free(G(L), sbx); 59 lj_bufx_free(L, sbx);
56 lj_bufx_init(L, sbx);
57 L->top = L->base+1; /* Chain buffer object. */ 60 L->top = L->base+1; /* Chain buffer object. */
58 return 1; 61 return 1;
59} 62}
@@ -83,6 +86,7 @@ LJLIB_CF(buffer_method_skip)
83LJLIB_CF(buffer_method_set) 86LJLIB_CF(buffer_method_set)
84{ 87{
85 SBufExt *sbx = buffer_tobuf(L); 88 SBufExt *sbx = buffer_tobuf(L);
89 GCobj *ref;
86 const char *p; 90 const char *p;
87 MSize len; 91 MSize len;
88#if LJ_HASFFI 92#if LJ_HASFFI
@@ -98,9 +102,11 @@ LJLIB_CF(buffer_method_set)
98 p = strdata(str); 102 p = strdata(str);
99 len = str->len; 103 len = str->len;
100 } 104 }
101 lj_bufx_free(G(L), sbx); 105 lj_bufx_free(L, sbx);
102 lj_bufx_init_cow(L, sbx, p, len); 106 lj_bufx_set_cow(L, sbx, p, len);
103 setgcref(sbx->cowref, gcV(L->base+1)); 107 ref = gcV(L->base+1);
108 setgcref(sbx->cowref, ref);
109 lj_gc_objbarrier(L, buffer_toudata(sbx), ref);
104 L->top = L->base+1; /* Chain buffer object. */ 110 L->top = L->base+1; /* Chain buffer object. */
105 return 1; 111 return 1;
106} 112}
@@ -249,8 +255,7 @@ LJLIB_CF(buffer_method_decode)
249LJLIB_CF(buffer_method___gc) 255LJLIB_CF(buffer_method___gc)
250{ 256{
251 SBufExt *sbx = buffer_tobuf(L); 257 SBufExt *sbx = buffer_tobuf(L);
252 lj_bufx_free(G(L), sbx); 258 lj_bufx_free(L, sbx);
253 lj_bufx_init(L, sbx);
254 return 0; 259 return 0;
255} 260}
256 261
@@ -272,7 +277,7 @@ LJLIB_CF(buffer_method___len)
272LJLIB_PUSH("buffer") LJLIB_SET(__metatable) 277LJLIB_PUSH("buffer") LJLIB_SET(__metatable)
273LJLIB_PUSH(top-1) LJLIB_SET(__index) 278LJLIB_PUSH(top-1) LJLIB_SET(__index)
274 279
275/* ------------------------------------------------------------------------ */ 280/* -- Buffer library functions -------------------------------------------- */
276 281
277#define LJLIB_MODULE_buffer 282#define LJLIB_MODULE_buffer
278 283
@@ -280,16 +285,33 @@ LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
280 285
281LJLIB_CF(buffer_new) 286LJLIB_CF(buffer_new)
282{ 287{
283 MSize sz = L->base == L->top ? 0u : 288 MSize sz = 0;
284 (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF); 289 int targ = 1;
285 GCtab *env = tabref(curr_func(L)->c.env); 290 GCtab *env, *dict = NULL;
286 GCudata *ud = lj_udata_new(L, sizeof(SBufExt), env); 291 GCudata *ud;
287 SBufExt *sbx = (SBufExt *)uddata(ud); 292 SBufExt *sbx;
293 if (L->base < L->top && !tvistab(L->base)) {
294 targ = 2;
295 if (!tvisnil(L->base))
296 sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF);
297 }
298 if (L->base+targ-1 < L->top) {
299 GCtab *options = lj_lib_checktab(L, targ);
300 cTValue *opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict"));
301 if (opt_dict && tvistab(opt_dict)) {
302 dict = tabV(opt_dict);
303 lj_serialize_dict_prep(L, dict);
304 }
305 }
306 env = tabref(curr_func(L)->c.env);
307 ud = lj_udata_new(L, sizeof(SBufExt), env);
288 ud->udtype = UDTYPE_BUFFER; 308 ud->udtype = UDTYPE_BUFFER;
289 /* NOBARRIER: The GCudata is new (marked white). */ 309 /* NOBARRIER: The GCudata is new (marked white). */
290 setgcref(ud->metatable, obj2gco(env)); 310 setgcref(ud->metatable, obj2gco(env));
291 setudataV(L, L->top++, ud); 311 setudataV(L, L->top++, ud);
312 sbx = (SBufExt *)uddata(ud);
292 lj_bufx_init(L, sbx); 313 lj_bufx_init(L, sbx);
314 setgcref(sbx->dict, obj2gco(dict));
293 if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); 315 if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
294 return 1; 316 return 1;
295} 317}
@@ -298,7 +320,8 @@ LJLIB_CF(buffer_encode)
298{ 320{
299 cTValue *o = lj_lib_checkany(L, 1); 321 cTValue *o = lj_lib_checkany(L, 1);
300 SBufExt sbx; 322 SBufExt sbx;
301 lj_bufx_init_borrow(L, &sbx, &G(L)->tmpbuf); 323 memset(&sbx, 0, sizeof(SBufExt));
324 lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf);
302 lj_serialize_put(&sbx, o); 325 lj_serialize_put(&sbx, o);
303 setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx)); 326 setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx));
304 lj_gc_check(L); 327 lj_gc_check(L);
@@ -309,7 +332,8 @@ LJLIB_CF(buffer_decode)
309{ 332{
310 GCstr *str = lj_lib_checkstrx(L, 1); 333 GCstr *str = lj_lib_checkstrx(L, 1);
311 SBufExt sbx; 334 SBufExt sbx;
312 lj_bufx_init_cow(L, &sbx, strdata(str), str->len); 335 memset(&sbx, 0, sizeof(SBufExt));
336 lj_bufx_set_cow(L, &sbx, strdata(str), str->len);
313 /* No need to set sbx.cowref here. */ 337 /* No need to set sbx.cowref here. */
314 setnilV(L->top++); 338 setnilV(L->top++);
315 lj_serialize_get(&sbx, L->top-1); 339 lj_serialize_get(&sbx, L->top-1);
diff --git a/src/lj_buf.h b/src/lj_buf.h
index 02f0ac61..b97d55ef 100644
--- a/src/lj_buf.h
+++ b/src/lj_buf.h
@@ -27,6 +27,7 @@ typedef struct SBufExt {
27 MRef bsb; /* Borrowed string buffer. */ 27 MRef bsb; /* Borrowed string buffer. */
28 }; 28 };
29 char *r; /* Read pointer. */ 29 char *r; /* Read pointer. */
30 GCRef dict; /* Serialization string dictionary table. */
30 int depth; /* Remaining recursion depth. */ 31 int depth; /* Remaining recursion depth. */
31} SBufExt; 32} SBufExt;
32 33
@@ -114,19 +115,17 @@ static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx)
114 setsbufXL(sbx, L, SBUF_FLAG_EXT); 115 setsbufXL(sbx, L, SBUF_FLAG_EXT);
115} 116}
116 117
117static LJ_AINLINE void lj_bufx_init_borrow(lua_State *L, SBufExt *sbx, SBuf *sb) 118static LJ_AINLINE void lj_bufx_set_borrow(lua_State *L, SBufExt *sbx, SBuf *sb)
118{ 119{
119 memset(sbx, 0, sizeof(SBufExt));
120 setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW); 120 setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW);
121 setmref(sbx->bsb, sb); 121 setmref(sbx->bsb, sb);
122 sbx->r = sbx->w = sbx->b = sb->b; 122 sbx->r = sbx->w = sbx->b = sb->b;
123 sbx->e = sb->e; 123 sbx->e = sb->e;
124} 124}
125 125
126static LJ_AINLINE void lj_bufx_init_cow(lua_State *L, SBufExt *sbx, 126static LJ_AINLINE void lj_bufx_set_cow(lua_State *L, SBufExt *sbx,
127 const char *p, MSize len) 127 const char *p, MSize len)
128{ 128{
129 memset(sbx, 0, sizeof(SBufExt));
130 setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW); 129 setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW);
131 sbx->r = sbx->b = (char *)p; 130 sbx->r = sbx->b = (char *)p;
132 sbx->w = sbx->e = (char *)p + len; 131 sbx->w = sbx->e = (char *)p + len;
@@ -142,9 +141,12 @@ static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx)
142 sbx->r = sbx->w = sbx->b; 141 sbx->r = sbx->w = sbx->b;
143} 142}
144 143
145static LJ_AINLINE void lj_bufx_free(global_State *g, SBufExt *sbx) 144static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx)
146{ 145{
147 if (!sbufiscow(sbx)) lj_mem_free(g, sbx->b, sbufsz(sbx)); 146 if (!sbufiscow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx));
147 setsbufXL(sbx, L, SBUF_FLAG_EXT);
148 setgcrefnull(sbx->cowref);
149 sbx->r = sbx->w = sbx->b = sbx->e = NULL;
148} 150}
149 151
150/* Low-level buffer put operations */ 152/* Low-level buffer put operations */
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index af4a03dd..56be4bb9 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -182,8 +182,10 @@ ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)")
182 182
183#if LJ_HASBUFFER 183#if LJ_HASBUFFER
184/* String buffer errors. */ 184/* String buffer errors. */
185ERRDEF(BUFFER_BADOPT, "bad options table")
185ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS) 186ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS)
186ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x") 187ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x")
188ERRDEF(BUFFER_BADDICTX, "cannot deserialize dictionary index %d")
187ERRDEF(BUFFER_DEPTH, "too deep to serialize") 189ERRDEF(BUFFER_DEPTH, "too deep to serialize")
188ERRDEF(BUFFER_DUPKEY, "duplicate table key") 190ERRDEF(BUFFER_DUPKEY, "duplicate table key")
189ERRDEF(BUFFER_EOB, "unexpected end of buffer") 191ERRDEF(BUFFER_EOB, "unexpected end of buffer")
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 1f382ea0..646a27b2 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -67,9 +67,10 @@ static void gc_mark(global_State *g, GCobj *o)
67 gc_markobj(g, tabref(gco2ud(o)->env)); 67 gc_markobj(g, tabref(gco2ud(o)->env));
68 if (LJ_HASBUFFER && gco2ud(o)->udtype == UDTYPE_BUFFER) { 68 if (LJ_HASBUFFER && gco2ud(o)->udtype == UDTYPE_BUFFER) {
69 SBufExt *sbx = (SBufExt *)uddata(gco2ud(o)); 69 SBufExt *sbx = (SBufExt *)uddata(gco2ud(o));
70 if (sbufiscow(sbx) && gcref(sbx->cowref) != NULL) { 70 if (sbufiscow(sbx) && gcref(sbx->cowref))
71 gc_markobj(g, gcref(sbx->cowref)); 71 gc_markobj(g, gcref(sbx->cowref));
72 } 72 if (gcref(sbx->dict))
73 gc_markobj(g, gcref(sbx->dict));
73 } 74 }
74 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) { 75 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) {
75 GCupval *uv = gco2uv(o); 76 GCupval *uv = gco2uv(o);
diff --git a/src/lj_obj.h b/src/lj_obj.h
index 0dae5fec..5547a79b 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -923,7 +923,7 @@ static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it)
923} 923}
924 924
925#define define_setV(name, type, tag) \ 925#define define_setV(name, type, tag) \
926static LJ_AINLINE void name(lua_State *L, TValue *o, type *v) \ 926static LJ_AINLINE void name(lua_State *L, TValue *o, const type *v) \
927{ \ 927{ \
928 setgcV(L, o, obj2gco(v), tag); \ 928 setgcV(L, o, obj2gco(v), tag); \
929} 929}
diff --git a/src/lj_serialize.c b/src/lj_serialize.c
index 49a25a7c..d84ebcb8 100644
--- a/src/lj_serialize.c
+++ b/src/lj_serialize.c
@@ -32,7 +32,7 @@ enum {
32 SER_TAG_NUM, 32 SER_TAG_NUM,
33 SER_TAG_TAB, /* 0x08 */ 33 SER_TAG_TAB, /* 0x08 */
34 SER_TAG_0x0e = SER_TAG_TAB+6, 34 SER_TAG_0x0e = SER_TAG_TAB+6,
35 SER_TAG_0x0f, 35 SER_TAG_DICT,
36 SER_TAG_INT64, /* 0x10 */ 36 SER_TAG_INT64, /* 0x10 */
37 SER_TAG_UINT64, 37 SER_TAG_UINT64,
38 SER_TAG_COMPLEX, 38 SER_TAG_COMPLEX,
@@ -120,6 +120,26 @@ static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv)
120 return NULL; 120 return NULL;
121} 121}
122 122
123/* Prepare string dictionary for use (once). */
124void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict)
125{
126 if (!dict->hmask) { /* No hash part means not prepared, yet. */
127 MSize i, len = lj_tab_len(dict);
128 if (!len) return;
129 lj_tab_resize(L, dict, dict->asize, hsize2hbits(len));
130 for (i = 1; i <= len && i < dict->asize; i++) {
131 cTValue *o = arrayslot(dict, i);
132 if (tvisstr(o)) {
133 if (!lj_tab_getstr(dict, strV(o))) { /* Ignore dups. */
134 lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1);
135 }
136 } else if (!tvisfalse(o)) {
137 lj_err_caller(L, LJ_ERR_BUFFER_BADOPT);
138 }
139 }
140 }
141}
142
123/* -- Internal serializer ------------------------------------------------- */ 143/* -- Internal serializer ------------------------------------------------- */
124 144
125/* Put serialized object into buffer. */ 145/* Put serialized object into buffer. */
@@ -174,12 +194,45 @@ static char *serialize_put(char *w, SBufExt *sbx, cTValue *o)
174 } 194 }
175 if (nhash) { /* Write hash entries. */ 195 if (nhash) { /* Write hash entries. */
176 const Node *node = noderef(t->node) + t->hmask; 196 const Node *node = noderef(t->node) + t->hmask;
177 for (;; node--) 197 GCtab *dict = tabref(sbx->dict);
178 if (!tvisnil(&node->val)) { 198 if (LJ_UNLIKELY(dict)) {
179 w = serialize_put(w, sbx, &node->key); 199 for (;; node--)
180 w = serialize_put(w, sbx, &node->val); 200 if (!tvisnil(&node->val)) {
181 if (--nhash == 0) break; 201 if (LJ_LIKELY(tvisstr(&node->key))) {
182 } 202 /* Inlined lj_tab_getstr is 30% faster. */
203 const GCstr *str = strV(&node->key);
204 Node *n = hashstr(dict, str);
205 do {
206 if (tvisstr(&n->key) && strV(&n->key) == str) {
207 uint32_t idx = n->val.u32.lo;
208 w = serialize_more(w, sbx, 1+5);
209 *w++ = SER_TAG_DICT;
210 w = serialize_wu124(w, idx);
211 break;
212 }
213 n = nextnode(n);
214 if (!n) {
215 MSize len = str->len;
216 w = serialize_more(w, sbx, 5+len);
217 w = serialize_wu124(w, SER_TAG_STR + len);
218 w = lj_buf_wmem(w, strdata(str), len);
219 break;
220 }
221 } while (1);
222 } else {
223 w = serialize_put(w, sbx, &node->key);
224 }
225 w = serialize_put(w, sbx, &node->val);
226 if (--nhash == 0) break;
227 }
228 } else {
229 for (;; node--)
230 if (!tvisnil(&node->val)) {
231 w = serialize_put(w, sbx, &node->key);
232 w = serialize_put(w, sbx, &node->val);
233 if (--nhash == 0) break;
234 }
235 }
183 } 236 }
184 sbx->depth++; 237 sbx->depth++;
185#if LJ_HASFFI 238#if LJ_HASFFI
@@ -266,6 +319,16 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
266 if (!tvisnum(o)) setnanV(o); 319 if (!tvisnum(o)) setnanV(o);
267 } else if (tp <= SER_TAG_TRUE) { 320 } else if (tp <= SER_TAG_TRUE) {
268 setpriV(o, ~tp); 321 setpriV(o, ~tp);
322 } else if (tp == SER_TAG_DICT) {
323 GCtab *dict;
324 uint32_t idx;
325 r = serialize_ru124(r, w, &idx);
326 idx++;
327 dict = tabref(sbx->dict);
328 if (dict && idx < dict->asize && tvisstr(arrayslot(dict, idx)))
329 copyTV(sbufL(sbx), o, arrayslot(dict, idx));
330 else
331 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx);
269 } else if (tp >= SER_TAG_TAB && tp < SER_TAG_TAB+6) { 332 } else if (tp >= SER_TAG_TAB && tp < SER_TAG_TAB+6) {
270 uint32_t narray = 0, nhash = 0; 333 uint32_t narray = 0, nhash = 0;
271 GCtab *t; 334 GCtab *t;
diff --git a/src/lj_serialize.h b/src/lj_serialize.h
index f5617790..ccf1d63d 100644
--- a/src/lj_serialize.h
+++ b/src/lj_serialize.h
@@ -13,6 +13,7 @@
13 13
14#define LJ_SERIALIZE_DEPTH 100 /* Default depth. */ 14#define LJ_SERIALIZE_DEPTH 100 /* Default depth. */
15 15
16LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict);
16LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); 17LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o);
17LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); 18LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o);
18 19
diff --git a/src/lj_tab.c b/src/lj_tab.c
index 27e58f0a..ed5fd2dd 100644
--- a/src/lj_tab.c
+++ b/src/lj_tab.c
@@ -16,25 +16,6 @@
16 16
17/* -- Object hashing ------------------------------------------------------ */ 17/* -- Object hashing ------------------------------------------------------ */
18 18
19/* Hash values are masked with the table hash mask and used as an index. */
20static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash)
21{
22 Node *n = noderef(t->node);
23 return &n[hash & t->hmask];
24}
25
26/* String IDs are generated when a string is interned. */
27#define hashstr(t, s) hashmask(t, (s)->sid)
28
29#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi)))
30#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1))
31#if LJ_GC64
32#define hashgcref(t, r) \
33 hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32))
34#else
35#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS)
36#endif
37
38/* Hash an arbitrary key and return its anchor position in the hash table. */ 19/* Hash an arbitrary key and return its anchor position in the hash table. */
39static Node *hashkey(const GCtab *t, cTValue *key) 20static Node *hashkey(const GCtab *t, cTValue *key)
40{ 21{
@@ -413,7 +394,7 @@ cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key)
413 return NULL; 394 return NULL;
414} 395}
415 396
416cTValue *lj_tab_getstr(GCtab *t, GCstr *key) 397cTValue *lj_tab_getstr(GCtab *t, const GCstr *key)
417{ 398{
418 Node *n = hashstr(t, key); 399 Node *n = hashstr(t, key);
419 do { 400 do {
@@ -546,7 +527,7 @@ TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
546 return lj_tab_newkey(L, t, &k); 527 return lj_tab_newkey(L, t, &k);
547} 528}
548 529
549TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key) 530TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key)
550{ 531{
551 TValue k; 532 TValue k;
552 Node *n = hashstr(t, key); 533 Node *n = hashstr(t, key);
diff --git a/src/lj_tab.h b/src/lj_tab.h
index 97436cc0..1efa9506 100644
--- a/src/lj_tab.h
+++ b/src/lj_tab.h
@@ -31,6 +31,25 @@ static LJ_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi)
31 return hi; 31 return hi;
32} 32}
33 33
34/* Hash values are masked with the table hash mask and used as an index. */
35static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash)
36{
37 Node *n = noderef(t->node);
38 return &n[hash & t->hmask];
39}
40
41/* String IDs are generated when a string is interned. */
42#define hashstr(t, s) hashmask(t, (s)->sid)
43
44#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi)))
45#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1))
46#if LJ_GC64
47#define hashgcref(t, r) \
48 hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32))
49#else
50#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS)
51#endif
52
34#define hsize2hbits(s) ((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0) 53#define hsize2hbits(s) ((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0)
35 54
36LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits); 55LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits);
@@ -50,14 +69,14 @@ LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize);
50/* Caveat: all getters except lj_tab_get() can return NULL! */ 69/* Caveat: all getters except lj_tab_get() can return NULL! */
51 70
52LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key); 71LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key);
53LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, GCstr *key); 72LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, const GCstr *key);
54LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key); 73LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key);
55 74
56/* Caveat: all setters require a write barrier for the stored value. */ 75/* Caveat: all setters require a write barrier for the stored value. */
57 76
58LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); 77LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key);
59LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); 78LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key);
60LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); 79LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key);
61LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); 80LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key);
62 81
63#define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize) 82#define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize)