From: fennecdjay Date: Tue, 2 Jul 2019 19:11:36 +0000 (+0200) Subject: :art: Improve Emit func X-Git-Tag: nightly~2382^2~3 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=7add0f91ca1915dacbb6515179d6ec63c066dd41;p=gwion.git :art: Improve Emit func --- diff --git a/Makefile b/Makefile index 353853e5..34bcf058 100644 --- 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 diff --git a/include/emit.h b/include/emit.h index ddbf81e0..fd7c8c4d 100644 --- a/include/emit.h +++ b/include/emit.h @@ -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); diff --git a/include/escape.h b/include/escape.h index 805a569a..fcf4b7cb 100644 --- a/include/escape.h +++ b/include/escape.h @@ -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 diff --git a/include/opcode.h b/include/opcode.h index 17c3343f..4605b40c 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -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 diff --git a/opcode.txt b/opcode.txt index 2ce93136..f88b8c99 100644 --- a/opcode.txt +++ b/opcode.txt @@ -121,6 +121,7 @@ FuncUsr RegPop RegPush Reg2Mem +Reg2Mem4 Overflow Next FuncUsrEnd diff --git a/src/emit/emit.c b/src/emit/emit.c index 929e1c64..473590b7 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -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; } diff --git a/src/emit/emitter.c b/src/emit/emitter.c index 97b61034..3ac80be7 100644 --- a/src/emit/emitter.c +++ b/src/emit/emitter.c @@ -11,19 +11,21 @@ #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)) diff --git a/src/emit/escape.c b/src/emit/escape.c index 68a32cbb..bbd68112 100644 --- a/src/emit/escape.c +++ b/src/emit/escape.c @@ -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['"'] = '"'; diff --git a/src/gwion.c b/src/gwion.c index b6d62bce..6ed44bb3 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -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); diff --git a/src/main.c b/src/main.c index 281e6a2a..5d27a751 100644 --- a/src/main.c +++ b/src/main.c @@ -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); } diff --git a/src/oo/nspc.c b/src/oo/nspc.c index a30f3627..4ecba648 100644 --- a/src/oo/nspc.c +++ b/src/oo/nspc.c @@ -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); diff --git a/src/vm/vm.c b/src/vm/vm.c index 4ff220d5..385996b3 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -299,7 +299,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&itof, &&ftoi, &&timeadv, &&setcode, &&funcptr, &&funcmember, - &&funcusr, &®pop, &®push, &®tomem, &&overflow, &&next, &&funcusrend, &&funcmemberend, + &&funcusr, &®pop, &®push, &®tomem, &®tomemother, &&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 index 00000000..c0026c47 --- /dev/null +++ b/tests/benchmark/fib-recurs.ck @@ -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); +} +<<>>; diff --git a/tests/benchmark/fib-recurs.gw b/tests/benchmark/fib-recurs.gw new file mode 100644 index 00000000..fef14c6f --- /dev/null +++ b/tests/benchmark/fib-recurs.gw @@ -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 index 00000000..6929769e --- /dev/null +++ b/tests/benchmark/fib-recurs.hs @@ -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 index 00000000..3b84ea32 --- /dev/null +++ b/tests/benchmark/fib-recurs.lua @@ -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 index 00000000..55092d23 --- /dev/null +++ b/tests/benchmark/fib-recurs.pl @@ -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 index 00000000..672317f8 --- /dev/null +++ b/tests/benchmark/fib-recurs.py @@ -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 index 00000000..00f33f13 --- /dev/null +++ b/tests/benchmark/fib-recurs.rb @@ -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 index 00000000..db980c49 --- /dev/null +++ b/tests/benchmark/fib-recurs.wren @@ -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)) diff --git a/tests/benchmark/method_call.lua b/tests/benchmark/method_call.lua index 45ce5357..20a6d6ac 100644 --- a/tests/benchmark/method_call.lua +++ b/tests/benchmark/method_call.lua @@ -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()