diff options
author | Mike Pall <mike> | 2021-06-01 00:55:51 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2021-06-01 00:55:51 +0200 |
commit | 61990cef05a4ee4abb7cd130c7e46160cd914d95 (patch) | |
tree | f95f5e68ce1077b91d6dd6b51a923f2ab56171d5 /src | |
parent | 394fb6267acba72ee984edcd331ad1bbde72056a (diff) | |
download | luajit-61990cef05a4ee4abb7cd130c7e46160cd914d95.tar.gz luajit-61990cef05a4ee4abb7cd130c7e46160cd914d95.tar.bz2 luajit-61990cef05a4ee4abb7cd130c7e46160cd914d95.zip |
String buffers, part 2b: Add extended string buffers. Use in serializer.
Sponsored by fmad.io.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib_buffer.c | 23 | ||||
-rw-r--r-- | src/lj_buf.c | 53 | ||||
-rw-r--r-- | src/lj_buf.h | 100 | ||||
-rw-r--r-- | src/lj_obj.h | 4 | ||||
-rw-r--r-- | src/lj_serialize.c | 124 | ||||
-rw-r--r-- | src/lj_serialize.h | 4 |
6 files changed, 210 insertions, 98 deletions
diff --git a/src/lib_buffer.c b/src/lib_buffer.c index e21362b8..c9ef9510 100644 --- a/src/lib_buffer.c +++ b/src/lib_buffer.c | |||
@@ -22,15 +22,13 @@ | |||
22 | 22 | ||
23 | #define LJLIB_MODULE_buffer | 23 | #define LJLIB_MODULE_buffer |
24 | 24 | ||
25 | /* Note: this uses interim structs until the SBuf reorg. */ | ||
26 | |||
27 | LJLIB_CF(buffer_encode) | 25 | LJLIB_CF(buffer_encode) |
28 | { | 26 | { |
29 | cTValue *o = lj_lib_checkany(L, 1); | 27 | cTValue *o = lj_lib_checkany(L, 1); |
30 | StrBuf sbuf; | 28 | SBufExt sbx; |
31 | sbuf.sb = lj_buf_tmp_(L); | 29 | lj_bufx_init_borrow(L, &sbx, &G(L)->tmpbuf); |
32 | lj_serialize_put(&sbuf, o); | 30 | lj_serialize_put(&sbx, o); |
33 | setstrV(L, L->top++, lj_buf_str(L, sbuf.sb)); | 31 | setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx)); |
34 | lj_gc_check(L); | 32 | lj_gc_check(L); |
35 | return 1; | 33 | return 1; |
36 | } | 34 | } |
@@ -38,16 +36,11 @@ LJLIB_CF(buffer_encode) | |||
38 | LJLIB_CF(buffer_decode) | 36 | LJLIB_CF(buffer_decode) |
39 | { | 37 | { |
40 | GCstr *str = lj_lib_checkstr(L, 1); | 38 | GCstr *str = lj_lib_checkstr(L, 1); |
41 | char *p = (char *)strdata(str); | 39 | SBufExt sbx; |
42 | SBuf sb; | 40 | lj_bufx_init_cow(L, &sbx, strdata(str), str->len); |
43 | StrBuf sbuf; | 41 | /* No need to set sbx.cowref here. */ |
44 | setsbufL(&sb, L); | ||
45 | sb.b = p; | ||
46 | sb.w = sb.e = p + str->len; | ||
47 | sbuf.sb = &sb; | ||
48 | sbuf.r = p; | ||
49 | setnilV(L->top++); | 42 | setnilV(L->top++); |
50 | lj_serialize_get(&sbuf, L->top-1); | 43 | lj_serialize_get(&sbx, L->top-1); |
51 | lj_gc_check(L); | 44 | lj_gc_check(L); |
52 | return 1; | 45 | return 1; |
53 | } | 46 | } |
diff --git a/src/lj_buf.c b/src/lj_buf.c index 66a096fb..889ccbca 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c | |||
@@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz) | |||
20 | { | 20 | { |
21 | MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz; | 21 | MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz; |
22 | char *b; | 22 | char *b; |
23 | GCSize flag; | ||
23 | if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF; | 24 | if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF; |
24 | while (nsz < sz) nsz += nsz; | 25 | while (nsz < sz) nsz += nsz; |
25 | b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz); | 26 | flag = sbufflag(sb); |
27 | if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */ | ||
28 | lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW"); | ||
29 | b = (char *)lj_mem_new(sbufL(sb), nsz); | ||
30 | setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW); | ||
31 | setgcrefnull(sbufX(sb)->cowref); | ||
32 | memcpy(b, sb->b, osz); | ||
33 | } else { | ||
34 | b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz); | ||
35 | } | ||
36 | if ((flag & SBUF_FLAG_EXT)) { | ||
37 | sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */ | ||
38 | } | ||
39 | /* Adjust buffer pointers. */ | ||
26 | sb->b = b; | 40 | sb->b = b; |
27 | sb->w = b + len; | 41 | sb->w = b + len; |
28 | sb->e = b + nsz; | 42 | sb->e = b + nsz; |
43 | if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */ | ||
44 | SBuf *bsb = mref(sbufX(sb)->bsb, SBuf); | ||
45 | bsb->b = b; | ||
46 | bsb->w = b + len; | ||
47 | bsb->e = b + nsz; | ||
48 | } | ||
29 | } | 49 | } |
30 | 50 | ||
31 | LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) | 51 | LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) |
@@ -39,11 +59,31 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) | |||
39 | 59 | ||
40 | LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz) | 60 | LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz) |
41 | { | 61 | { |
42 | MSize len = sbuflen(sb); | 62 | if (sbufisext(sb)) { |
43 | lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); | 63 | SBufExt *sbx = (SBufExt *)sb; |
44 | if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) | 64 | MSize len = sbufxlen(sbx); |
45 | lj_err_mem(sbufL(sb)); | 65 | if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) |
46 | buf_grow(sb, len + sz); | 66 | lj_err_mem(sbufL(sbx)); |
67 | if (len + sz > sbufsz(sbx)) { /* Must grow. */ | ||
68 | buf_grow((SBuf *)sbx, len + sz); | ||
69 | } else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) { | ||
70 | /* Also grow to avoid excessive compactions, if slack < size/8. */ | ||
71 | buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */ | ||
72 | return sbx->w; | ||
73 | } | ||
74 | if (sbx->r != sbx->b) { /* Compact by moving down. */ | ||
75 | memmove(sbx->b, sbx->r, len); | ||
76 | sbx->r = sbx->b; | ||
77 | sbx->w = sbx->b + len; | ||
78 | lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact"); | ||
79 | } | ||
80 | } else { | ||
81 | MSize len = sbuflen(sb); | ||
82 | lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); | ||
83 | if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) | ||
84 | lj_err_mem(sbufL(sb)); | ||
85 | buf_grow(sb, len + sz); | ||
86 | } | ||
47 | return sb->w; | 87 | return sb->w; |
48 | } | 88 | } |
49 | 89 | ||
@@ -58,6 +98,7 @@ void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb) | |||
58 | sb->w = b + n; | 98 | sb->w = b + n; |
59 | sb->e = b + (osz >> 1); | 99 | sb->e = b + (osz >> 1); |
60 | } | 100 | } |
101 | lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt"); | ||
61 | } | 102 | } |
62 | 103 | ||
63 | char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) | 104 | char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) |
diff --git a/src/lj_buf.h b/src/lj_buf.h index 268fce5e..1fb70146 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h | |||
@@ -10,13 +10,53 @@ | |||
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_str.h" | 11 | #include "lj_str.h" |
12 | 12 | ||
13 | /* Resizable string buffers. SBuf struct definition in lj_obj.h. */ | 13 | /* Resizable string buffers. */ |
14 | #define sbufsz(sb) ((MSize)((sb)->e - (sb)->b)) | ||
15 | #define sbuflen(sb) ((MSize)((sb)->w - (sb)->b)) | ||
16 | #define sbufleft(sb) ((MSize)((sb)->e - (sb)->w)) | ||
17 | 14 | ||
18 | #define sbufL(sb) (mref((sb)->L, lua_State)) | 15 | /* The SBuf struct definition is in lj_obj.h: |
19 | #define setsbufL(sb, l) (setmref((sb)->L, (l))) | 16 | ** char *w; Write pointer. |
17 | ** char *e; End pointer. | ||
18 | ** char *b; Base pointer. | ||
19 | ** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB. | ||
20 | */ | ||
21 | |||
22 | /* Extended string buffer. */ | ||
23 | typedef struct SBufExt { | ||
24 | SBufHeader; | ||
25 | union { | ||
26 | GCRef cowref; /* Copy-on-write object reference. */ | ||
27 | MRef bsb; /* Borrowed string buffer. */ | ||
28 | }; | ||
29 | char *r; /* Read pointer. */ | ||
30 | int depth; /* Remaining recursion depth. */ | ||
31 | } SBufExt; | ||
32 | |||
33 | #define sbufsz(sb) ((MSize)((sb)->e - (sb)->b)) | ||
34 | #define sbuflen(sb) ((MSize)((sb)->w - (sb)->b)) | ||
35 | #define sbufleft(sb) ((MSize)((sb)->e - (sb)->w)) | ||
36 | #define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r)) | ||
37 | #define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b)) | ||
38 | |||
39 | #define SBUF_MASK_FLAG (7) | ||
40 | #define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG) | ||
41 | #define SBUF_FLAG_EXT 1 /* Extended string buffer. */ | ||
42 | #define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */ | ||
43 | #define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */ | ||
44 | |||
45 | #define sbufL(sb) \ | ||
46 | ((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L)) | ||
47 | #define setsbufL(sb, l) (setmref((sb)->L, (l))) | ||
48 | #define setsbufXL(sb, l, flag) \ | ||
49 | (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag))) | ||
50 | #define setsbufXL_(sb, l) \ | ||
51 | (setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG))) | ||
52 | |||
53 | #define sbufflag(sb) (mrefu((sb)->L)) | ||
54 | #define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT) | ||
55 | #define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW) | ||
56 | #define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW) | ||
57 | #define sbufX(sb) \ | ||
58 | (lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb)) | ||
59 | #define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag))) | ||
20 | 60 | ||
21 | /* Buffer management */ | 61 | /* Buffer management */ |
22 | LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz); | 62 | LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz); |
@@ -45,6 +85,7 @@ static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L) | |||
45 | 85 | ||
46 | static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) | 86 | static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) |
47 | { | 87 | { |
88 | lj_assertG(!sbufisext(sb), "bad free of SBufExt"); | ||
48 | lj_mem_free(g, sb->b, sbufsz(sb)); | 89 | lj_mem_free(g, sb->b, sbufsz(sb)); |
49 | } | 90 | } |
50 | 91 | ||
@@ -62,6 +103,46 @@ static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz) | |||
62 | return sb->w; | 103 | return sb->w; |
63 | } | 104 | } |
64 | 105 | ||
106 | /* Extended buffer management */ | ||
107 | static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx) | ||
108 | { | ||
109 | memset(sbx, 0, sizeof(SBufExt)); | ||
110 | setsbufXL(sbx, L, SBUF_FLAG_EXT); | ||
111 | } | ||
112 | |||
113 | static LJ_AINLINE void lj_bufx_init_borrow(lua_State *L, SBufExt *sbx, SBuf *sb) | ||
114 | { | ||
115 | memset(sbx, 0, sizeof(SBufExt)); | ||
116 | setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW); | ||
117 | setmref(sbx->bsb, sb); | ||
118 | sbx->r = sbx->w = sbx->b = sb->b; | ||
119 | sbx->e = sb->e; | ||
120 | } | ||
121 | |||
122 | static LJ_AINLINE void lj_bufx_init_cow(lua_State *L, SBufExt *sbx, | ||
123 | const char *p, MSize len) | ||
124 | { | ||
125 | memset(sbx, 0, sizeof(SBufExt)); | ||
126 | setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW); | ||
127 | sbx->r = sbx->b = (char *)p; | ||
128 | sbx->w = sbx->e = (char *)p + len; | ||
129 | } | ||
130 | |||
131 | static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx) | ||
132 | { | ||
133 | if (sbufiscow(sbx)) { | ||
134 | setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW)); | ||
135 | setgcrefnull(sbx->cowref); | ||
136 | sbx->b = sbx->e = NULL; | ||
137 | } | ||
138 | sbx->r = sbx->w = sbx->b; | ||
139 | } | ||
140 | |||
141 | static LJ_AINLINE void lj_bufx_free(global_State *g, SBufExt *sbx) | ||
142 | { | ||
143 | if (!sbufiscow(sbx)) lj_mem_free(g, sbx->b, sbufsz(sbx)); | ||
144 | } | ||
145 | |||
65 | /* Low-level buffer put operations */ | 146 | /* Low-level buffer put operations */ |
66 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); | 147 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); |
67 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); | 148 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); |
@@ -97,11 +178,4 @@ static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb) | |||
97 | return lj_str_new(L, sb->b, sbuflen(sb)); | 178 | return lj_str_new(L, sb->b, sbuflen(sb)); |
98 | } | 179 | } |
99 | 180 | ||
100 | /* Interim user-accessible string buffer. */ | ||
101 | typedef struct StrBuf { | ||
102 | SBuf *sb; /* Pointer to system buffer. */ | ||
103 | char *r; /* String buffer read pointer. */ | ||
104 | int depth; /* Remaining recursion depth. */ | ||
105 | } StrBuf; | ||
106 | |||
107 | #endif | 181 | #endif |
diff --git a/src/lj_obj.h b/src/lj_obj.h index 2150e4e2..9b691e49 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -34,13 +34,17 @@ typedef struct MRef { | |||
34 | 34 | ||
35 | #if LJ_GC64 | 35 | #if LJ_GC64 |
36 | #define mref(r, t) ((t *)(void *)(r).ptr64) | 36 | #define mref(r, t) ((t *)(void *)(r).ptr64) |
37 | #define mrefu(r) ((r).ptr64) | ||
37 | 38 | ||
38 | #define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p)) | 39 | #define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p)) |
40 | #define setmrefu(r, u) ((r).ptr64 = (uint64_t)(u)) | ||
39 | #define setmrefr(r, v) ((r).ptr64 = (v).ptr64) | 41 | #define setmrefr(r, v) ((r).ptr64 = (v).ptr64) |
40 | #else | 42 | #else |
41 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) | 43 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) |
44 | #define mrefu(r) ((r).ptr32) | ||
42 | 45 | ||
43 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) | 46 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) |
47 | #define setmrefu(r, u) ((r).ptr32 = (uint32_t)(u)) | ||
44 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) | 48 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) |
45 | #endif | 49 | #endif |
46 | 50 | ||
diff --git a/src/lj_serialize.c b/src/lj_serialize.c index 13220c17..4e76502a 100644 --- a/src/lj_serialize.c +++ b/src/lj_serialize.c | |||
@@ -55,11 +55,11 @@ LJ_STATIC_ASSERT((SER_TAG_TAB & 7) == 0); | |||
55 | 55 | ||
56 | /* -- Helper functions ---------------------------------------------------- */ | 56 | /* -- Helper functions ---------------------------------------------------- */ |
57 | 57 | ||
58 | static LJ_AINLINE char *serialize_more(char *w, StrBuf *sbuf, MSize sz) | 58 | static LJ_AINLINE char *serialize_more(char *w, SBufExt *sbx, MSize sz) |
59 | { | 59 | { |
60 | if (LJ_UNLIKELY(sz > (MSize)(sbuf->sb->e - w))) { | 60 | if (LJ_UNLIKELY(sz > (MSize)(sbx->e - w))) { |
61 | sbuf->sb->w = w; | 61 | sbx->w = w; |
62 | w = lj_buf_more2(sbuf->sb, sz); | 62 | w = lj_buf_more2((SBuf *)sbx, sz); |
63 | } | 63 | } |
64 | return w; | 64 | return w; |
65 | } | 65 | } |
@@ -90,14 +90,14 @@ static LJ_AINLINE char *serialize_wu124(char *w, uint32_t v) | |||
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | static LJ_NOINLINE char *serialize_ru124_(char *r, char *e, uint32_t *pv) | 93 | static LJ_NOINLINE char *serialize_ru124_(char *r, char *w, uint32_t *pv) |
94 | { | 94 | { |
95 | uint32_t v = *pv; | 95 | uint32_t v = *pv; |
96 | if (v != 0xff) { | 96 | if (v != 0xff) { |
97 | if (r >= e) return NULL; | 97 | if (r >= w) return NULL; |
98 | v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++; | 98 | v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++; |
99 | } else { | 99 | } else { |
100 | if (r + 4 > e) return NULL; | 100 | if (r + 4 > w) return NULL; |
101 | v = lj_getu32(r); r += 4; | 101 | v = lj_getu32(r); r += 4; |
102 | #if LJ_BE | 102 | #if LJ_BE |
103 | v = lj_bswap(v); | 103 | v = lj_bswap(v); |
@@ -107,13 +107,13 @@ static LJ_NOINLINE char *serialize_ru124_(char *r, char *e, uint32_t *pv) | |||
107 | return r; | 107 | return r; |
108 | } | 108 | } |
109 | 109 | ||
110 | static LJ_AINLINE char *serialize_ru124(char *r, char *e, uint32_t *pv) | 110 | static LJ_AINLINE char *serialize_ru124(char *r, char *w, uint32_t *pv) |
111 | { | 111 | { |
112 | if (LJ_LIKELY(r < e)) { | 112 | if (LJ_LIKELY(r < w)) { |
113 | uint32_t v = *(uint8_t *)r; r++; | 113 | uint32_t v = *(uint8_t *)r; r++; |
114 | *pv = v; | 114 | *pv = v; |
115 | if (LJ_UNLIKELY(v >= 0xe0)) { | 115 | if (LJ_UNLIKELY(v >= 0xe0)) { |
116 | r = serialize_ru124_(r, e, pv); | 116 | r = serialize_ru124_(r, w, pv); |
117 | } | 117 | } |
118 | return r; | 118 | return r; |
119 | } | 119 | } |
@@ -123,30 +123,30 @@ static LJ_AINLINE char *serialize_ru124(char *r, char *e, uint32_t *pv) | |||
123 | /* -- Internal serializer ------------------------------------------------- */ | 123 | /* -- Internal serializer ------------------------------------------------- */ |
124 | 124 | ||
125 | /* Put serialized object into buffer. */ | 125 | /* Put serialized object into buffer. */ |
126 | static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o) | 126 | static char *serialize_put(char *w, SBufExt *sbx, cTValue *o) |
127 | { | 127 | { |
128 | if (LJ_LIKELY(tvisstr(o))) { | 128 | if (LJ_LIKELY(tvisstr(o))) { |
129 | const GCstr *str = strV(o); | 129 | const GCstr *str = strV(o); |
130 | MSize len = str->len; | 130 | MSize len = str->len; |
131 | w = serialize_more(w, sbuf, 5+len); | 131 | w = serialize_more(w, sbx, 5+len); |
132 | w = serialize_wu124(w, SER_TAG_STR + len); | 132 | w = serialize_wu124(w, SER_TAG_STR + len); |
133 | w = lj_buf_wmem(w, strdata(str), len); | 133 | w = lj_buf_wmem(w, strdata(str), len); |
134 | } else if (tvisint(o)) { | 134 | } else if (tvisint(o)) { |
135 | uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o); | 135 | uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o); |
136 | w = serialize_more(w, sbuf, 1+4); | 136 | w = serialize_more(w, sbx, 1+4); |
137 | *w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4; | 137 | *w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4; |
138 | } else if (tvisnum(o)) { | 138 | } else if (tvisnum(o)) { |
139 | uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64; | 139 | uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64; |
140 | w = serialize_more(w, sbuf, 1+sizeof(lua_Number)); | 140 | w = serialize_more(w, sbx, 1+sizeof(lua_Number)); |
141 | *w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8; | 141 | *w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8; |
142 | } else if (tvispri(o)) { | 142 | } else if (tvispri(o)) { |
143 | w = serialize_more(w, sbuf, 1); | 143 | w = serialize_more(w, sbx, 1); |
144 | *w++ = (char)(SER_TAG_NIL + ~itype(o)); | 144 | *w++ = (char)(SER_TAG_NIL + ~itype(o)); |
145 | } else if (tvistab(o)) { | 145 | } else if (tvistab(o)) { |
146 | const GCtab *t = tabV(o); | 146 | const GCtab *t = tabV(o); |
147 | uint32_t narray = 0, nhash = 0, one = 2; | 147 | uint32_t narray = 0, nhash = 0, one = 2; |
148 | if (sbuf->depth <= 0) lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DEPTH); | 148 | if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH); |
149 | sbuf->depth--; | 149 | sbx->depth--; |
150 | if (t->asize > 0) { /* Determine max. length of array part. */ | 150 | if (t->asize > 0) { /* Determine max. length of array part. */ |
151 | ptrdiff_t i; | 151 | ptrdiff_t i; |
152 | TValue *array = tvref(t->array); | 152 | TValue *array = tvref(t->array); |
@@ -163,32 +163,32 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o) | |||
163 | nhash += !tvisnil(&node[i].val); | 163 | nhash += !tvisnil(&node[i].val); |
164 | } | 164 | } |
165 | /* Write number of array slots and hash slots. */ | 165 | /* Write number of array slots and hash slots. */ |
166 | w = serialize_more(w, sbuf, 1+2*5); | 166 | w = serialize_more(w, sbx, 1+2*5); |
167 | *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0)); | 167 | *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0)); |
168 | if (narray) w = serialize_wu124(w, narray); | 168 | if (narray) w = serialize_wu124(w, narray); |
169 | if (nhash) w = serialize_wu124(w, nhash); | 169 | if (nhash) w = serialize_wu124(w, nhash); |
170 | if (narray) { /* Write array entries. */ | 170 | if (narray) { /* Write array entries. */ |
171 | cTValue *oa = tvref(t->array) + (one >> 2); | 171 | cTValue *oa = tvref(t->array) + (one >> 2); |
172 | cTValue *oe = tvref(t->array) + narray; | 172 | cTValue *oe = tvref(t->array) + narray; |
173 | while (oa < oe) w = serialize_put(w, sbuf, oa++); | 173 | while (oa < oe) w = serialize_put(w, sbx, oa++); |
174 | } | 174 | } |
175 | if (nhash) { /* Write hash entries. */ | 175 | if (nhash) { /* Write hash entries. */ |
176 | const Node *node = noderef(t->node) + t->hmask; | 176 | const Node *node = noderef(t->node) + t->hmask; |
177 | for (;; node--) | 177 | for (;; node--) |
178 | if (!tvisnil(&node->val)) { | 178 | if (!tvisnil(&node->val)) { |
179 | w = serialize_put(w, sbuf, &node->key); | 179 | w = serialize_put(w, sbx, &node->key); |
180 | w = serialize_put(w, sbuf, &node->val); | 180 | w = serialize_put(w, sbx, &node->val); |
181 | if (--nhash == 0) break; | 181 | if (--nhash == 0) break; |
182 | } | 182 | } |
183 | } | 183 | } |
184 | sbuf->depth++; | 184 | sbx->depth++; |
185 | #if LJ_HASFFI | 185 | #if LJ_HASFFI |
186 | } else if (tviscdata(o)) { | 186 | } else if (tviscdata(o)) { |
187 | CTState *cts = ctype_cts(sbufL(sbuf->sb)); | 187 | CTState *cts = ctype_cts(sbufL(sbx)); |
188 | CType *s = ctype_raw(cts, cdataV(o)->ctypeid); | 188 | CType *s = ctype_raw(cts, cdataV(o)->ctypeid); |
189 | uint8_t *sp = cdataptr(cdataV(o)); | 189 | uint8_t *sp = cdataptr(cdataV(o)); |
190 | if (ctype_isinteger(s->info) && s->size == 8) { | 190 | if (ctype_isinteger(s->info) && s->size == 8) { |
191 | w = serialize_more(w, sbuf, 1+8); | 191 | w = serialize_more(w, sbx, 1+8); |
192 | *w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64; | 192 | *w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64; |
193 | #if LJ_BE | 193 | #if LJ_BE |
194 | { uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); } | 194 | { uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); } |
@@ -197,7 +197,7 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o) | |||
197 | #endif | 197 | #endif |
198 | w += 8; | 198 | w += 8; |
199 | } else if (ctype_iscomplex(s->info) && s->size == 16) { | 199 | } else if (ctype_iscomplex(s->info) && s->size == 16) { |
200 | w = serialize_more(w, sbuf, 1+16); | 200 | w = serialize_more(w, sbx, 1+16); |
201 | *w++ = SER_TAG_COMPLEX; | 201 | *w++ = SER_TAG_COMPLEX; |
202 | #if LJ_BE | 202 | #if LJ_BE |
203 | { /* Only swap the doubles. The re/im order stays the same. */ | 203 | { /* Only swap the doubles. The re/im order stays the same. */ |
@@ -213,8 +213,8 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o) | |||
213 | } | 213 | } |
214 | #endif | 214 | #endif |
215 | } else if (tvislightud(o)) { | 215 | } else if (tvislightud(o)) { |
216 | uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbuf->sb)), o); | 216 | uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbx)), o); |
217 | w = serialize_more(w, sbuf, 1+sizeof(ud)); | 217 | w = serialize_more(w, sbx, 1+sizeof(ud)); |
218 | if (ud == 0) { | 218 | if (ud == 0) { |
219 | *w++ = SER_TAG_NULL; | 219 | *w++ = SER_TAG_NULL; |
220 | } else if (LJ_32 || checku32(ud)) { | 220 | } else if (LJ_32 || checku32(ud)) { |
@@ -237,28 +237,28 @@ static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o) | |||
237 | #if LJ_HASFFI | 237 | #if LJ_HASFFI |
238 | badenc: | 238 | badenc: |
239 | #endif | 239 | #endif |
240 | lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADENC, lj_typename(o)); | 240 | lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADENC, lj_typename(o)); |
241 | } | 241 | } |
242 | return w; | 242 | return w; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* Get serialized object from buffer. */ | 245 | /* Get serialized object from buffer. */ |
246 | static char *serialize_get(char *r, StrBuf *sbuf, TValue *o) | 246 | static char *serialize_get(char *r, SBufExt *sbx, TValue *o) |
247 | { | 247 | { |
248 | char *e = sbuf->sb->e; | 248 | char *w = sbx->w; |
249 | uint32_t tp; | 249 | uint32_t tp; |
250 | r = serialize_ru124(r, e, &tp); if (LJ_UNLIKELY(!r)) goto eob; | 250 | r = serialize_ru124(r, w, &tp); if (LJ_UNLIKELY(!r)) goto eob; |
251 | if (LJ_LIKELY(tp >= SER_TAG_STR)) { | 251 | if (LJ_LIKELY(tp >= SER_TAG_STR)) { |
252 | uint32_t len = tp - SER_TAG_STR; | 252 | uint32_t len = tp - SER_TAG_STR; |
253 | if (LJ_UNLIKELY(len > (uint32_t)(e - r))) goto eob; | 253 | if (LJ_UNLIKELY(len > (uint32_t)(w - r))) goto eob; |
254 | setstrV(sbufL(sbuf->sb), o, lj_str_new(sbufL(sbuf->sb), r, len)); | 254 | setstrV(sbufL(sbx), o, lj_str_new(sbufL(sbx), r, len)); |
255 | r += len; | 255 | r += len; |
256 | } else if (tp == SER_TAG_INT) { | 256 | } else if (tp == SER_TAG_INT) { |
257 | if (LJ_UNLIKELY(r + 4 > e)) goto eob; | 257 | if (LJ_UNLIKELY(r + 4 > w)) goto eob; |
258 | setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r))); | 258 | setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r))); |
259 | r += 4; | 259 | r += 4; |
260 | } else if (tp == SER_TAG_NUM) { | 260 | } else if (tp == SER_TAG_NUM) { |
261 | if (LJ_UNLIKELY(r + 8 > e)) goto eob; | 261 | if (LJ_UNLIKELY(r + 8 > w)) goto eob; |
262 | memcpy(o, r, 8); r += 8; | 262 | memcpy(o, r, 8); r += 8; |
263 | #if LJ_BE | 263 | #if LJ_BE |
264 | o->u64 = lj_bswap64(o->u64); | 264 | o->u64 = lj_bswap64(o->u64); |
@@ -270,34 +270,34 @@ static char *serialize_get(char *r, StrBuf *sbuf, TValue *o) | |||
270 | uint32_t narray = 0, nhash = 0; | 270 | uint32_t narray = 0, nhash = 0; |
271 | GCtab *t; | 271 | GCtab *t; |
272 | if (tp >= SER_TAG_TAB+2) { | 272 | if (tp >= SER_TAG_TAB+2) { |
273 | r = serialize_ru124(r, e, &narray); if (LJ_UNLIKELY(!r)) goto eob; | 273 | r = serialize_ru124(r, w, &narray); if (LJ_UNLIKELY(!r)) goto eob; |
274 | } | 274 | } |
275 | if ((tp & 1)) { | 275 | if ((tp & 1)) { |
276 | r = serialize_ru124(r, e, &nhash); if (LJ_UNLIKELY(!r)) goto eob; | 276 | r = serialize_ru124(r, w, &nhash); if (LJ_UNLIKELY(!r)) goto eob; |
277 | } | 277 | } |
278 | t = lj_tab_new(sbufL(sbuf->sb), narray, hsize2hbits(nhash)); | 278 | t = lj_tab_new(sbufL(sbx), narray, hsize2hbits(nhash)); |
279 | settabV(sbufL(sbuf->sb), o, t); | 279 | settabV(sbufL(sbx), o, t); |
280 | if (narray) { | 280 | if (narray) { |
281 | TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4); | 281 | TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4); |
282 | TValue *oe = tvref(t->array) + narray; | 282 | TValue *oe = tvref(t->array) + narray; |
283 | while (oa < oe) r = serialize_get(r, sbuf, oa++); | 283 | while (oa < oe) r = serialize_get(r, sbx, oa++); |
284 | } | 284 | } |
285 | if (nhash) { | 285 | if (nhash) { |
286 | do { | 286 | do { |
287 | TValue k, *v; | 287 | TValue k, *v; |
288 | r = serialize_get(r, sbuf, &k); | 288 | r = serialize_get(r, sbx, &k); |
289 | v = lj_tab_set(sbufL(sbuf->sb), t, &k); | 289 | v = lj_tab_set(sbufL(sbx), t, &k); |
290 | if (LJ_UNLIKELY(!tvisnil(v))) | 290 | if (LJ_UNLIKELY(!tvisnil(v))) |
291 | lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DUPKEY); | 291 | lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DUPKEY); |
292 | r = serialize_get(r, sbuf, v); | 292 | r = serialize_get(r, sbx, v); |
293 | } while (--nhash); | 293 | } while (--nhash); |
294 | } | 294 | } |
295 | #if LJ_HASFFI | 295 | #if LJ_HASFFI |
296 | } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) { | 296 | } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) { |
297 | uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8; | 297 | uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8; |
298 | GCcdata *cd; | 298 | GCcdata *cd; |
299 | if (LJ_UNLIKELY(r + sz > e)) goto eob; | 299 | if (LJ_UNLIKELY(r + sz > w)) goto eob; |
300 | cd = lj_cdata_new_(sbufL(sbuf->sb), | 300 | cd = lj_cdata_new_(sbufL(sbx), |
301 | tp == SER_TAG_INT64 ? CTID_INT64 : | 301 | tp == SER_TAG_INT64 ? CTID_INT64 : |
302 | tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE, | 302 | tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE, |
303 | sz); | 303 | sz); |
@@ -307,50 +307,50 @@ static char *serialize_get(char *r, StrBuf *sbuf, TValue *o) | |||
307 | if (sz == 16) | 307 | if (sz == 16) |
308 | ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]); | 308 | ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]); |
309 | #endif | 309 | #endif |
310 | setcdataV(sbufL(sbuf->sb), o, cd); | 310 | setcdataV(sbufL(sbx), o, cd); |
311 | #endif | 311 | #endif |
312 | } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) { | 312 | } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) { |
313 | uintptr_t ud = 0; | 313 | uintptr_t ud = 0; |
314 | if (tp == SER_TAG_LIGHTUD32) { | 314 | if (tp == SER_TAG_LIGHTUD32) { |
315 | if (LJ_UNLIKELY(r + 4 > e)) goto eob; | 315 | if (LJ_UNLIKELY(r + 4 > w)) goto eob; |
316 | ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)); | 316 | ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)); |
317 | r += 4; | 317 | r += 4; |
318 | } | 318 | } |
319 | #if LJ_64 | 319 | #if LJ_64 |
320 | else if (tp == SER_TAG_LIGHTUD64) { | 320 | else if (tp == SER_TAG_LIGHTUD64) { |
321 | if (LJ_UNLIKELY(r + 8 > e)) goto eob; | 321 | if (LJ_UNLIKELY(r + 8 > w)) goto eob; |
322 | memcpy(&ud, r, 8); r += 8; | 322 | memcpy(&ud, r, 8); r += 8; |
323 | #if LJ_BE | 323 | #if LJ_BE |
324 | ud = lj_bswap64(ud); | 324 | ud = lj_bswap64(ud); |
325 | #endif | 325 | #endif |
326 | } | 326 | } |
327 | setrawlightudV(o, lj_lightud_intern(sbufL(sbuf->sb), (void *)ud)); | 327 | setrawlightudV(o, lj_lightud_intern(sbufL(sbx), (void *)ud)); |
328 | #else | 328 | #else |
329 | setrawlightudV(o, (void *)ud); | 329 | setrawlightudV(o, (void *)ud); |
330 | #endif | 330 | #endif |
331 | } else { | 331 | } else { |
332 | lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADDEC, tp); | 332 | lj_err_callerv(sbufL(sbx), LJ_ERR_BUFFER_BADDEC, tp); |
333 | } | 333 | } |
334 | return r; | 334 | return r; |
335 | eob: | 335 | eob: |
336 | lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_EOB); | 336 | lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_EOB); |
337 | return NULL; | 337 | return NULL; |
338 | } | 338 | } |
339 | 339 | ||
340 | StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sbuf, cTValue *o) | 340 | SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) |
341 | { | 341 | { |
342 | sbuf->depth = LJ_SERIALIZE_DEPTH; | 342 | sbx->depth = LJ_SERIALIZE_DEPTH; |
343 | sbuf->sb->w = serialize_put(sbuf->sb->w, sbuf, o); | 343 | sbx->w = serialize_put(sbx->w, sbx, o); |
344 | return sbuf; | 344 | return sbx; |
345 | } | 345 | } |
346 | 346 | ||
347 | StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sbuf, TValue *o) | 347 | SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) |
348 | { | 348 | { |
349 | char *r = serialize_get(sbuf->r, sbuf, o); | 349 | char *r = serialize_get(sbx->r, sbx, o); |
350 | if (r != sbuf->sb->w) | 350 | if (r != sbx->w) |
351 | lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_LEFTOV); | 351 | lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_LEFTOV); |
352 | sbuf->r = r; | 352 | sbx->r = r; |
353 | return sbuf; | 353 | return sbx; |
354 | } | 354 | } |
355 | 355 | ||
356 | #endif | 356 | #endif |
diff --git a/src/lj_serialize.h b/src/lj_serialize.h index 95d62f4e..f5617790 100644 --- a/src/lj_serialize.h +++ b/src/lj_serialize.h | |||
@@ -13,8 +13,8 @@ | |||
13 | 13 | ||
14 | #define LJ_SERIALIZE_DEPTH 100 /* Default depth. */ | 14 | #define LJ_SERIALIZE_DEPTH 100 /* Default depth. */ |
15 | 15 | ||
16 | LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sb, cTValue *o); | 16 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); |
17 | LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sb, TValue *o); | 17 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); |
18 | 18 | ||
19 | #endif | 19 | #endif |
20 | 20 | ||