diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_buffer.c | 60 | ||||
-rw-r--r-- | src/lj_buf.h | 16 | ||||
-rw-r--r-- | src/lj_errmsg.h | 2 | ||||
-rw-r--r-- | src/lj_gc.c | 5 | ||||
-rw-r--r-- | src/lj_obj.h | 2 | ||||
-rw-r--r-- | src/lj_serialize.c | 77 | ||||
-rw-r--r-- | src/lj_serialize.h | 1 | ||||
-rw-r--r-- | src/lj_tab.c | 23 | ||||
-rw-r--r-- | src/lj_tab.h | 23 |
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. */ |
37 | static SBufExt *buffer_tobuf(lua_State *L) | 35 | static 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 | |||
52 | LJLIB_CF(buffer_method_free) | 56 | LJLIB_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) | |||
83 | LJLIB_CF(buffer_method_set) | 86 | LJLIB_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) | |||
249 | LJLIB_CF(buffer_method___gc) | 255 | LJLIB_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) | |||
272 | LJLIB_PUSH("buffer") LJLIB_SET(__metatable) | 277 | LJLIB_PUSH("buffer") LJLIB_SET(__metatable) |
273 | LJLIB_PUSH(top-1) LJLIB_SET(__index) | 278 | LJLIB_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 | ||
281 | LJLIB_CF(buffer_new) | 286 | LJLIB_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 | ||
117 | static LJ_AINLINE void lj_bufx_init_borrow(lua_State *L, SBufExt *sbx, SBuf *sb) | 118 | static 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 | ||
126 | static LJ_AINLINE void lj_bufx_init_cow(lua_State *L, SBufExt *sbx, | 126 | static 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 | ||
145 | static LJ_AINLINE void lj_bufx_free(global_State *g, SBufExt *sbx) | 144 | static 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. */ |
185 | ERRDEF(BUFFER_BADOPT, "bad options table") | ||
185 | ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS) | 186 | ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS) |
186 | ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x") | 187 | ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x") |
188 | ERRDEF(BUFFER_BADDICTX, "cannot deserialize dictionary index %d") | ||
187 | ERRDEF(BUFFER_DEPTH, "too deep to serialize") | 189 | ERRDEF(BUFFER_DEPTH, "too deep to serialize") |
188 | ERRDEF(BUFFER_DUPKEY, "duplicate table key") | 190 | ERRDEF(BUFFER_DUPKEY, "duplicate table key") |
189 | ERRDEF(BUFFER_EOB, "unexpected end of buffer") | 191 | ERRDEF(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) \ |
926 | static LJ_AINLINE void name(lua_State *L, TValue *o, type *v) \ | 926 | static 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). */ | ||
124 | void 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 | ||
16 | LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict); | ||
16 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); | 17 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); |
17 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); | 18 | LJ_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. */ | ||
20 | static 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. */ |
39 | static Node *hashkey(const GCtab *t, cTValue *key) | 20 | static 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 | ||
416 | cTValue *lj_tab_getstr(GCtab *t, GCstr *key) | 397 | cTValue *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 | ||
549 | TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key) | 530 | TValue *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. */ | ||
35 | static 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 | ||
36 | LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits); | 55 | LJ_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 | ||
52 | LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key); | 71 | LJ_FUNCA cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key); |
53 | LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, GCstr *key); | 72 | LJ_FUNC cTValue *lj_tab_getstr(GCtab *t, const GCstr *key); |
54 | LJ_FUNCA cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key); | 73 | LJ_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 | ||
58 | LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); | 77 | LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key); |
59 | LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); | 78 | LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key); |
60 | LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key); | 79 | LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key); |
61 | LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key); | 80 | LJ_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) |