static int setjitmode(lua_State *L, int mode) { int idx = 0; if (L->base == L->top || tvisnil(L->base)) { /* jit.on/off/flush([nil]) */ mode |= LUAJIT_MODE_ENGINE; } else { /* jit.on/off/flush(func|proto, nil|true|false) */ if (tvisfunc(L->base) || tvisproto(L->base)) idx = 1; else if (!tvistrue(L->base)) /* jit.on/off/flush(true, nil|true|false) */ goto err; if (L->base+1 < L->top && tvisbool(L->base+1)) mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC; else mode |= LUAJIT_MODE_FUNC; } if (luaJIT_setmode(L, idx, mode) != 1) { err: #if LJ_HASJIT lj_err_arg(L, 1, LJ_ERR_NOLFUNC); #else lj_err_caller(L, LJ_ERR_NOJIT); #endif } return 0; }
static IOFileUD *io_tofile(lua_State *L) { IOFileUD *iof = io_tofilep(L); if (iof->fp == NULL) lj_err_caller(L, LJ_ERR_IOCLFL); return iof; }
static FILE *io_stdfile(lua_State *L, ptrdiff_t id) { IOFileUD *iof = IOSTDF_IOF(L, id); if (iof->fp == NULL) lj_err_caller(L, LJ_ERR_IOSTDCL); return iof->fp; }
/* Convert bitfield to TValue. */ int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp) { CTInfo info = s->info; CTSize pos, bsz; uint32_t val; lua_assert(ctype_isbitfield(info)); /* NYI: packed bitfields may cause misaligned reads. */ switch (ctype_bitcsz(info)) { case 4: val = *(uint32_t *)sp; break; case 2: val = *(uint16_t *)sp; break; case 1: val = *(uint8_t *)sp; break; default: lua_assert(0); val = 0; break; } /* Check if a packed bitfield crosses a container boundary. */ pos = ctype_bitpos(info); bsz = ctype_bitbsz(info); lua_assert(pos < 8*ctype_bitcsz(info)); lua_assert(bsz > 0 && bsz <= 8*ctype_bitcsz(info)); if (pos + bsz > 8*ctype_bitcsz(info)) lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); if (!(info & CTF_BOOL)) { CTSize shift = 32 - bsz; if (!(info & CTF_UNSIGNED)) { setintV(o, (int32_t)(val << (shift-pos)) >> shift); } else {
static int io_file_lines(lua_State *L) { int n = (int)(L->top - L->base); if (n > LJ_MAX_UPVAL) lj_err_caller(L, LJ_ERR_UNPACK); lua_pushcclosure(L, io_file_iter, n); return 1; }
static int io_file_iter(lua_State *L) { GCfunc *fn = curr_func(L); IOFileUD *iof = uddata(udataV(&fn->c.upvalue[0])); int n = fn->c.nupvalues - 1; if (iof->fp == NULL) lj_err_caller(L, LJ_ERR_IOCLFL); L->top = L->base; if (n) { /* Copy upvalues with options to stack. */ if (n > LUAI_MAXCSTACK) lj_err_caller(L, LJ_ERR_STKOV); lj_state_checkstack(L, (MSize)n); memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue)); L->top += n; } n = io_file_read(L, iof->fp, 0); if (ferror(iof->fp)) lj_err_callermsg(L, strVdata(L->top-2)); if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) { io_file_close(L, iof); /* Return values are ignored. */ return 0; } return n; }
/* Index C data by a TValue. Return CType and pointer. */ CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, uint8_t **pp, CTInfo *qual) { uint8_t *p = (uint8_t *)cdataptr(cd); CType *ct = ctype_get(cts, cd->ctypeid); ptrdiff_t idx; /* Resolve reference for cdata object. */ if (ctype_isref(ct->info)) { lua_assert(ct->size == CTSIZE_PTR); p = *(uint8_t **)p; ct = ctype_child(cts, ct); } collect_attrib: /* Skip attributes and collect qualifiers. */ while (ctype_isattrib(ct->info)) { if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; ct = ctype_child(cts, ct); } lua_assert(!ctype_isref(ct->info)); /* Interning rejects refs to refs. */ if (tvisint(key)) { idx = (ptrdiff_t)intV(key); goto integer_key; } else if (tvisnum(key)) { /* Numeric key. */ #ifdef _MSC_VER /* Workaround for MSVC bug. */ volatile #endif lua_Number n = numV(key); idx = LJ_64 ? (ptrdiff_t)n : (ptrdiff_t)lj_num2int(n); integer_key: if (ctype_ispointer(ct->info)) { CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */ if (sz == CTSIZE_INVALID) lj_err_caller(cts->L, LJ_ERR_FFI_INVSIZE); if (ctype_isptr(ct->info)) { p = (uint8_t *)cdata_getptr(p, ct->size); } else if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) { if ((ct->info & CTF_COMPLEX)) idx &= 1; *qual |= CTF_CONST; /* Valarray elements are constant. */ } *pp = p + idx*(int32_t)sz; return ct; } } else if (tviscdata(key)) { /* Integer cdata key. */ GCcdata *cdk = cdataV(key); CType *ctk = ctype_raw(cts, cdk->ctypeid); if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk); if (ctype_isinteger(ctk->info)) { lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ctk, (uint8_t *)&idx, cdataptr(cdk), 0); goto integer_key; } } else if (tvisstr(key)) { /* String key. */ GCstr *name = strV(key); if (ctype_isstruct(ct->info)) { CTSize ofs; CType *fct = lj_ctype_getfieldq(cts, ct, name, &ofs, qual); if (fct) { *pp = p + ofs; return fct; } } else if (ctype_iscomplex(ct->info)) { if (name->len == 2) { *qual |= CTF_CONST; /* Complex fields are constant. */ if (strdata(name)[0] == 'r' && strdata(name)[1] == 'e') { *pp = p; return ct; } else if (strdata(name)[0] == 'i' && strdata(name)[1] == 'm') { *pp = p + (ct->size >> 1); return ct; } } } else if (cd->ctypeid == CTID_CTYPEID) {
/* Public API function: control the JIT engine. */ int luaJIT_setmode(lua_State *L, int idx, int mode) { global_State *g = G(L); int mm = mode & LUAJIT_MODE_MASK; lj_trace_abort(g); /* Abort recording on any state change. */ /* Avoid pulling the rug from under our own feet. */ if ((g->hookmask & HOOK_GC)) lj_err_caller(L, LJ_ERR_NOGCMM); switch (mm) { #if LJ_HASJIT case LUAJIT_MODE_ENGINE: if ((mode & LUAJIT_MODE_FLUSH)) { lj_trace_flushall(L); } else { if (!(mode & LUAJIT_MODE_ON)) G2J(g)->flags &= ~(uint32_t)JIT_F_ON; #if LJ_TARGET_X86ORX64 else if ((G2J(g)->flags & JIT_F_SSE2)) G2J(g)->flags |= (uint32_t)JIT_F_ON; else return 0; /* Don't turn on JIT compiler without SSE2 support. */ #else else G2J(g)->flags |= (uint32_t)JIT_F_ON; #endif lj_dispatch_update(g); } break; case LUAJIT_MODE_FUNC: case LUAJIT_MODE_ALLFUNC: case LUAJIT_MODE_ALLSUBFUNC: { cTValue *tv = idx == 0 ? frame_prev(L->base-1) : idx > 0 ? L->base + (idx-1) : L->top + idx; GCproto *pt; if ((idx == 0 || tvisfunc(tv)) && isluafunc(&gcval(tv)->fn)) pt = funcproto(&gcval(tv)->fn); /* Cannot use funcV() for frame slot. */ else if (tvisproto(tv)) pt = protoV(tv); else return 0; /* Failed. */ if (mm != LUAJIT_MODE_ALLSUBFUNC) setptmode(g, pt, mode); if (mm != LUAJIT_MODE_FUNC) setptmode_all(g, pt, mode); break; } case LUAJIT_MODE_TRACE: if (!(mode & LUAJIT_MODE_FLUSH)) return 0; /* Failed. */ lj_trace_flush(G2J(g), idx); break; #else case LUAJIT_MODE_ENGINE: case LUAJIT_MODE_FUNC: case LUAJIT_MODE_ALLFUNC: case LUAJIT_MODE_ALLSUBFUNC: UNUSED(idx); if ((mode & LUAJIT_MODE_ON)) return 0; /* Failed. */ break; #endif case LUAJIT_MODE_WRAPCFUNC: if ((mode & LUAJIT_MODE_ON)) { if (idx != 0) { cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; if (tvislightud(tv)) g->wrapf = (lua_CFunction)lightudV(tv); else return 0; /* Failed. */ } else { return 0; /* Failed. */ } g->bc_cfunc_ext = BCINS_AD(BC_FUNCCW, 0, 0); } else { g->bc_cfunc_ext = BCINS_AD(BC_FUNCC, 0, 0); } break; default: return 0; /* Failed. */ }