]> Nishi Git Mirror - gwion.git/commitdiff
:art: Unrolled in the VM
authorJérémie Astor <fennecdjay@gmail.com>
Thu, 21 Jan 2021 22:30:04 +0000 (23:30 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Thu, 21 Jan 2021 22:30:04 +0000 (23:30 +0100)
include/opcode.h
opcode.txt
src/emit/emit.c
src/vm/vm.c
src/vm/vm_code.c

index 9a695e7297511519259c3b91a1098665729f6622..064bee1ad0218813a18d10f81f00ace66b5242ec 100644 (file)
@@ -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
index aafc48c99873015cfa4d3e19fd8e7ecaeb459d7a..4504ca628fda666a50234ab52725fbcd1ca80d3a 100644 (file)
@@ -138,6 +138,7 @@ BranchEqInt
 BranchNeqInt
 BranchEqFloat
 BranchNeqFloat
+Unroll
 ArrayAppend
 AutoLoop
 ArrayTop
@@ -180,5 +181,6 @@ GackEnd
 Gack
 NoOp
 EOC
+Unroll2
 OP_MAX
 DotTmplVal
index fe0c4e068da3a3935ed5da1d138d009a6eb71fa2..9188b1f96bf95a77988b6ce902b5e6b8844c687a 100644 (file)
@@ -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;
index 479ddb03baa377eb696a0144a10fac91403a7b2c..451852ceb839850c16342ae06e5512acc2311c1f 100644 (file)
@@ -322,7 +322,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&setcode,
     &&regmove, &&regtomem, &&regtomemother, &&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, &&regpushimm
+    &&gacktype, &&gackend, &&gack, &&noop, &&eoc, &&unroll2, &&other, &&regpushimm
   };
   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;
index 7511f57ef50bac407540ce33056b985e28ff4ad4..6a12813fbe91c4c3d5e535f33fd4b903b4e51ee9 100644 (file)
@@ -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;