diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h index e96c8a53..45f8f8cb 100644 --- a/src/host/buildvm_libbc.h +++ b/src/host/buildvm_libbc.h @@ -3,6 +3,20 @@ static const int libbc_endian = 0; static const uint8_t libbc_code[] = { +#if LJ_FR2 +0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, +0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3, +16,0,5,0,21,1,0,0,76,1,2,0,0,2,10,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3, +0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,8,5,0,59,9,5,0,66,6,3,2,10,6,0,0,88,7,1, +128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,11,0,0,0,16,16,0,12,0,16,1,9,0,43,2, +0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,9,5,0,18,10,6,0,66,7,3,2,10,7, +0,0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12, +0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128, +8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14, +0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2, +0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4, +2,0,76,3,2,0,75,0,1,0,0,2,0 +#else 0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, 0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3, 16,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3, @@ -15,6 +29,7 @@ static const uint8_t libbc_code[] = { 0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2, 0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4, 2,0,76,3,2,0,75,0,1,0,0,2,0 +#endif }; static const struct { const char *name; int ofs; } libbc_map[] = { diff --git a/src/lib_base.c b/src/lib_base.c index 713bdae5..6bb71d54 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -87,10 +87,11 @@ static int ffh_pairs(lua_State *L, MMS mm) cTValue *mo = lj_meta_lookup(L, o, mm); if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) { L->top = o+1; /* Only keep one argument. */ - copyTV(L, L->base-1, mo); /* Replace callable. */ + copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ return FFH_TAILCALL; } else { if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE); + if (LJ_FR2) { copyTV(L, o-1, o); o--; } setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1))); if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0); return FFH_RES(3); @@ -132,7 +133,7 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.) lj_err_caller(L, LJ_ERR_PROTMT); setgcref(t->metatable, obj2gco(mt)); if (mt) { lj_gc_objbarriert(L, t, mt); } - settabV(L, L->base-1, t); + settabV(L, L->base-1-LJ_FR2, t); return FFH_RES(1); } @@ -145,6 +146,7 @@ LJLIB_CF(getfenv) LJLIB_REC(.) o = lj_debug_frame(L, level, &level); if (o == NULL) lj_err_arg(L, 1, LJ_ERR_INVLVL); + if (LJ_FR2) o--; } fn = &gcval(o)->fn; settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env)); @@ -166,6 +168,7 @@ LJLIB_CF(setfenv) o = lj_debug_frame(L, level, &level); if (o == NULL) lj_err_arg(L, 1, LJ_ERR_INVLVL); + if (LJ_FR2) o--; } fn = &gcval(o)->fn; if (!isluafunc(fn)) @@ -258,7 +261,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) if (base == 10) { TValue *o = lj_lib_checkany(L, 1); if (lj_strscan_numberobj(o)) { - copyTV(L, L->base-1, o); + copyTV(L, L->base-1-LJ_FR2, o); return FFH_RES(1); } #if LJ_HASFFI @@ -271,11 +274,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { int32_t i; lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); - setintV(L->base-1, i); + setintV(L->base-1-LJ_FR2, i); return FFH_RES(1); } lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), - (uint8_t *)&(L->base-1)->n, o, 0); + (uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0); return FFH_RES(1); } } @@ -291,14 +294,14 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) while (lj_char_isspace((unsigned char)(*ep))) ep++; if (*ep == '\0') { if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u)) - setintV(L->base-1, (int32_t)ul); + setintV(L->base-1-LJ_FR2, (int32_t)ul); else - setnumV(L->base-1, (lua_Number)ul); + setnumV(L->base-1-LJ_FR2, (lua_Number)ul); return FFH_RES(1); } } } - setnilV(L->base-1); + setnilV(L->base-1-LJ_FR2); return FFH_RES(1); } @@ -308,11 +311,11 @@ LJLIB_ASM(tostring) LJLIB_REC(.) cTValue *mo; L->top = o+1; /* Only keep one argument. */ if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { - copyTV(L, L->base-1, mo); /* Replace callable. */ + copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */ return FFH_TAILCALL; } lj_gc_check(L); - setstrV(L, L->base-1, lj_strfmt_obj(L, L->base)); + setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base)); return FFH_RES(1); } @@ -535,7 +538,7 @@ LJLIB_CF(coroutine_status) if (co == L) s = "running"; else if (co->status == LUA_YIELD) s = "suspended"; else if (co->status != 0) s = "dead"; - else if (co->base > tvref(co->stack)+1) s = "normal"; + else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal"; else if (co->top == co->base) s = "dead"; else s = "suspended"; lua_pushstring(L, s); @@ -577,8 +580,8 @@ static int ffh_resume(lua_State *L, lua_State *co, int wrap) (co->status == 0 && co->top == co->base)) { ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD; if (wrap) lj_err_caller(L, em); - setboolV(L->base-1, 0); - setstrV(L, L->base, lj_err_str(L, em)); + setboolV(L->base-1-LJ_FR2, 0); + setstrV(L, L->base-LJ_FR2, lj_err_str(L, em)); return FFH_RES(2); } lj_state_growstack(co, (MSize)(L->top - L->base)); diff --git a/src/lib_bit.c b/src/lib_bit.c index ffdc29c1..25731900 100644 --- a/src/lib_bit.c +++ b/src/lib_bit.c @@ -33,7 +33,7 @@ static int bit_result64(lua_State *L, CTypeID id, uint64_t x) { GCcdata *cd = lj_cdata_new_(L, id, 8); *(uint64_t *)cdataptr(cd) = x; - setcdataV(L, L->base-1, cd); + setcdataV(L, L->base-1-LJ_FR2, cd); return FFH_RES(1); } #else @@ -56,7 +56,7 @@ LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) { #if LJ_HASFFI CTypeID id = 0; - setintV(L->base-1, (int32_t)lj_carith_check64(L, 1, &id)); + setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id)); return FFH_RES(1); #else lj_lib_checknumber(L, 1); diff --git a/src/lib_ffi.c b/src/lib_ffi.c index bc2339ce..d64f2167 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -138,7 +138,7 @@ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm) } } copyTV(L, base, L->top); - tv = L->top-1; + tv = L->top-1-LJ_FR2; } return lj_meta_tailcall(L, tv); } diff --git a/src/lib_math.c b/src/lib_math.c index 87ec2883..225630d0 100644 --- a/src/lib_math.c +++ b/src/lib_math.c @@ -57,7 +57,7 @@ LJLIB_ASM(math_log) LJLIB_REC(math_log) #else x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y); #endif - setnumV(L->base-1, x*y); /* Do NOT join the expression to x / y. */ + setnumV(L->base-1-LJ_FR2, x*y); /* Do NOT join the expression to x / y. */ return FFH_RES(1); } return FFH_RETRY; diff --git a/src/lib_string.c b/src/lib_string.c index 6ca7a76b..6cab0a19 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -58,7 +58,7 @@ LJLIB_ASM(string_byte) LJLIB_REC(string_range 0) lj_state_checkstack(L, (MSize)n); p = (const unsigned char *)strdata(s) + start; for (i = 0; i < n; i++) - setintV(L->base + i-1, p[i]); + setintV(L->base + i-1-LJ_FR2, p[i]); return FFH_RES(n); } @@ -72,7 +72,7 @@ LJLIB_ASM(string_char) LJLIB_REC(.) lj_err_arg(L, i, LJ_ERR_BADVAL); buf[i-1] = (char)k; } - setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)nargs)); + setstrV(L, L->base-1-LJ_FR2, lj_str_new(L, buf, (size_t)nargs)); return FFH_RES(1); } diff --git a/src/lj_api.c b/src/lj_api.c index 4a7809bc..6ad09b9d 100644 --- a/src/lj_api.c +++ b/src/lj_api.c @@ -284,8 +284,8 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2) } else { L->top = base+2; lj_vm_call(L, base, 1+1); - L->top -= 2; - return tvistruecond(L->top+1); + L->top -= 2+LJ_FR2; + return tvistruecond(L->top+1+LJ_FR2); } } } @@ -307,8 +307,8 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2) } else { L->top = base+2; lj_vm_call(L, base, 1+1); - L->top -= 2; - return tvistruecond(L->top+1); + L->top -= 2+LJ_FR2; + return tvistruecond(L->top+1+LJ_FR2); } } } @@ -704,8 +704,8 @@ LUA_API void lua_concat(lua_State *L, int n) n -= (int)(L->top - top); L->top = top+2; lj_vm_call(L, top, 1+1); - L->top--; - copyTV(L, L->top-1, L->top); + L->top -= 1+LJ_FR2; + copyTV(L, L->top-1, L->top+LJ_FR2); } while (--n > 0); } else if (n == 0) { /* Push empty string. */ setstrV(L, L->top, &G(L)->strempty); @@ -724,8 +724,8 @@ LUA_API void lua_gettable(lua_State *L, int idx) if (v == NULL) { L->top += 2; lj_vm_call(L, L->top-2, 1+1); - L->top -= 2; - v = L->top+1; + L->top -= 2+LJ_FR2; + v = L->top+1+LJ_FR2; } copyTV(L, L->top-1, v); } @@ -740,8 +740,8 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k) if (v == NULL) { L->top += 2; lj_vm_call(L, L->top-2, 1+1); - L->top -= 2; - v = L->top+1; + L->top -= 2+LJ_FR2; + v = L->top+1+LJ_FR2; } copyTV(L, L->top, v); incr_top(L); @@ -882,13 +882,14 @@ LUA_API void lua_settable(lua_State *L, int idx) o = lj_meta_tset(L, t, L->top-2); if (o) { /* NOBARRIER: lj_meta_tset ensures the table is not black. */ - copyTV(L, o, L->top-1); L->top -= 2; + copyTV(L, o, L->top+1); } else { - L->top += 3; - copyTV(L, L->top-1, L->top-6); - lj_vm_call(L, L->top-3, 0+1); - L->top -= 3; + TValue *base = L->top; + copyTV(L, base+2, base-3-LJ_FR2); + L->top = base+3; + lj_vm_call(L, base, 0+1); + L->top -= 3+LJ_FR2; } } @@ -902,14 +903,14 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k) setstrV(L, &key, lj_str_newz(L, k)); o = lj_meta_tset(L, t, &key); if (o) { - L->top--; /* NOBARRIER: lj_meta_tset ensures the table is not black. */ - copyTV(L, o, L->top); + copyTV(L, o, --L->top); } else { - L->top += 3; - copyTV(L, L->top-1, L->top-6); - lj_vm_call(L, L->top-3, 0+1); - L->top -= 2; + TValue *base = L->top; + copyTV(L, base+2, base-3-LJ_FR2); + L->top = base+3; + lj_vm_call(L, base, 0+1); + L->top -= 2+LJ_FR2; } } @@ -1016,11 +1017,24 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n) /* -- Calls --------------------------------------------------------------- */ +#if LJ_FR2 +static TValue *api_call_base(lua_State *L, int nargs) +{ + TValue *o = L->top, *base = o - nargs; + L->top = o+1; + for (; o > base; o--) copyTV(L, o, o-1); + setnilV(o); + return o+1; +} +#else +#define api_call_base(L, nargs) (L->top - (nargs)) +#endif + LUA_API void lua_call(lua_State *L, int nargs, int nresults) { api_check(L, L->status == 0 || L->status == LUA_ERRERR); api_checknelems(L, nargs+1); - lj_vm_call(L, L->top - nargs, nresults+1); + lj_vm_call(L, api_call_base(L, nargs), nresults+1); } LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) @@ -1038,7 +1052,7 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) api_checkvalidindex(L, o); ef = savestack(L, o); } - status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef); + status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef); if (status) hook_restore(g, oldh); return status; } @@ -1046,12 +1060,14 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) { GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); + TValue *top = L->top; fn->c.f = func; - setfuncV(L, L->top, fn); - setlightudV(L->top+1, checklightudptr(L, ud)); + setfuncV(L, top++, fn); + if (LJ_FR2) setnilV(top++); + setlightudV(top++, checklightudptr(L, ud)); cframe_nres(L->cframe) = 1+0; /* Zero results. */ - L->top += 2; - return L->top-1; /* Now call the newly allocated C function. */ + L->top = top; + return top-1; /* Now call the newly allocated C function. */ } LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) @@ -1068,10 +1084,11 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) { if (luaL_getmetafield(L, idx, field)) { - TValue *base = L->top--; - copyTV(L, base, index2adr(L, idx)); - L->top = base+1; - lj_vm_call(L, base, 1+1); + TValue *top = L->top--; + if (LJ_FR2) setnilV(top++); + copyTV(L, top++, index2adr(L, idx)); + L->top = top; + lj_vm_call(L, top-1, 1+1); return 1; } return 0; @@ -1098,12 +1115,14 @@ LUA_API int lua_yield(lua_State *L, int nresults) } else { /* Yield from hook: add a pseudo-frame. */ TValue *top = L->top; hook_leave(g); - top->u64 = cframe_multres(cf); - setcont(top+1, lj_cont_hook); - setframe_pc(top+1, cframe_pc(cf)-1); - setframe_gc(top+2, obj2gco(L), LJ_TTHREAD); - setframe_ftsz(top+2, ((char *)(top+3)-(char *)L->base)+FRAME_CONT); - L->top = L->base = top+3; + (top++)->u64 = cframe_multres(cf); + setcont(top, lj_cont_hook); + if (LJ_FR2) top++; + setframe_pc(top, cframe_pc(cf)-1); + if (LJ_FR2) top++; + setframe_gc(top, obj2gco(L), LJ_TTHREAD); + setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT); + L->top = L->base = top+1; #if LJ_TARGET_X64 lj_err_throw(L, LUA_YIELD); #else @@ -1120,7 +1139,9 @@ LUA_API int lua_yield(lua_State *L, int nresults) LUA_API int lua_resume(lua_State *L, int nargs) { if (L->cframe == NULL && L->status <= LUA_YIELD) - return lj_vm_resume(L, L->top - nargs, 0, 0); + return lj_vm_resume(L, + L->status == 0 ? api_call_base(L, nargs) : L->top - nargs, + 0, 0); L->top = L->base; setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); incr_top(L); diff --git a/src/lj_arch.h b/src/lj_arch.h index 36b38886..8f3796fc 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h @@ -365,8 +365,11 @@ #endif #endif +/* 2-slot frame info. */ +#define LJ_FR2 0 + /* Disable or enable the JIT compiler. */ -#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) +#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) || LJ_FR2 #define LJ_HASJIT 0 #else #define LJ_HASJIT 1 diff --git a/src/lj_asm.c b/src/lj_asm.c index e740e8a8..6002392c 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1913,7 +1913,7 @@ static void asm_tail_link(ASMState *as) mres = (int32_t)(snap->nslots - baseslot); switch (bc_op(*pc)) { case BC_CALLM: case BC_CALLMT: - mres -= (int32_t)(1 + bc_a(*pc) + bc_c(*pc)); break; + mres -= (int32_t)(1 + LJ_FR2 + bc_a(*pc) + bc_c(*pc)); break; case BC_RETM: mres -= (int32_t)(bc_a(*pc) + bc_d(*pc)); break; case BC_TSETM: mres -= (int32_t)bc_a(*pc); break; default: if (bc_op(*pc) < BC_FUNCF) mres = 0; break; diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h index 8339367b..f8915cfb 100644 --- a/src/lj_asm_arm.h +++ b/src/lj_asm_arm.h @@ -481,7 +481,7 @@ static void asm_retf(ASMState *as, IRIns *ir) { Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); void *pc = ir_kptr(IR(ir->op2)); - int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); + int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1)); as->topslot -= (BCReg)delta; if ((int32_t)as->topslot < 0) as->topslot = 0; irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index bc521596..346e0254 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h @@ -372,7 +372,7 @@ static void asm_retf(ASMState *as, IRIns *ir) { Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); void *pc = ir_kptr(IR(ir->op2)); - int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); + int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1)); as->topslot -= (BCReg)delta; if ((int32_t)as->topslot < 0) as->topslot = 0; irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 815d9058..6fc8dfb7 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h @@ -361,7 +361,7 @@ static void asm_retf(ASMState *as, IRIns *ir) { Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); void *pc = ir_kptr(IR(ir->op2)); - int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); + int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1)); as->topslot -= (BCReg)delta; if ((int32_t)as->topslot < 0) as->topslot = 0; irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index bd97764f..c4c7300d 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h @@ -643,7 +643,7 @@ static void asm_retf(ASMState *as, IRIns *ir) { Reg base = ra_alloc1(as, REF_BASE, RSET_GPR); void *pc = ir_kptr(IR(ir->op2)); - int32_t delta = 1+bc_a(*((const BCIns *)pc - 1)); + int32_t delta = 1+LJ_FR2+bc_a(*((const BCIns *)pc - 1)); as->topslot -= (BCReg)delta; if ((int32_t)as->topslot < 0) as->topslot = 0; irt_setmark(IR(REF_BASE)->t); /* Children must not coalesce with BASE reg. */ diff --git a/src/lj_bcdump.h b/src/lj_bcdump.h index 940ed147..ba6edfcc 100644 --- a/src/lj_bcdump.h +++ b/src/lj_bcdump.h @@ -42,8 +42,9 @@ #define BCDUMP_F_BE 0x01 #define BCDUMP_F_STRIP 0x02 #define BCDUMP_F_FFI 0x04 +#define BCDUMP_F_FR2 0x08 -#define BCDUMP_F_KNOWN (BCDUMP_F_FFI*2-1) +#define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1) /* Type codes for the GC constants of a prototype. Plus length for strings. */ enum { diff --git a/src/lj_bcread.c b/src/lj_bcread.c index cea20e90..898f029c 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -394,6 +394,7 @@ static int bcread_header(LexState *ls) 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; diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index a70735ca..cc51d0b2 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -309,8 +309,9 @@ static void bcwrite_header(BCWriteCtx *ctx) *p++ = BCDUMP_HEAD3; *p++ = BCDUMP_VERSION; *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + - (LJ_BE ? BCDUMP_F_BE : 0) + - ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0); + LJ_BE*BCDUMP_F_BE + + ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) + + LJ_FR2*BCDUMP_F_FR2; if (!ctx->strip) { p = lj_strfmt_wuleb128(p, len); p = lj_buf_wmem(p, name, len); diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c index 5fe63a76..60735ade 100644 --- a/src/lj_ccallback.c +++ b/src/lj_ccallback.c @@ -422,7 +422,7 @@ static void callback_conv_args(CTState *cts, lua_State *L) if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) { ct = ctype_get(cts, id); - rid = ctype_cid(ct->info); + rid = ctype_cid(ct->info); /* Return type. x86: +(spadj<<16). */ fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot)); fntp = LJ_TFUNC; } else { /* Must set up frame first, before throwing the error. */ @@ -431,9 +431,16 @@ static void callback_conv_args(CTState *cts, lua_State *L) fn = (GCfunc *)L; fntp = LJ_TTHREAD; } - o->u32.lo = LJ_CONT_FFI_CALLBACK; /* Continuation returns from callback. */ - o->u32.hi = rid; /* Return type. x86: +(spadj<<16). */ - o++; + /* Continuation returns from callback. */ + if (LJ_FR2) { + (o++)->u64 = LJ_CONT_FFI_CALLBACK; + (o++)->u64 = rid; + o++; + } else { + o->u32.lo = LJ_CONT_FFI_CALLBACK; + o->u32.hi = rid; + o++; + } setframe_gc(o, obj2gco(fn), fntp); setframe_ftsz(o, ((char *)(o+1) - (char *)L->base) + FRAME_CONT); L->top = L->base = ++o; @@ -486,8 +493,13 @@ static void callback_conv_args(CTState *cts, lua_State *L) L->top = o; #if LJ_TARGET_X86 /* Store stack adjustment for returns from non-cdecl callbacks. */ - if (ctype_cconv(ct->info) != CTCC_CDECL) + if (ctype_cconv(ct->info) != CTCC_CDECL) { +#if LJ_FR2 + (L->base-3)->u64 |= (nsp << (16+2)); +#else (L->base-2)->u32.hi |= (nsp << (16+2)); +#endif + } #endif while (gcsteps-- > 0) lj_gc_check(L); @@ -496,7 +508,11 @@ static void callback_conv_args(CTState *cts, lua_State *L) /* Convert Lua object to callback result. */ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o) { +#if LJ_FR2 + CType *ctr = ctype_raw(cts, (uint16_t)(L->base-3)->u64); +#else CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi); +#endif #if LJ_TARGET_X86 cts->cb.gpr[2] = 0; #endif @@ -565,7 +581,7 @@ void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o) } callback_conv_result(cts, L, o); /* Finally drop C frame and continuation frame. */ - L->top -= 2; + L->top -= 2+2*LJ_FR2; L->base = obase; L->cframe = cframe_prev(L->cframe); cts->cb.slot = 0; /* Blacklist C function that called the callback. */ diff --git a/src/lj_crecord.c b/src/lj_crecord.c index eb37597a..10334cec 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -1123,7 +1123,7 @@ static void crec_snap_caller(jit_State *J) ptrdiff_t delta; if (!frame_islua(base-1) || J->framedepth <= 0) lj_trace_err(J, LJ_TRERR_NYICALL); - J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); + J->pc = frame_pc(base-1); delta = 1+LJ_FR2+bc_a(J->pc[-1]); L->top = base; L->base = base - delta; J->base[-1] = TREF_FALSE; J->base -= delta; J->baseslot -= (BCReg)delta; diff --git a/src/lj_debug.c b/src/lj_debug.c index 1b794753..e9117b31 100644 --- a/src/lj_debug.c +++ b/src/lj_debug.c @@ -24,7 +24,7 @@ /* Get frame corresponding to a level. */ cTValue *lj_debug_frame(lua_State *L, int level, int *size) { - cTValue *frame, *nextframe, *bot = tvref(L->stack); + cTValue *frame, *nextframe, *bot = tvref(L->stack)+LJ_FR2; /* Traverse frames backwards. */ for (nextframe = frame = L->base-1; frame > bot; ) { if (frame_gc(frame) == obj2gco(L)) @@ -184,7 +184,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar, TValue *nextframe = size ? frame + size : NULL; GCfunc *fn = frame_func(frame); BCPos pc = debug_framepc(L, fn, nextframe); - if (!nextframe) nextframe = L->top; + if (!nextframe) nextframe = L->top+LJ_FR2; if ((int)slot1 < 0) { /* Negative slot number is for varargs. */ if (pc != NO_BCPOS) { GCproto *pt = funcproto(fn); @@ -194,7 +194,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar, nextframe = frame; frame = frame_prevd(frame); } - if (frame + slot1 < nextframe) { + if (frame + slot1+LJ_FR2 < nextframe) { *name = "(*vararg)"; return frame+slot1; } @@ -205,7 +205,7 @@ static TValue *debug_localname(lua_State *L, const lua_Debug *ar, if (pc != NO_BCPOS && (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL) ; - else if (slot1 > 0 && frame + slot1 < nextframe) + else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe) *name = "(*temporary)"; return frame+slot1; } @@ -268,7 +268,7 @@ restart: *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins)))); if (ip > proto_bc(pt)) { BCIns insp = ip[-1]; - if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 && + if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 && bc_d(insp) == bc_b(ins)) return "method"; } @@ -290,7 +290,7 @@ const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name) cTValue *pframe; GCfunc *fn; BCPos pc; - if (frame <= tvref(L->stack)) + if (frame <= tvref(L->stack)+LJ_FR2) return NULL; if (frame_isvarg(frame)) frame = frame_prevd(frame); diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index ea196ef2..8ce587a3 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c @@ -393,7 +393,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) if (bc_op(ins) == BC_UCLO) ins = pc[bc_j(ins)]; switch (bc_op(ins)) { - case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1; + case BC_CALLM: case BC_CALLMT: return bc_a(ins) + bc_c(ins) + nres-1+1+LJ_FR2; case BC_RETM: return bc_a(ins) + bc_d(ins) + nres-1; case BC_TSETM: return bc_a(ins) + nres-1; default: return pt->framesize; diff --git a/src/lj_err.c b/src/lj_err.c index a824ee66..5be938e4 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -106,7 +106,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) return cf; } } - if (frame <= tvref(L->stack)) + if (frame <= tvref(L->stack)+LJ_FR2) break; switch (frame_typep(frame)) { case FRAME_LUA: /* Lua frame. */ @@ -171,7 +171,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) } /* No C frame. */ if (errcode) { - L->base = tvref(L->stack)+1; + L->base = tvref(L->stack)+1+LJ_FR2; L->cframe = NULL; unwindstack(L, L->base); if (G(L)->panic) @@ -494,7 +494,7 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) /* Find error function for runtime errors. Requires an extra stack traversal. */ static ptrdiff_t finderrfunc(lua_State *L) { - cTValue *frame = L->base-1, *bot = tvref(L->stack); + cTValue *frame = L->base-1, *bot = tvref(L->stack)+LJ_FR2; void *cf = L->cframe; while (frame > bot && cf) { while (cframe_nres(cframe_raw(cf)) < 0) { /* cframe without frame? */ @@ -530,8 +530,8 @@ static ptrdiff_t finderrfunc(lua_State *L) break; case FRAME_PCALL: case FRAME_PCALLH: - if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue))) /* xpcall? */ - return savestack(L, frame-1); /* Point to xpcall's errorfunc. */ + if (frame_func(frame_prevd(frame))->c.ffid == FF_xpcall) + return savestack(L, frame_prevd(frame)+1); /* xpcall's errorfunc. */ return 0; default: lua_assert(0); @@ -554,8 +554,9 @@ LJ_NOINLINE void lj_err_run(lua_State *L) lj_err_throw(L, LUA_ERRERR); } L->status = LUA_ERRERR; - copyTV(L, top, top-1); + copyTV(L, top+LJ_FR2, top-1); copyTV(L, top-1, errfunc); + if (LJ_FR2) setnilV(top++); L->top = top+1; lj_vm_call(L, top, 1+1); /* Stack: |errfunc|msg| -> |msg| */ } @@ -630,6 +631,7 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) const BCIns *pc = cframe_Lpc(L); if (((ptrdiff_t)pc & FRAME_TYPE) != FRAME_LUA) { const char *tname = lj_typename(o); + if (LJ_FR2) o++; setframe_pc(o, pc); setframe_gc(o, obj2gco(L), LJ_TTHREAD); L->top = L->base = o+1; diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index b65759a5..55cdc63e 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -107,6 +107,7 @@ static void recff_stitch(jit_State *J) TValue *pframe = frame_prevl(base-1); TRef trcont; + lua_assert(!LJ_FR2); /* TODO_FR2: handle frame shift. */ /* Move func + args up in Lua stack and insert continuation. */ memmove(&base[1], &base[-1], sizeof(TValue)*(J->maxslot+1)); setframe_ftsz(base+1, ((char *)(base+1) - (char *)pframe) + FRAME_CONT); @@ -466,6 +467,7 @@ static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd) TValue argv0, argv1; TRef tmp; int errcode; + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ /* Swap function and traceback. */ tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp; copyTV(J->L, &argv0, &rd->argv[0]); diff --git a/src/lj_frame.h b/src/lj_frame.h index 061b396c..226d74f1 100644 --- a/src/lj_frame.h +++ b/src/lj_frame.h @@ -11,7 +11,16 @@ /* -- Lua stack frame ----------------------------------------------------- */ -/* Frame type markers in callee function slot (callee base-1). */ +/* Frame type markers in LSB of PC (4-byte aligned) or delta (8-byte aligned: +** +** PC 00 Lua frame +** delta 001 C frame +** delta 010 Continuation frame +** delta 011 Lua vararg frame +** delta 101 cpcall() frame +** delta 110 ff pcall() frame +** delta 111 ff pcall() frame with active hook +*/ enum { FRAME_LUA, FRAME_C, FRAME_CONT, FRAME_VARG, FRAME_LUAP, FRAME_CP, FRAME_PCALL, FRAME_PCALLH @@ -21,12 +30,47 @@ enum { #define FRAME_TYPEP (FRAME_TYPE|FRAME_P) /* Macros to access and modify Lua frames. */ +#if LJ_FR2 +/* Two-slot frame info, required for 64 bit PC/GCRef: +** +** base-2 base-1 | base base+1 ... +** [func PC/delta/ft] | [slots ...] +** ^-- frame | ^-- base ^-- top +** +** Continuation frames: +** +** base-4 base-3 base-2 base-1 | base base+1 ... +** [cont PC ] [func PC/delta/ft] | [slots ...] +** ^-- frame | ^-- base ^-- top +*/ +#define frame_gc(f) (gcval((f)-1)) +#define frame_ftsz(f) ((ptrdiff_t)(f)->ftsz) +#define frame_pc(f) ((const BCIns *)frame_ftsz(f)) +#define setframe_gc(f, p, tp) (setgcVraw((f)-1, (p), (tp))) +#define setframe_ftsz(f, sz) ((f)->ftsz = (sz)) +#define setframe_pc(f, pc) ((f)->ftsz = (int64_t)(intptr_t)(pc)) +#else +/* One-slot frame info, sufficient for 32 bit PC/GCRef: +** +** base-1 | base base+1 ... +** lo hi | +** [func | PC/delta/ft] | [slots ...] +** ^-- frame | ^-- base ^-- top +** +** Continuation frames: +** +** base-2 base-1 | base base+1 ... +** lo hi lo hi | +** [cont | PC] [func | PC/delta/ft] | [slots ...] +** ^-- frame | ^-- base ^-- top +*/ #define frame_gc(f) (gcref((f)->fr.func)) #define frame_ftsz(f) ((ptrdiff_t)(f)->fr.tp.ftsz) #define frame_pc(f) (mref((f)->fr.tp.pcr, const BCIns)) #define setframe_gc(f, p, tp) (setgcref((f)->fr.func, (p)), UNUSED(tp)) #define setframe_ftsz(f, sz) ((f)->fr.tp.ftsz = (int32_t)(sz)) #define setframe_pc(f, pc) (setmref((f)->fr.tp.pcr, (pc))) +#endif #define frame_type(f) (frame_ftsz(f) & FRAME_TYPE) #define frame_typep(f) (frame_ftsz(f) & FRAME_TYPEP) @@ -42,9 +86,16 @@ enum { enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */ +#if LJ_FR2 +#define frame_contpc(f) (frame_pc((f)-2)) +#define frame_contv(f) (((f)-3)->u64) +#else #define frame_contpc(f) (frame_pc((f)-1)) #define frame_contv(f) (((f)-1)->u32.lo) -#if LJ_64 +#endif +#if LJ_FR2 +#define frame_contf(f) ((ASMFunction)(uintptr_t)((f)-3)->u64) +#elif LJ_64 #define frame_contf(f) \ ((ASMFunction)(void *)((intptr_t)lj_vm_asm_begin + \ (intptr_t)(int32_t)((f)-1)->u32.lo)) @@ -54,7 +105,7 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */ #define frame_iscont_fficb(f) \ (LJ_HASFFI && frame_contv(f) == LJ_CONT_FFI_CALLBACK) -#define frame_prevl(f) ((f) - (1+bc_a(frame_pc(f)[-1]))) +#define frame_prevl(f) ((f) - (1+LJ_FR2+bc_a(frame_pc(f)[-1]))) #define frame_prevd(f) ((TValue *)((char *)(f) - frame_sized(f))) #define frame_prev(f) (frame_islua(f)?frame_prevl(f):frame_prevd(f)) /* Note: this macro does not skip over FRAME_VARG. */ diff --git a/src/lj_gc.c b/src/lj_gc.c index 5a7127c2..d6dfde93 100644 --- a/src/lj_gc.c +++ b/src/lj_gc.c @@ -268,12 +268,12 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th) { TValue *frame, *top = th->top-1, *bot = tvref(th->stack); /* Note: extra vararg frame not skipped, marks function twice (harmless). */ - for (frame = th->base-1; frame > bot; frame = frame_prev(frame)) { + for (frame = th->base-1; frame > bot+LJ_FR2; frame = frame_prev(frame)) { GCfunc *fn = frame_func(frame); TValue *ftop = frame; if (isluafunc(fn)) ftop += funcproto(fn)->framesize; if (ftop > top) top = ftop; - gc_markobj(g, fn); /* Need to mark hidden function (or L). */ + if (!LJ_FR2) gc_markobj(g, fn); /* Need to mark hidden function (or L). */ } top++; /* Correct bias of -1 (frame == base-1). */ if (top > tvref(th->maxstack)) top = tvref(th->maxstack); @@ -284,7 +284,7 @@ static MSize gc_traverse_frames(global_State *g, lua_State *th) static void gc_traverse_thread(global_State *g, lua_State *th) { TValue *o, *top = th->top; - for (o = tvref(th->stack)+1; o < top; o++) + for (o = tvref(th->stack)+1+LJ_FR2; o < top; o++) gc_marktv(g, o); if (g->gc.state == GCSatomic) { top = tvref(th->stack) + th->stacksize; @@ -456,13 +456,14 @@ static void gc_call_finalizer(global_State *g, lua_State *L, int errcode; TValue *top; lj_trace_abort(g); - top = L->top; - L->top = top+2; hook_entergc(g); /* Disable hooks and new traces during __gc. */ g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */ - copyTV(L, top, mo); - setgcV(L, top+1, o, ~o->gch.gct); - errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|o| -> | */ + top = L->top; + copyTV(L, top++, mo); + if (LJ_FR2) setnilV(top++); + setgcV(L, top, o, ~o->gch.gct); + L->top = top+1; + errcode = lj_vm_pcall(L, top, 1+0, -1); /* Stack: |mo|o| -> | */ hook_restore(g, oldh); g->gc.threshold = oldt; /* Restore GC threshold. */ if (errcode) diff --git a/src/lj_lib.h b/src/lj_lib.h index 5bfd8d7c..dff99c09 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h @@ -47,8 +47,13 @@ LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); /* Avoid including lj_frame.h. */ +#if LJ_FR2 +#define lj_lib_upvalue(L, n) \ + (&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1]) +#else #define lj_lib_upvalue(L, n) \ (&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1]) +#endif #if LJ_TARGET_WINDOWS #define lj_lib_checkfpu(L) \ diff --git a/src/lj_meta.c b/src/lj_meta.c index 520c3763..d26ed220 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c @@ -80,12 +80,16 @@ int lj_meta_tailcall(lua_State *L, cTValue *tv) TValue *base = L->base; TValue *top = L->top; const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */ - copyTV(L, base-1, tv); /* Replace frame with new object. */ - top->u32.lo = LJ_CONT_TAILCALL; - setframe_pc(top, pc); - setframe_gc(top+1, obj2gco(L), LJ_TTHREAD); /* Dummy frame object. */ - setframe_ftsz(top+1, ((char *)(top+2) - (char *)base) + FRAME_CONT); - L->base = L->top = top+2; + copyTV(L, base-1-LJ_FR2, tv); /* Replace frame with new object. */ + if (LJ_FR2) + (top++)->u64 = LJ_CONT_TAILCALL; + else + top->u32.lo = LJ_CONT_TAILCALL; + setframe_pc(top++, pc); + if (LJ_FR2) top++; + setframe_gc(top, obj2gco(L), LJ_TTHREAD); /* Dummy frame object. */ + setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT); + L->base = L->top = top+1; /* ** before: [old_mo|PC] [... ...] ** ^base ^top @@ -116,11 +120,13 @@ static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo, */ TValue *top = L->top; if (curr_funcisL(L)) top = curr_topL(L); - setcont(top, cont); /* Assembler VM stores PC in upper word. */ - copyTV(L, top+1, mo); /* Store metamethod and two arguments. */ - copyTV(L, top+2, a); - copyTV(L, top+3, b); - return top+2; /* Return new base. */ + setcont(top++, cont); /* Assembler VM stores PC in upper word or FR2. */ + if (LJ_FR2) setnilV(top++); + copyTV(L, top++, mo); /* Store metamethod and two arguments. */ + if (LJ_FR2) setnilV(top++); + copyTV(L, top, a); + copyTV(L, top+1, b); + return top; /* Return new base. */ } /* -- C helpers for some instructions, called from assembler VM ----------- */ @@ -256,10 +262,11 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) ** after mm: [...][CAT stack ...] <--push-- [result] ** next step: [...][CAT stack .............] */ - copyTV(L, top+2, top); /* Careful with the order of stack copies! */ - copyTV(L, top+1, top-1); - copyTV(L, top, mo); + copyTV(L, top+2*LJ_FR2+2, top); /* Carefully ordered stack copies! */ + copyTV(L, top+2*LJ_FR2+1, top-1); + copyTV(L, top+LJ_FR2, mo); setcont(top-1, lj_cont_cat); + if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; } return top+1; /* Trigger metamethod call. */ } else { /* Pick as many strings as possible from the top and concatenate them: @@ -327,12 +334,14 @@ TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne) return (TValue *)(intptr_t)ne; } top = curr_top(L); - setcont(top, ne ? lj_cont_condf : lj_cont_condt); - copyTV(L, top+1, mo); + setcont(top++, ne ? lj_cont_condf : lj_cont_condt); + if (LJ_FR2) setnilV(top++); + copyTV(L, top++, mo); + if (LJ_FR2) setnilV(top++); it = ~(uint32_t)o1->gch.gct; - setgcV(L, top+2, o1, it); - setgcV(L, top+3, o2, it); - return top+2; /* Trigger metamethod call. */ + setgcV(L, top, o1, it); + setgcV(L, top+1, o2, it); + return top; /* Trigger metamethod call. */ } return (TValue *)(intptr_t)ne; } @@ -431,7 +440,8 @@ void lj_meta_call(lua_State *L, TValue *func, TValue *top) TValue *p; if (!tvisfunc(mo)) lj_err_optype_call(L, func); - for (p = top; p > func; p--) copyTV(L, p, p-1); + for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1); + if (LJ_FR2) copyTV(L, func+2, func); copyTV(L, func, mo); } diff --git a/src/lj_obj.h b/src/lj_obj.h index e5724859..438c83d4 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -131,7 +131,7 @@ typedef struct SBuf { /* Frame link. */ typedef union { int32_t ftsz; /* Frame type and size of previous frame. */ - MRef pcr; /* Overlaps PC for Lua frames. */ + MRef pcr; /* Or PC for Lua frames. */ } FrameLink; /* Tagged value. */ @@ -147,12 +147,16 @@ typedef LJ_ALIGN(8) union TValue { , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ ) }; +#if LJ_FR2 + int64_t ftsz; /* Frame type and size of previous frame, or PC. */ +#else struct { LJ_ENDIAN_LOHI( GCRef func; /* Function for next frame (or dummy L). */ , FrameLink tp; /* Link to previous frame. */ ) } fr; +#endif struct { LJ_ENDIAN_LOHI( uint32_t lo; /* Lower 32 bits of number. */ @@ -584,7 +588,11 @@ struct lua_State { #define registry(L) (&G(L)->registrytv) /* Macros to access the currently executing (Lua) function. */ +#if LJ_FR2 +#define curr_func(L) (&gcref((L->base-2)->gcr)->fn) +#else #define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) +#endif #define curr_funcisL(L) (isluafunc(curr_func(L))) #define curr_proto(L) (funcproto(curr_func(L))) #define curr_topL(L) (L->base + curr_proto(L)->framesize) @@ -732,10 +740,16 @@ static LJ_AINLINE void setlightudV(TValue *o, void *p) #if LJ_64 #define checklightudptr(L, p) \ (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) +#else +#define checklightudptr(L, p) (p) +#endif + +#if LJ_FR2 +#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)(void *)(f)) +#elif LJ_64 #define setcont(o, f) \ ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) #else -#define checklightudptr(L, p) (p) #define setcont(o, f) setlightudV((o), (void *)(f)) #endif diff --git a/src/lj_parse.c b/src/lj_parse.c index 198ddfc9..91282768 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -662,14 +662,14 @@ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key) BCReg idx, func, obj = expr_toanyreg(fs, e); expr_free(fs, e); func = fs->freereg; - bcemit_AD(fs, BC_MOV, func+1, obj); /* Copy object to first argument. */ + bcemit_AD(fs, BC_MOV, func+1+LJ_FR2, obj); /* Copy object to 1st argument. */ lua_assert(expr_isstrk(key)); idx = const_str(fs, key); if (idx <= BCMAX_C) { - bcreg_reserve(fs, 2); + bcreg_reserve(fs, 2+LJ_FR2); bcemit_ABC(fs, BC_TGETS, func, obj, idx); } else { - bcreg_reserve(fs, 3); + bcreg_reserve(fs, 3+LJ_FR2); bcemit_AD(fs, BC_KSTR, func+2, idx); bcemit_ABC(fs, BC_TGETV, func, obj, func+2); fs->freereg--; @@ -1913,11 +1913,11 @@ static void parse_args(LexState *ls, ExpDesc *e) lua_assert(e->k == VNONRELOC); base = e->u.s.info; /* Base register for call. */ if (args.k == VCALL) { - ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1); + ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - LJ_FR2); } else { if (args.k != VVOID) expr_tonextreg(fs, &args); - ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base); + ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - LJ_FR2); } expr_init(e, VCALL, bcemit_INS(fs, ins)); e->u.s.aux = base; @@ -1957,6 +1957,7 @@ static void expr_primary(LexState *ls, ExpDesc *v) parse_args(ls, v); } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { expr_tonextreg(fs, v); + if (LJ_FR2) bcreg_reserve(fs, 1); parse_args(ls, v); } else { break; @@ -2537,7 +2538,8 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) lex_check(ls, TK_in); line = ls->linenumber; assign_adjust(ls, 3, expr_list(ls, &e), &e); - bcreg_bump(fs, 3); /* The iterator needs another 3 slots (func + 2 args). */ + /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */ + bcreg_bump(fs, 3+LJ_FR2); isnext = (nvars <= 5 && predict_next(ls, fs, exprpc)); var_add(ls, 3); /* Hidden control variables. */ lex_check(ls, TK_do); diff --git a/src/lj_record.c b/src/lj_record.c index 01c09c58..539fd197 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -502,6 +502,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) static LoopEvent rec_iterl(jit_State *J, const BCIns iterins) { BCReg ra = bc_a(iterins); + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ if (!tref_isnil(getslot(J, ra))) { /* Looping back? */ J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */ J->maxslot = ra-1+bc_b(J->pc[-1]); @@ -672,6 +673,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs) TValue *functv = &J->L->base[func]; TRef *fbase = &J->base[func]; ptrdiff_t i; + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ for (i = 0; i <= nargs; i++) (void)getslot(J, func+i); /* Ensure func and all args have a reference. */ if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ @@ -788,7 +790,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) BCIns callins = *(frame_pc(frame)-1); ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults; BCReg cbase = bc_a(callins); - GCproto *pt = funcproto(frame_func(frame - (cbase+1))); + GCproto *pt = funcproto(frame_func(frame - (cbase+1-LJ_FR2))); + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame teardown. */ if ((pt->flags & PROTO_NOJIT)) lj_trace_err(J, LJ_TRERR_CJITOFF); if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { @@ -973,6 +976,7 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) lj_trace_err(J, LJ_TRERR_NOMM); } ok: + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ base[0] = ix->mobj; copyTV(J->L, basev+0, &ix->mobjv); lj_record_call(J, func, 2); @@ -989,6 +993,7 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv) BCReg func = rec_mm_prep(J, lj_cont_ra); TRef *base = J->base + func; TValue *basev = J->L->base + func; + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv); base[1] = tr; copyTV(J->L, basev+1, tv); #if LJ_52 @@ -1011,6 +1016,7 @@ static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt); TRef *base = J->base + func; TValue *tv = J->L->base + func; + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key; copyTV(J->L, tv+0, &ix->mobjv); copyTV(J->L, tv+1, &ix->valv); @@ -1261,6 +1267,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra); TRef *base = J->base + func; TValue *tv = J->L->base + func; + lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */ base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key; setfuncV(J->L, tv+0, funcV(&ix->mobjv)); copyTV(J->L, tv+1, &ix->tabv); @@ -2135,28 +2142,28 @@ void lj_record_ins(jit_State *J) /* -- Calls and vararg handling ----------------------------------------- */ case BC_ITERC: - J->base[ra] = getslot(J, ra-3); - J->base[ra+1] = getslot(J, ra-2); - J->base[ra+2] = getslot(J, ra-1); + J->base[ra] = getslot(J, ra-3-LJ_FR2); + J->base[ra+1] = getslot(J, ra-2-LJ_FR2); + J->base[ra+2] = getslot(J, ra-1-LJ_FR2); { /* Do the actual copy now because lj_record_call needs the values. */ TValue *b = &J->L->base[ra]; - copyTV(J->L, b, b-3); - copyTV(J->L, b+1, b-2); - copyTV(J->L, b+2, b-1); + copyTV(J->L, b, b-3-LJ_FR2); + copyTV(J->L, b+1, b-2-LJ_FR2); + copyTV(J->L, b+2, b-1-LJ_FR2); } lj_record_call(J, ra, (ptrdiff_t)rc-1); break; /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ case BC_CALLM: - rc = (BCReg)(J->L->top - J->L->base) - ra; + rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; /* fallthrough */ case BC_CALL: lj_record_call(J, ra, (ptrdiff_t)rc-1); break; case BC_CALLMT: - rc = (BCReg)(J->L->top - J->L->base) - ra; + rc = (BCReg)(J->L->top - J->L->base) - ra - LJ_FR2; /* fallthrough */ case BC_CALLT: lj_record_tailcall(J, ra, (ptrdiff_t)rc-1); diff --git a/src/lj_snap.c b/src/lj_snap.c index 2917424f..4bac2d28 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c @@ -100,6 +100,7 @@ static BCReg snapshot_framelinks(jit_State *J, SnapEntry *map) GCfunc *fn = frame_func(frame); cTValue *ftop = isluafunc(fn) ? (frame+funcproto(fn)->framesize) : J->L->top; MSize f = 0; + lua_assert(!LJ_FR2); /* TODO_FR2: store 64 bit PCs. */ map[f++] = SNAP_MKPC(J->pc); /* The current PC is always the first entry. */ while (frame > lim) { /* Backwards traversal of all frames above base. */ if (frame_islua(frame)) { @@ -241,7 +242,8 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, case BCMbase: if (op >= BC_CALLM && op <= BC_VARG) { BCReg top = (op == BC_CALLM || op == BC_CALLMT || bc_c(ins) == 0) ? - maxslot : (bc_a(ins) + bc_c(ins)); + maxslot : (bc_a(ins) + bc_c(ins)+LJ_FR2); + if (LJ_FR2) DEF_SLOT(bc_a(ins)+1); s = bc_a(ins) - ((op == BC_ITERC || op == BC_ITERN) ? 3 : 0); for (; s < top; s++) USE_SLOT(s); for (; s < maxslot; s++) DEF_SLOT(s); @@ -836,6 +838,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr) snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp); o->u32.hi = tmp.u32.lo; } else if ((sn & (SNAP_CONT|SNAP_FRAME))) { + lua_assert(!LJ_FR2); /* TODO_FR2: store 64 bit PCs. */ /* Overwrite tag with frame link. */ setframe_ftsz(o, snap_slot(sn) != 0 ? (int32_t)*flinks-- : ftsz0); L->base = o+1; diff --git a/src/lj_state.c b/src/lj_state.c index 344f8fe1..f7cdb8f3 100644 --- a/src/lj_state.c +++ b/src/lj_state.c @@ -49,6 +49,7 @@ ** one extra slot if mobj is not a function. Only lj_meta_tset needs 5 ** slots above top, but then mobj is always a function. So we can get by ** with 5 extra slots. +** LJ_FR2: We need 2 more slots for the frame PC and the continuation PC. */ /* Resize stack slots and adjust pointers in state. */ @@ -128,8 +129,9 @@ static void stack_init(lua_State *L1, lua_State *L) L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA; stend = st + L1->stacksize; setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1); - L1->base = L1->top = st+1; - setthreadV(L1, st, L1); /* Needed for curr_funcisL() on empty stack. */ + setthreadV(L1, st++, L1); /* Needed for curr_funcisL() on empty stack. */ + if (LJ_FR2) setnilV(st++); + L1->base = L1->top = st; while (st < stend) /* Clear new slots. */ setnilV(st++); } @@ -253,7 +255,7 @@ LUA_API void lua_close(lua_State *L) for (i = 0;;) { hook_enter(g); L->status = 0; - L->base = L->top = tvref(L->stack) + 1; + L->base = L->top = tvref(L->stack) + 1 + LJ_FR2; L->cframe = NULL; if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == 0) { if (++i >= 10) break; diff --git a/src/lj_trace.c b/src/lj_trace.c index f386b95e..7d2ce8f2 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c @@ -830,7 +830,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) ERRNO_RESTORE switch (bc_op(*pc)) { case BC_CALLM: case BC_CALLMT: - return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); + return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc) + LJ_FR2); case BC_RETM: return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc)); case BC_TSETM: diff --git a/src/lj_vmevent.c b/src/lj_vmevent.c index e14ad5b6..8e10a627 100644 --- a/src/lj_vmevent.c +++ b/src/lj_vmevent.c @@ -27,6 +27,7 @@ ptrdiff_t lj_vmevent_prepare(lua_State *L, VMEvent ev) if (tv && tvisfunc(tv)) { lj_state_checkstack(L, LUA_MINSTACK); setfuncV(L, L->top++, funcV(tv)); + if (LJ_FR2) setnilV(L->top++); return savestack(L, L->top); } }