One Level Up
Top Level
src/lj_bcread.c - luajit-2.0-src
Functions defined
Macros defined
Source code
- #define lj_bcread_c
- #define LUA_CORE
- #include "lj_obj.h"
- #include "lj_gc.h"
- #include "lj_err.h"
- #include "lj_buf.h"
- #include "lj_str.h"
- #include "lj_tab.h"
- #include "lj_bc.h"
- #if LJ_HASFFI
- #include "lj_ctype.h"
- #include "lj_cdata.h"
- #include "lualib.h"
- #endif
- #include "lj_lex.h"
- #include "lj_bcdump.h"
- #include "lj_state.h"
- #include "lj_strfmt.h"
- #define bcread_flags(ls) ls->level
- #define bcread_swap(ls) \
- ((bcread_flags(ls) & BCDUMP_F_BE) != LJ_BE*BCDUMP_F_BE)
- #define bcread_oldtop(L, ls) restorestack(L, ls->lastline)
- #define bcread_savetop(L, ls, top) \
- ls->lastline = (BCLine)savestack(L, (top))
- static LJ_NOINLINE void bcread_error(LexState *ls, ErrMsg em)
- {
- lua_State *L = ls->L;
- const char *name = ls->chunkarg;
- if (*name == BCDUMP_HEAD1) name = "(binary)";
- else if (*name == '@' || *name == '=') name++;
- lj_strfmt_pushf(L, "%s: %s", name, err2msg(em));
- lj_err_throw(L, LUA_ERRSYNTAX);
- }
- static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
- {
- lua_assert(len != 0);
- if (len > LJ_MAX_BUF || ls->c < 0)
- bcread_error(ls, LJ_ERR_BCBAD);
- do {
- const char *buf;
- size_t sz;
- char *p = sbufB(&ls->sb);
- MSize n = (MSize)(ls->pe - ls->p);
- if (n) {
- if (sbuflen(&ls->sb)) {
- lua_assert(ls->pe == sbufP(&ls->sb));
- if (ls->p != p) memmove(p, ls->p, n);
- } else {
- p = lj_buf_need(&ls->sb, len);
- memcpy(p, ls->p, n);
- }
- ls->p = p;
- ls->pe = p + n;
- }
- setsbufP(&ls->sb, p + n);
- buf = ls->rfunc(ls->L, ls->rdata, &sz);
- if (buf == NULL || sz == 0) {
- if (need) bcread_error(ls, LJ_ERR_BCBAD);
- ls->c = -1;
- break;
- }
- if (n) {
- n += (MSize)sz;
- p = lj_buf_need(&ls->sb, n < len ? len : n);
- memcpy(sbufP(&ls->sb), buf, sz);
- setsbufP(&ls->sb, p + n);
- ls->p = p;
- ls->pe = p + n;
- } else {
- ls->p = buf;
- ls->pe = buf + sz;
- }
- } while (ls->p + len > ls->pe);
- }
- static LJ_AINLINE void bcread_need(LexState *ls, MSize len)
- {
- if (LJ_UNLIKELY(ls->p + len > ls->pe))
- bcread_fill(ls, len, 1);
- }
- static LJ_AINLINE void bcread_want(LexState *ls, MSize len)
- {
- if (LJ_UNLIKELY(ls->p + len > ls->pe))
- bcread_fill(ls, len, 0);
- }
- static LJ_AINLINE uint8_t *bcread_mem(LexState *ls, MSize len)
- {
- uint8_t *p = (uint8_t *)ls->p;
- ls->p += len;
- lua_assert(ls->p <= ls->pe);
- return p;
- }
- static void bcread_block(LexState *ls, void *q, MSize len)
- {
- memcpy(q, bcread_mem(ls, len), len);
- }
- static LJ_AINLINE uint32_t bcread_byte(LexState *ls)
- {
- lua_assert(ls->p < ls->pe);
- return (uint32_t)(uint8_t)*ls->p++;
- }
- static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls)
- {
- uint32_t v = lj_buf_ruleb128(&ls->p);
- lua_assert(ls->p <= ls->pe);
- return v;
- }
- static uint32_t bcread_uleb128_33(LexState *ls)
- {
- const uint8_t *p = (const uint8_t *)ls->p;
- uint32_t v = (*p++ >> 1);
- if (LJ_UNLIKELY(v >= 0x40)) {
- int sh = -1;
- v &= 0x3f;
- do {
- v |= ((*p & 0x7f) << (sh += 7));
- } while (*p++ >= 0x80);
- }
- ls->p = (char *)p;
- lua_assert(ls->p <= ls->pe);
- return v;
- }
- static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg)
- {
- void *lineinfo = (void *)proto_lineinfo(pt);
- bcread_block(ls, lineinfo, sizedbg);
-
- if (bcread_swap(ls) && pt->numline >= 256) {
- MSize i, n = pt->sizebc-1;
- if (pt->numline < 65536) {
- uint16_t *p = (uint16_t *)lineinfo;
- for (i = 0; i < n; i++) p[i] = (uint16_t)((p[i] >> 8)|(p[i] << 8));
- } else {
- uint32_t *p = (uint32_t *)lineinfo;
- for (i = 0; i < n; i++) p[i] = lj_bswap(p[i]);
- }
- }
- }
- static const void *bcread_varinfo(GCproto *pt)
- {
- const uint8_t *p = proto_uvinfo(pt);
- MSize n = pt->sizeuv;
- if (n) while (*p++ || --n) ;
- return p;
- }
- static void bcread_ktabk(LexState *ls, TValue *o)
- {
- MSize tp = bcread_uleb128(ls);
- if (tp >= BCDUMP_KTAB_STR) {
- MSize len = tp - BCDUMP_KTAB_STR;
- const char *p = (const char *)bcread_mem(ls, len);
- setstrV(ls->L, o, lj_str_new(ls->L, p, len));
- } else if (tp == BCDUMP_KTAB_INT) {
- setintV(o, (int32_t)bcread_uleb128(ls));
- } else if (tp == BCDUMP_KTAB_NUM) {
- o->u32.lo = bcread_uleb128(ls);
- o->u32.hi = bcread_uleb128(ls);
- } else {
- lua_assert(tp <= BCDUMP_KTAB_TRUE);
- setpriV(o, ~tp);
- }
- }
- static GCtab *bcread_ktab(LexState *ls)
- {
- MSize narray = bcread_uleb128(ls);
- MSize nhash = bcread_uleb128(ls);
- GCtab *t = lj_tab_new(ls->L, narray, hsize2hbits(nhash));
- if (narray) {
- MSize i;
- TValue *o = tvref(t->array);
- for (i = 0; i < narray; i++, o++)
- bcread_ktabk(ls, o);
- }
- if (nhash) {
- MSize i;
- for (i = 0; i < nhash; i++) {
- TValue key;
- bcread_ktabk(ls, &key);
- lua_assert(!tvisnil(&key));
- bcread_ktabk(ls, lj_tab_set(ls->L, t, &key));
- }
- }
- return t;
- }
- static void bcread_kgc(LexState *ls, GCproto *pt, MSize sizekgc)
- {
- MSize i;
- GCRef *kr = mref(pt->k, GCRef) - (ptrdiff_t)sizekgc;
- for (i = 0; i < sizekgc; i++, kr++) {
- MSize tp = bcread_uleb128(ls);
- if (tp >= BCDUMP_KGC_STR) {
- MSize len = tp - BCDUMP_KGC_STR;
- const char *p = (const char *)bcread_mem(ls, len);
- setgcref(*kr, obj2gco(lj_str_new(ls->L, p, len)));
- } else if (tp == BCDUMP_KGC_TAB) {
- setgcref(*kr, obj2gco(bcread_ktab(ls)));
- #if LJ_HASFFI
- } else if (tp != BCDUMP_KGC_CHILD) {
- CTypeID id = tp == BCDUMP_KGC_COMPLEX ? CTID_COMPLEX_DOUBLE :
- tp == BCDUMP_KGC_I64 ? CTID_INT64 : CTID_UINT64;
- CTSize sz = tp == BCDUMP_KGC_COMPLEX ? 16 : 8;
- GCcdata *cd = lj_cdata_new_(ls->L, id, sz);
- TValue *p = (TValue *)cdataptr(cd);
- setgcref(*kr, obj2gco(cd));
- p[0].u32.lo = bcread_uleb128(ls);
- p[0].u32.hi = bcread_uleb128(ls);
- if (tp == BCDUMP_KGC_COMPLEX) {
- p[1].u32.lo = bcread_uleb128(ls);
- p[1].u32.hi = bcread_uleb128(ls);
- }
- #endif
- } else {
- lua_State *L = ls->L;
- lua_assert(tp == BCDUMP_KGC_CHILD);
- if (L->top <= bcread_oldtop(L, ls))
- bcread_error(ls, LJ_ERR_BCBAD);
- L->top--;
- setgcref(*kr, obj2gco(protoV(L->top)));
- }
- }
- }
- static void bcread_knum(LexState *ls, GCproto *pt, MSize sizekn)
- {
- MSize i;
- TValue *o = mref(pt->k, TValue);
- for (i = 0; i < sizekn; i++, o++) {
- int isnum = (ls->p[0] & 1);
- uint32_t lo = bcread_uleb128_33(ls);
- if (isnum) {
- o->u32.lo = lo;
- o->u32.hi = bcread_uleb128(ls);
- } else {
- setintV(o, lo);
- }
- }
- }
- static void bcread_bytecode(LexState *ls, GCproto *pt, MSize sizebc)
- {
- BCIns *bc = proto_bc(pt);
- bc[0] = BCINS_AD((pt->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF,
- pt->framesize, 0);
- bcread_block(ls, bc+1, (sizebc-1)*(MSize)sizeof(BCIns));
-
- if (bcread_swap(ls)) {
- MSize i;
- for (i = 1; i < sizebc; i++) bc[i] = lj_bswap(bc[i]);
- }
- }
- static void bcread_uv(LexState *ls, GCproto *pt, MSize sizeuv)
- {
- if (sizeuv) {
- uint16_t *uv = proto_uv(pt);
- bcread_block(ls, uv, sizeuv*2);
-
- if (bcread_swap(ls)) {
- MSize i;
- for (i = 0; i < sizeuv; i++)
- uv[i] = (uint16_t)((uv[i] >> 8)|(uv[i] << 8));
- }
- }
- }
- GCproto *lj_bcread_proto(LexState *ls)
- {
- GCproto *pt;
- MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept;
- MSize ofsk, ofsuv, ofsdbg;
- MSize sizedbg = 0;
- BCLine firstline = 0, numline = 0;
-
- flags = bcread_byte(ls);
- numparams = bcread_byte(ls);
- framesize = bcread_byte(ls);
- sizeuv = bcread_byte(ls);
- sizekgc = bcread_uleb128(ls);
- sizekn = bcread_uleb128(ls);
- sizebc = bcread_uleb128(ls) + 1;
- if (!(bcread_flags(ls) & BCDUMP_F_STRIP)) {
- sizedbg = bcread_uleb128(ls);
- if (sizedbg) {
- firstline = bcread_uleb128(ls);
- numline = bcread_uleb128(ls);
- }
- }
-
- sizept = (MSize)sizeof(GCproto) +
- sizebc*(MSize)sizeof(BCIns) +
- sizekgc*(MSize)sizeof(GCRef);
- sizept = (sizept + (MSize)sizeof(TValue)-1) & ~((MSize)sizeof(TValue)-1);
- ofsk = sizept; sizept += sizekn*(MSize)sizeof(TValue);
- ofsuv = sizept; sizept += ((sizeuv+1)&~1)*2;
- ofsdbg = sizept; sizept += sizedbg;
-
- pt = (GCproto *)lj_mem_newgco(ls->L, (MSize)sizept);
- pt->gct = ~LJ_TPROTO;
- pt->numparams = (uint8_t)numparams;
- pt->framesize = (uint8_t)framesize;
- pt->sizebc = sizebc;
- setmref(pt->k, (char *)pt + ofsk);
- setmref(pt->uv, (char *)pt + ofsuv);
- pt->sizekgc = 0;
- pt->sizekn = sizekn;
- pt->sizept = sizept;
- pt->sizeuv = (uint8_t)sizeuv;
- pt->flags = (uint8_t)flags;
- pt->trace = 0;
- setgcref(pt->chunkname, obj2gco(ls->chunkname));
-
- *(uint32_t *)((char *)pt + ofsk - sizeof(GCRef)*(sizekgc+1)) = 0;
-
- bcread_bytecode(ls, pt, sizebc);
- bcread_uv(ls, pt, sizeuv);
-
- bcread_kgc(ls, pt, sizekgc);
- pt->sizekgc = sizekgc;
- bcread_knum(ls, pt, sizekn);
-
- pt->firstline = firstline;
- pt->numline = numline;
- if (sizedbg) {
- MSize sizeli = (sizebc-1) << (numline < 256 ? 0 : numline < 65536 ? 1 : 2);
- setmref(pt->lineinfo, (char *)pt + ofsdbg);
- setmref(pt->uvinfo, (char *)pt + ofsdbg + sizeli);
- bcread_dbg(ls, pt, sizedbg);
- setmref(pt->varinfo, bcread_varinfo(pt));
- } else {
- setmref(pt->lineinfo, NULL);
- setmref(pt->uvinfo, NULL);
- setmref(pt->varinfo, NULL);
- }
- return pt;
- }
- static int bcread_header(LexState *ls)
- {
- uint32_t flags;
- bcread_want(ls, 3+5+5);
- if (bcread_byte(ls) != BCDUMP_HEAD2 ||
- bcread_byte(ls) != BCDUMP_HEAD3 ||
- bcread_byte(ls) != BCDUMP_VERSION) return 0;
- bcread_flags(ls) = flags = bcread_uleb128(ls);
- if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0;
- if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0;
- if ((flags & BCDUMP_F_FFI)) {
- #if LJ_HASFFI
- lua_State *L = ls->L;
- if (!ctype_ctsG(G(L))) {
- ptrdiff_t oldtop = savestack(L, L->top);
- luaopen_ffi(L);
- L->top = restorestack(L, oldtop);
- }
- #else
- return 0;
- #endif
- }
- if ((flags & BCDUMP_F_STRIP)) {
- ls->chunkname = lj_str_newz(ls->L, ls->chunkarg);
- } else {
- MSize len = bcread_uleb128(ls);
- bcread_need(ls, len);
- ls->chunkname = lj_str_new(ls->L, (const char *)bcread_mem(ls, len), len);
- }
- return 1;
- }
- GCproto *lj_bcread(LexState *ls)
- {
- lua_State *L = ls->L;
- lua_assert(ls->c == BCDUMP_HEAD1);
- bcread_savetop(L, ls, L->top);
- lj_buf_reset(&ls->sb);
-
- if (!bcread_header(ls))
- bcread_error(ls, LJ_ERR_BCFMT);
- for (;;) {
- GCproto *pt;
- MSize len;
- const char *startp;
-
- if (ls->p < ls->pe && ls->p[0] == 0) {
- ls->p++;
- break;
- }
- bcread_want(ls, 5);
- len = bcread_uleb128(ls);
- if (!len) break;
- bcread_need(ls, len);
- startp = ls->p;
- pt = lj_bcread_proto(ls);
- if (ls->p != startp + len)
- bcread_error(ls, LJ_ERR_BCBAD);
- setprotoV(L, L->top, pt);
- incr_top(L);
- }
- if ((int32_t)(2*(uint32_t)(ls->pe - ls->p)) > 0 ||
- L->top-1 != bcread_oldtop(L, ls))
- bcread_error(ls, LJ_ERR_BCBAD);
-
- L->top--;
- return protoV(L->top);
- }
One Level Up
Top Level