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