From 1619b6087b9c921cf492ae8deb1eb2ed044c75d4 Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 8 Sep 2022 20:05:13 +0300 Subject: [PATCH] mild optimization of v_set argument consumption --- src/jit/nvm_x86_64.c | 8 ++++---- src/vm.c | 33 ++++++++++++++++++--------------- src/vm.h | 13 +++++++++---- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index f34968f5..c2df2e6c 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -160,18 +160,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, 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_SETN(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, false, true, true, false); return x; } +INS B i_SETU(B s, B x, Scope** pscs, u32* bc) { POS_UPD; v_set(pscs, s, x, true, true, true, false); return x; } INS B i_SETM(B s, B f, B x, Scope** pscs, u32* bc) { POS_UPD; B w = v_get(pscs, s, true); B r = c2(f,w,x); dec(f); - v_set(pscs, s, r, true, false); dec(s); + v_set(pscs, s, r, true, false, true, false); return r; } INS B i_SETC(B s, B f, Scope** pscs, u32* bc) { POS_UPD; B x = v_get(pscs, s, true); B r = c1(f,x); dec(f); - v_set(pscs, s, r, true, false); dec(s); + v_set(pscs, s, r, true, false, true, false); return r; } FORCE_INLINE B gotoNextBodyJIT(Scope* sc, Body* body) { diff --git a/src/vm.c b/src/vm.c index 52417caa..e60386fa 100644 --- a/src/vm.c +++ b/src/vm.c @@ -498,15 +498,18 @@ FORCE_INLINE bool v_merge(Scope* pscs[], B s, B x, bool upd, bool hdr) { SGet(x) for (usz i = 0; i < oia; i++) { B cx = m_unit(Get(x,i)); - if (!hdr) v_set (pscs, op[i], cx, upd, true); - else if (!v_seth(pscs, op[i], cx)) { dec(cx); return false; } - dec(cx); + if (!hdr) v_set(pscs, op[i], cx, upd, true, false, true); + else { + bool ok = v_seth(pscs, op[i], cx); + dec(cx); + if (!ok) return false; + } } } else { B cells = toCells(incG(x)); B* xp = harr_ptr(cells); for (usz i = 0; i < oia; i++) { - if (!hdr) v_set (pscs, op[i], xp[i], upd, true); + if (!hdr) v_set (pscs, op[i], xp[i], upd, true, false, false); else if (!v_seth(pscs, op[i], xp[i])) { dec(cells); return false; } } dec(cells); @@ -524,25 +527,25 @@ NOINLINE void v_setF(Scope* pscs[], B s, B x, bool upd) { B c = sp[i]; if (isVar(c)) { Scope* sc = pscs[(u16)(c.u>>32)]; - v_set(pscs, c, ns_getU(x, pos2gid(sc->body, (u32)c.u)), upd, true); + v_set(pscs, c, ns_getU(x, pos2gid(sc->body, (u32)c.u)), upd, true, false, false); } 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, true); + v_set(pscs, c, ns_getNU(x, ext->vars[(u32)c.u + ext->varAm], true), upd, true, false, false); } else if (isObj(c)) { assert(TY(c) == t_fldAlias); FldAlias* cf = c(FldAlias,c); - v_set(pscs, cf->obj, ns_getU(x, cf->p), upd, true); + v_set(pscs, cf->obj, ns_getU(x, cf->p), upd, true, false, false); } 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, true); + SGet(x) + for (u64 i = 0; i < ia; i++) v_set(pscs, sp[i], Get(x,i), upd, true, false, true); } else if (s.u == bi_N.u) { return; } else if (isObj(s)) { if (TY(s) == t_arrMerge) v_merge(pscs, s, x, upd, false); - else if (TY(s) == t_fldAlias) thrF("Assignment: Cannot assign non-namespace to a list containing aliases"); // v_set(pscs, c(FldAlias, s)->obj, x, upd, true); + else if (TY(s) == t_fldAlias) thrF("Assignment: Cannot assign non-namespace to a list containing aliases"); else UD; } else if (isExt(s)) { Scope* sc = pscs[(u16)(s.u>>32)]; @@ -581,7 +584,7 @@ NOINLINE bool v_sethF(Scope* pscs[], B s, B x) { } if (TY(s)==t_vfyObj) return equal(c(WrappedObj,s)->obj,x); if (TY(s)==t_arrMerge) return v_merge(pscs, s, x, false, true); - if (TY(s)==t_fldAlias) return false; // return v_seth(pscs, c(FldAlias, s)->obj, x); + if (TY(s)==t_fldAlias) return false; UD; } @@ -827,19 +830,19 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume 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 SETN: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, false, true, true, false); ADD(x); break; } + case SETU: { P(s) P(x) GS_UPD; POS_UPD; v_set(pscs, s, x, true, true, true, false); ADD(x); break; } case SETM: { P(s)P(f)P(x) GS_UPD; POS_UPD; B w = v_get(pscs, s, true); B r = c2(f,w,x); dec(f); - v_set(pscs, s, r, true, false); dec(s); + v_set(pscs, s, r, true, false, true, false); ADD(r); break; } case SETC: { P(s)P(f) GS_UPD; POS_UPD; B x = v_get(pscs, s, true); B r = c1(f,x); dec(f); - v_set(pscs, s, r, true, false); dec(s); + v_set(pscs, s, r, true, false, true, false); ADD(r); break; } diff --git a/src/vm.h b/src/vm.h index 829a9652..dceae4c1 100644 --- a/src/vm.h +++ b/src/vm.h @@ -66,7 +66,7 @@ enum { FN1Ci, FN1Oi, FN2Ci, FN2Oi, // FN__ alternatives that don't take the function from the stack, but instead as an 2×u32 immediate in the bytecode SETNi, SETUi, SETMi, SETCi, // SET_ alternatives that expect the set variable as a depth-position pair like VAR_ SETNv, SETUv, SETMv, SETCv, // SET_i alternatives that also don't return the result - SETH1, SETH2, PRED1, PRED2, // internal versions of SETH and PRED, with 2×u64 arguments (only 1 for PRED1) specifying bodies to jump to on fail (or NULL if is last) + SETH1, SETH2, PRED1, PRED2, // versions of SETH and PRED with 2×u64 arguments (only 1 for PRED1) specifying bodies to jump to on fail (or NULL if is last) DFND0, DFND1, DFND2, // internal versions of DFND with a specific type, and a u64 argument representing the block pointer FAIL, // this body cannot be called monadically/dyadically BC_SIZE @@ -299,9 +299,14 @@ FORCE_INLINE void v_setI(Scope* sc, u32 p, B x, bool upd, bool chk) { // consume sc->vars[p] = x; } } -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_setF(pscs, s, x, upd); - else v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), upd, chk); +FORCE_INLINE void v_set(Scope* pscs[], B s, B x, bool upd, bool chk, bool consumeS, bool consumeX) { // if chk is false, content variables _may_ not be checked to be set + if (LIKELY(isVar(s))) { + v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, consumeX? x : inc(x), upd, chk); + } else { + v_setF(pscs, s, x, upd); + if (consumeX) dec(x); + if (consumeS) dec(s); + } } FORCE_INLINE bool v_seth(Scope* pscs[], B s, B x) { // doesn't consume; s cannot contain extended variables