From b624878941b4643ddf4c364d99cc45469d70aa00 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Mon, 24 Jun 2019 19:17:37 +0200 Subject: [PATCH] :cra: Encode bytecode : smile --- include/instr.h | 3 +- include/vm.h | 1 + src/emit/emit.c | 8 ++- src/vm/vm.c | 181 ++++++++++++++++++++++++----------------------- src/vm/vm_code.c | 31 +++++++- 5 files changed, 129 insertions(+), 95 deletions(-) diff --git a/include/instr.h b/include/instr.h index a84f8d4a..1f97a27d 100644 --- a/include/instr.h +++ b/include/instr.h @@ -20,7 +20,7 @@ enum Kind { typedef struct Instr_ * Instr; typedef void (*f_instr)(const VM_Shred, const Instr); struct Instr_ { - m_bit opcode; + m_uint opcode; union { m_float f; m_uint m_val; @@ -28,6 +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) INSTR(EOC); INSTR(DTOR_EOC); diff --git a/include/vm.h b/include/vm.h index 0106d504..09399e59 100644 --- a/include/vm.h +++ b/include/vm.h @@ -3,6 +3,7 @@ typedef struct VM_Code_* VM_Code; struct VM_Code_ { + m_bit *bytecode; union { Vector instr; m_uint native_func; diff --git a/src/emit/emit.c b/src/emit/emit.c index 9ab3b8ac..31059000 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1664,13 +1664,15 @@ ANN static void emit_func_def_return(const Emitter emit) { } ANN static void emit_func_def_code(const Emitter emit, const Func func) { - func->code = emit_code(emit); if(GET_FLAG(func->def, dtor)) { - emit->env->class_def->nspc->dtor = func->code; - Instr instr = (Instr)vector_back(func->code->instr); + Instr instr = (Instr)vector_back(&emit->code->instr); instr->opcode = eOP_MAX; instr->execute = DTOR_EOC; instr->m_val = (m_uint)emit->gwion->mp; + } + func->code = emit_code(emit); + if(GET_FLAG(func->def, dtor)) { + emit->env->class_def->nspc->dtor = func->code; ADD_REF(func->code) } // TODO: find why we need this diff --git a/src/vm/vm.c b/src/vm/vm.c index d7d18216..0433aec9 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -114,8 +114,8 @@ ANN static inline m_bool overflow_(const m_bit* mem, const VM_Shred c) { return mem > (((m_bit*)c + sizeof(struct VM_Shred_) + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP*16)); } -ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const Instr instr) { - const VM_Shred sh = new_shred_base(shred, (VM_Code)instr->m_val); +ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code code) { + const VM_Shred sh = new_shred_base(shred, code); vm_add_shred(shred->info->vm, sh); sh->tick->parent = shred->tick; if(!shred->tick->child.ptr) @@ -124,17 +124,17 @@ ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const Instr in return sh; } -ANN static inline VM_Shred init_fork_shred(const VM_Shred shred, const Instr instr) { - const VM_Shred sh = new_shred_base(shred, (VM_Code)instr->m_val); +ANN static inline VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code) { + const VM_Shred sh = new_shred_base(shred, code); vm_fork(shred->info->vm, sh); return sh; } #define TEST0(t, pos) if(!*(t*)(reg-pos)){ exception(shred, "ZeroDivideException"); break; } #define DISPATCH()\ - instr =(Instr)(ip[pc++]);\ + byte = bytecode + (pc++) * BYTECODE_SZ;\ VM_INFO;\ - goto *dispatch[instr->opcode]; + goto *dispatch[*(m_bit*)byte]; #define OP(t, sz, op, ...) \ reg -= sz;\ @@ -232,6 +232,9 @@ _Pragma(STRINGIFY(COMPILER diagnostic push)) \ _Pragma(STRINGIFY(COMPILER diagnostic ignored UNINITIALIZED) #define PRAGMA_POP() _Pragma(STRINGIFY(COMPILER diagnostic pop)) \ +#define VAL (*(m_uint*)(byte + SZ_INT)) +#define FVAL (*(m_float*)(byte + SZ_INT)) +#define VAL2 (*(m_uint*)(byte + SZ_INT*2)) __attribute__ ((optimize("-O2"))) ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] static const void* dispatch[] = { @@ -288,8 +291,9 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] register m_bit next; while((shred = shreduler_get(s))) { register VM_Code code = shred->code; - register m_uint* ip = code->instr->ptr + OFFSET; + register m_bit* bytecode = code->bytecode; register size_t pc = shred->pc; + register m_bit* byte; register m_bit* reg = shred->reg; register m_bit* mem = shred->mem; register union { @@ -299,43 +303,43 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] } a; MUTEX_LOCK(s->mutex); do { - register Instr instr; DISPATCH(); + DISPATCH(); regsetimm: - *(m_uint*)(reg + (m_int)instr->m_val2) = instr->m_val; + *(m_uint*)(reg + (m_int)VAL2) = VAL; DISPATCH(); regpushimm: - *(m_uint*)reg = instr->m_val; + *(m_uint*)reg = VAL; reg += SZ_INT; DISPATCH(); regpushfloat: - *(m_float*)reg = instr->f; + *(m_float*)reg = FVAL; reg += SZ_FLOAT; DISPATCH(); regpushother: // LOOP_OPTIM - for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) - *(m_bit**)(reg+i) = (m_bit*)(instr->m_val + i); - reg += instr->m_val2; + for(m_uint i = 0; i <= VAL2; i+= SZ_INT) + *(m_bit**)(reg+i) = (m_bit*)(VAL + i); + reg += VAL2; DISPATCH(); regpushaddr: - *(m_uint**)reg = &instr->m_val; + *(m_uint**)reg = &VAL; reg += SZ_INT; DISPATCH() regpushmem: - *(m_uint*)reg = *(m_uint*)(mem + instr->m_val); + *(m_uint*)reg = *(m_uint*)(mem + VAL); reg += SZ_INT; DISPATCH(); regpushmemfloat: - *(m_float*)reg = *(m_float*)(mem + instr->m_val); + *(m_float*)reg = *(m_float*)(mem + VAL); reg += SZ_FLOAT; DISPATCH(); regpushmemother: - for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) - *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + instr->m_val) + i); - reg += instr->m_val2; + for(m_uint i = 0; i <= VAL2; i+= SZ_INT) + *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + VAL) + i); + reg += VAL2; DISPATCH(); regpushmemaddr: - *(m_bit**)reg = mem + instr->m_val; + *(m_bit**)reg = mem + VAL; reg += SZ_INT; DISPATCH() pushnow: @@ -343,32 +347,32 @@ pushnow: reg += SZ_FLOAT; DISPATCH(); baseint: - *(m_uint*)reg = *(m_uint*)(shred->base + instr->m_val); + *(m_uint*)reg = *(m_uint*)(shred->base + VAL); reg += SZ_INT; DISPATCH(); basefloat: - *(m_float*)reg = *(m_float*)(shred->base + instr->m_val); + *(m_float*)reg = *(m_float*)(shred->base + VAL); reg += SZ_FLOAT; DISPATCH(); baseother: // LOOP_OPTIM - for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) - *(m_uint*)(reg+i) = *(m_uint*)((shred->base + instr->m_val) + i); - reg += instr->m_val2; + for(m_uint i = 0; i <= VAL2; i+= SZ_INT) + *(m_uint*)(reg+i) = *(m_uint*)((shred->base + VAL) + i); + reg += VAL2; DISPATCH(); baseaddr: - *(m_bit**)reg = (shred->base + instr->m_val); + *(m_bit**)reg = (shred->base + VAL); reg += SZ_INT; DISPATCH(); regtoreg: - *(m_uint*)(reg + (m_int)instr->m_val) = *(m_uint*)(reg + (m_int)instr->m_val2); + *(m_uint*)(reg + (m_int)VAL) = *(m_uint*)(reg + (m_int)VAL2); DISPATCH() regtoregaddr: *(m_uint**)reg = &*(m_uint*)(reg-SZ_INT); reg += SZ_INT; DISPATCH() memsetimm: - *(m_uint*)(mem+instr->m_val) = instr->m_val2; + *(m_uint*)(mem+VAL) = VAL2; DISPATCH(); regpushme: *(M_Object*)reg = shred->info->me; @@ -382,24 +386,24 @@ funcreturn: pc = *(m_uint*)(mem-SZ_INT*2); code = *(VM_Code*)(mem-SZ_INT*3); mem -= (*(m_uint*)(mem-SZ_INT*4) + SZ_INT*4); - ip = code->instr->ptr + OFFSET; + bytecode = code->bytecode; DISPATCH(); _goto: - pc = instr->m_val; + pc = VAL; DISPATCH(); allocint: - *(m_uint*)reg = *(m_uint*)(mem+instr->m_val) = 0; + *(m_uint*)reg = *(m_uint*)(mem+VAL) = 0; reg += SZ_INT; DISPATCH() allocfloat: - *(m_float*)reg = *(m_float*)(mem+instr->m_val) = 0; + *(m_float*)reg = *(m_float*)(mem+VAL) = 0; reg += SZ_FLOAT; DISPATCH() allocother: // LOOP_OPTIM - for(m_uint i = 0; i <= instr->m_val; i += SZ_INT) - *(m_uint*)(reg+i) = (*(m_uint*)(mem+instr->m_val+i) = 0); - reg += instr->m_val2; + for(m_uint i = 0; i <= VAL; i += SZ_INT) + *(m_uint*)(reg+i) = (*(m_uint*)(mem+VAL+i) = 0); + reg += VAL2; DISPATCH() intplus: INT_OP(+) @@ -566,18 +570,18 @@ funcusr: mem += push; *(m_uint*) mem = push;mem += SZ_INT; *(VM_Code*) mem = code; mem += SZ_INT; - *(m_uint*) mem = pc + instr->m_val2; mem += SZ_INT; + *(m_uint*) mem = pc + VAL2; mem += SZ_INT; *(m_uint*) mem = a.code->stack_depth; mem += SZ_INT; next = eFuncUsrEnd; } regpop: - reg -= instr->m_val; + reg -= VAL; DISPATCH(); regpush: - reg += instr->m_val; + reg += VAL; DISPATCH(); regtomem: - *(m_uint*)(mem+instr->m_val) = *(m_uint*)(reg+instr->m_val2); + *(m_uint*)(mem+VAL) = *(m_uint*)(reg+VAL2); DISPATCH() overflow: if(overflow_(mem, shred)) { @@ -589,7 +593,7 @@ PRAGMA_PUSH() goto *dispatch[next]; PRAGMA_POP() funcusrend: - ip = (code = a.code)->instr->ptr + OFFSET; + bytecode = (code = a.code)->bytecode; pc = 0; DISPATCH(); funcmemberend: @@ -597,62 +601,66 @@ funcmemberend: shred->reg = reg; shred->pc = pc; shred->code = code; - ((f_mfun)a.code->native_func)((*(M_Object*)mem), reg, shred); - reg += instr->m_val; - shred->mem = (mem -= instr->m_val2); - if(!s->curr)break; + { + const m_uint val = VAL; + const m_uint val2 = VAL2; + ((f_mfun)a.code->native_func)((*(M_Object*)mem), reg, shred); + reg += val; + shred->mem = (mem -= val2); + if(!s->curr)break; + } pc = shred->pc; DISPATCH() sporkini: - a.child = (instr->m_val2 ? init_spork_shred : init_fork_shred)(shred, instr); + a.child = (VAL2 ? init_spork_shred : init_fork_shred)(shred, (VM_Code)VAL); DISPATCH() sporkfunc: // LOOP_OPTIM - for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) - *(m_uint*)(a.child->reg + i) = *(m_uint*)(reg + i + (m_int)instr->m_val2); - a.child->reg += instr->m_val; + for(m_uint i = 0; i < VAL; i+= SZ_INT) + *(m_uint*)(a.child->reg + i) = *(m_uint*)(reg + i + (m_int)VAL2); + a.child->reg += VAL; DISPATCH() sporkexp: // LOOP_OPTIM - for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) + for(m_uint i = 0; i < VAL; i+= SZ_INT) *(m_uint*)(a.child->mem + i) = *(m_uint*)(mem+i); DISPATCH() forkend: - fork_launch(vm, a.child->info->me, instr->m_val2); + fork_launch(vm, a.child->info->me, VAL2); sporkend: *(M_Object*)(reg-SZ_INT) = a.child->info->me; DISPATCH() brancheqint: reg -= SZ_INT; if(!*(m_uint*)reg) - pc = instr->m_val; + pc = VAL; DISPATCH(); branchneint: reg -= SZ_INT; if(*(m_uint*)reg) - pc = instr->m_val; + pc = VAL; DISPATCH(); brancheqfloat: reg -= SZ_FLOAT; if(!*(m_float*)reg) - pc = instr->m_val; + pc = VAL; DISPATCH(); branchnefloat: reg -= SZ_FLOAT; if(*(m_float*)reg) - pc = instr->m_val; + pc = VAL; DISPATCH(); arrayappend: m_vector_add(ARRAY(a.obj), reg); release(a.obj, shred); DISPATCH() autoloop: - m_vector_get(ARRAY(a.obj), *(m_uint*)(mem + instr->m_val), mem + instr->m_val + SZ_INT); + m_vector_get(ARRAY(a.obj), *(m_uint*)(mem + VAL), mem + VAL + SZ_INT); goto autoloopcount; autoloopptr: - *(m_bit**)(*(M_Object*)(mem + instr->m_val + SZ_INT))->data = m_vector_addr(ARRAY(a.obj), *(m_uint*)(mem + instr->m_val)); + *(m_bit**)(*(M_Object*)(mem + VAL + SZ_INT))->data = m_vector_addr(ARRAY(a.obj), *(m_uint*)(mem + VAL)); autoloopcount: - *(m_uint*)reg = m_vector_size(ARRAY(a.obj)) - (*(m_uint*)(mem + instr->m_val))++; + *(m_uint*)reg = m_vector_size(ARRAY(a.obj)) - (*(m_uint*)(mem + VAL))++; reg += SZ_INT; DISPATCH() arraytop: @@ -662,10 +670,10 @@ arraytop: goto _goto; arrayaccess: { - const m_int idx = *(m_int*)(reg + SZ_INT * instr->m_val); + const m_int idx = *(m_int*)(reg + SZ_INT * VAL); if(idx < 0 || (m_uint)idx >= m_vector_size(ARRAY(a.obj))) { gw_err(_(" ... at index [%" INT_F "]\n"), idx); - gw_err(_(" ... at dimension [%" INT_F "]\n"), instr->m_val); + gw_err(_(" ... at dimension [%" INT_F "]\n"), VAL); shred->code = code; shred->mem = mem; exception(shred, "ArrayOutofBounds"); @@ -674,20 +682,20 @@ arrayaccess: DISPATCH() } arrayget: - m_vector_get(ARRAY(a.obj), *(m_int*)(reg + SZ_INT * instr->m_val), (reg + (m_int)instr->m_val2)); + m_vector_get(ARRAY(a.obj), *(m_int*)(reg + SZ_INT * VAL), (reg + (m_int)VAL2)); DISPATCH() arrayaddr: - *(m_bit**)(reg + (m_int)instr->m_val2) = m_vector_addr(ARRAY(a.obj), *(m_int*)(reg + SZ_INT * instr->m_val)); + *(m_bit**)(reg + (m_int)VAL2) = m_vector_addr(ARRAY(a.obj), *(m_int*)(reg + SZ_INT * VAL)); DISPATCH() arrayvalid: vector_pop(&shred->gc); goto regpush; newobj: - *(M_Object*)reg = new_object(vm->gwion->mp, shred, (Type)instr->m_val2); + *(M_Object*)reg = new_object(vm->gwion->mp, shred, (Type)VAL2); reg += SZ_INT; DISPATCH() addref: - if((a.obj = instr->m_val ? **(M_Object**)(reg-SZ_INT) : + if((a.obj = VAL ? **(M_Object**)(reg-SZ_INT) : *(M_Object*)(reg-SZ_INT))) ++a.obj->ref; DISPATCH() @@ -705,7 +713,7 @@ assign: DISPATCH() } remref: - release(*(M_Object*)(mem + instr->m_val), shred); + release(*(M_Object*)(mem + VAL), shred); DISPATCH() except: if(!(a.obj = *(M_Object*)(reg-SZ_INT))) { @@ -715,55 +723,52 @@ except: DISPATCH(); allocmemberaddr: a.obj = *(M_Object*)mem; - *(m_bit**)reg = a.obj->data + instr->m_val; + *(m_bit**)reg = a.obj->data + VAL; reg += SZ_INT; DISPATCH() dotmember: - *(m_uint*)(reg-SZ_INT) = *(m_uint*)(a.obj->data + instr->m_val); + *(m_uint*)(reg-SZ_INT) = *(m_uint*)(a.obj->data + VAL); DISPATCH() dotfloat: - *(m_float*)(reg-SZ_INT) = *(m_float*)(a.obj->data + instr->m_val); + *(m_float*)(reg-SZ_INT) = *(m_float*)(a.obj->data + VAL); reg += SZ_FLOAT - SZ_INT; DISPATCH() dotother: // LOOP_OPTIM - for(m_uint i = 0; i <= instr->m_val2; i += SZ_INT) - *(m_uint*)(reg+i-SZ_INT) = *(m_uint*)((a.obj->data + instr->m_val) + i); - reg += instr->m_val2 - SZ_INT; + for(m_uint i = 0; i <= VAL2; i += SZ_INT) + *(m_uint*)(reg+i-SZ_INT) = *(m_uint*)((a.obj->data + VAL) + i); + reg += VAL2 - SZ_INT; DISPATCH() dotaddr: - *(m_bit**)(reg-SZ_INT) = (a.obj->data + instr->m_val); + *(m_bit**)(reg-SZ_INT) = (a.obj->data + VAL); DISPATCH() staticint: - *(m_uint*)reg = *(m_uint*)instr->m_val; + *(m_uint*)reg = *(m_uint*)VAL; reg += SZ_INT; DISPATCH() staticfloat: - *(m_float*)reg = *(m_float*)instr->m_val; + *(m_float*)reg = *(m_float*)VAL; reg += SZ_FLOAT; DISPATCH() staticother: // LOOP_OPTIM -// for(m_uint i = 0; i <= instr->m_val2; i += SZ_INT) -// *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)instr->m_val + i); - memcpy(reg, (m_bit*)instr->m_val, instr->m_val2); - reg += instr->m_val2; +// for(m_uint i = 0; i <= VAL2; i += SZ_INT) +// *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)VAL + i); + memcpy(reg, (m_bit*)VAL, VAL2); + reg += VAL2; DISPATCH() dotfunc: assert(a.obj); reg += SZ_INT; dotstaticfunc: PRAGMA_PUSH() - *(VM_Code*)(reg-SZ_INT) = ((Func)vector_at(a.obj->vtable, instr->m_val))->code; + *(VM_Code*)(reg-SZ_INT) = ((Func)vector_at(a.obj->vtable, VAL))->code; PRAGMA_POP() DISPATCH() -staticcode: - instr->m_val = (m_uint)(a.code = (*(VM_Code*)reg = ((Func)instr->m_val)->code)); - instr->opcode = eRegPushImm; - reg += SZ_INT; - DISPATCH() +staticcode: // TODO: remove me +exit(5); pushstr: - *(M_Object*)reg = new_string2(vm->gwion->mp, shred, (m_str)instr->m_val); + *(M_Object*)reg = new_string2(vm->gwion->mp, shred, (m_str)VAL); reg += SZ_INT; DISPATCH(); gcini: @@ -777,17 +782,17 @@ gcend: _release(a.obj, shred); DISPATCH() gack: - gack(reg, instr); + gack(reg, (Instr)VAL); DISPATCH() other: shred->code = code; shred->reg = reg; shred->mem = mem; shred->pc = pc; - instr->execute(shred, instr); + ((f_instr)VAL2)(shred, (Instr)VAL); if(!s->curr)break; code = shred->code; - ip = shred->code->instr->ptr + OFFSET; + bytecode = code->bytecode; reg = shred->reg; mem = shred->mem; pc = shred->pc; diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index 627e644c..a3376a12 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -23,7 +23,6 @@ ANN /*static*/ void free_code_instr(const Vector v, const Gwion gwion) { f(instr, gwion); mp_free(gwion->mp, Instr, instr); } -// free_vector(gwion->mp, v); } ANN static void _free_code_instr(const Vector v, const Gwion gwion) { @@ -33,16 +32,42 @@ ANN static void _free_code_instr(const Vector v, const Gwion gwion) { ANN static void free_vm_code(VM_Code a, Gwion gwion) { if(a->memoize) memoize_end(gwion->mp, a->memoize); - if(!GET_FLAG(a, builtin)) + if(!GET_FLAG(a, builtin)) { + _mp_free(gwion->mp, vector_size(a->instr) * SZ_INT, a->bytecode); _free_code_instr(a->instr, gwion); + } free_mstr(gwion->mp, a->name); mp_free(gwion->mp , VM_Code, a); } +ANN static m_bit* tobytecode(MemPool p, const VM_Code code, const Vector v) { + const m_uint sz = vector_size(v); + m_bit *ptr = _mp_malloc(p, sz * BYTECODE_SZ); + for(m_uint i= 0; i < sz; ++i) { + const Instr instr = (Instr)vector_at(v, i); + if(instr->opcode == ePushStaticCode) { + instr->opcode = eRegPushImm; + instr->m_val = (m_uint)code; + } + if(instr->opcode < eGack) + memcpy(ptr + i*BYTECODE_SZ, instr, BYTECODE_SZ); + else { + *(m_bit*)(ptr + (i*BYTECODE_SZ)) = instr->opcode; + *(Instr*)(ptr + (i*BYTECODE_SZ) + SZ_INT) = instr; + *(f_instr*)(ptr + (i*BYTECODE_SZ) + SZ_INT*2) = instr->execute; + } + } + return ptr; +} + + VM_Code new_vm_code(MemPool p, const Vector instr, const m_uint stack_depth, const ae_flag flag, const m_str name) { VM_Code code = mp_calloc(p, VM_Code); - code->instr = instr ? vector_copy(p, instr) : NULL; + if(instr) { + code->instr = vector_copy(p, instr); + code->bytecode = tobytecode(p, code, instr); + } code->name = mstrdup(p, name); code->stack_depth = stack_depth; code->flag = flag; -- 2.43.0