]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve Emit func
authorfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 2 Jul 2019 19:11:36 +0000 (21:11 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Tue, 2 Jul 2019 19:11:36 +0000 (21:11 +0200)
21 files changed:
Makefile
include/emit.h
include/escape.h
include/opcode.h
opcode.txt
src/emit/emit.c
src/emit/emitter.c
src/emit/escape.c
src/gwion.c
src/main.c
src/oo/nspc.c
src/vm/vm.c
tests/benchmark/fib-recurs.ck [new file with mode: 0644]
tests/benchmark/fib-recurs.gw [new file with mode: 0644]
tests/benchmark/fib-recurs.hs [new file with mode: 0644]
tests/benchmark/fib-recurs.lua [new file with mode: 0644]
tests/benchmark/fib-recurs.pl [new file with mode: 0644]
tests/benchmark/fib-recurs.py [new file with mode: 0644]
tests/benchmark/fib-recurs.rb [new file with mode: 0644]
tests/benchmark/fib-recurs.wren [new file with mode: 0644]
tests/benchmark/method_call.lua

index 353853e588213cfd4fe186c9df39283930233180..34bcf0582b8b6646b5beaa9d2a7e449afc6e914e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,8 @@ util_src := $(wildcard src/util/*.c)
 emit_src := $(wildcard src/emit/*.c)
 opt_src := $(wildcard opt/*.c)
 
+test_dir := $(filter-out tests/benchmark, $(wildcard tests/*))
+
 # add boolean
 ifeq (${DEBUG_STACK}, 1)
 CFLAGS += -DDEBUG_STACK
@@ -107,7 +109,7 @@ uninstall:
        rm ${PREFIX}/${PRG}
 
 test:
-       @bash help/test.sh tests/* examples
+       @bash help/test.sh ${test_dir}
 
 include $(wildcard .d/*.d)
 include util/intl.mk
index ddbf81e0cbf54d4a154b0f90c4c6c62e9d44d647..fd7c8c4dd4a1fe633e3de28a7ba9b2f0407cb4f0 100644 (file)
@@ -20,13 +20,14 @@ struct Emitter_ {
   Code*  code;
   struct Gwion_ *gwion;
   struct Vector_  stack;
+  struct Vector_ pure;
   struct Vector_  variadic;
   char *escape;
   m_bool memoize;
 };
 
-ANEW ANN Emitter new_emitter(void/*const Env*/);
-ANN void free_emitter(Emitter);
+ANEW ANN Emitter new_emitter(MemPool);
+ANN void free_emitter(MemPool, Emitter);
 ANEW ANN VM_Code emit_code(const Emitter);
 ANN VM_Code emit_ast(const Emitter emit, Ast ast);
 ANN m_bool emit_exp_call1(const Emitter, const Func);
index 805a569a120c4480cf678800ad4d3264405c9c94..fcf4b7cb95110439a5a6dd9281453bd64ab2c454 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef __ESCAPE
 #define __ESCAPE
-char* escape_table(void);
+char* escape_table(MemPool);
 ANN m_int str2char(const Emitter, const m_str, const loc_t);
 ANN m_bool escape_str(const Emitter, m_str, const loc_t);
 #endif
index 17c3343f0e2b61a6cefa9427e6c6570cb451b8cb..4605b40c6b3aa88217488d9c9d2fb6433e59cafc 100644 (file)
@@ -124,6 +124,7 @@ enum {
   eRegPop,
   eRegPush,
   eReg2Mem,
+  eReg2Mem4,
   eOverflow,
   eNext,
   eFuncUsrEnd,
@@ -297,6 +298,7 @@ enum {
 #define  RegPop              (f_instr)eRegPop
 #define  RegPush             (f_instr)eRegPush
 #define  Reg2Mem             (f_instr)eReg2Mem
+#define  Reg2Mem4            (f_instr)eReg2Mem4
 #define  Overflow            (f_instr)eOverflow
 #define  Next                (f_instr)eNext
 #define  FuncUsrEnd          (f_instr)eFuncUsrEnd
index 2ce931361933e580a4993e123a79f18482911a6f..f88b8c998e764fee5f4ee0b2961fc4f5f80fc4cf 100644 (file)
@@ -121,6 +121,7 @@ FuncUsr
 RegPop
 RegPush
 Reg2Mem
+Reg2Mem4
 Overflow
 Next
 FuncUsrEnd
index 929e1c64e95f69bf3aed8a80a3738e02054396ef..473590b757611b7f9a6fc206cc98596618682b4a 100644 (file)
@@ -124,6 +124,7 @@ ANN static void emit_pop_scope(const Emitter emit) {
     Instr instr = emit_add_instr(emit, ObjectRelease);
     instr->m_val = (m_uint)offset;
   }
+  vector_pop(&emit->pure);
 }
 
 ANN static inline void emit_push_code(const Emitter emit, const m_str name) {
@@ -137,6 +138,7 @@ ANN static inline void emit_pop_code(const Emitter emit)   {
 
 ANN static inline void emit_push_scope(const Emitter emit) {
   frame_push(emit->code->frame);
+  vector_add(&emit->pure, 0);
 }
 
 ANN static inline m_uint emit_code_size(const Emitter emit) {
@@ -231,6 +233,10 @@ ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) {
   return GW_OK;
 }
 
+ANN static inline void emit_notpure(const Emitter emit) {
+  ++VPTR(&emit->pure, VLEN(&emit->pure));
+}
+
 ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type,
     const Array_Sub arr, const uint is_ref) {
   Array_Sub array = arr;
@@ -257,6 +263,7 @@ ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type,
     instr->m_val2 = (m_uint)type;
     emit_pre_ctor(emit, type);
   }
+  emit_notpure(emit);
   return GW_OK;
 }
 
@@ -385,6 +392,7 @@ ANN static m_bool prim_array(const Emitter emit, const Exp_Primary * primary) {
   instr->m_val = (m_uint)type;
   instr->m_val2 = type->array_depth == 1 ? array_base(type)->size : SZ_INT;
   emit_add_instr(emit, GcAdd);
+  emit_notpure(emit);
   return GW_OK;
 }
 
@@ -832,28 +840,35 @@ ANN static Instr get_prelude(const Emitter emit, const Func f) {
   return instr;
 }
 
+ANN static void emit_args(const Emitter emit, const Func f) {
+  const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0;
+  if((f->def->stack_depth - member) == SZ_INT) {
+    const Instr instr = emit_add_instr(emit, Reg2Mem);
+    instr->m_val = member;
+  } else {
+    const Instr instr = emit_add_instr(emit, Reg2Mem4);
+    instr->m_val = member;
+    instr->m_val2 = f->def->stack_depth - member;
+  }
+}
+
 ANN static Instr emit_call(const Emitter emit, const Func f) {
   const Instr memoize = !(emit->memoize && GET_FLAG(f, pure)) ? NULL : emit_add_instr(emit, MemoizeCall);
-  f_instr exec;
   const Instr prelude = get_prelude(emit, f);
-  if(f->def->stack_depth) {
-    const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0;
-    prelude->m_val = f->def->stack_depth;
-    if(member) {
-      const Instr instr = emit_add_instr(emit, Reg2Mem);
-      instr->m_val2 = f->def->stack_depth - SZ_INT;
-      ++prelude->m_val2;
-    }
-    for(m_uint i = 0; i < f->def->stack_depth - member; i += SZ_INT) {
-      const Instr instr = emit_add_instr(emit, Reg2Mem);
-      instr->m_val = (instr->m_val2 = i) + member;
-      ++prelude->m_val2;
-    }
+  prelude->m_val = f->def->stack_depth;
+  const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0;
+  if(member) {
+    const Instr instr = emit_add_instr(emit, Reg2Mem);
+    instr->m_val2 = f->def->stack_depth - SZ_INT;
+    ++prelude->m_val2;
+  }
+  if(f->def->stack_depth - member) {
+    emit_args(emit, f);
+    ++prelude->m_val2;
   }
-  exec = Overflow;
   if(memoize)
     memoize->m_val = prelude->m_val2 + 1;
-  return emit_add_instr(emit, exec);
+  return emit_add_instr(emit, Overflow);
 }
 
 ANN m_bool emit_exp_call1(const Emitter emit, const Func f) {
@@ -911,7 +926,7 @@ static inline void stack_alloc_this(const Emitter emit) {
 static m_bool scoped_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) {
   ++emit->env->scope->depth;
   emit_push_scope(emit);
-  const m_bool pure = SAFE_FLAG(emit->env->func, pure);
+  const m_bool pure = !vector_back(&emit->pure);
   if(!pure)
     emit_add_instr(emit, GcIni);
   CHECK_BB(emit_stmt(emit, stmt, pop))
@@ -1082,13 +1097,10 @@ ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) {
 }
 
 ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) {
-  Exp arg = e->args;
-  if(arg)
+  if(e->args) {
     CHECK_BB(emit_exp(emit, e->args, 0))
-  regpop(emit, SZ_INT);
-  for(m_uint i = 0; i < e->m_func->def->stack_depth; i += SZ_INT) {
-    const Instr instr = emit_add_instr(emit, Reg2Mem);
-    instr->m_val = instr->m_val2 = i;
+    regpop(emit, SZ_INT);
+    emit_args(emit, e->m_func);
   }
   emit_add_instr(emit, Goto);
   return GW_OK;
@@ -1137,7 +1149,7 @@ ANN static void emit_pop_stack(const Emitter emit, const m_uint index) {
 
 ANN static m_uint get_decl_size(Var_Decl_List a) {
   m_uint size = 0;
-  do if(GET_FLAG(a->self->value, used))
+  do //if(GET_FLAG(a->self->value, used))
     size += a->self->value->type->size;
   while((a = a->next));
   return size;
@@ -1678,9 +1690,6 @@ ANN static void emit_func_def_code(const Emitter emit, const Func func) {
     emit->env->class_def->nspc->dtor = func->code;
     ADD_REF(func->code)
   }
-  // TODO: find why we need this
-  assert(func->def->stack_depth == func->code->stack_depth);
-  func->def->stack_depth = func->code->stack_depth;
 }
 
 ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) {
@@ -1807,6 +1816,7 @@ ANN static VM_Code emit_free_stack(const Emitter emit) {
   for(m_uint i = vector_size(&emit->stack) + 1; --i;)
     emit_free_code(emit, (Code*)vector_at(&emit->stack, i - 1));
   vector_clear(&emit->stack);
+  vector_clear(&emit->pure);
   emit_free_code(emit, emit->code);
   return NULL;
 }
index 97b6103475207831fc1c9c6cc7f9085b0332d6fd..3ac80be7ab863a037f6c630c3f78019e18acb5b5 100644 (file)
 #include "emit.h"
 #include "escape.h"
 
-ANEW Emitter new_emitter(void) {
-  Emitter emit = (Emitter)xcalloc(1, sizeof(struct Emitter_));
+ANEW Emitter new_emitter(MemPool p) {
+  Emitter emit = (Emitter)mp_calloc(p, Emitter);
   vector_init(&emit->stack);
+  vector_init(&emit->pure);
   vector_init(&emit->variadic);
-  emit->escape = escape_table();
+  emit->escape = escape_table(p);
   return emit;
 }
 
-ANN void free_emitter(Emitter a) {
+ANN void free_emitter(MemPool p, Emitter a) {
   vector_release(&a->stack);
+  vector_release(&a->pure);
   vector_release(&a->variadic);
-  xfree(a->escape);
-  xfree(a);
+  mp_free2(p, 256, a->escape);
+  mp_free(p, Emitter, a);
 }
 
 __attribute__((returns_nonnull))
index 68a32cbbbd24ae0ee90ec12e838774959ce1713a..bbd68112beff06e3cd3d5aaeff0ff7a7d1f6071c 100644 (file)
@@ -7,8 +7,8 @@
 #include "emit.h"
 #include "escape.h"
 
-char* escape_table(void) {
-  char *escape = (char*)calloc(256, sizeof(char));
+char* escape_table(MemPool p) {
+  char *escape = (char*)mp_calloc2(p, 256);
   escape['0'] = '0';
   escape['\''] = '\'';
   escape['"'] = '"';
index b6d62bce33ceb21a9091a6143305c357912720c0..6ed44bb301822031001b06ef1b6e567c74e52d4e 100644 (file)
@@ -61,7 +61,7 @@ ANN m_bool gwion_ini(const Gwion gwion, Arg* arg) {
   gwion->mp = mempool_ini((sizeof(VM_Shred) + SIZEOF_REG + SIZEOF_MEM) / SZ_INT);
   gwion->st = new_symbol_table(gwion->mp, 65347);
   gwion->vm = new_vm(gwion->mp, 1);
-  gwion->emit = new_emitter();
+  gwion->emit = new_emitter(gwion->mp);
   gwion->env = new_env(gwion->mp);
   gwion->emit->env = gwion->env;
   gwion->emit->gwion = gwion;
@@ -97,7 +97,7 @@ ANN void gwion_end(const Gwion gwion) {
   MUTEX_UNLOCK(gwion->vm->shreduler->mutex);
   free_env(gwion->env);
   free_vm_shred(gwion->vm->cleaner_shred);
-  free_emitter(gwion->emit);
+  free_emitter(gwion->mp, gwion->emit);
   free_vm(gwion->vm);
   free_plug(gwion);
   free_gwiondata(gwion->mp, gwion->data);
index 281e6a2a30460ea5360232078dd7436632930db3..5d27a751154361f4b70bc85add2032ae8b843ae5 100644 (file)
@@ -24,6 +24,8 @@ int main(int argc, char** argv) {
   arg_release(&arg);
   if(ini > 0)
     gwion_run(&gwion);
+#ifndef NDEBUG
   gwion_end(&gwion);
+#endif
   THREAD_RETURN(EXIT_SUCCESS);
 }
index a30f36273f42dab081305ed8f7ed4b05fdc5d1a8..4ecba6480b4a4f75cab5ea93c68beef1c6a1191e 100644 (file)
@@ -32,13 +32,9 @@ ANN static void free_nspc_value(const Nspc a, Gwion gwion) {
   Value v;
   if(!a->is_union) {
     while(scope_iter(&iter, &v) > 0) {
-const Type  t = (GET_FLAG(v, builtin) && v->type->array_depth) ?
-  v->type : NULL;
       if(isa(v->type, t_object) > 0)
         nspc_release_object(a, v, gwion);
       REM_REF(v, gwion);
-if(t)
-    REM_REF(t, gwion);
     }
   }
   free_scope(gwion->mp, a->info->value);
index 4ff220d5cb2422650b02a2f8ddf1872fd203f07a..385996b3a6692f0e092ccd841cc5320d43a3f573 100644 (file)
@@ -299,7 +299,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&itof, &&ftoi,
     &&timeadv,
     &&setcode, &&funcptr, &&funcmember,
-    &&funcusr, &&regpop, &&regpush, &&regtomem, &&overflow, &&next, &&funcusrend, &&funcmemberend,
+    &&funcusr, &&regpop, &&regpush, &&regtomem, &&regtomemother, &&overflow, &&next, &&funcusrend, &&funcmemberend,
     &&sporkini, &&sporkini, &&sporkfunc, &&sporkexp, &&forkend, &&sporkend,
     &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
     &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
@@ -606,6 +606,9 @@ regpush:
 regtomem:
   *(m_uint*)(mem+VAL) = *(m_uint*)(reg+VAL2);
   DISPATCH()
+regtomemother:
+  memcpy(mem+VAL, reg, VAL2);
+  DISPATCH()
 overflow:
   if(overflow_(mem, shred)) {
     exception(shred, "StackOverflow");
diff --git a/tests/benchmark/fib-recurs.ck b/tests/benchmark/fib-recurs.ck
new file mode 100644 (file)
index 0000000..c0026c4
--- /dev/null
@@ -0,0 +1,10 @@
+//int count = 0;
+fun int recursive_fib(int n)
+{
+//    ++count;
+    if (n < 2)
+        return n;
+    else
+        return recursive_fib(n - 2) + recursive_fib(n - 1);
+}
+<<<recursive_fib(40)>>>;
diff --git a/tests/benchmark/fib-recurs.gw b/tests/benchmark/fib-recurs.gw
new file mode 100644 (file)
index 0000000..fef14c6
--- /dev/null
@@ -0,0 +1,8 @@
+fun int recursive_fib(int n) {
+    if (n < 2)
+        return n;
+    else
+        return recursive_fib(n - 2) + recursive_fib(n - 1);
+}
+//<<<5 => recursive_fib>>>;
+<<<40 => recursive_fib>>>;
diff --git a/tests/benchmark/fib-recurs.hs b/tests/benchmark/fib-recurs.hs
new file mode 100644 (file)
index 0000000..6929769
--- /dev/null
@@ -0,0 +1,6 @@
+fib :: Int -> Int
+fib n
+  | n < 2 = n
+  | otherwise = (fib (n-2)) + (fib (n-1))
+
+main = print $ fib 40
diff --git a/tests/benchmark/fib-recurs.lua b/tests/benchmark/fib-recurs.lua
new file mode 100644 (file)
index 0000000..3b84ea3
--- /dev/null
@@ -0,0 +1,6 @@
+local function fib(n)
+    if n <= 2 then return 1 end
+    return fib(n - 1) + fib(n - 2)
+end
+
+print(fib(40))
diff --git a/tests/benchmark/fib-recurs.pl b/tests/benchmark/fib-recurs.pl
new file mode 100644 (file)
index 0000000..55092d2
--- /dev/null
@@ -0,0 +1,9 @@
+sub fibonacci_recurs {
+   my ($number) = @_;
+   if ($number < 2) { # base case
+      return $number;
+   }
+   return fibonacci_recurs($number-1) + fibonacci_recurs($number-2);
+}
+
+print fibonacci_recurs(40) , "\n";
diff --git a/tests/benchmark/fib-recurs.py b/tests/benchmark/fib-recurs.py
new file mode 100644 (file)
index 0000000..672317f
--- /dev/null
@@ -0,0 +1,7 @@
+def fibonacci_recurs(n):
+  if n < 2:
+    return n;
+  else:
+    return (fibonacci_recurs(n-1) + fibonacci_recurs(n-2))
+
+print(fibonacci_recurs(40))
diff --git a/tests/benchmark/fib-recurs.rb b/tests/benchmark/fib-recurs.rb
new file mode 100644 (file)
index 0000000..00f33f1
--- /dev/null
@@ -0,0 +1,5 @@
+def fibonacci_recurs( n )
+  if n < 2 then return n end
+  return ( fibonacci_recurs( n - 1 ) + fibonacci_recurs( n - 2 ) )
+end
+puts fibonacci_recurs(40)
diff --git a/tests/benchmark/fib-recurs.wren b/tests/benchmark/fib-recurs.wren
new file mode 100644 (file)
index 0000000..db980c4
--- /dev/null
@@ -0,0 +1,8 @@
+class Fib {
+  static get(n) {
+    if (n < 2) return n
+    return get(n - 1) + get(n - 2)
+  }
+}
+
+System.print(Fib.get(40))
index 45ce53577b927bd705beea50c3a3f18155a553b2..20a6d6ac83d30e6a5dbdbcb13f94f0f07e891b6d 100644 (file)
@@ -53,7 +53,6 @@ end
 -----------------------------------------------------------
 
 function main ()
-  local start = os.clock()
   local N = 100000
 
   local val = 1
@@ -87,7 +86,6 @@ function main ()
     val = ntoggle:activate():value()
   end
   print(val and "true" or "false")
-  io.write(string.format("elapsed: %.8f\n", os.clock() - start))
 end
 
 main()