From: Jérémie Astor Date: Wed, 30 Dec 2020 01:48:32 +0000 (+0100) Subject: :art: Peephole optimization X-Git-Tag: nightly~1073 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=da3bd8e397d5e30b3fc2e55941691f9a40495165;p=gwion.git :art: Peephole optimization --- diff --git a/include/instr.h b/include/instr.h index c5286af0..b084ce4a 100644 --- a/include/instr.h +++ b/include/instr.h @@ -28,7 +28,7 @@ struct Instr_ { m_uint m_val2; void (*execute)(const VM_Shred shred, const Instr instr); }; -#define BYTECODE_SZ (sizeof(struct Instr_) - SZ_INT) +#define BYTECODE_SZ ((2*sizeof(unsigned)) + sizeof(struct Instr_) - SZ_INT*2) INSTR(EOC); INSTR(DTOR_EOC); @@ -49,7 +49,6 @@ INSTR(ArrayStruct); /* vararg */ INSTR(VarargIni); -INSTR(VarargCheck); INSTR(DotTmpl); INSTR(GTmpl); diff --git a/include/opcode.h b/include/opcode.h index a94876d0..60813e0d 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -125,8 +125,7 @@ enum { eCastF2I, eTime_Advance, eSetCode, - eRegPop, - eRegPush, + eRegMove, eReg2Mem, eReg2Mem4, eOverflow, @@ -313,8 +312,7 @@ enum { #define CastF2I (f_instr)eCastF2I #define Time_Advance (f_instr)eTime_Advance #define SetCode (f_instr)eSetCode -#define RegPop (f_instr)eRegPop -#define RegPush (f_instr)eRegPush +#define RegMove (f_instr)eRegMove #define Reg2Mem (f_instr)eReg2Mem #define Reg2Mem4 (f_instr)eReg2Mem4 #define Overflow (f_instr)eOverflow diff --git a/include/vararg.h b/include/vararg.h index 76feea9f..14dbdf14 100644 --- a/include/vararg.h +++ b/include/vararg.h @@ -3,7 +3,7 @@ struct Vararg_ { struct Vector_ t; // types m_bit *d; // d(ata) - m_uint o, i, s, l; // o(ffset), i(ndex), s(ize), l(en) + m_uint /*o, i, s,*/ l; // o(ffset), i(ndex), s(ize), l(en) m_uint pc; }; ANN void emit_vararg_end(const Emitter emit, const m_uint pc); diff --git a/opcode.txt b/opcode.txt index 840be081..f8f71c43 100644 --- a/opcode.txt +++ b/opcode.txt @@ -122,8 +122,7 @@ CastI2F CastF2I Time_Advance SetCode -RegPop -RegPush +RegMove Reg2Mem Reg2Mem4 Overflow diff --git a/src/emit/emit.c b/src/emit/emit.c index 2e26303f..d4d1a2c6 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -82,14 +82,20 @@ static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, Al static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 }; static const f_instr structmember[] = { StructMember, StructMemberFloat, StructMemberOther, StructMemberAddr }; +#define regmove(name, op) \ +ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ + const Instr instr = emit_add_instr(emit, RegMove); \ + instr->m_val = op sz; \ + return instr; \ +} +regmove(pop,-) +regmove(push,) #define regxxx(name, instr) \ ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ const Instr instr = emit_add_instr(emit, Reg##instr); \ instr->m_val = sz; \ return instr; \ } -regxxx(pop, Pop) -regxxx(push, Push) regxxx(pushi, PushImm) regxxx(seti, SetImm) @@ -125,7 +131,7 @@ ANN static void emit_struct_ctor(const Emitter emit, const Type type, const m_ui regpush(emit, SZ_INT *2); const Instr prelude = emit_add_instr(emit, SetCode); prelude->m_val2 = 2; - prelude->m_val = SZ_INT*3; + prelude->m_val = -SZ_INT*3; const Instr next = emit_add_instr(emit, Overflow); next->m_val2 = code_offset; emit->code->frame->curr_offset -= SZ_INT; @@ -322,7 +328,7 @@ ANN void emit_ext_ctor(const Emitter emit, const Type t) { regpush(emit, SZ_INT*2); const Instr prelude = emit_add_instr(emit, SetCode); prelude->m_val2 = 2; - prelude->m_val = SZ_INT; + prelude->m_val = -SZ_INT; emit_add_instr(emit, Reg2Mem); const Instr next = emit_add_instr(emit, Overflow); next->m_val2 = offset; @@ -769,7 +775,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *d if(!vflag(v, vflag_member)) { v->from->offset = emit_local(emit, type); exec = (f_instr*)(allocword); - if(GET_FLAG(decl->td, late)) { // ref or emit_var ? + if(GET_FLAG(v, late)) { // ref or emit_var ? const Instr clean = emit_add_instr(emit, MemSetImm); clean->m_val = v->from->offset; } @@ -1148,7 +1154,7 @@ ANN static m_bool me_arg(MemoizeEmitter *me) { ANN static Instr emit_call(const Emitter emit, const Func f) { const Instr prelude = get_prelude(emit, f); - prelude->m_val = f->def->stack_depth; + prelude->m_val = -f->def->stack_depth; const m_uint member = vflag(f->value_ref, vflag_member) ? SZ_INT : 0; if(member) { const Instr instr = emit_add_instr(emit, Reg2Mem); @@ -1621,9 +1627,14 @@ ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, co ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) { CHECK_BB(variadic_state(emit, stmt, 1)) CHECK_BB(emit_exp(emit, stmt->exp)) - const Instr check = emit_add_instr(emit, VarargCheck); + const Instr s = emit_add_instr(emit, DotMember); + s->m_val = SZ_INT * 5; + const Instr nonnull = emit_add_instr(emit, Goto); + regpop(emit, SZ_INT); + const Instr check = emit_add_instr(emit, Goto); const Instr member = emit_add_instr(emit, DotMember4); member->m_val = SZ_INT*2; + nonnull->m_val = emit_code_size(emit); const Instr instr = emit_add_instr(emit, BranchEqInt); const m_uint pc = emit_code_size(emit); emit_stmt(emit, stmt->body, 1); diff --git a/src/lib/array.c b/src/lib/array.c index 21da4fc6..e356907f 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -191,8 +191,8 @@ static OP_CHECK(opck_array_sr) { } ANN static inline m_bool emit_array_shift(const Emitter emit, const f_instr exec) { - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -SZ_INT; (void)emit_add_instr(emit, exec); return GW_OK; } @@ -243,8 +243,8 @@ static OP_EMIT(opem_array_sr) { const Exp_Binary* bin = (Exp_Binary*)data; if(bin->rhs->type->array_depth == bin->lhs->type->array_depth) return emit_array_shift(emit, ArrayConcatRight); - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -SZ_INT; emit_gc(emit, 0); (void)emit_add_instr(emit, ArrayAppendFront); return GW_OK; @@ -254,8 +254,8 @@ static OP_EMIT(opem_array_sl) { const Exp_Binary* bin = (Exp_Binary*)data; if(bin->lhs->type->array_depth == bin->rhs->type->array_depth) return emit_array_shift(emit, ArrayConcatLeft); - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = bin->rhs->type->size; + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -bin->rhs->type->size; emit_gc(emit, -SZ_INT); emit_add_instr(emit, ArrayAppend); return GW_OK; @@ -332,8 +332,8 @@ static OP_CHECK(opck_array) { } ANN static void array_loop(const Emitter emit, const m_uint depth) { - const Instr pre_pop = emit_add_instr(emit, RegPop); - pre_pop->m_val = depth * SZ_INT; + const Instr pre_pop = emit_add_instr(emit, RegMove); + pre_pop->m_val = -depth * SZ_INT; for(m_uint i = 0; i < depth - 1; ++i) { const Instr access = emit_add_instr(emit, ArrayAccess); access->m_val = i * SZ_INT; @@ -342,8 +342,8 @@ ANN static void array_loop(const Emitter emit, const m_uint depth) { get->m_val = i * SZ_INT; get->m_val2 = -SZ_INT; } - const Instr post_pop = emit_add_instr(emit, RegPop); - post_pop->m_val = SZ_INT; + const Instr post_pop = emit_add_instr(emit, RegMove); + post_pop->m_val = -SZ_INT; const Instr access = emit_add_instr(emit, ArrayAccess); access->m_val = depth * SZ_INT; } @@ -352,7 +352,8 @@ ANN static void array_finish(const Emitter emit, const m_uint depth, const m_uint size, const m_bool is_var) { const Instr get = emit_add_instr(emit, is_var ? ArrayAddr : ArrayGet); get->m_val = depth * SZ_INT; - const Instr push = emit_add_instr(emit, ArrayValid); + emit_add_instr(emit, ArrayValid); + const Instr push = emit_add_instr(emit, RegMove); push->m_val = is_var ? SZ_INT : size; } diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index 6e893764..55ba5e94 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -34,8 +34,8 @@ static OP_EMIT(opem_func_assign) { fptr_instr(emit, bin->lhs->type->info->func, 2); (void)emit_add_instr(emit, int_r_assign); if(!is_fptr(emit->gwion, bin->lhs->type) && vflag(bin->rhs->type->info->func->value_ref, vflag_member)) { - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -SZ_INT; const Instr cpy = emit_add_instr(emit, Reg2Reg); cpy->m_val = -SZ_INT; } @@ -235,8 +235,8 @@ static OP_CHECK(opck_fptr_cast) { } static void member_fptr(const Emitter emit) { - const Instr instr = emit_add_instr(emit, RegPop); - instr->m_val = SZ_INT; + const Instr instr = emit_add_instr(emit, RegMove); + instr->m_val = -SZ_INT; const Instr dup = emit_add_instr(emit, Reg2Reg); dup->m_val = -SZ_INT; } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index 3f71c388..3ad5a6b7 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -136,7 +136,7 @@ ANN static inline void emit_struct_data(const Emitter emit, const Value v, const const Instr instr = emit_kind(emit, v->type->size, emit_addr, structmember); instr->m_val = v->from->offset; if(!emit_addr) { - const Instr instr = emit_add_instr(emit, RegPush); + const Instr instr = emit_add_instr(emit, RegMove); instr->m_val = v->type->size -SZ_INT; } } @@ -294,9 +294,18 @@ ANN void struct_release(const VM_Shred shred, const Type base, const m_bit *ptr) } static OP_EMIT(opem_not_object) { - const Instr instr = (Instr)vector_back(&emit->code->instr); - if(instr->opcode == eGWOP_EXCEPT) - vector_pop(&emit->code->instr); + const Vector v = &emit->code->instr; + const Instr last = (Instr)vector_pop(v); + mp_free(emit->gwion->mp, Instr, last); + const Instr back = (Instr)vector_back(v); + if(back->opcode == eGWOP_EXCEPT) { + vector_pop(v); + mp_free(emit->gwion->mp, Instr, back); + emit_add_instr(emit, IntNot); + return GW_OK; + } + const Instr instr = emit_add_instr(emit, RegSetImm); + instr->m_val2 = -SZ_INT; return GW_OK; } diff --git a/src/lib/ptr.c b/src/lib/ptr.c index 98e146b9..cbb1793e 100644 --- a/src/lib/ptr.c +++ b/src/lib/ptr.c @@ -56,8 +56,8 @@ static INSTR(instr_ptr_assign_obj) { } static OP_EMIT(opem_ptr_assign) { - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -SZ_INT; const Exp_Binary* bin = (Exp_Binary*)data; if(isa(bin->lhs->type, emit->gwion->type[et_object]) > 0) { const Instr instr = emit_add_instr(emit, RegAddRefAddr); diff --git a/src/lib/union.c b/src/lib/union.c index 5f68019d..bf368cdc 100644 --- a/src/lib/union.c +++ b/src/lib/union.c @@ -25,8 +25,8 @@ static OP_CHECK(opck_none) { } static OP_EMIT(opem_none) { - const Instr instr = emit_add_instr(emit, RegPop); - instr->m_val = SZ_INT; + const Instr instr = emit_add_instr(emit, RegMove); + instr->m_val = -SZ_INT; return GW_OK; } diff --git a/src/lib/vararg.c b/src/lib/vararg.c index 35d38061..a3c87d57 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -46,18 +46,18 @@ static MFUN(mfun_vararg_cpy) { arg->d = (m_bit*)xmalloc(round2szint(*(m_uint*)(o->data + SZ_INT*2))); m_uint offset = 0; for(m_uint i = 0; i < vector_size(&arg->t); ++i) { - const Type t = (Type)vector_at(&arg->t, arg->i); + const Type t = (Type)vector_at(&arg->t, *(m_uint*)(o->data + SZ_INT*4)); *(m_uint*)(arg->d + offset) = *(m_uint*)(src->d + offset); if(isa(t, shred->info->vm->gwion->type[et_object]) > 0) ++(*(M_Object*)(arg->d + offset))->ref; offset += t->size; } - arg->s = vector_size(&arg->t); - arg->i = src->i; - arg->o = src->o; const M_Object obj = new_object(shred->info->mp, shred, o->type_ref); *(struct Vararg_**)obj->data = arg; *(m_uint*)(obj->data + SZ_INT*2) = *(m_uint*)(o->data + SZ_INT*2); + *(m_uint*)(obj->data + SZ_INT*3) = *(m_uint*)(o->data + SZ_INT*3); + *(m_uint*)(obj->data + SZ_INT*4) = *(m_uint*)(o->data + SZ_INT*4); + *(m_uint*)(obj->data + SZ_INT*4) = vector_size(&arg->t); // can we copy? *(M_Object*)RETURN = obj; } @@ -81,28 +81,22 @@ INSTR(VarargIni) { } offset += t->size; } - arg->s = vector_size(kinds); + *(m_uint*)(o->data + SZ_INT * 5) = vector_size(kinds); } *(M_Object*)REG(-SZ_INT) = o; } -INSTR(VarargCheck) { - const M_Object o = *(M_Object*)(shred->reg-SZ_INT); - struct Vararg_ *arg = *(struct Vararg_**)o->data; - if(arg->s) - return; - shred->reg -= SZ_INT; - shred->pc = instr->m_val; -} - static INSTR(VarargEnd) { const M_Object o = *(M_Object*)REG(0); struct Vararg_* arg = *(struct Vararg_**)o->data; - arg->o += arg->t.ptr ? ((Type)vector_at(&arg->t, arg->i))->size : 0; - if(++arg->i < arg->s) - shred->pc = instr->m_val; - else - arg->i = arg->o = 0; + *(m_uint*)(o->data + SZ_INT*3) += arg->t.ptr ? ((Type)vector_at(&arg->t, *(m_uint*)(o->data + SZ_INT*4)))->size : 0; + if(++*(m_uint*)(o->data + SZ_INT*4) == *(m_uint*)(o->data + SZ_INT * 5)) { +// if(++*(m_uint*)(o->data + SZ_INT*4) < *(m_uint*)(o->data + SZ_INT * 5)) +// shred->pc = instr->m_val; +// else + *(m_uint*)(o->data + SZ_INT*4) = *(m_uint*)(o->data + SZ_INT*3) = 0; + ++shred->pc; + } } static OP_CHECK(opck_vararg_cast) { @@ -116,12 +110,12 @@ static INSTR(VarargCast) { Except(shred, "Using Vararg outside varloop"); struct Vararg_* arg = *(struct Vararg_**)o->data; const Type t = (Type)instr->m_val, - u = (Type)vector_at(&arg->t, arg->i); + u = (Type)vector_at(&arg->t, *(m_uint*)(o->data + SZ_INT*4)); if(isa(u, t) > 0 || (u == shred->info->vm->gwion->type[et_error] && isa(t, shred->info->vm->gwion->type[et_object]) > 0)) { for(m_uint i = 0; i < t->size; i += SZ_INT) - *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i); + *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + *(m_uint*)(o->data + SZ_INT*3) + i); } else Except(shred, "InvalidVariadicAccess"); } @@ -130,7 +124,7 @@ static OP_EMIT(opem_vararg_cast) { const Exp_Cast* cast = (Exp_Cast*)data; const Instr instr = emit_add_instr(emit, VarargCast); instr->m_val = (m_uint)exp_self(cast)->type; - const Instr push = emit_add_instr(emit, RegPush); + const Instr push = emit_add_instr(emit, RegMove); push->m_val = exp_self(cast)->type->size - SZ_INT; return GW_OK; } @@ -157,9 +151,10 @@ static GACK(gack_vararg) { } ANN void emit_vararg_end(const Emitter emit, const m_uint pc) { - const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = SZ_INT; - const Instr instr = emit_add_instr(emit, VarargEnd); + const Instr pop = emit_add_instr(emit, RegMove); + pop->m_val = -SZ_INT; + (void)emit_add_instr(emit, VarargEnd); + const Instr instr = emit_add_instr(emit, Goto); instr->m_val = pc; } @@ -173,6 +168,12 @@ GWION_IMPORT(vararg) { GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL)) GWI_BB(gwi_item_ini(gwi, "int", "@len")) GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL)) + GWI_BB(gwi_item_ini(gwi, "int", "@o")) + GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL)) + GWI_BB(gwi_item_ini(gwi, "int", "@i")) + GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL)) + GWI_BB(gwi_item_ini(gwi, "int", "@s")) + GWI_BB(gwi_item_end(gwi, ae_flag_none, NULL)) GWI_BB(gwi_func_ini(gwi, "Vararg", "cpy")) GWI_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) diff --git a/src/vm/vm.c b/src/vm/vm.c index 3dd682e7..e12d49f8 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -166,7 +166,7 @@ ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, co #define ADISPATCH() { ADVANCE(); SDISPATCH(); } -#define PC ((*(unsigned*)(byte + 1)) + 1) +#define PC (*(unsigned*)(byte + 1)) #define OP(t, sz, op, ...) \ reg -= sz;\ @@ -318,7 +318,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&itof, &&ftoi, &&timeadv, &&setcode, - &®pop, &®push, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcmemberend, + &®move, &®tomem, &®tomemother, &&overflow, &&funcusrend, &&funcmemberend, &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid, @@ -631,11 +631,8 @@ PRAGMA_PUSH() next = eFuncMemberEnd; } PRAGMA_POP() -regpop: - reg -= VAL; - DISPATCH(); -regpush: - reg += VAL; +regmove: + reg += (m_int)VAL; DISPATCH(); regtomem: *(m_uint*)(mem+VAL) = *(m_uint*)(reg+(m_int)VAL2); @@ -757,7 +754,7 @@ arrayvalid: // are we sure it is the array ? // rather increase ref vector_pop(&shred->gc); - goto regpush; + DISPATCH() newobj: *(M_Object*)reg = new_object(vm->gwion->mp, NULL, (Type)VAL2); reg += SZ_INT; diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index 663f6c4e..c5180e4f 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -30,7 +30,6 @@ ANN void free_vmcode(VM_Code a, Gwion gwion) { if(a->memoize) memoize_end(gwion->mp, a->memoize); if(!a->builtin) { -// _mp_free(gwion->mp, vector_size(a->instr) * SZ_INT, a->bytecode); _mp_free(gwion->mp, vector_size(a->instr) * BYTECODE_SZ, a->bytecode); _free_code_instr(a->instr, gwion); } @@ -40,34 +39,95 @@ ANN void free_vmcode(VM_Code a, Gwion gwion) { mp_free(gwion->mp , VM_Code, a); } +static inline uint isgoto(const unsigned opcode) { + return opcode == eGoto || + opcode == eBranchEqInt || opcode == eBranchNeqInt || + opcode == eBranchEqFloat || opcode == eBranchNeqFloat; +} + +static inline void setpc(const m_bit *data, const m_uint i) { + *(unsigned*)(data+1) = i + 1; +} + ANN static m_bit* tobytecode(MemPool p, const VM_Code code) { const Vector v = code->instr; const m_uint sz = vector_size(v); m_bit *ptr = _mp_malloc(p, sz * BYTECODE_SZ); + struct Vector_ nop; + vector_init(&nop); for(m_uint i= 0; i < sz; ++i) { + m_bit *const data = ptr + i*BYTECODE_SZ; const Instr instr = (Instr)vector_at(v, i); - if(instr->opcode < eOP_MAX) - memcpy(ptr + i*BYTECODE_SZ, instr, BYTECODE_SZ); - else { - *(m_bit*)(ptr + (i*BYTECODE_SZ)) = instr->opcode; -// *(m_bit*)(ptr + (i*BYTECODE_SZ)) = eOP_MAX; - *(Instr*)(ptr + (i*BYTECODE_SZ) + SZ_INT) = instr; - *(f_instr*)(ptr + (i*BYTECODE_SZ) + SZ_INT*2) = instr->execute; + if(instr->opcode < eOP_MAX) { + if(instr->opcode == eRegMove) { + m_int move = (m_int)instr->m_val; + m_uint j = 0; + Instr next; + while((next = (Instr)vector_at(v, i + j +1)) && next->opcode == eRegMove) { + ++j; vector_add(&nop, i+j); + move += (m_int)next->m_val; + next->opcode = eNoOp; + } + if((instr->m_val = move)) { + memcpy(data, instr, BYTECODE_SZ); + setpc(data, i); + } else { + vector_add(&nop, i); + instr->opcode = eNoOp; + } + i += j; + 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; } - *(unsigned*)(ptr + (i*BYTECODE_SZ) + 1) = i; + setpc(data, i); + } + if(!vector_size(&nop)) { + vector_release(&nop); + return ptr; } - return ptr; + m_bit *const final = _mp_malloc(p, sz * BYTECODE_SZ); // could use smaller size + for(m_uint i= 0, j = 0; i < sz; ++i) { + const Instr instr = (Instr)vector_at(v, i); + unsigned opcode = instr->opcode; + if(opcode != eNoOp) { + m_bit *const base = ptr + i*BYTECODE_SZ, + *const data = final + j*BYTECODE_SZ; +// if(!isgoto(opcode)) + memcpy(data, base, BYTECODE_SZ); + if(isgoto(opcode)) { + m_bit pc = 0; + for(m_uint k = 0; k < vector_size(&nop); ++k) { + if(instr->m_val <= vector_at(&nop, k)) + break; + ++pc; + } + *(m_uint*)(data + SZ_INT) = instr->m_val > pc ? instr->m_val - pc : 0; + } + setpc(data, j); + ++j; + } + } + vector_release(&nop); + mp_free2(p, sz*BYTECODE_SZ, ptr); + return final; } - VM_Code new_vmcode(MemPool p, const Vector instr, const m_uint stack_depth, - const int builtin, const m_str name) { + const int builtin, const m_str name) { VM_Code code = mp_calloc(p, VM_Code); + code->name = mstrdup(p, name); if(instr) { code->instr = vector_copy(p, instr); code->bytecode = tobytecode(p, code); } - code->name = mstrdup(p, name); code->stack_depth = stack_depth; code->builtin = builtin; code->ref = 1;