lj_serialize.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. ** Object de/serialization.
  3. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
  4. */
  5. #define lj_serialize_c
  6. #define LUA_CORE
  7. #include "lj_obj.h"
  8. #if LJ_HASBUFFER
  9. #include "lj_err.h"
  10. #include "lj_buf.h"
  11. #include "lj_str.h"
  12. #include "lj_tab.h"
  13. #include "lj_udata.h"
  14. #if LJ_HASFFI
  15. #include "lj_ctype.h"
  16. #include "lj_cdata.h"
  17. #endif
  18. #if LJ_HASJIT
  19. #include "lj_ir.h"
  20. #endif
  21. #include "lj_serialize.h"
  22. /* Tags for internal serialization format. */
  23. enum {
  24. SER_TAG_NIL, /* 0x00 */
  25. SER_TAG_FALSE,
  26. SER_TAG_TRUE,
  27. SER_TAG_NULL,
  28. SER_TAG_LIGHTUD32,
  29. SER_TAG_LIGHTUD64,
  30. SER_TAG_INT,
  31. SER_TAG_NUM,
  32. SER_TAG_TAB, /* 0x08 */
  33. SER_TAG_DICT_MT = SER_TAG_TAB+6,
  34. SER_TAG_DICT_STR,
  35. SER_TAG_INT64, /* 0x10 */
  36. SER_TAG_UINT64,
  37. SER_TAG_COMPLEX,
  38. SER_TAG_0x13,
  39. SER_TAG_0x14,
  40. SER_TAG_0x15,
  41. SER_TAG_0x16,
  42. SER_TAG_0x17,
  43. SER_TAG_0x18, /* 0x18 */
  44. SER_TAG_0x19,
  45. SER_TAG_0x1a,
  46. SER_TAG_0x1b,
  47. SER_TAG_0x1c,
  48. SER_TAG_0x1d,
  49. SER_TAG_0x1e,
  50. SER_TAG_0x1f,
  51. SER_TAG_STR, /* 0x20 + str->len */
  52. };
  53. LJ_STATIC_ASSERT((SER_TAG_TAB & 7) == 0);
  54. /* -- Helper functions ---------------------------------------------------- */
  55. static LJ_AINLINE char *serialize_more(char *w, SBufExt *sbx, MSize sz)
  56. {
  57. if (LJ_UNLIKELY(sz > (MSize)(sbx->e - w))) {
  58. sbx->w = w;
  59. w = lj_buf_more2((SBuf *)sbx, sz);
  60. }
  61. return w;
  62. }
  63. /* Write U124 to buffer. */
  64. static LJ_NOINLINE char *serialize_wu124_(char *w, uint32_t v)
  65. {
  66. if (v < 0x1fe0) {
  67. v -= 0xe0;
  68. *w++ = (char)(0xe0 | (v >> 8)); *w++ = (char)v;
  69. } else {
  70. *w++ = (char)0xff;
  71. #if LJ_BE
  72. v = lj_bswap(v);
  73. #endif
  74. memcpy(w, &v, 4); w += 4;
  75. }
  76. return w;
  77. }
  78. static LJ_AINLINE char *serialize_wu124(char *w, uint32_t v)
  79. {
  80. if (LJ_LIKELY(v < 0xe0)) {
  81. *w++ = (char)v;
  82. return w;
  83. } else {
  84. return serialize_wu124_(w, v);
  85. }
  86. }
  87. static LJ_NOINLINE char *serialize_ru124_(char *r, char *w, uint32_t *pv)
  88. {
  89. uint32_t v = *pv;
  90. if (v != 0xff) {
  91. if (r >= w) return NULL;
  92. v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++;
  93. } else {
  94. if (r + 4 > w) return NULL;
  95. v = lj_getu32(r); r += 4;
  96. #if LJ_BE
  97. v = lj_bswap(v);
  98. #endif
  99. }
  100. *pv = v;
  101. return r;
  102. }
  103. static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv)
  104. {
  105. if (LJ_LIKELY(r < w)) {
  106. uint32_t v = *(uint8_t *)r; r++;
  107. *pv = v;
  108. if (LJ_UNLIKELY(v >= 0xe0)) {
  109. r = serialize_ru124_(r, w, pv);
  110. }
  111. return r;
  112. }
  113. return NULL;
  114. }
  115. /* Prepare string dictionary for use (once). */
  116. void LJ_FASTCALL lj_serialize_dict_prep_str(lua_State *L, GCtab *dict)
  117. {
  118. if (!dict->hmask) { /* No hash part means not prepared, yet. */
  119. MSize i, len = lj_tab_len(dict);
  120. if (!len) return;
  121. lj_tab_resize(L, dict, dict->asize, hsize2hbits(len));
  122. for (i = 1; i <= len && i < dict->asize; i++) {
  123. cTValue *o = arrayslot(dict, i);
  124. if (tvisstr(o)) {
  125. if (!lj_tab_getstr(dict, strV(o))) { /* Ignore dups. */
  126. lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1);
  127. }
  128. } else if (!tvisfalse(o)) {
  129. lj_err_caller(L, LJ_ERR_BUFFER_BADOPT);
  130. }
  131. }
  132. }
  133. }
  134. /* Prepare metatable dictionary for use (once). */
  135. void LJ_FASTCALL lj_serialize_dict_prep_mt(lua_State *L, GCtab *dict)
  136. {
  137. if (!dict->hmask) { /* No hash part means not prepared, yet. */
  138. MSize i, len = lj_tab_len(dict);
  139. if (!len) return;
  140. lj_tab_resize(L, dict, dict->asize, hsize2hbits(len));
  141. for (i = 1; i <= len && i < dict->asize; i++) {
  142. cTValue *o = arrayslot(dict, i);
  143. if (tvistab(o)) {
  144. if (tvisnil(lj_tab_get(L, dict, o))) { /* Ignore dups. */
  145. lj_tab_newkey(L, dict, o)->u64 = (uint64_t)(i-1);
  146. }
  147. } else if (!tvisfalse(o)) {
  148. lj_err_caller(L, LJ_ERR_BUFFER_BADOPT);
  149. }
  150. }
  151. }
  152. }
  153. /* -- Internal serializer ------------------------------------------------- */
  154. /* Put serialized object into buffer. */
  155. static char *serialize_put(char *w, SBufExt *sbx, cTValue *o)
  156. {
  157. if (LJ_LIKELY(tvisstr(o))) {
  158. const GCstr *str = strV(o);
  159. MSize len = str->len;
  160. w = serialize_more(w, sbx, 5+len);
  161. w = serialize_wu124(w, SER_TAG_STR + len);
  162. w = lj_buf_wmem(w, strdata(str), len);
  163. } else if (tvisint(o)) {
  164. uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o);
  165. w = serialize_more(w, sbx, 1+4);
  166. *w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4;
  167. } else if (tvisnum(o)) {
  168. uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64;
  169. w = serialize_more(w, sbx, 1+sizeof(lua_Number));
  170. *w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8;
  171. } else if (tvispri(o)) {
  172. w = serialize_more(w, sbx, 1);
  173. *w++ = (char)(SER_TAG_NIL + ~itype(o));
  174. } else if (tvistab(o)) {
  175. const GCtab *t = tabV(o);
  176. uint32_t narray = 0, nhash = 0, one = 2;
  177. if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH);
  178. sbx->depth--;
  179. if (t->asize > 0) { /* Determine max. length of array part. */
  180. ptrdiff_t i;
  181. TValue *array = tvref(t->array);
  182. for (i = (ptrdiff_t)t->asize-1; i >= 0; i--)
  183. if (!tvisnil(&array[i]))
  184. break;
  185. narray = (uint32_t)(i+1);
  186. if (narray && tvisnil(&array[0])) one = 4;
  187. }
  188. if (t->hmask > 0) { /* Count number of used hash slots. */
  189. uint32_t i, hmask = t->hmask;
  190. Node *node = noderef(t->node);
  191. for (i = 0; i <= hmask; i++)
  192. nhash += !tvisnil(&node[i].val);
  193. }
  194. /* Write metatable index. */
  195. if (LJ_UNLIKELY(tabref(sbx->dict_mt)) && tabref(t->metatable)) {
  196. TValue mto;
  197. Node *n;
  198. settabV(sbufL(sbx), &mto, tabref(t->metatable));
  199. n = hashgcref(tabref(sbx->dict_mt), mto.gcr);
  200. do {
  201. if (n->key.u64 == mto.u64) {
  202. uint32_t idx = n->val.u32.lo;
  203. w = serialize_more(w, sbx, 1+5);
  204. *w++ = SER_TAG_DICT_MT;
  205. w = serialize_wu124(w, idx);
  206. break;
  207. }
  208. } while ((n = nextnode(n)));
  209. }
  210. /* Write number of array slots and hash slots. */
  211. w = serialize_more(w, sbx, 1+2*5);
  212. *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0));
  213. if (narray) w = serialize_wu124(w, narray);
  214. if (nhash) w = serialize_wu124(w, nhash);
  215. if (narray) { /* Write array entries. */
  216. cTValue *oa = tvref(t->array) + (one >> 2);
  217. cTValue *oe = tvref(t->array) + narray;
  218. while (oa < oe) w = serialize_put(w, sbx, oa++);
  219. }
  220. if (nhash) { /* Write hash entries. */
  221. const Node *node = noderef(t->node) + t->hmask;
  222. GCtab *dict_str = tabref(sbx->dict_str);
  223. if (LJ_UNLIKELY(dict_str)) {
  224. for (;; node--)
  225. if (!tvisnil(&node->val)) {
  226. if (LJ_LIKELY(tvisstr(&node->key))) {
  227. /* Inlined lj_tab_getstr is 30% faster. */
  228. const GCstr *str = strV(&node->key);
  229. Node *n = hashstr(dict_str, str);
  230. do {
  231. if (tvisstr(&n->key) && strV(&n->key) == str) {
  232. uint32_t idx = n->val.u32.lo;
  233. w = serialize_more(w, sbx, 1+5);
  234. *w++ = SER_TAG_DICT_STR;
  235. w = serialize_wu124(w, idx);
  236. break;
  237. }
  238. n = nextnode(n);
  239. if (!n) {
  240. MSize len = str->len;
  241. w = serialize_more(w, sbx, 5+len);
  242. w = serialize_wu124(w, SER_TAG_STR + len);
  243. w = lj_buf_wmem(w, strdata(str), len);
  244. break;
  245. }
  246. } while (1);
  247. } else {
  248. w = serialize_put(w, sbx, &node->key);
  249. }
  250. w = serialize_put(w, sbx, &node->val);
  251. if (--nhash == 0) break;
  252. }
  253. } else {
  254. for (;; node--)
  255. if (!tvisnil(&node->val)) {
  256. w = serialize_put(w, sbx, &node->key);
  257. w = serialize_put(w, sbx, &node->val);
  258. if (--nhash == 0) break;
  259. }
  260. }
  261. }
  262. sbx->depth++;
  263. #if LJ_HASFFI
  264. } else if (tviscdata(o)) {
  265. CTState *cts = ctype_cts(sbufL(sbx));
  266. CType *s = ctype_raw(cts, cdataV(o)->ctypeid);
  267. uint8_t *sp = cdataptr(cdataV(o));
  268. if (ctype_isinteger(s->info) && s->size == 8) {
  269. w = serialize_more(w, sbx, 1+8);
  270. *w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64;
  271. #if LJ_BE
  272. { uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); }
  273. #else
  274. memcpy(w, sp, 8);
  275. #endif
  276. w += 8;
  277. } else if (ctype_iscomplex(s->info) && s->size == 16) {
  278. w = serialize_more(w, sbx, 1+16);
  279. *w++ = SER_TAG_COMPLEX;
  280. #if LJ_BE
  281. { /* Only swap the doubles. The re/im order stays the same. */
  282. uint64_t u = lj_bswap64(((uint64_t *)sp)[0]); memcpy(w, &u, 8);
  283. u = lj_bswap64(((uint64_t *)sp)[1]); memcpy(w+8, &u, 8);
  284. }
  285. #else
  286. memcpy(w, sp, 16);
  287. #endif
  288. w += 16;
  289. } else {
  290. goto badenc; /* NYI other cdata */
  291. }
  292. #endif
  293. } else if (tvislightud(o)) {
  294. uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbx)), o);
  295. w = serialize_more(w, sbx, 1+sizeof(ud));
  296. if (ud == 0) {
  297. *w++ = SER_TAG_NULL;
  298. } else if (LJ_32 || checku32(ud)) {
  299. #if LJ_BE && LJ_64
  300. ud = lj_bswap64(ud);
  301. #elif LJ_BE
  302. ud = lj_bswap(ud);
  303. #endif
  304. *w++ = SER_TAG_LIGHTUD32; memcpy(w, &ud, 4); w += 4;
  305. #if LJ_64
  306. } else {
  307. #if LJ_BE
  308. ud = lj_bswap64(ud);
  309. #endif
  310. *w++ = SER_TAG_LIGHTUD64; memcpy(w, &ud, 8); w += 8;
  311. #endif
  312. }
  313. } else {
  314. /* NYI userdata */
  315. #if LJ_HASFFI
  316. badenc:
  317. #endif
  318. lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADENC, lj_typename(o));
  319. }
  320. return w;
  321. }
  322. /* Get serialized object from buffer. */
  323. static char *serialize_get(char *r, SBufExt *sbx, TValue *o)
  324. {
  325. char *w = sbx->w;
  326. uint32_t tp;
  327. r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob;
  328. if (LJ_LIKELY(tp >= SER_TAG_STR)) {
  329. uint32_t len = tp - SER_TAG_STR;
  330. if (LJ_UNLIKELY(len > (uint32_t)(w - r))) goto eob;
  331. setstrV(sbufL(sbx), o, lj_str_new(sbufL(sbx), r, len));
  332. r += len;
  333. } else if (tp == SER_TAG_INT) {
  334. if (LJ_UNLIKELY(r + 4 > w)) goto eob;
  335. setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)));
  336. r += 4;
  337. } else if (tp == SER_TAG_NUM) {
  338. if (LJ_UNLIKELY(r + 8 > w)) goto eob;
  339. memcpy(o, r, 8); r += 8;
  340. #if LJ_BE
  341. o->u64 = lj_bswap64(o->u64);
  342. #endif
  343. if (!tvisnum(o)) setnanV(o); /* Fix non-canonical NaNs. */
  344. } else if (tp <= SER_TAG_TRUE) {
  345. setpriV(o, ~tp);
  346. } else if (tp == SER_TAG_DICT_STR) {
  347. GCtab *dict_str;
  348. uint32_t idx;
  349. r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob;
  350. idx++;
  351. dict_str = tabref(sbx->dict_str);
  352. if (dict_str && idx < dict_str->asize && tvisstr(arrayslot(dict_str, idx)))
  353. copyTV(sbufL(sbx), o, arrayslot(dict_str, idx));
  354. else
  355. lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx);
  356. } else if (tp >= SER_TAG_TAB && tp <= SER_TAG_DICT_MT) {
  357. uint32_t narray = 0, nhash = 0;
  358. GCtab *t, *mt = NULL;
  359. if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH);
  360. sbx->depth--;
  361. if (tp == SER_TAG_DICT_MT) {
  362. GCtab *dict_mt;
  363. uint32_t idx;
  364. r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob;
  365. idx++;
  366. dict_mt = tabref(sbx->dict_mt);
  367. if (dict_mt && idx < dict_mt->asize && tvistab(arrayslot(dict_mt, idx)))
  368. mt = tabV(arrayslot(dict_mt, idx));
  369. else
  370. lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDICTX, idx);
  371. r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob;
  372. if (!(tp >= SER_TAG_TAB && tp < SER_TAG_DICT_MT)) goto badtag;
  373. }
  374. if (tp >= SER_TAG_TAB+2) {
  375. r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob;
  376. }
  377. if ((tp & 1)) {
  378. r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob;
  379. }
  380. t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash));
  381. /* NOBARRIER: The table is new (marked white). */
  382. setgcref(t->metatable, obj2gco(mt));
  383. settabV(sbufL(sbx), o, t);
  384. if (narray) {
  385. TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4);
  386. TValue *oe = tvref(t->array) + narray;
  387. while (oa < oe) r = serialize_get(r, sbx, oa++);
  388. }
  389. if (nhash) {
  390. do {
  391. TValue k, *v;
  392. r = serialize_get(r, sbx, &k);
  393. v = lj_tab_set(sbufL(sbx), t, &k);
  394. if (LJ_UNLIKELY(!tvisnil(v)))
  395. lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DUPKEY);
  396. r = serialize_get(r, sbx, v);
  397. } while (--nhash);
  398. }
  399. sbx->depth++;
  400. #if LJ_HASFFI
  401. } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) {
  402. uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8;
  403. GCcdata *cd;
  404. if (LJ_UNLIKELY(r + sz > w)) goto eob;
  405. if (LJ_UNLIKELY(!ctype_ctsG(G(sbufL(sbx))))) goto badtag;
  406. cd = lj_cdata_new_(sbufL(sbx),
  407. tp == SER_TAG_INT64 ? CTID_INT64 :
  408. tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE,
  409. sz);
  410. memcpy(cdataptr(cd), r, sz); r += sz;
  411. #if LJ_BE
  412. *(uint64_t *)cdataptr(cd) = lj_bswap64(*(uint64_t *)cdataptr(cd));
  413. if (sz == 16)
  414. ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]);
  415. #endif
  416. if (sz == 16) { /* Fix non-canonical NaNs. */
  417. TValue *cdo = (TValue *)cdataptr(cd);
  418. if (!tvisnum(&cdo[0])) setnanV(&cdo[0]);
  419. if (!tvisnum(&cdo[1])) setnanV(&cdo[1]);
  420. }
  421. setcdataV(sbufL(sbx), o, cd);
  422. #endif
  423. } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) {
  424. uintptr_t ud = 0;
  425. if (tp == SER_TAG_LIGHTUD32) {
  426. if (LJ_UNLIKELY(r + 4 > w)) goto eob;
  427. ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r));
  428. r += 4;
  429. }
  430. #if LJ_64
  431. else if (tp == SER_TAG_LIGHTUD64) {
  432. if (LJ_UNLIKELY(r + 8 > w)) goto eob;
  433. memcpy(&ud, r, 8); r += 8;
  434. #if LJ_BE
  435. ud = lj_bswap64(ud);
  436. #endif
  437. }
  438. setrawlightudV(o, lj_lightud_intern(sbufL(sbx), (void *)ud));
  439. #else
  440. setrawlightudV(o, (void *)ud);
  441. #endif
  442. } else {
  443. badtag:
  444. lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp);
  445. }
  446. return r;
  447. eob:
  448. lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_EOB);
  449. return NULL;
  450. }
  451. /* -- External serialization API ------------------------------------------ */
  452. /* Encode to buffer. */
  453. SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o)
  454. {
  455. sbx->depth = LJ_SERIALIZE_DEPTH;
  456. sbx->w = serialize_put(sbx->w, sbx, o);
  457. return sbx;
  458. }
  459. /* Decode from buffer. */
  460. char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o)
  461. {
  462. sbx->depth = LJ_SERIALIZE_DEPTH;
  463. return serialize_get(sbx->r, sbx, o);
  464. }
  465. /* Stand-alone encoding, borrowing from global temporary buffer. */
  466. GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o)
  467. {
  468. SBufExt sbx;
  469. char *w;
  470. memset(&sbx, 0, sizeof(SBufExt));
  471. lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf);
  472. sbx.depth = LJ_SERIALIZE_DEPTH;
  473. w = serialize_put(sbx.w, &sbx, o);
  474. return lj_str_new(L, sbx.b, (size_t)(w - sbx.b));
  475. }
  476. /* Stand-alone decoding, copy-on-write from string. */
  477. void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str)
  478. {
  479. SBufExt sbx;
  480. char *r;
  481. memset(&sbx, 0, sizeof(SBufExt));
  482. lj_bufx_set_cow(L, &sbx, strdata(str), str->len);
  483. /* No need to set sbx.cowref here. */
  484. sbx.depth = LJ_SERIALIZE_DEPTH;
  485. r = serialize_get(sbx.r, &sbx, o);
  486. if (r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV);
  487. }
  488. #if LJ_HASJIT
  489. /* Peek into buffer to find the result IRType for specialization purposes. */
  490. LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx)
  491. {
  492. uint32_t tp;
  493. if (serialize_ru124(sbx->r, sbx->w, &tp)) {
  494. /* This must match the handling of all tags in the decoder above. */
  495. switch (tp) {
  496. case SER_TAG_NIL: return IRT_NIL;
  497. case SER_TAG_FALSE: return IRT_FALSE;
  498. case SER_TAG_TRUE: return IRT_TRUE;
  499. case SER_TAG_NULL: case SER_TAG_LIGHTUD32: case SER_TAG_LIGHTUD64:
  500. return IRT_LIGHTUD;
  501. case SER_TAG_INT: return LJ_DUALNUM ? IRT_INT : IRT_NUM;
  502. case SER_TAG_NUM: return IRT_NUM;
  503. case SER_TAG_TAB: case SER_TAG_TAB+1: case SER_TAG_TAB+2:
  504. case SER_TAG_TAB+3: case SER_TAG_TAB+4: case SER_TAG_TAB+5:
  505. case SER_TAG_DICT_MT:
  506. return IRT_TAB;
  507. case SER_TAG_INT64: case SER_TAG_UINT64: case SER_TAG_COMPLEX:
  508. return IRT_CDATA;
  509. case SER_TAG_DICT_STR:
  510. default:
  511. return IRT_STR;
  512. }
  513. }
  514. return IRT_NIL; /* Will fail on actual decode. */
  515. }
  516. #endif
  517. #endif