From 4c5121e19a68faff4d1fc0b85d2495dddb60269b Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 21 Jan 2021 23:30:04 +0100 Subject: [PATCH] :art: Unrolled in the VM --- include/opcode.h | 4 ++++ opcode.txt | 2 ++ src/emit/emit.c | 18 ------------------ src/vm/vm.c | 19 +++++++++++++++++-- src/vm/vm_code.c | 24 +++++++++++++----------- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/include/opcode.h b/include/opcode.h index 9a695e72..064bee1a 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -141,6 +141,7 @@ enum { eBranchNeqInt, eBranchEqFloat, eBranchNeqFloat, + eUnroll, eArrayAppend, eAutoLoop, eArrayTop, @@ -183,6 +184,7 @@ enum { eGack, eNoOp, eEOC, + eUnroll2, eOP_MAX, eDotTmplVal, }; @@ -327,6 +329,7 @@ enum { #define BranchNeqInt (f_instr)eBranchNeqInt #define BranchEqFloat (f_instr)eBranchEqFloat #define BranchNeqFloat (f_instr)eBranchNeqFloat +#define Unroll (f_instr)eUnroll #define ArrayAppend (f_instr)eArrayAppend #define AutoLoop (f_instr)eAutoLoop #define ArrayTop (f_instr)eArrayTop @@ -369,6 +372,7 @@ enum { #define Gack (f_instr)eGack #define NoOp (f_instr)eNoOp #define EOC (f_instr)eEOC +#define Unroll2 (f_instr)eUnroll2 #define OP_MAX (f_instr)eOP_MAX #define DotTmplVal (f_instr)eDotTmplVal #endif diff --git a/opcode.txt b/opcode.txt index aafc48c9..4504ca62 100644 --- a/opcode.txt +++ b/opcode.txt @@ -138,6 +138,7 @@ BranchEqInt BranchNeqInt BranchEqFloat BranchNeqFloat +Unroll ArrayAppend AutoLoop ArrayTop @@ -180,5 +181,6 @@ GackEnd Gack NoOp EOC +Unroll2 OP_MAX DotTmplVal diff --git a/src/emit/emit.c b/src/emit/emit.c index fe0c4e06..9188b1f9 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1681,24 +1681,6 @@ ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) { return ret; } -static INSTR(Unroll) { - const m_uint n = *(m_uint*)MEM(instr->m_val -SZ_INT); - const m_uint idx = *(m_uint*)MEM(instr->m_val); - if(idx) { - if(idx >= n) - *(m_uint*)MEM(instr->m_val) -= n; - else { - *(m_uint*)MEM(instr->m_val) = 0; - shred->pc += instr->m_val2*(idx+1); - } - } else - shred->pc += instr->m_val2 *n + 1; -} - -INSTR(Unroll2) { - exit(4); -} - ANN static m_bool stmt_loop_roll(const Emitter emit, const Stmt stmt, const m_uint offset) { const Instr cpy = emit_add_instr(emit, RegPushMem4); cpy->m_val = offset; diff --git a/src/vm/vm.c b/src/vm/vm.c index 479ddb03..451852ce 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -322,7 +322,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&setcode, &®move, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcmemberend, &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend, - &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, + &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&unroll, &&arrayappend, &&autoloop, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid, &&newobj, &&addref, &&addrefaddr, &&structaddref, &&structaddrefaddr, &&objassign, &&assign, &&remref, &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr, @@ -331,7 +331,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&upvalueint, &&upvaluefloat, &&upvalueother, &&upvalueaddr, &&dotfunc, &&gcini, &&gcadd, &&gcend, - &&gacktype, &&gackend, &&gack, &&noop, &&eoc, &&other, &®pushimm + &&gacktype, &&gackend, &&gack, &&noop, &&eoc, &&unroll2, &&other, &®pushimm }; const Shreduler s = vm->shreduler; register VM_Shred shred; @@ -711,6 +711,20 @@ brancheqfloat: branchnefloat: reg -= SZ_FLOAT; BRANCH_DISPATCH(*(m_float*)reg); +unroll: +{ + const m_uint n = *(m_uint*)(mem + VAL - SZ_INT); + const m_uint idx = *(m_uint*)(mem + VAL); + if(idx) { + if(idx >= n) { + *(m_uint*)(mem + VAL) -= n; + DISPATCH() + } + *(m_uint*)(mem + VAL) = 0; + PC_DISPATCH(PC + VAL2*(idx)); + } + PC_DISPATCH(PC + VAL2 *n + 1); +} arrayappend: m_vector_add(ARRAY(*(M_Object*)(reg-SZ_INT)), reg); DISPATCH() @@ -941,6 +955,7 @@ noop: other: VM_OUT ((f_instr)VAL2)(shred, (Instr)VAL); +unroll2: in: if(!s->curr) break; diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index 7511f57e..6a12813f 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -49,9 +49,8 @@ static inline void setpc(const m_bit *data, const m_uint i) { *(unsigned*)(data+1) = i + 1; } -INSTR(Unroll2); ANN static m_bit* tobytecode(MemPool p, const VM_Code code) { - const Vector v = code->instr; + const Vector v = code->instr; const m_uint sz = vector_size(v); m_bit *ptr = _mp_malloc(p, sz * BYTECODE_SZ); struct Vector_ nop; @@ -78,29 +77,32 @@ ANN static m_bit* tobytecode(MemPool p, const VM_Code code) { } i += j; continue; - } - if(instr->opcode != eNoOp) - memcpy(data, instr, BYTECODE_SZ); - else - vector_add(&nop, i); - } else { - if(instr->execute == Unroll2) { + } else if(instr->opcode == eUnroll2) { const Instr unroll = (Instr)instr->m_val; - const m_uint pc = vector_find(v, unroll); - m_uint reduce = 0; + const m_uint pc = vector_find(v, (m_uint)unroll); + m_uint reduce_pre = 0, reduce = 0; for(m_uint j = 0; j < vector_size(&nop); ++j) { const m_uint at = vector_at(&nop, j); + if(at < pc) + ++reduce_pre; if(at >= pc) { if(at >= (pc + unroll->m_val2)) break; ++reduce; } } + m_bit *const unroll_data = ptr + (pc-reduce_pre)*BYTECODE_SZ; unroll->m_val2 -= reduce; + *(m_uint*)(unroll_data + SZ_INT *2) -= reduce; instr->opcode = eNoOp; vector_add(&nop, i); continue; } + if(instr->opcode != eNoOp) + memcpy(data, instr, BYTECODE_SZ); + else + vector_add(&nop, i); + } else { *(m_bit*)(data) = instr->opcode; *(Instr*)(data + SZ_INT) = instr; *(f_instr*)(data + SZ_INT*2) = instr->execute; -- 2.43.0