]> Nishi Git Mirror - gwion.git/commitdiff
:cra: Encode bytecode : smile
authorfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 24 Jun 2019 17:17:37 +0000 (19:17 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 24 Jun 2019 17:17:37 +0000 (19:17 +0200)
include/instr.h
include/vm.h
src/emit/emit.c
src/vm/vm.c
src/vm/vm_code.c

index a84f8d4a4870bdb494b8239947ce84f6af6a6337..1f97a27dc2cf8c4e070ac677eafb6cf88ab35f36 100644 (file)
@@ -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);
index 0106d504346c5ea437891efd6ee1e066d92f154d..09399e5954ba21bb4ce99d6e4834c59feaeebd76 100644 (file)
@@ -3,6 +3,7 @@
 
 typedef struct VM_Code_* VM_Code;
 struct VM_Code_ {
+  m_bit *bytecode;
   union {
     Vector instr;
     m_uint native_func;
index 9ab3b8ac80efbd62ba2b135aa7f37b3fd54552e2..3105900074237ed02165b00f909e089b57d02c15 100644 (file)
@@ -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
index d7d182168dc09794954da42ad8d669fa642d9621..0433aec9ae295780afb47b5ab31409e3afb24667 100644 (file)
@@ -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;
index 627e644c8b9de80d09f9ec7ed1319f5d032684e8..a3376a127ee818057649cf63e07b753e54557226 100644 (file)
@@ -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;