diff options
author | Mike Pall <mike> | 2021-06-07 12:03:22 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2021-06-07 12:03:22 +0200 |
commit | ac02a120ef249aac37b4847705a3099bd4b92967 (patch) | |
tree | ce8dde84c0cf6017752dd605088dc80f8626ea1a /src/lj_serialize.c | |
parent | 4216bdfb2a18b213d226da26361417c537c36743 (diff) | |
download | luajit-ac02a120ef249aac37b4847705a3099bd4b92967.tar.gz luajit-ac02a120ef249aac37b4847705a3099bd4b92967.tar.bz2 luajit-ac02a120ef249aac37b4847705a3099bd4b92967.zip |
String buffers, part 2e: add serialization string dictionary.
Sponsored by fmad.io.
Diffstat (limited to 'src/lj_serialize.c')
-rw-r--r-- | src/lj_serialize.c | 77 |
1 files changed, 70 insertions, 7 deletions
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; |