diff options
Diffstat (limited to 'src/lj_bcwrite.c')
-rw-r--r-- | src/lj_bcwrite.c | 245 |
1 files changed, 112 insertions, 133 deletions
diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index d836497e..2c70ff47 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #include "lj_obj.h" | 9 | #include "lj_obj.h" |
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_str.h" | 11 | #include "lj_buf.h" |
12 | #include "lj_bc.h" | 12 | #include "lj_bc.h" |
13 | #if LJ_HASFFI | 13 | #if LJ_HASFFI |
14 | #include "lj_ctype.h" | 14 | #include "lj_ctype.h" |
@@ -17,99 +17,67 @@ | |||
17 | #include "lj_dispatch.h" | 17 | #include "lj_dispatch.h" |
18 | #include "lj_jit.h" | 18 | #include "lj_jit.h" |
19 | #endif | 19 | #endif |
20 | #include "lj_strfmt.h" | ||
20 | #include "lj_bcdump.h" | 21 | #include "lj_bcdump.h" |
21 | #include "lj_vm.h" | 22 | #include "lj_vm.h" |
22 | 23 | ||
23 | /* Context for bytecode writer. */ | 24 | /* Context for bytecode writer. */ |
24 | typedef struct BCWriteCtx { | 25 | typedef struct BCWriteCtx { |
25 | SBuf sb; /* Output buffer. */ | 26 | SBuf sb; /* Output buffer. */ |
26 | lua_State *L; /* Lua state. */ | ||
27 | GCproto *pt; /* Root prototype. */ | 27 | GCproto *pt; /* Root prototype. */ |
28 | lua_Writer wfunc; /* Writer callback. */ | 28 | lua_Writer wfunc; /* Writer callback. */ |
29 | void *wdata; /* Writer callback data. */ | 29 | void *wdata; /* Writer callback data. */ |
30 | int strip; /* Strip debug info. */ | 30 | int strip; /* Strip debug info. */ |
31 | int status; /* Status from writer callback. */ | 31 | int status; /* Status from writer callback. */ |
32 | #ifdef LUA_USE_ASSERT | ||
33 | global_State *g; | ||
34 | #endif | ||
32 | } BCWriteCtx; | 35 | } BCWriteCtx; |
33 | 36 | ||
34 | /* -- Output buffer handling ---------------------------------------------- */ | 37 | #ifdef LUA_USE_ASSERT |
35 | 38 | #define lj_assertBCW(c, ...) lj_assertG_(ctx->g, (c), __VA_ARGS__) | |
36 | /* Resize buffer if needed. */ | 39 | #else |
37 | static LJ_NOINLINE void bcwrite_resize(BCWriteCtx *ctx, MSize len) | 40 | #define lj_assertBCW(c, ...) ((void)ctx) |
38 | { | 41 | #endif |
39 | MSize sz = ctx->sb.sz * 2; | ||
40 | while (ctx->sb.n + len > sz) sz = sz * 2; | ||
41 | lj_str_resizebuf(ctx->L, &ctx->sb, sz); | ||
42 | } | ||
43 | |||
44 | /* Need a certain amount of buffer space. */ | ||
45 | static LJ_AINLINE void bcwrite_need(BCWriteCtx *ctx, MSize len) | ||
46 | { | ||
47 | if (LJ_UNLIKELY(ctx->sb.n + len > ctx->sb.sz)) | ||
48 | bcwrite_resize(ctx, len); | ||
49 | } | ||
50 | |||
51 | /* Add memory block to buffer. */ | ||
52 | static void bcwrite_block(BCWriteCtx *ctx, const void *p, MSize len) | ||
53 | { | ||
54 | uint8_t *q = (uint8_t *)(ctx->sb.buf + ctx->sb.n); | ||
55 | MSize i; | ||
56 | ctx->sb.n += len; | ||
57 | for (i = 0; i < len; i++) q[i] = ((uint8_t *)p)[i]; | ||
58 | } | ||
59 | |||
60 | /* Add byte to buffer. */ | ||
61 | static LJ_AINLINE void bcwrite_byte(BCWriteCtx *ctx, uint8_t b) | ||
62 | { | ||
63 | ctx->sb.buf[ctx->sb.n++] = b; | ||
64 | } | ||
65 | |||
66 | /* Add ULEB128 value to buffer. */ | ||
67 | static void bcwrite_uleb128(BCWriteCtx *ctx, uint32_t v) | ||
68 | { | ||
69 | MSize n = ctx->sb.n; | ||
70 | uint8_t *p = (uint8_t *)ctx->sb.buf; | ||
71 | for (; v >= 0x80; v >>= 7) | ||
72 | p[n++] = (uint8_t)((v & 0x7f) | 0x80); | ||
73 | p[n++] = (uint8_t)v; | ||
74 | ctx->sb.n = n; | ||
75 | } | ||
76 | 42 | ||
77 | /* -- Bytecode writer ----------------------------------------------------- */ | 43 | /* -- Bytecode writer ----------------------------------------------------- */ |
78 | 44 | ||
79 | /* Write a single constant key/value of a template table. */ | 45 | /* Write a single constant key/value of a template table. */ |
80 | static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) | 46 | static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) |
81 | { | 47 | { |
82 | bcwrite_need(ctx, 1+10); | 48 | char *p = lj_buf_more(&ctx->sb, 1+10); |
83 | if (tvisstr(o)) { | 49 | if (tvisstr(o)) { |
84 | const GCstr *str = strV(o); | 50 | const GCstr *str = strV(o); |
85 | MSize len = str->len; | 51 | MSize len = str->len; |
86 | bcwrite_need(ctx, 5+len); | 52 | p = lj_buf_more(&ctx->sb, 5+len); |
87 | bcwrite_uleb128(ctx, BCDUMP_KTAB_STR+len); | 53 | p = lj_strfmt_wuleb128(p, BCDUMP_KTAB_STR+len); |
88 | bcwrite_block(ctx, strdata(str), len); | 54 | p = lj_buf_wmem(p, strdata(str), len); |
89 | } else if (tvisint(o)) { | 55 | } else if (tvisint(o)) { |
90 | bcwrite_byte(ctx, BCDUMP_KTAB_INT); | 56 | *p++ = BCDUMP_KTAB_INT; |
91 | bcwrite_uleb128(ctx, intV(o)); | 57 | p = lj_strfmt_wuleb128(p, intV(o)); |
92 | } else if (tvisnum(o)) { | 58 | } else if (tvisnum(o)) { |
93 | if (!LJ_DUALNUM && narrow) { /* Narrow number constants to integers. */ | 59 | if (!LJ_DUALNUM && narrow) { /* Narrow number constants to integers. */ |
94 | lua_Number num = numV(o); | 60 | lua_Number num = numV(o); |
95 | int32_t k = lj_num2int(num); | 61 | int32_t k = lj_num2int(num); |
96 | if (num == (lua_Number)k) { /* -0 is never a constant. */ | 62 | if (num == (lua_Number)k) { /* -0 is never a constant. */ |
97 | bcwrite_byte(ctx, BCDUMP_KTAB_INT); | 63 | *p++ = BCDUMP_KTAB_INT; |
98 | bcwrite_uleb128(ctx, k); | 64 | p = lj_strfmt_wuleb128(p, k); |
65 | ctx->sb.w = p; | ||
99 | return; | 66 | return; |
100 | } | 67 | } |
101 | } | 68 | } |
102 | bcwrite_byte(ctx, BCDUMP_KTAB_NUM); | 69 | *p++ = BCDUMP_KTAB_NUM; |
103 | bcwrite_uleb128(ctx, o->u32.lo); | 70 | p = lj_strfmt_wuleb128(p, o->u32.lo); |
104 | bcwrite_uleb128(ctx, o->u32.hi); | 71 | p = lj_strfmt_wuleb128(p, o->u32.hi); |
105 | } else { | 72 | } else { |
106 | lua_assert(tvispri(o)); | 73 | lj_assertBCW(tvispri(o), "unhandled type %d", itype(o)); |
107 | bcwrite_byte(ctx, BCDUMP_KTAB_NIL+~itype(o)); | 74 | *p++ = BCDUMP_KTAB_NIL+~itype(o); |
108 | } | 75 | } |
76 | ctx->sb.w = p; | ||
109 | } | 77 | } |
110 | 78 | ||
111 | /* Write a template table. */ | 79 | /* Write a template table. */ |
112 | static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t) | 80 | static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) |
113 | { | 81 | { |
114 | MSize narray = 0, nhash = 0; | 82 | MSize narray = 0, nhash = 0; |
115 | if (t->asize > 0) { /* Determine max. length of array part. */ | 83 | if (t->asize > 0) { /* Determine max. length of array part. */ |
@@ -127,8 +95,9 @@ static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t) | |||
127 | nhash += !tvisnil(&node[i].val); | 95 | nhash += !tvisnil(&node[i].val); |
128 | } | 96 | } |
129 | /* Write number of array slots and hash slots. */ | 97 | /* Write number of array slots and hash slots. */ |
130 | bcwrite_uleb128(ctx, narray); | 98 | p = lj_strfmt_wuleb128(p, narray); |
131 | bcwrite_uleb128(ctx, nhash); | 99 | p = lj_strfmt_wuleb128(p, nhash); |
100 | ctx->sb.w = p; | ||
132 | if (narray) { /* Write array entries (may contain nil). */ | 101 | if (narray) { /* Write array entries (may contain nil). */ |
133 | MSize i; | 102 | MSize i; |
134 | TValue *o = tvref(t->array); | 103 | TValue *o = tvref(t->array); |
@@ -155,12 +124,13 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt) | |||
155 | for (i = 0; i < sizekgc; i++, kr++) { | 124 | for (i = 0; i < sizekgc; i++, kr++) { |
156 | GCobj *o = gcref(*kr); | 125 | GCobj *o = gcref(*kr); |
157 | MSize tp, need = 1; | 126 | MSize tp, need = 1; |
127 | char *p; | ||
158 | /* Determine constant type and needed size. */ | 128 | /* Determine constant type and needed size. */ |
159 | if (o->gch.gct == ~LJ_TSTR) { | 129 | if (o->gch.gct == ~LJ_TSTR) { |
160 | tp = BCDUMP_KGC_STR + gco2str(o)->len; | 130 | tp = BCDUMP_KGC_STR + gco2str(o)->len; |
161 | need = 5+gco2str(o)->len; | 131 | need = 5+gco2str(o)->len; |
162 | } else if (o->gch.gct == ~LJ_TPROTO) { | 132 | } else if (o->gch.gct == ~LJ_TPROTO) { |
163 | lua_assert((pt->flags & PROTO_CHILD)); | 133 | lj_assertBCW((pt->flags & PROTO_CHILD), "prototype has unexpected child"); |
164 | tp = BCDUMP_KGC_CHILD; | 134 | tp = BCDUMP_KGC_CHILD; |
165 | #if LJ_HASFFI | 135 | #if LJ_HASFFI |
166 | } else if (o->gch.gct == ~LJ_TCDATA) { | 136 | } else if (o->gch.gct == ~LJ_TCDATA) { |
@@ -171,34 +141,38 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt) | |||
171 | } else if (id == CTID_UINT64) { | 141 | } else if (id == CTID_UINT64) { |
172 | tp = BCDUMP_KGC_U64; | 142 | tp = BCDUMP_KGC_U64; |
173 | } else { | 143 | } else { |
174 | lua_assert(id == CTID_COMPLEX_DOUBLE); | 144 | lj_assertBCW(id == CTID_COMPLEX_DOUBLE, |
145 | "bad cdata constant CTID %d", id); | ||
175 | tp = BCDUMP_KGC_COMPLEX; | 146 | tp = BCDUMP_KGC_COMPLEX; |
176 | } | 147 | } |
177 | #endif | 148 | #endif |
178 | } else { | 149 | } else { |
179 | lua_assert(o->gch.gct == ~LJ_TTAB); | 150 | lj_assertBCW(o->gch.gct == ~LJ_TTAB, |
151 | "bad constant GC type %d", o->gch.gct); | ||
180 | tp = BCDUMP_KGC_TAB; | 152 | tp = BCDUMP_KGC_TAB; |
181 | need = 1+2*5; | 153 | need = 1+2*5; |
182 | } | 154 | } |
183 | /* Write constant type. */ | 155 | /* Write constant type. */ |
184 | bcwrite_need(ctx, need); | 156 | p = lj_buf_more(&ctx->sb, need); |
185 | bcwrite_uleb128(ctx, tp); | 157 | p = lj_strfmt_wuleb128(p, tp); |
186 | /* Write constant data (if any). */ | 158 | /* Write constant data (if any). */ |
187 | if (tp >= BCDUMP_KGC_STR) { | 159 | if (tp >= BCDUMP_KGC_STR) { |
188 | bcwrite_block(ctx, strdata(gco2str(o)), gco2str(o)->len); | 160 | p = lj_buf_wmem(p, strdata(gco2str(o)), gco2str(o)->len); |
189 | } else if (tp == BCDUMP_KGC_TAB) { | 161 | } else if (tp == BCDUMP_KGC_TAB) { |
190 | bcwrite_ktab(ctx, gco2tab(o)); | 162 | bcwrite_ktab(ctx, p, gco2tab(o)); |
163 | continue; | ||
191 | #if LJ_HASFFI | 164 | #if LJ_HASFFI |
192 | } else if (tp != BCDUMP_KGC_CHILD) { | 165 | } else if (tp != BCDUMP_KGC_CHILD) { |
193 | cTValue *p = (TValue *)cdataptr(gco2cd(o)); | 166 | cTValue *q = (TValue *)cdataptr(gco2cd(o)); |
194 | bcwrite_uleb128(ctx, p[0].u32.lo); | 167 | p = lj_strfmt_wuleb128(p, q[0].u32.lo); |
195 | bcwrite_uleb128(ctx, p[0].u32.hi); | 168 | p = lj_strfmt_wuleb128(p, q[0].u32.hi); |
196 | if (tp == BCDUMP_KGC_COMPLEX) { | 169 | if (tp == BCDUMP_KGC_COMPLEX) { |
197 | bcwrite_uleb128(ctx, p[1].u32.lo); | 170 | p = lj_strfmt_wuleb128(p, q[1].u32.lo); |
198 | bcwrite_uleb128(ctx, p[1].u32.hi); | 171 | p = lj_strfmt_wuleb128(p, q[1].u32.hi); |
199 | } | 172 | } |
200 | #endif | 173 | #endif |
201 | } | 174 | } |
175 | ctx->sb.w = p; | ||
202 | } | 176 | } |
203 | } | 177 | } |
204 | 178 | ||
@@ -207,7 +181,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt) | |||
207 | { | 181 | { |
208 | MSize i, sizekn = pt->sizekn; | 182 | MSize i, sizekn = pt->sizekn; |
209 | cTValue *o = mref(pt->k, TValue); | 183 | cTValue *o = mref(pt->k, TValue); |
210 | bcwrite_need(ctx, 10*sizekn); | 184 | char *p = lj_buf_more(&ctx->sb, 10*sizekn); |
211 | for (i = 0; i < sizekn; i++, o++) { | 185 | for (i = 0; i < sizekn; i++, o++) { |
212 | int32_t k; | 186 | int32_t k; |
213 | if (tvisint(o)) { | 187 | if (tvisint(o)) { |
@@ -220,55 +194,55 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt) | |||
220 | k = lj_num2int(num); | 194 | k = lj_num2int(num); |
221 | if (num == (lua_Number)k) { /* -0 is never a constant. */ | 195 | if (num == (lua_Number)k) { /* -0 is never a constant. */ |
222 | save_int: | 196 | save_int: |
223 | bcwrite_uleb128(ctx, 2*(uint32_t)k | ((uint32_t)k & 0x80000000u)); | 197 | p = lj_strfmt_wuleb128(p, 2*(uint32_t)k | ((uint32_t)k&0x80000000u)); |
224 | if (k < 0) { | 198 | if (k < 0) |
225 | char *p = &ctx->sb.buf[ctx->sb.n-1]; | 199 | p[-1] = (p[-1] & 7) | ((k>>27) & 0x18); |
226 | *p = (*p & 7) | ((k>>27) & 0x18); | ||
227 | } | ||
228 | continue; | 200 | continue; |
229 | } | 201 | } |
230 | } | 202 | } |
231 | bcwrite_uleb128(ctx, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u))); | 203 | p = lj_strfmt_wuleb128(p, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u))); |
232 | if (o->u32.lo >= 0x80000000u) { | 204 | if (o->u32.lo >= 0x80000000u) |
233 | char *p = &ctx->sb.buf[ctx->sb.n-1]; | 205 | p[-1] = (p[-1] & 7) | ((o->u32.lo>>27) & 0x18); |
234 | *p = (*p & 7) | ((o->u32.lo>>27) & 0x18); | 206 | p = lj_strfmt_wuleb128(p, o->u32.hi); |
235 | } | ||
236 | bcwrite_uleb128(ctx, o->u32.hi); | ||
237 | } | 207 | } |
238 | } | 208 | } |
209 | ctx->sb.w = p; | ||
239 | } | 210 | } |
240 | 211 | ||
241 | /* Write bytecode instructions. */ | 212 | /* Write bytecode instructions. */ |
242 | static void bcwrite_bytecode(BCWriteCtx *ctx, GCproto *pt) | 213 | static char *bcwrite_bytecode(BCWriteCtx *ctx, char *p, GCproto *pt) |
243 | { | 214 | { |
244 | MSize nbc = pt->sizebc-1; /* Omit the [JI]FUNC* header. */ | 215 | MSize nbc = pt->sizebc-1; /* Omit the [JI]FUNC* header. */ |
245 | #if LJ_HASJIT | 216 | #if LJ_HASJIT |
246 | uint8_t *p = (uint8_t *)&ctx->sb.buf[ctx->sb.n]; | 217 | uint8_t *q = (uint8_t *)p; |
247 | #endif | 218 | #endif |
248 | bcwrite_block(ctx, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns)); | 219 | p = lj_buf_wmem(p, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns)); |
220 | UNUSED(ctx); | ||
249 | #if LJ_HASJIT | 221 | #if LJ_HASJIT |
250 | /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */ | 222 | /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */ |
251 | if ((pt->flags & PROTO_ILOOP) || pt->trace) { | 223 | if ((pt->flags & PROTO_ILOOP) || pt->trace) { |
252 | jit_State *J = L2J(ctx->L); | 224 | jit_State *J = L2J(sbufL(&ctx->sb)); |
253 | MSize i; | 225 | MSize i; |
254 | for (i = 0; i < nbc; i++, p += sizeof(BCIns)) { | 226 | for (i = 0; i < nbc; i++, q += sizeof(BCIns)) { |
255 | BCOp op = (BCOp)p[LJ_ENDIAN_SELECT(0, 3)]; | 227 | BCOp op = (BCOp)q[LJ_ENDIAN_SELECT(0, 3)]; |
256 | if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP || | 228 | if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP || |
257 | op == BC_JFORI) { | 229 | op == BC_JFORI) { |
258 | p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL); | 230 | q[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL); |
259 | } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) { | 231 | } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) { |
260 | BCReg rd = p[LJ_ENDIAN_SELECT(2, 1)] + (p[LJ_ENDIAN_SELECT(3, 0)] << 8); | 232 | BCReg rd = q[LJ_ENDIAN_SELECT(2, 1)] + (q[LJ_ENDIAN_SELECT(3, 0)] << 8); |
261 | memcpy(p, &traceref(J, rd)->startins, 4); | 233 | memcpy(q, &traceref(J, rd)->startins, 4); |
262 | } | 234 | } |
263 | } | 235 | } |
264 | } | 236 | } |
265 | #endif | 237 | #endif |
238 | return p; | ||
266 | } | 239 | } |
267 | 240 | ||
268 | /* Write prototype. */ | 241 | /* Write prototype. */ |
269 | static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) | 242 | static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) |
270 | { | 243 | { |
271 | MSize sizedbg = 0; | 244 | MSize sizedbg = 0; |
245 | char *p; | ||
272 | 246 | ||
273 | /* Recursively write children of prototype. */ | 247 | /* Recursively write children of prototype. */ |
274 | if ((pt->flags & PROTO_CHILD)) { | 248 | if ((pt->flags & PROTO_CHILD)) { |
@@ -282,31 +256,32 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) | |||
282 | } | 256 | } |
283 | 257 | ||
284 | /* Start writing the prototype info to a buffer. */ | 258 | /* Start writing the prototype info to a buffer. */ |
285 | lj_str_resetbuf(&ctx->sb); | 259 | p = lj_buf_need(&ctx->sb, |
286 | ctx->sb.n = 5; /* Leave room for final size. */ | 260 | 5+4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2); |
287 | bcwrite_need(ctx, 4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2); | 261 | p += 5; /* Leave room for final size. */ |
288 | 262 | ||
289 | /* Write prototype header. */ | 263 | /* Write prototype header. */ |
290 | bcwrite_byte(ctx, (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI))); | 264 | *p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI)); |
291 | bcwrite_byte(ctx, pt->numparams); | 265 | *p++ = pt->numparams; |
292 | bcwrite_byte(ctx, pt->framesize); | 266 | *p++ = pt->framesize; |
293 | bcwrite_byte(ctx, pt->sizeuv); | 267 | *p++ = pt->sizeuv; |
294 | bcwrite_uleb128(ctx, pt->sizekgc); | 268 | p = lj_strfmt_wuleb128(p, pt->sizekgc); |
295 | bcwrite_uleb128(ctx, pt->sizekn); | 269 | p = lj_strfmt_wuleb128(p, pt->sizekn); |
296 | bcwrite_uleb128(ctx, pt->sizebc-1); | 270 | p = lj_strfmt_wuleb128(p, pt->sizebc-1); |
297 | if (!ctx->strip) { | 271 | if (!ctx->strip) { |
298 | if (proto_lineinfo(pt)) | 272 | if (proto_lineinfo(pt)) |
299 | sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); | 273 | sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); |
300 | bcwrite_uleb128(ctx, sizedbg); | 274 | p = lj_strfmt_wuleb128(p, sizedbg); |
301 | if (sizedbg) { | 275 | if (sizedbg) { |
302 | bcwrite_uleb128(ctx, pt->firstline); | 276 | p = lj_strfmt_wuleb128(p, pt->firstline); |
303 | bcwrite_uleb128(ctx, pt->numline); | 277 | p = lj_strfmt_wuleb128(p, pt->numline); |
304 | } | 278 | } |
305 | } | 279 | } |
306 | 280 | ||
307 | /* Write bytecode instructions and upvalue refs. */ | 281 | /* Write bytecode instructions and upvalue refs. */ |
308 | bcwrite_bytecode(ctx, pt); | 282 | p = bcwrite_bytecode(ctx, p, pt); |
309 | bcwrite_block(ctx, proto_uv(pt), pt->sizeuv*2); | 283 | p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2); |
284 | ctx->sb.w = p; | ||
310 | 285 | ||
311 | /* Write constants. */ | 286 | /* Write constants. */ |
312 | bcwrite_kgc(ctx, pt); | 287 | bcwrite_kgc(ctx, pt); |
@@ -314,18 +289,19 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) | |||
314 | 289 | ||
315 | /* Write debug info, if not stripped. */ | 290 | /* Write debug info, if not stripped. */ |
316 | if (sizedbg) { | 291 | if (sizedbg) { |
317 | bcwrite_need(ctx, sizedbg); | 292 | p = lj_buf_more(&ctx->sb, sizedbg); |
318 | bcwrite_block(ctx, proto_lineinfo(pt), sizedbg); | 293 | p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); |
294 | ctx->sb.w = p; | ||
319 | } | 295 | } |
320 | 296 | ||
321 | /* Pass buffer to writer function. */ | 297 | /* Pass buffer to writer function. */ |
322 | if (ctx->status == 0) { | 298 | if (ctx->status == 0) { |
323 | MSize n = ctx->sb.n - 5; | 299 | MSize n = sbuflen(&ctx->sb) - 5; |
324 | MSize nn = (lj_fls(n)+8)*9 >> 6; | 300 | MSize nn = (lj_fls(n)+8)*9 >> 6; |
325 | ctx->sb.n = 5 - nn; | 301 | char *q = ctx->sb.b + (5 - nn); |
326 | bcwrite_uleb128(ctx, n); /* Fill in final size. */ | 302 | p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */ |
327 | lua_assert(ctx->sb.n == 5); | 303 | lj_assertBCW(p == ctx->sb.b + 5, "bad ULEB128 write"); |
328 | ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf+5-nn, nn+n, ctx->wdata); | 304 | ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata); |
329 | } | 305 | } |
330 | } | 306 | } |
331 | 307 | ||
@@ -335,20 +311,21 @@ static void bcwrite_header(BCWriteCtx *ctx) | |||
335 | GCstr *chunkname = proto_chunkname(ctx->pt); | 311 | GCstr *chunkname = proto_chunkname(ctx->pt); |
336 | const char *name = strdata(chunkname); | 312 | const char *name = strdata(chunkname); |
337 | MSize len = chunkname->len; | 313 | MSize len = chunkname->len; |
338 | lj_str_resetbuf(&ctx->sb); | 314 | char *p = lj_buf_need(&ctx->sb, 5+5+len); |
339 | bcwrite_need(ctx, 5+5+len); | 315 | *p++ = BCDUMP_HEAD1; |
340 | bcwrite_byte(ctx, BCDUMP_HEAD1); | 316 | *p++ = BCDUMP_HEAD2; |
341 | bcwrite_byte(ctx, BCDUMP_HEAD2); | 317 | *p++ = BCDUMP_HEAD3; |
342 | bcwrite_byte(ctx, BCDUMP_HEAD3); | 318 | *p++ = BCDUMP_VERSION; |
343 | bcwrite_byte(ctx, BCDUMP_VERSION); | 319 | *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + |
344 | bcwrite_byte(ctx, (ctx->strip ? BCDUMP_F_STRIP : 0) + | 320 | LJ_BE*BCDUMP_F_BE + |
345 | (LJ_BE ? BCDUMP_F_BE : 0) + | 321 | ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) + |
346 | ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0)); | 322 | LJ_FR2*BCDUMP_F_FR2; |
347 | if (!ctx->strip) { | 323 | if (!ctx->strip) { |
348 | bcwrite_uleb128(ctx, len); | 324 | p = lj_strfmt_wuleb128(p, len); |
349 | bcwrite_block(ctx, name, len); | 325 | p = lj_buf_wmem(p, name, len); |
350 | } | 326 | } |
351 | ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf, ctx->sb.n, ctx->wdata); | 327 | ctx->status = ctx->wfunc(sbufL(&ctx->sb), ctx->sb.b, |
328 | (MSize)(p - ctx->sb.b), ctx->wdata); | ||
352 | } | 329 | } |
353 | 330 | ||
354 | /* Write footer of bytecode dump. */ | 331 | /* Write footer of bytecode dump. */ |
@@ -356,7 +333,7 @@ static void bcwrite_footer(BCWriteCtx *ctx) | |||
356 | { | 333 | { |
357 | if (ctx->status == 0) { | 334 | if (ctx->status == 0) { |
358 | uint8_t zero = 0; | 335 | uint8_t zero = 0; |
359 | ctx->status = ctx->wfunc(ctx->L, &zero, 1, ctx->wdata); | 336 | ctx->status = ctx->wfunc(sbufL(&ctx->sb), &zero, 1, ctx->wdata); |
360 | } | 337 | } |
361 | } | 338 | } |
362 | 339 | ||
@@ -364,8 +341,8 @@ static void bcwrite_footer(BCWriteCtx *ctx) | |||
364 | static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud) | 341 | static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud) |
365 | { | 342 | { |
366 | BCWriteCtx *ctx = (BCWriteCtx *)ud; | 343 | BCWriteCtx *ctx = (BCWriteCtx *)ud; |
367 | UNUSED(dummy); | 344 | UNUSED(L); UNUSED(dummy); |
368 | lj_str_resizebuf(L, &ctx->sb, 1024); /* Avoids resize for most prototypes. */ | 345 | lj_buf_need(&ctx->sb, 1024); /* Avoids resize for most prototypes. */ |
369 | bcwrite_header(ctx); | 346 | bcwrite_header(ctx); |
370 | bcwrite_proto(ctx, ctx->pt); | 347 | bcwrite_proto(ctx, ctx->pt); |
371 | bcwrite_footer(ctx); | 348 | bcwrite_footer(ctx); |
@@ -378,16 +355,18 @@ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, | |||
378 | { | 355 | { |
379 | BCWriteCtx ctx; | 356 | BCWriteCtx ctx; |
380 | int status; | 357 | int status; |
381 | ctx.L = L; | ||
382 | ctx.pt = pt; | 358 | ctx.pt = pt; |
383 | ctx.wfunc = writer; | 359 | ctx.wfunc = writer; |
384 | ctx.wdata = data; | 360 | ctx.wdata = data; |
385 | ctx.strip = strip; | 361 | ctx.strip = strip; |
386 | ctx.status = 0; | 362 | ctx.status = 0; |
387 | lj_str_initbuf(&ctx.sb); | 363 | #ifdef LUA_USE_ASSERT |
364 | ctx.g = G(L); | ||
365 | #endif | ||
366 | lj_buf_init(L, &ctx.sb); | ||
388 | status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); | 367 | status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); |
389 | if (status == 0) status = ctx.status; | 368 | if (status == 0) status = ctx.status; |
390 | lj_str_freebuf(G(ctx.L), &ctx.sb); | 369 | lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb); |
391 | return status; | 370 | return status; |
392 | } | 371 | } |
393 | 372 | ||