aboutsummaryrefslogtreecommitdiff
path: root/src/lj_serialize.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_serialize.c83
1 files changed, 68 insertions, 15 deletions
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 }