From 72896feb8f8a1003aca059851bcc67f729600cbd Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 3 Jul 2021 18:04:27 +0300 Subject: [PATCH] merged SET_i+POPS --- src/jit/nvm_x86_64.c | 55 +++++++++++++++++++++++++++++--------------- src/vm.c | 25 +++++++++++++------- src/vm.h | 1 + 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 6fea660c..5bf4c964 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -127,12 +127,10 @@ INS B i_SETM(B s, B f, B x, Scope** pscs, u32* bc) { POS_UPD; } INS B i_SETNi( B x, Scope* sc, u32 p, u32* bc) { POS_UPD; 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 w = v_getI(sc, p); - B r = c2(f,w,x); dec(f); - v_setI(sc, p, inc(r), true); - return r; -} +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 void i_SETNv(B x, Scope* sc, u32 p, u32* bc) { POS_UPD; 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 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)); @@ -194,19 +192,27 @@ typedef struct SRef { B v; i32 p; } SRef; typedef struct OptRes { u32* bc; u32* offset; B refs; } OptRes; static OptRes opt(u32* bc0) { TSALLOC(SRef, stk, 8); - TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 2: immediate SET; 3: immediate FN1_/FN2C; 4: FN2O; 5: replace with PUSH; 6: decrement 1 data; 10+N: ignore N data + TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 2: immediate SET; 3: immediate FN1_/FN2C; 4: FN2O; 5: replace with PUSH; 6: decrement 1 data; 7: SET_i+POPS merge; 10+N: ignore N data TSALLOC(u64, data, 64); // variable length; whatever things are needed for the specific action - u8 rm_map[] = {10,10,10,11,12,6,6,99,99,99,11,12,13,14,15,16,17,18,19}; + u8 rm_map[] = {10,10,10,11,12,6,6,11,99,99,11,12,13,14,15,16,17,18,19}; #define RM(N) actions[N] = rm_map[actions[N]] u32* bc = bc0; usz pos = 0; while (true) { u32* sbc = bc; - #define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; }) bool ret = false; u8 cact = 0; + #define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; }) #define S(N,I) SRef N = stk[TSSIZE(stk)-1-(I)]; - switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("JIT optimization: didn't already expect immediate FN__"); + switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("optimization: didn't expect already immediate FN__"); case ADDU: case ADDI: cact = 0; TSADD(stk,SREF(b(L64), pos)); break; + case POPS: { assert(TSSIZE(actions) > 0); + u64 asz = TSSIZE(actions); + if (actions[asz-1]!=2) goto defIns; + actions[asz-1] = 7; + cact = 10; + TSSIZE(stk)--; + break; + } case LOCM: { u32 d = *bc++; u32 p = *bc++; TSADD(stk,SREF(tag((u64)d<<32 | (u32)p, VAR_TAG), pos)); break; @@ -303,13 +309,13 @@ static OptRes opt(u32* bc0) { for (i32 i = 0; i < added; i++) TSADD(stk, SREF(bi_optOut, -1)) } #undef S - TSADD(actions, cact); #undef L64 - #undef RM + TSADD(actions, cact); if (ret) break; bc = nextBC(sbc); pos++; } + #undef RM TSFREE(stk); TSALLOC(u32, rbc, TSSIZE(actions)); @@ -327,12 +333,20 @@ static OptRes opt(u32* bc0) { u64 psz = TSSIZE(rbc); #define A64(X) { u64 a64=(X); TSADD(rbc, (u32)a64); TSADD(rbc, a64>>32); } switch (ctype) { default: UD; - case 2: assert(v==SETN|v==SETU|v==SETM); + case 2: { assert(v==SETN|v==SETU|v==SETM); TSADD(rbc, v==SETN? SETNi : v==SETU? SETUi : SETMi); u64 d = data[dpos++]; TSADD(rbc, (u16)(d>>32)); TSADD(rbc, (u32)d); break; + } + case 7: { assert(v==SETN|v==SETU|v==SETM); + TSADD(rbc, v==SETN? SETNv : v==SETU? SETUv : SETMv); + u64 d = data[dpos++]; + TSADD(rbc, (u16)(d>>32)); + TSADD(rbc, (u32)d); + break; + } case 3: assert(v==FN1C|v==FN1O|v==FN2C); TSADD(rbc, v==FN1C? FN1Ci : v==FN1O? FN1Oi : FN2Ci); A64(data[dpos++]); @@ -479,10 +493,12 @@ Nvm_res m_nvm(Body* body) { #define POS_UPD(R1,R2) IMM(R1, off); MOV8mro(r_ENV, R1, offsetof(Env,bcL)); #define GS_SET(R) MOV8pr(&gStack, R) #define GET(R,P,U) { i32 p = SPOSq(-(P)); if (U && lGPos!=p) { Reg t=LEA0(R,r_CS,p,0); GS_SET(t); lGPos=p; if(U!=2) MOV8rm(R,t); } else { MOV8rmo(R, r_CS, p); } } + #define NORES(D) if (depth>D) MOV8rm(R_RES, SPOS(R_A3, -D, 0)); // call at end if rax is unset; arg is removed stack item count switch (*bc++) { case POPS: TOPp; CCALL(i_POPS); - if (depth>1) { u8 t = SPOS(R_A3, -1, 0); MOV8rm(R_RES, t); } + // if (depth>1) MOV8rm(R_RES, SPOS(R_A3, -1, 0)); + NORES(1); break; case ADDI: TOPs; { u64 x = L64; IMM(R_RES, x); IMM(R_A3, v(b(x))); INCV(R_A3); break; } // (u64 v, S) case ADDU: TOPs; IMM(R_RES, L64); @@ -527,15 +543,18 @@ Nvm_res m_nvm(Body* body) { case SETU: TOPp; GET(R_A1,1,1); LEAi(R_A2,R_SP,VAR(pscs,0)); IMM(R_A3,off); CCALL(i_SETU); break; // (B s, B x, Scope** pscs, u32* bc) case SETM: TOPp; GET(R_A1,1,1) GET(R_A2,2,1); LEAi(R_A3,R_SP,VAR(pscs,0)); IMM(R_A4,off); CCALL(i_SETM); break; // (B s, B f, B x, Scope** pscs, u32* bc) // TODO SETNi doesn't really need to update gStack - case SETNi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETNi); break; } // ( B x, Scope* sc, u32 p, u32* bc) - case SETUi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETUi); break; } // ( B x, Scope* sc, u32 p, u32* bc) - case SETMi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,1,1); LSC(R_A2,d); IMM(R_A3,p); IMM(R_A4,off); CCALL(i_SETMi); break; } // (B f, B x, Scope* sc, u32 p, u32* bc) + case SETNi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETNi); break; } // ( B x, Scope* sc, u32 p, u32* bc) + case SETUi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETUi); break; } // ( B x, Scope* sc, u32 p, u32* bc) + case SETMi:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,1,1); LSC(R_A2,d); IMM(R_A3,p); IMM(R_A4,off); CCALL(i_SETMi); break; } // (B f, B x, Scope* sc, u32 p, u32* bc) + case SETNv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETNv); NORES(1); break; } // ( B x, Scope* sc, u32 p, u32* bc) + case SETUv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,0,2); LSC(R_A1,d); IMM(R_A2,p); IMM(R_A3,off); CCALL(i_SETUv); NORES(1); break; } // ( B x, Scope* sc, u32 p, u32* bc) + case SETMv:TOPp; { u64 d=*bc++; u64 p=*bc++; GET(R_A1,1,1); LSC(R_A2,d); IMM(R_A3,p); IMM(R_A4,off); CCALL(i_SETMv); NORES(2); break; } // (B f, B x, Scope* sc, u32 p, u32* bc) case FLDO: TOPp; GET(R_A1,0,2); IMM(R_A1,*bc++); MOV(R_A2,r_SC); CCALL(i_FLDO); break; // (B, u32 p, Scope* sc) case NSPM: TOPp; IMM(R_A1,*bc++); CCALL(i_NSPM); break; // (B, u32 l) case CHKV: TOPp; IMM(R_A1,off); INV(2,0,i_CHKV); break; // (B, u32* bc, S) case RETD: GS_SET(r_CS); MOV(R_A0,r_SC); CCALL(i_RETD); ret=true; break; // (Scope* sc) case RETN: GS_SET(r_CS); ret=true; break; - default: thrF("JIT: Unsupported bytecode %i", *s); + default: thrF("JIT: Unsupported bytecode %i/%S", *s, nameBC(s)); } #undef GET #undef GS_SET diff --git a/src/vm.c b/src/vm.c index acaef818..f4cc8fa3 100644 --- a/src/vm.c +++ b/src/vm.c @@ -14,7 +14,8 @@ #define FOR_BC(F) F(PUSH) F(VARO) F(VARM) F(ARRO) F(ARRM) F(FN1C) F(FN2C) F(OP1D) F(OP2D) F(TR2D) \ F(TR3D) F(SETN) F(SETU) F(SETM) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \ F(OP2H) F(LOCO) F(LOCM) F(VFYM) F(SETH) F(RETN) F(FLDO) F(FLDM) F(NSPM) F(RETD) F(SYSV) F(LOCU) \ - F(EXTO) F(EXTM) F(EXTU) F(ADDI) F(ADDU) F(FN1Ci)F(FN1Oi)F(FN2Ci)F(FN2Oi) + F(EXTO) F(EXTM) F(EXTU) F(ADDI) F(ADDU) F(FN1Ci)F(FN1Oi)F(FN2Ci)F(FN2Oi) \ + F(SETNi)F(SETUi)F(SETMi)F(SETNv)F(SETUv)F(SETMv) u32* nextBC(u32* p) { switch(*p) { @@ -31,7 +32,7 @@ u32* nextBC(u32* p) { case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case ADDI: case ADDU: - case FN1Ci: case FN1Oi: case FN2Ci: case SETNi: case SETUi: case SETMi: + case FN1Ci: case FN1Oi: case FN2Ci: case SETNi: case SETUi: case SETMi: case SETNv: case SETUv: case SETMv: return p+3; case FN2Oi: return p+5; @@ -42,9 +43,13 @@ i32 stackDiff(u32* p) { if (*p==ARRO|*p==ARRM) return 1-p[1]; switch(*p) { default: UD; // case ARRO: case ARRM: return 1-p[1]; case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 1; - case FN1Ci:case FN1Oi:case CHKV: case VFYM: case FLDO: case FLDM: case SETNi:case SETUi:case RETD: case NSPM: return 0; - case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case SETMi:case POPS: case OP2H: case SETH: case RETN: return -1; - case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return -2; + case FN1Ci:case FN1Oi:case CHKV: case VFYM: case FLDO: case FLDM: case RETD: case NSPM: return 0; + case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case POPS: case OP2H: case SETH: case RETN: return -1; + case OP2D: case TR3D: case FN2C: case FN2O: case TR3O: return -2; + + case SETN: return -1; case SETNi:return 0; case SETNv:return -1; + case SETU: return -1; case SETUi:return 0; case SETUv:return -1; + case SETM: return -2; case SETMi:return -1; case SETMv:return -2; } } i32 stackConsumed(u32* p) { @@ -52,9 +57,13 @@ i32 stackConsumed(u32* p) { switch(*p) { default: UD; // case ARRO: case ARRM: return -p[1]; case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 0; case CHKV: case VFYM: case RETD: return 0; - case FN1Ci:case FN1Oi:case FLDO: case FLDM: case NSPM: case RETN: case POPS: case SETNi:case SETUi:return 1; - case FN2Ci:case FN2Oi:case FN1C: case FN1O: case SETMi:case OP1D: case TR2D: case SETN: case SETU: case OP2H: case SETH: return 2; - case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return 3; + case FN1Ci:case FN1Oi:case FLDO: case FLDM: case NSPM: case RETN: case POPS: return 1; + case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case OP2H: case SETH: return 2; + case OP2D: case TR3D: case FN2C: case FN2O: case TR3O: return 3; + + case SETN: return 2; case SETNi: case SETNv: return 1; + case SETU: return 2; case SETUi: case SETUv: return 1; + case SETM: return 3; case SETMi: case SETMv: return 2; } } i32 stackAdded(u32* p) { diff --git a/src/vm.h b/src/vm.h index 4d7b295d..27ccf9de 100644 --- a/src/vm.h +++ b/src/vm.h @@ -47,6 +47,7 @@ enum { ADDI, ADDU, // separate PUSH for refcounting needed/not needed (stores the object inline as 2 u32s, instead of reading from `objs`) 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, // SET_ alternatives that expect the set variable as a depth-position pair like LOC_ + SETNv, SETUv, SETMv, // SET_i alternatives that also don't return the result BC_SIZE };