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);
/* vararg */
INSTR(VarargIni);
-INSTR(VarargCheck);
INSTR(DotTmpl);
INSTR(GTmpl);
eCastF2I,
eTime_Advance,
eSetCode,
- eRegPop,
- eRegPush,
+ eRegMove,
eReg2Mem,
eReg2Mem4,
eOverflow,
#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
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);
CastF2I
Time_Advance
SetCode
-RegPop
-RegPush
+RegMove
Reg2Mem
Reg2Mem4
Overflow
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)
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;
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;
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;
}
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);
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);
}
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;
}
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;
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;
}
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;
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;
}
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;
}
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;
}
}
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;
}
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;
}
}
}
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;
}
}
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);
}
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;
}
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;
}
}
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) {
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");
}
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;
}
}
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;
}
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))
#define ADISPATCH() { ADVANCE(); SDISPATCH(); }
-#define PC ((*(unsigned*)(byte + 1)) + 1)
+#define PC (*(unsigned*)(byte + 1))
#define OP(t, sz, op, ...) \
reg -= sz;\
&&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,
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);
// 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;
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);
}
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;