aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib_buffer.c17
-rw-r--r--src/lj_buf.h3
-rw-r--r--src/lj_gc.c6
-rw-r--r--src/lj_serialize.c83
-rw-r--r--src/lj_serialize.h3
5 files changed, 88 insertions, 24 deletions
diff --git a/src/lib_buffer.c b/src/lib_buffer.c
index ae065759..2e364861 100644
--- a/src/lib_buffer.c
+++ b/src/lib_buffer.c
@@ -288,7 +288,7 @@ LJLIB_CF(buffer_new)
288{ 288{
289 MSize sz = 0; 289 MSize sz = 0;
290 int targ = 1; 290 int targ = 1;
291 GCtab *env, *dict = NULL; 291 GCtab *env, *dict_str = NULL, *dict_mt = NULL;
292 GCudata *ud; 292 GCudata *ud;
293 SBufExt *sbx; 293 SBufExt *sbx;
294 if (L->base < L->top && !tvistab(L->base)) { 294 if (L->base < L->top && !tvistab(L->base)) {
@@ -298,10 +298,16 @@ LJLIB_CF(buffer_new)
298 } 298 }
299 if (L->base+targ-1 < L->top) { 299 if (L->base+targ-1 < L->top) {
300 GCtab *options = lj_lib_checktab(L, targ); 300 GCtab *options = lj_lib_checktab(L, targ);
301 cTValue *opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict")); 301 cTValue *opt_dict, *opt_mt;
302 opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict"));
302 if (opt_dict && tvistab(opt_dict)) { 303 if (opt_dict && tvistab(opt_dict)) {
303 dict = tabV(opt_dict); 304 dict_str = tabV(opt_dict);
304 lj_serialize_dict_prep(L, dict); 305 lj_serialize_dict_prep_str(L, dict_str);
306 }
307 opt_mt = lj_tab_getstr(options, lj_str_newlit(L, "metatable"));
308 if (opt_mt && tvistab(opt_mt)) {
309 dict_mt = tabV(opt_mt);
310 lj_serialize_dict_prep_mt(L, dict_mt);
305 } 311 }
306 } 312 }
307 env = tabref(curr_func(L)->c.env); 313 env = tabref(curr_func(L)->c.env);
@@ -312,7 +318,8 @@ LJLIB_CF(buffer_new)
312 setudataV(L, L->top++, ud); 318 setudataV(L, L->top++, ud);
313 sbx = (SBufExt *)uddata(ud); 319 sbx = (SBufExt *)uddata(ud);
314 lj_bufx_init(L, sbx); 320 lj_bufx_init(L, sbx);
315 setgcref(sbx->dict, obj2gco(dict)); 321 setgcref(sbx->dict_str, obj2gco(dict_str));
322 setgcref(sbx->dict_mt, obj2gco(dict_mt));
316 if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); 323 if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
317 return 1; 324 return 1;
318} 325}
diff --git a/src/lj_buf.h b/src/lj_buf.h
index 4ace2685..e2ac922e 100644
--- a/src/lj_buf.h
+++ b/src/lj_buf.h
@@ -27,7 +27,8 @@ 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 GCRef dict_str; /* Serialization string dictionary table. */
31 GCRef dict_mt; /* Serialization metatable dictionary table. */
31 int depth; /* Remaining recursion depth. */ 32 int depth; /* Remaining recursion depth. */
32} SBufExt; 33} SBufExt;
33 34
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 646a27b2..5a238542 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -69,8 +69,10 @@ static void gc_mark(global_State *g, GCobj *o)
69 SBufExt *sbx = (SBufExt *)uddata(gco2ud(o)); 69 SBufExt *sbx = (SBufExt *)uddata(gco2ud(o));
70 if (sbufiscow(sbx) && gcref(sbx->cowref)) 70 if (sbufiscow(sbx) && gcref(sbx->cowref))
71 gc_markobj(g, gcref(sbx->cowref)); 71 gc_markobj(g, gcref(sbx->cowref));
72 if (gcref(sbx->dict)) 72 if (gcref(sbx->dict_str))
73 gc_markobj(g, gcref(sbx->dict)); 73 gc_markobj(g, gcref(sbx->dict_str));
74 if (gcref(sbx->dict_mt))
75 gc_markobj(g, gcref(sbx->dict_mt));
74 } 76 }
75 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) { 77 } else if (LJ_UNLIKELY(gct == ~LJ_TUPVAL)) {
76 GCupval *uv = gco2uv(o); 78 GCupval *uv = gco2uv(o);
diff --git a/src/lj_serialize.c b/src/lj_serialize.c
index 70ff4796..e12e3668 100644
--- a/src/lj_serialize.c
+++ b/src/lj_serialize.c
@@ -34,8 +34,8 @@ enum {
34 SER_TAG_INT, 34 SER_TAG_INT,
35 SER_TAG_NUM, 35 SER_TAG_NUM,
36 SER_TAG_TAB, /* 0x08 */ 36 SER_TAG_TAB, /* 0x08 */
37 SER_TAG_0x0e = SER_TAG_TAB+6, 37 SER_TAG_DICT_MT = SER_TAG_TAB+6,
38 SER_TAG_DICT, 38 SER_TAG_DICT_STR,
39 SER_TAG_INT64, /* 0x10 */ 39 SER_TAG_INT64, /* 0x10 */
40 SER_TAG_UINT64, 40 SER_TAG_UINT64,
41 SER_TAG_COMPLEX, 41 SER_TAG_COMPLEX,
@@ -124,7 +124,7 @@ static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv)
124} 124}
125 125
126/* Prepare string dictionary for use (once). */ 126/* Prepare string dictionary for use (once). */
127void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict) 127void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict)
128{ 128{
129 if (!dict->hmask) { /* No hash part means not prepared, yet. */ 129 if (!dict->hmask) { /* No hash part means not prepared, yet. */
130 MSize i, len = lj_tab_len(dict); 130 MSize i, len = lj_tab_len(dict);
@@ -143,6 +143,26 @@ void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict)
143 } 143 }
144} 144}
145 145
146/* Prepare metatable dictionary for use (once). */
147void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict)
148{
149 if (!dict->hmask) { /* No hash part means not prepared, yet. */
150 MSize i, len = lj_tab_len(dict);
151 if (!len) return;
152 lj_tab_resize(L, dict, dict->asize, hsize2hbits(len));
153 for (i = 1; i <= len && i < dict->asize; i++) {
154 cTValue *o = arrayslot(dict, i);
155 if (tvistab(o)) {
156 if (tvisnil(lj_tab_get(L, dict, o))) { /* Ignore dups. */
157 lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1);
158 }
159 } else if (!tvisfalse(o)) {
160 lj_err_caller(L, LJ_ERR_BUFFER_BADOPT);
161 }
162 }
163 }
164}
165
146/* -- Internal serializer ------------------------------------------------- */ 166/* -- Internal serializer ------------------------------------------------- */
147 167
148/* Put serialized object into buffer. */ 168/* Put serialized object into buffer. */
@@ -185,6 +205,22 @@ static char *serialize_put(char *w, SBufExt *sbx, cTValue *o)
185 for (i = 0; i <= hmask; i++) 205 for (i = 0; i <= hmask; i++)
186 nhash += !tvisnil(&node[i].val); 206 nhash += !tvisnil(&node[i].val);
187 } 207 }
208 /* Write metatable index. */
209 if (LJ_UNLIKELY(tabref(sbx->dict_mt)) && tabref(t->metatable)) {
210 TValue mto;
211 Node *n;
212 settabV(sbufL(sbx), &mto, tabref(t->metatable));
213 n = hashgcref(tabref(sbx->dict_mt), mto.gcr);
214 do {
215 if (n->key.u64 == mto.u64) {
216 uint32_t idx = n->val.u32.lo;
217 w = serialize_more(w, sbx, 1+5);
218 *w++ = SER_TAG_DICT_MT;
219 w = serialize_wu124(w, idx);
220 break;
221 }
222 } while ((n = nextnode(n)));
223 }
188 /* Write number of array slots and hash slots. */ 224 /* Write number of array slots and hash slots. */
189 w = serialize_more(w, sbx, 1+2*5); 225 w = serialize_more(w, sbx, 1+2*5);
190 *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0)); 226 *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0));
@@ -197,19 +233,19 @@ static char *serialize_put(char *w, SBufExt *sbx, cTValue *o)
197 } 233 }
198 if (nhash) { /* Write hash entries. */ 234 if (nhash) { /* Write hash entries. */
199 const Node *node = noderef(t->node) + t->hmask; 235 const Node *node = noderef(t->node) + t->hmask;
200 GCtab *dict = tabref(sbx->dict); 236 GCtab *dict_str = tabref(sbx->dict_str);
201 if (LJ_UNLIKELY(dict)) { 237 if (LJ_UNLIKELY(dict_str)) {
202 for (;; node--) 238 for (;; node--)
203 if (!tvisnil(&node->val)) { 239 if (!tvisnil(&node->val)) {
204 if (LJ_LIKELY(tvisstr(&node->key))) { 240 if (LJ_LIKELY(tvisstr(&node->key))) {
205 /* Inlined lj_tab_getstr is 30% faster. */ 241 /* Inlined lj_tab_getstr is 30% faster. */
206 const GCstr *str = strV(&node->key); 242 const GCstr *str = strV(&node->key);
207 Node *n = hashstr(dict, str); 243 Node *n = hashstr(dict_str, str);
208 do { 244 do {
209 if (tvisstr(&n->key) && strV(&n->key) == str) { 245 if (tvisstr(&n->key) && strV(&n->key) == str) {
210 uint32_t idx = n->val.u32.lo; 246 uint32_t idx = n->val.u32.lo;
211 w = serialize_more(w, sbx, 1+5); 247 w = serialize_more(w, sbx, 1+5);
212 *w++ = SER_TAG_DICT; 248 *w++ = SER_TAG_DICT_STR;
213 w = serialize_wu124(w, idx); 249 w = serialize_wu124(w, idx);
214 break; 250 break;
215 } 251 }
@@ -322,19 +358,32 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
322 if (!tvisnum(o)) setnanV(o); 358 if (!tvisnum(o)) setnanV(o);
323 } else if (tp <= SER_TAG_TRUE) { 359 } else if (tp <= SER_TAG_TRUE) {
324 setpriV(o, ~tp); 360 setpriV(o, ~tp);
325 } else if (tp == SER_TAG_DICT) { 361 } else if (tp == SER_TAG_DICT_STR) {
326 GCtab *dict; 362 GCtab *dict_str;
327 uint32_t idx; 363 uint32_t idx;
328 r = serialize_ru124(r, w, &idx); 364 r = serialize_ru124(r, w, &idx);
329 idx++; 365 idx++;
330 dict = tabref(sbx->dict); 366 dict_str = tabref(sbx->dict_str);
331 if (dict && idx < dict->asize && tvisstr(arrayslot(dict, idx))) 367 if (dict_str && idx < dict_str->asize && tvisstr(arrayslot(dict_str, idx)))
332 copyTV(sbufL(sbx), o, arrayslot(dict, idx)); 368 copyTV(sbufL(sbx), o, arrayslot(dict_str, idx));
333 else 369 else
334 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx); 370 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx);
335 } else if (tp >= SER_TAG_TAB && tp < SER_TAG_TAB+6) { 371 } else if (tp >= SER_TAG_TAB && tp <= SER_TAG_DICT_MT) {
336 uint32_t narray = 0, nhash = 0; 372 uint32_t narray = 0, nhash = 0;
337 GCtab *t; 373 GCtab *t, *mt = NULL;
374 if (tp == SER_TAG_DICT_MT) {
375 GCtab *dict_mt;
376 uint32_t idx;
377 r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob;
378 idx++;
379 dict_mt = tabref(sbx->dict_mt);
380 if (dict_mt && idx < dict_mt->asize && tvistab(arrayslot(dict_mt, idx)))
381 mt = tabV(arrayslot(dict_mt, idx));
382 else
383 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx);
384 r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob;
385 if (!(tp >= SER_TAG_TAB && tp < SER_TAG_DICT_MT)) goto badtag;
386 }
338 if (tp >= SER_TAG_TAB+2) { 387 if (tp >= SER_TAG_TAB+2) {
339 r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob; 388 r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob;
340 } 389 }
@@ -342,6 +391,8 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
342 r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob; 391 r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob;
343 } 392 }
344 t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash)); 393 t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash));
394 /* NOBARRIER: The table is new (marked white). */
395 setgcref(t->metatable, obj2gco(mt));
345 settabV(sbufL(sbx), o, t); 396 settabV(sbufL(sbx), o, t);
346 if (narray) { 397 if (narray) {
347 TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4); 398 TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4);
@@ -395,6 +446,7 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
395 setrawlightudV(o, (void *)ud); 446 setrawlightudV(o, (void *)ud);
396#endif 447#endif
397 } else { 448 } else {
449badtag:
398 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp); 450 lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp);
399 } 451 }
400 return r; 452 return r;
@@ -460,10 +512,11 @@ LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx)
460 case SER_TAG_NUM: return IRT_NUM; 512 case SER_TAG_NUM: return IRT_NUM;
461 case SER_TAG_TAB: case SER_TAG_TAB+1: case SER_TAG_TAB+2: 513 case SER_TAG_TAB: case SER_TAG_TAB+1: case SER_TAG_TAB+2:
462 case SER_TAG_TAB+3: case SER_TAG_TAB+4: case SER_TAG_TAB+5: 514 case SER_TAG_TAB+3: case SER_TAG_TAB+4: case SER_TAG_TAB+5:
515 case SER_TAG_DICT_MT:
463 return IRT_TAB; 516 return IRT_TAB;
464 case SER_TAG_INT64: case SER_TAG_UINT64: case SER_TAG_COMPLEX: 517 case SER_TAG_INT64: case SER_TAG_UINT64: case SER_TAG_COMPLEX:
465 return IRT_CDATA; 518 return IRT_CDATA;
466 case SER_TAG_DICT: 519 case SER_TAG_DICT_STR:
467 default: 520 default:
468 return IRT_STR; 521 return IRT_STR;
469 } 522 }
diff --git a/src/lj_serialize.h b/src/lj_serialize.h
index 9bd780ca..1fda23eb 100644
--- a/src/lj_serialize.h
+++ b/src/lj_serialize.h
@@ -13,7 +13,8 @@
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 void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict);
17LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict);
17LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); 18LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o);
18LJ_FUNC char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); 19LJ_FUNC char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o);
19LJ_FUNC GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o); 20LJ_FUNC GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o);