diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 903aa92e..c435017d 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -146,18 +146,18 @@ INS B i_EXTU(u32 p, Scope* sc) { vars[p] = bi_optOut; return r; } -INS B i_SETN(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, false); dec(s); return x; } -INS B i_SETU(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, true ); dec(s); return x; } +INS B i_SETN(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, false, true); dec(s); return x; } +INS B i_SETU(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, true, true); dec(s); return x; } INS B i_SETM(B s, B f, B x, Scope** pscs, u32* bc) { POS_UPD; - B w = v_get(pscs, s); + B w = v_get(pscs, s, true); B r = c2(f,w,x); dec(f); - v_set(pscs, s, r, true); dec(s); + v_set(pscs, s, r, true, false); dec(s); return r; } INS B i_SETC(B s, B f, Scope** pscs, u32* bc) { POS_UPD; - B x = v_get(pscs, s); + B x = v_get(pscs, s, true); B r = c1(f,x); dec(f); - v_set(pscs, s, r, true); dec(s); + v_set(pscs, s, r, true, false); dec(s); return r; } FORCE_INLINE B gotoNextBodyJIT(Scope* sc, Body* body) { @@ -182,14 +182,14 @@ INS B i_PRED2(B x, Scope* sc, u32* bc, Body* v1, Body* v2) { POS_UPD; if (o2b(x)) return bi_okHdr; return gotoNextBodyJIT(sc, q_N(sc->vars[2])? v1 : v2); } -INS B i_SETNi( B x, Scope* sc, u32 p ) { v_setI(sc, p, inc(x), false); return x; } -INS B i_SETUi( B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, inc(x), true ); return x; } -INS B i_SETMi(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p),x); dec(f); v_setI(sc, p, inc(r), true); return r; } -INS B i_SETCi(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p) ); dec(f); v_setI(sc, p, inc(r), true); return r; } -INS void i_SETNv(B x, Scope* sc, u32 p ) { v_setI(sc, p, x, false); } -INS void i_SETUv(B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, x, true ); } -INS void i_SETMv(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p),x); dec(f); v_setI(sc, p, r, true); } -INS void i_SETCv(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p) ); dec(f); v_setI(sc, p, r, true); } +INS B i_SETNi( B x, Scope* sc, u32 p ) { v_setI(sc, p, inc(x), false, false); return x; } +INS B i_SETUi( B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, inc(x), true, false); return x; } +INS B i_SETMi(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p, false),x); dec(f); v_setI(sc, p, inc(r), true, false); return r; } +INS B i_SETCi(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p, false) ); dec(f); v_setI(sc, p, inc(r), true, false); return r; } +INS void i_SETNv(B x, Scope* sc, u32 p ) { v_setI(sc, p, x, false, false); } +INS void i_SETUv(B x, Scope* sc, u32 p, u32* bc) { POS_UPD; v_setI(sc, p, x, true, false); } +INS void i_SETMv(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_getI(sc, p, false),x); dec(f); v_setI(sc, p, r, true, false); } +INS void i_SETCv(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p, false) ); dec(f); v_setI(sc, p, r, true, false); } INS B i_FLDO(B ns, u32 p, Scope* sc) { if (!isNsp(ns)) thrM("Trying to read a field from non-namespace"); B r = inc(ns_getU(ns, sc->body->nsDesc->nameList, p)); diff --git a/src/jit/x86_64.h b/src/jit/x86_64.h index 907e211d..7f7867a3 100644 --- a/src/jit/x86_64.h +++ b/src/jit/x86_64.h @@ -210,8 +210,7 @@ static NOINLINE void asm_write(u8* P, u64 SZ) { // #define POP(O,I) {REX4(O,0),0x58+((O)&7)} // #define BYTES4(I) ((UC)(I)),((UC)((I)>>8)),((UC)((I)>>16)),((UC)((I)>>24)) -// #define BYTES8(I) BYTES4(I) ,((UC)((I)>>32)),((UC)((I)>>40)) \ -// ,((UC)((I)>>48)),((UC)((I)>>56)) +// #define BYTES8(I) BYTES4(I) ,((UC)((I)>>32)),((UC)((I)>>40)),((UC)((I)>>48)),((UC)((I)>>56)) // #define MOV_MR(O,I,OFF) {REX8(O,I),0x89,0x40+A_0REG(O,I),OFF} // #define MOV_MR0(O,I) {REX8(O,I),0x89,A_0REG(O,I)} // TODO is broken on (12,14) diff --git a/src/vm.c b/src/vm.c index aab5981e..e743810a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -438,21 +438,21 @@ NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd) { if (isVar(c)) { Scope* sc = pscs[(u16)(c.u>>32)]; i32 nameID = sc->body->varIDs[(u32)c.u]; - v_set(pscs, c, ns_getU(x, sc->body->nsDesc->nameList, nameID), upd); + v_set(pscs, c, ns_getU(x, sc->body->nsDesc->nameList, nameID), upd, true); } else if (isExt(c)) { ScopeExt* ext = pscs[(u16)(c.u>>32)]->ext; - v_set(pscs, c, ns_getNU(x, ext->vars[(u32)c.u + ext->varAm], true), upd); + v_set(pscs, c, ns_getNU(x, ext->vars[(u32)c.u + ext->varAm], true), upd, true); } else if (isObj(c)) { assert(v(c)->type == t_fldAlias); Scope* sc = pscs[0]; FldAlias* cf = c(FldAlias,c); - v_set(pscs, cf->obj, ns_getU(x, sc->body->nsDesc->nameList, cf->p), upd); + v_set(pscs, cf->obj, ns_getU(x, sc->body->nsDesc->nameList, cf->p), upd, true); } else thrM("Assignment: extracting non-name from namespace"); } return; } SGetU(x) - for (u64 i = 0; i < ia; i++) v_set(pscs, sp[i], GetU(x,i), upd); + for (u64 i = 0; i < ia; i++) v_set(pscs, sp[i], GetU(x,i), upd, true); } } NOINLINE bool v_sethR(Scope* pscs[], B s, B x) { @@ -491,6 +491,7 @@ NOINLINE B v_getR(Scope* pscs[], B s) { if (isExt(s)) { Scope* sc = pscs[(u16)(s.u>>32)]; B r = sc->ext->vars[(u32)s.u]; + if (r.u==bi_noVar.u) thrM("↩: Reading variable that hasn't been set"); sc->ext->vars[(u32)s.u] = bi_optOut; return r; } else { @@ -498,7 +499,7 @@ NOINLINE B v_getR(Scope* pscs[], B s) { usz ia = a(s)->ia; B* sp = harr_ptr(s); HArr_p r = m_harrUv(ia); - for (u64 i = 0; i < ia; i++) r.a[i] = v_get(pscs, sp[i]); + for (u64 i = 0; i < ia; i++) r.a[i] = v_get(pscs, sp[i], true); return r.b; } } @@ -679,19 +680,19 @@ B evalBC(Block* bl, Body* b, Scope* sc) { // doesn't consume vars[p] = bi_optOut; break; } - case SETN: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, false); dec(s); ADD(x); break; } - case SETU: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, true ); dec(s); ADD(x); break; } + case SETN: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, false, true); dec(s); ADD(x); break; } + case SETU: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, true, true); dec(s); ADD(x); break; } case SETM: { P(s)P(f)P(x) GS_UPD; POS_UPD; - B w = v_get(pscs, s); + B w = v_get(pscs, s, true); B r = c2(f,w,x); dec(f); - v_set(pscs, s, r, true); dec(s); + v_set(pscs, s, r, true, false); dec(s); ADD(r); break; } case SETC: { P(s)P(f) GS_UPD; POS_UPD; - B x = v_get(pscs, s); + B x = v_get(pscs, s, true); B r = c1(f,x); dec(f); - v_set(pscs, s, r, true); dec(s); + v_set(pscs, s, r, true, false); dec(s); ADD(r); break; } diff --git a/src/vm.h b/src/vm.h index ac2515db..c59b5561 100644 --- a/src/vm.h +++ b/src/vm.h @@ -251,33 +251,34 @@ typedef struct VfyObj { NOINLINE B v_getR(Scope* pscs[], B s); // doesn't consume -static inline B v_getI(Scope* sc, u32 p) { +FORCE_INLINE B v_getI(Scope* sc, u32 p, bool chk) { B r = sc->vars[p]; + if (chk && r.u==bi_noVar.u) thrM("↩: Reading variable that hasn't been set"); sc->vars[p] = bi_optOut; return r; } -static inline B v_get(Scope* pscs[], B s) { // get value representing s, replacing with bi_optOut; doesn't consume +FORCE_INLINE B v_get(Scope* pscs[], B s, bool chk) { // get value representing s, replacing with bi_optOut; doesn't consume; if chk is false, content variables _may_ not be checked to be set if (RARE(!isVar(s))) return v_getR(pscs, s); - return v_getI(pscs[(u16)(s.u>>32)], (u32)s.u); + return v_getI(pscs[(u16)(s.u>>32)], (u32)s.u, chk); } NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd); // doesn't consume NOINLINE bool v_sethR(Scope* pscs[], B s, B x); // doesn't consume -static inline void v_setI(Scope* sc, u32 p, B x, bool upd) { // consumes x - B prev = sc->vars[p]; +FORCE_INLINE void v_setI(Scope* sc, u32 p, B x, bool upd, bool chk) { // consumes x if (upd) { - if (prev.u==bi_noVar.u) thrM("↩: Updating undefined variable"); + B prev = sc->vars[p]; + if (chk && prev.u==bi_noVar.u) thrM("↩: Updating variable that hasn't been set"); dec(prev); } sc->vars[p] = x; } -static inline void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume +FORCE_INLINE void v_set(Scope* pscs[], B s, B x, bool upd, bool chk) { // doesn't consume; if chk is false, content variables _may_ not be checked to be set if (RARE(!isVar(s))) v_setR(pscs, s, x, upd); - else v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), upd); + else v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), upd, chk); } -static inline bool v_seth(Scope* pscs[], B s, B x) { // doesn't consume; s cannot contain extended variables +FORCE_INLINE bool v_seth(Scope* pscs[], B s, B x) { // doesn't consume; s cannot contain extended variables if (RARE(!isVar(s))) return v_sethR(pscs, s, x); - v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), false); + v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), false, false); return true; }