mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6318 from dearblue/shrink-vm-vars
Shrink variables in `mrb_vm_exec()`
This commit is contained in:
@@ -1270,7 +1270,8 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
|
||||
|
||||
#define UNWIND_ENSURE(mrb, ci, pc, tag, return_ci, val) \
|
||||
do { \
|
||||
if ((proc = (ci)->proc) && !MRB_PROC_CFUNC_P(proc) && (irep = proc->body.irep) && irep->clen > 0 && \
|
||||
const struct RProc *proc = (ci)->proc; \
|
||||
if (proc && !MRB_PROC_CFUNC_P(proc) && (irep = proc->body.irep) && irep->clen > 0 && \
|
||||
(ch = catch_handler_find(irep, pc, MRB_CATCH_FILTER_ENSURE))) { \
|
||||
THROW_TAGGED_BREAK(mrb, tag, return_ci, val); \
|
||||
} \
|
||||
@@ -1329,8 +1330,8 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
|
||||
|
||||
#ifdef MRB_USE_VM_SWITCH_DISPATCH
|
||||
|
||||
#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) {
|
||||
#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; L_ ## insn ## _BODY:
|
||||
#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*ci->pc); CODE_FETCH_HOOK(mrb, irep, ci->pc, regs); switch (insn) {
|
||||
#define CASE(insn,ops) case insn: { const mrb_code *pc = ci->pc+1; FETCH_ ## ops (); ci->pc = pc; } L_ ## insn ## _BODY:
|
||||
#define NEXT goto L_END_DISPATCH
|
||||
#define JUMP NEXT
|
||||
#define END_DISPATCH L_END_DISPATCH:;}}
|
||||
@@ -1338,8 +1339,8 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
|
||||
#else
|
||||
|
||||
#define INIT_DISPATCH JUMP; return mrb_nil_value();
|
||||
#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; L_ ## insn ## _BODY:
|
||||
#define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn]
|
||||
#define CASE(insn,ops) L_ ## insn: { const mrb_code *pc = ci->pc+1; FETCH_ ## ops (); ci->pc = pc; } L_ ## insn ## _BODY:
|
||||
#define NEXT insn=BYTECODE_DECODER(*ci->pc); CODE_FETCH_HOOK(mrb, irep, ci->pc, regs); goto *optable[insn]
|
||||
#define JUMP NEXT
|
||||
|
||||
#define END_DISPATCH
|
||||
@@ -1388,12 +1389,13 @@ check_target_class(mrb_state *mrb)
|
||||
return target;
|
||||
}
|
||||
|
||||
#define regs (mrb->c->ci->stack)
|
||||
#define regs (ci->stack)
|
||||
|
||||
static mrb_value
|
||||
hash_new_from_regs(mrb_state *mrb, mrb_int argc, mrb_int idx)
|
||||
{
|
||||
mrb_value hash = mrb_hash_new_capa(mrb, argc);
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
while (argc--) {
|
||||
mrb_hash_set(mrb, hash, regs[idx+0], regs[idx+1]);
|
||||
idx += 2;
|
||||
@@ -1404,12 +1406,10 @@ hash_new_from_regs(mrb_state *mrb, mrb_int argc, mrb_int idx)
|
||||
#define ary_new_from_regs(mrb, argc, idx) mrb_ary_new_from_values(mrb, (argc), ®s[idx]);
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
|
||||
mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq)
|
||||
{
|
||||
/* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
|
||||
const mrb_irep *irep = proc->body.irep;
|
||||
const mrb_pool_value *pool = irep->pool;
|
||||
const mrb_sym *syms = irep->syms;
|
||||
/* mrb_assert(MRB_PROC_CFUNC_P(begin_proc)) */
|
||||
const mrb_irep *irep = begin_proc->body.irep;
|
||||
mrb_code insn;
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
@@ -1419,6 +1419,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
|
||||
uint16_t c;
|
||||
mrb_sym mid;
|
||||
const struct mrb_irep_catch_handler *ch;
|
||||
mrb_callinfo *ci;
|
||||
|
||||
#ifndef MRB_USE_VM_SWITCH_DISPATCH
|
||||
static const void * const optable[] = {
|
||||
@@ -1430,6 +1431,10 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
|
||||
|
||||
mrb->exc = NULL;
|
||||
|
||||
ci = mrb->c->ci;
|
||||
CI_PROC_SET(ci, begin_proc);
|
||||
ci->pc = iseq;
|
||||
|
||||
RETRY_TRY_BLOCK:
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
@@ -1441,7 +1446,6 @@ RETRY_TRY_BLOCK:
|
||||
goto L_RAISE;
|
||||
}
|
||||
mrb->jmp = &c_jmp;
|
||||
CI_PROC_SET(mrb->c->ci, proc);
|
||||
|
||||
INIT_DISPATCH {
|
||||
CASE(OP_NOP, Z) {
|
||||
@@ -1455,18 +1459,18 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_LOADL, BB) {
|
||||
switch (pool[b].tt) { /* number */
|
||||
switch (irep->pool[b].tt) { /* number */
|
||||
case IREP_TT_INT32:
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i32);
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i32);
|
||||
break;
|
||||
case IREP_TT_INT64:
|
||||
#if defined(MRB_INT64)
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i64);
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i64);
|
||||
break;
|
||||
#else
|
||||
#if defined(MRB_64BIT)
|
||||
if (INT32_MIN <= pool[b].u.i64 && pool[b].u.i64 <= INT32_MAX) {
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i64);
|
||||
if (INT32_MIN <= irep->pool[b].u.i64 && irep->pool[b].u.i64 <= INT32_MAX) {
|
||||
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i64);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1475,7 +1479,7 @@ RETRY_TRY_BLOCK:
|
||||
case IREP_TT_BIGINT:
|
||||
#ifdef MRB_USE_BIGINT
|
||||
{
|
||||
const char *s = pool[b].u.str;
|
||||
const char *s = irep->pool[b].u.str;
|
||||
regs[a] = mrb_bint_new_str(mrb, s+2, (uint8_t)s[0], s[1]);
|
||||
}
|
||||
break;
|
||||
@@ -1484,7 +1488,7 @@ RETRY_TRY_BLOCK:
|
||||
#endif
|
||||
#ifndef MRB_NO_FLOAT
|
||||
case IREP_TT_FLOAT:
|
||||
regs[a] = mrb_float_value(mrb, pool[b].u.f);
|
||||
regs[a] = mrb_float_value(mrb, irep->pool[b].u.f);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -1530,7 +1534,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_LOADSYM, BB) {
|
||||
SET_SYM_VALUE(regs[a], syms[b]);
|
||||
SET_SYM_VALUE(regs[a], irep->syms[b]);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
@@ -1555,46 +1559,54 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_GETGV, BB) {
|
||||
mrb_value val = mrb_gv_get(mrb, syms[b]);
|
||||
mrb_value val = mrb_gv_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = val;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETGV, BB) {
|
||||
mrb_gv_set(mrb, syms[b], regs[a]);
|
||||
mrb_gv_set(mrb, irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_GETSV, BB) {
|
||||
mrb_value val = mrb_vm_special_get(mrb, syms[b]);
|
||||
mrb_value val = mrb_vm_special_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = val;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETSV, BB) {
|
||||
mrb_vm_special_set(mrb, syms[b], regs[a]);
|
||||
mrb_vm_special_set(mrb, irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_GETIV, BB) {
|
||||
regs[a] = mrb_iv_get(mrb, regs[0], syms[b]);
|
||||
regs[a] = mrb_iv_get(mrb, regs[0], irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETIV, BB) {
|
||||
mrb_iv_set(mrb, regs[0], syms[b], regs[a]);
|
||||
mrb_iv_set(mrb, regs[0], irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_GETCV, BB) {
|
||||
mrb_value val;
|
||||
val = mrb_vm_cv_get(mrb, syms[b]);
|
||||
val = mrb_vm_cv_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = val;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETCV, BB) {
|
||||
mrb_vm_cv_set(mrb, syms[b], regs[a]);
|
||||
mrb_vm_cv_set(mrb, irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
@@ -1645,24 +1657,28 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_GETCONST, BB) {
|
||||
mrb_value v = mrb_vm_const_get(mrb, syms[b]);
|
||||
mrb_value v = mrb_vm_const_get(mrb, irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = v;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETCONST, BB) {
|
||||
mrb_vm_const_set(mrb, syms[b], regs[a]);
|
||||
mrb_vm_const_set(mrb, irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_GETMCNST, BB) {
|
||||
mrb_value v = mrb_const_get(mrb, regs[a], syms[b]);
|
||||
mrb_value v = mrb_const_get(mrb, regs[a], irep->syms[b]);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = v;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETMCNST, BB) {
|
||||
mrb_const_set(mrb, regs[a+1], syms[b], regs[a]);
|
||||
mrb_const_set(mrb, regs[a+1], irep->syms[b], regs[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
@@ -1691,33 +1707,33 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_JMP, S) {
|
||||
pc += (int16_t)a;
|
||||
ci->pc += (int16_t)a;
|
||||
JUMP;
|
||||
}
|
||||
CASE(OP_JMPIF, BS) {
|
||||
if (mrb_test(regs[a])) {
|
||||
pc += (int16_t)b;
|
||||
ci->pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_JMPNOT, BS) {
|
||||
if (!mrb_test(regs[a])) {
|
||||
pc += (int16_t)b;
|
||||
ci->pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_JMPNIL, BS) {
|
||||
if (mrb_nil_p(regs[a])) {
|
||||
pc += (int16_t)b;
|
||||
ci->pc += (int16_t)b;
|
||||
JUMP;
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_JMPUW, S) {
|
||||
a = (uint32_t)((pc - irep->iseq) + (int16_t)a);
|
||||
a = (uint32_t)((ci->pc - irep->iseq) + (int16_t)a);
|
||||
CHECKPOINT_RESTORE(RBREAK_TAG_JUMP) {
|
||||
struct RBreak *brk = (struct RBreak*)mrb->exc;
|
||||
mrb_value target = mrb_break_value_get(brk);
|
||||
@@ -1727,7 +1743,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
CHECKPOINT_MAIN(RBREAK_TAG_JUMP) {
|
||||
if (irep->clen > 0 &&
|
||||
(ch = catch_handler_find(irep, pc, MRB_CATCH_FILTER_ENSURE))) {
|
||||
(ch = catch_handler_find(irep, ci->pc, MRB_CATCH_FILTER_ENSURE))) {
|
||||
/* avoiding a jump from a catch handler into the same handler */
|
||||
if (a < mrb_irep_catch_handler_unpack(ch->begin) || a >= mrb_irep_catch_handler_unpack(ch->end)) {
|
||||
THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, mrb->c->ci, mrb_fixnum_value(a));
|
||||
@@ -1737,7 +1753,7 @@ RETRY_TRY_BLOCK:
|
||||
CHECKPOINT_END(RBREAK_TAG_JUMP);
|
||||
|
||||
mrb->exc = NULL; /* clear break object */
|
||||
pc = irep->iseq + a;
|
||||
ci->pc = irep->iseq + a;
|
||||
JUMP;
|
||||
}
|
||||
|
||||
@@ -1800,11 +1816,10 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
}
|
||||
else {
|
||||
mrb_callinfo *ci;
|
||||
mrb_exc_set(mrb, exc);
|
||||
L_RAISE:
|
||||
ci = mrb->c->ci;
|
||||
while (!(proc = ci->proc) || MRB_PROC_CFUNC_P(ci->proc) || !(irep = proc->body.irep) || irep->clen < 1 ||
|
||||
while (!ci->proc || MRB_PROC_CFUNC_P(ci->proc) || !(irep = ci->proc->body.irep) || irep->clen < 1 ||
|
||||
(ch = catch_handler_find(irep, ci->pc, MRB_CATCH_FILTER_ALL)) == NULL) {
|
||||
if (ci != mrb->c->cibase) {
|
||||
ci = cipop(mrb);
|
||||
@@ -1815,7 +1830,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
}
|
||||
else if (mrb->c == mrb->root_c) {
|
||||
mrb->c->ci->stack = mrb->c->stbase;
|
||||
ci->stack = mrb->c->stbase;
|
||||
mrb->jmp = prev_jmp;
|
||||
return mrb_obj_value(mrb->exc);
|
||||
}
|
||||
@@ -1834,12 +1849,9 @@ RETRY_TRY_BLOCK:
|
||||
L_CATCH_TAGGED_BREAK: /* from THROW_TAGGED_BREAK() or UNWIND_ENSURE() */
|
||||
ci = mrb->c->ci;
|
||||
}
|
||||
proc = ci->proc;
|
||||
irep = proc->body.irep;
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
irep = ci->proc->body.irep;
|
||||
stack_extend(mrb, irep->nregs);
|
||||
pc = irep->iseq + mrb_irep_catch_handler_unpack(ch->target);
|
||||
ci->pc = irep->iseq + mrb_irep_catch_handler_unpack(ch->target);
|
||||
}
|
||||
NEXT;
|
||||
}
|
||||
@@ -1866,10 +1878,9 @@ RETRY_TRY_BLOCK:
|
||||
|
||||
CASE(OP_SENDB, BBB)
|
||||
L_SENDB:
|
||||
mid = syms[b];
|
||||
mid = irep->syms[b];
|
||||
L_SENDB_SYM:
|
||||
{
|
||||
mrb_callinfo *ci;
|
||||
mrb_method_t m;
|
||||
mrb_value recv, blk;
|
||||
mrb_int bidx, new_bidx;
|
||||
@@ -1905,6 +1916,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
else {
|
||||
blk = ensure_block(mrb, regs[bidx]);
|
||||
ci = mrb->c->ci;
|
||||
regs[new_bidx] = blk;
|
||||
}
|
||||
|
||||
@@ -1930,12 +1942,9 @@ RETRY_TRY_BLOCK:
|
||||
CI_PROC_SET(ci, p);
|
||||
if (!MRB_PROC_CFUNC_P(p)) {
|
||||
/* setup environment for calling method */
|
||||
proc = p;
|
||||
irep = proc->body.irep;
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
irep = p->body.irep;
|
||||
stack_extend(mrb, (irep->nregs < 4) ? 4 : irep->nregs);
|
||||
pc = irep->iseq;
|
||||
ci->pc = irep->iseq;
|
||||
JUMP;
|
||||
}
|
||||
else {
|
||||
@@ -1963,22 +1972,17 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
else {
|
||||
mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
|
||||
proc = ci[-1].proc;
|
||||
irep = proc->body.irep;
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
irep = ci[-1].proc->body.irep;
|
||||
}
|
||||
}
|
||||
mrb_assert(ci > mrb->c->cibase);
|
||||
ci->stack[0] = recv;
|
||||
/* pop stackpos */
|
||||
ci = cipop(mrb);
|
||||
pc = ci->pc;
|
||||
JUMP;
|
||||
}
|
||||
|
||||
CASE(OP_CALL, Z) {
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
mrb_value recv = ci->stack[0];
|
||||
const struct RProc *p = mrb_proc_ptr(recv);
|
||||
|
||||
@@ -2001,16 +2005,14 @@ RETRY_TRY_BLOCK:
|
||||
if (mrb->exc) goto L_RAISE;
|
||||
/* pop stackpos */
|
||||
ci = cipop(mrb);
|
||||
pc = ci->pc;
|
||||
ci[1].stack[0] = recv;
|
||||
irep = mrb->c->ci->proc->body.irep;
|
||||
irep = ci->proc->body.irep;
|
||||
}
|
||||
else {
|
||||
/* setup environment for calling method */
|
||||
proc = p;
|
||||
irep = p->body.irep;
|
||||
if (!irep) {
|
||||
mrb->c->ci->stack[0] = mrb_nil_value();
|
||||
ci->stack[0] = mrb_nil_value();
|
||||
a = 0;
|
||||
goto L_OP_RETURN_BODY;
|
||||
}
|
||||
@@ -2022,15 +2024,12 @@ RETRY_TRY_BLOCK:
|
||||
if (MRB_PROC_ENV_P(p)) {
|
||||
regs[0] = MRB_PROC_ENV(p)->stack[0];
|
||||
}
|
||||
pc = irep->iseq;
|
||||
ci->pc = irep->iseq;
|
||||
}
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
JUMP;
|
||||
}
|
||||
|
||||
CASE(OP_SUPER, BB) {
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
mrb_value recv;
|
||||
struct RClass* target_class = CI_TARGET_CLASS(ci);
|
||||
|
||||
@@ -2060,7 +2059,7 @@ RETRY_TRY_BLOCK:
|
||||
mrb_int lv = (b>>0)&0xf;
|
||||
mrb_value *stack;
|
||||
|
||||
if (mrb->c->ci->mid == 0 || CI_TARGET_CLASS(mrb->c->ci) == NULL) {
|
||||
if (ci->mid == 0 || CI_TARGET_CLASS(ci) == NULL) {
|
||||
L_NOSUPER:
|
||||
RAISE_LIT(mrb, E_NOMETHOD_ERROR, "super called outside of method");
|
||||
}
|
||||
@@ -2111,14 +2110,13 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_ENTER, W) {
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
mrb_int argc = ci->n;
|
||||
mrb_value *argv = regs+1;
|
||||
|
||||
mrb_int m1 = MRB_ASPEC_REQ(a);
|
||||
|
||||
/* no other args */
|
||||
if ((a & ~0x7c0001) == 0 && argc < 15 && MRB_PROC_STRICT_P(proc)) {
|
||||
if ((a & ~0x7c0001) == 0 && argc < 15 && MRB_PROC_STRICT_P(ci->proc)) {
|
||||
if (argc+(ci->nk==15) != m1) { /* count kdict too */
|
||||
argnum_error(mrb, m1);
|
||||
goto L_RAISE;
|
||||
@@ -2225,7 +2223,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
/* skip initializer of passed arguments */
|
||||
if (o > 0 && argc > m1+m2)
|
||||
pc += (argc - m1 - m2)*3;
|
||||
ci->pc += (argc - m1 - m2)*3;
|
||||
}
|
||||
else {
|
||||
mrb_int rnum = 0;
|
||||
@@ -2241,7 +2239,7 @@ RETRY_TRY_BLOCK:
|
||||
if (m2 > 0 && argc-m2 > m1) {
|
||||
value_move(®s[m1+o+r+1], &argv[m1+o+rnum], m2);
|
||||
}
|
||||
pc += o*3;
|
||||
ci->pc += o*3;
|
||||
}
|
||||
|
||||
/* need to be update blk first to protect blk from GC */
|
||||
@@ -2257,7 +2255,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
/* format arguments for generated code */
|
||||
mrb->c->ci->n = (uint8_t)len;
|
||||
ci->n = (uint8_t)len;
|
||||
|
||||
/* clear local (but non-argument) variables */
|
||||
if (irep->nlocals-blk_pos-1 > 0) {
|
||||
@@ -2267,8 +2265,8 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_KARG, BB) {
|
||||
mrb_value k = mrb_symbol_value(syms[b]);
|
||||
mrb_int kidx = mrb_ci_kidx(mrb->c->ci);
|
||||
mrb_value k = mrb_symbol_value(irep->syms[b]);
|
||||
mrb_int kidx = mrb_ci_kidx(ci);
|
||||
mrb_value kdict, v;
|
||||
|
||||
if (kidx < 0 || !mrb_hash_p(kdict=regs[kidx]) || !mrb_hash_key_p(mrb, kdict, k)) {
|
||||
@@ -2281,8 +2279,8 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_KEY_P, BB) {
|
||||
mrb_value k = mrb_symbol_value(syms[b]);
|
||||
mrb_int kidx = mrb_ci_kidx(mrb->c->ci);
|
||||
mrb_value k = mrb_symbol_value(irep->syms[b]);
|
||||
mrb_int kidx = mrb_ci_kidx(ci);
|
||||
mrb_value kdict;
|
||||
mrb_bool key_p = FALSE;
|
||||
|
||||
@@ -2294,7 +2292,7 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_KEYEND, Z) {
|
||||
mrb_int kidx = mrb_ci_kidx(mrb->c->ci);
|
||||
mrb_int kidx = mrb_ci_kidx(ci);
|
||||
mrb_value kdict;
|
||||
|
||||
if (kidx >= 0 && mrb_hash_p(kdict=regs[kidx]) && !mrb_hash_empty_p(mrb, kdict)) {
|
||||
@@ -2306,41 +2304,34 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_BREAK, B) {
|
||||
if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
|
||||
if (MRB_PROC_ORPHAN_P(proc) || !MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) {
|
||||
if (MRB_PROC_STRICT_P(ci->proc)) goto NORMAL_RETURN;
|
||||
if (MRB_PROC_ORPHAN_P(ci->proc) || !MRB_PROC_ENV_P(ci->proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(ci->proc))) {
|
||||
L_BREAK_ERROR:
|
||||
RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "break from proc-closure");
|
||||
}
|
||||
else {
|
||||
struct REnv *e = MRB_PROC_ENV(proc);
|
||||
struct REnv *e = MRB_PROC_ENV(ci->proc);
|
||||
|
||||
if (e->cxt != mrb->c) {
|
||||
goto L_BREAK_ERROR;
|
||||
}
|
||||
}
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
proc = proc->upper;
|
||||
while (mrb->c->cibase < ci && ci[-1].proc != proc) {
|
||||
const struct RProc *dst = ci->proc->upper;
|
||||
while (mrb->c->cibase < ci && ci[-1].proc != dst) {
|
||||
ci--;
|
||||
}
|
||||
if (ci == mrb->c->cibase) {
|
||||
goto L_BREAK_ERROR;
|
||||
}
|
||||
c = a; // release the "a" variable, which can handle 32-bit values
|
||||
a = ci - mrb->c->cibase;
|
||||
goto L_UNWINDING;
|
||||
}
|
||||
CASE(OP_RETURN_BLK, B) {
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
|
||||
if (!MRB_PROC_ENV_P(proc) || MRB_PROC_STRICT_P(proc)) {
|
||||
if (!MRB_PROC_ENV_P(ci->proc) || MRB_PROC_STRICT_P(ci->proc)) {
|
||||
goto NORMAL_RETURN;
|
||||
}
|
||||
|
||||
const struct RProc *dst;
|
||||
mrb_callinfo *cibase;
|
||||
cibase = mrb->c->cibase;
|
||||
dst = top_proc(mrb, proc);
|
||||
const struct RProc *dst = top_proc(mrb, ci->proc);
|
||||
mrb_callinfo *cibase = mrb->c->cibase;
|
||||
|
||||
if (MRB_PROC_ENV_P(dst)) {
|
||||
struct REnv *e = MRB_PROC_ENV(dst);
|
||||
@@ -2358,12 +2349,9 @@ RETRY_TRY_BLOCK:
|
||||
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
|
||||
goto L_RAISE;
|
||||
}
|
||||
c = a; // release the "a" variable, which can handle 32-bit values
|
||||
a = ci - mrb->c->cibase;
|
||||
goto L_UNWINDING;
|
||||
}
|
||||
CASE(OP_RETURN, B) {
|
||||
mrb_callinfo *ci;
|
||||
mrb_int acc;
|
||||
mrb_value v;
|
||||
|
||||
@@ -2378,9 +2366,8 @@ RETRY_TRY_BLOCK:
|
||||
v = mrb_break_value_get(brk);
|
||||
}
|
||||
else {
|
||||
L_UNWINDING: // for a check on the role of `a` and `c`, see `goto L_UNWINDING`
|
||||
ci = mrb->c->cibase + a;
|
||||
v = regs[c];
|
||||
L_UNWINDING:
|
||||
v = mrb->c->ci->stack[a];
|
||||
}
|
||||
mrb_gc_protect(mrb, v);
|
||||
}
|
||||
@@ -2438,12 +2425,8 @@ RETRY_TRY_BLOCK:
|
||||
mrb->jmp = prev_jmp;
|
||||
return v;
|
||||
}
|
||||
pc = ci->pc;
|
||||
DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid)));
|
||||
proc = ci->proc;
|
||||
irep = proc->body.irep;
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
irep = ci->proc->body.irep;
|
||||
|
||||
ci[1].stack[0] = v;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
@@ -2821,13 +2804,13 @@ RETRY_TRY_BLOCK:
|
||||
size_t len;
|
||||
mrb_sym sym;
|
||||
|
||||
mrb_assert((pool[b].tt&IREP_TT_NFLAG)==0);
|
||||
len = pool[b].tt >> 2;
|
||||
if (pool[b].tt & IREP_TT_SFLAG) {
|
||||
sym = mrb_intern_static(mrb, pool[b].u.str, len);
|
||||
mrb_assert((irep->pool[b].tt&IREP_TT_NFLAG)==0);
|
||||
len = irep->pool[b].tt >> 2;
|
||||
if (irep->pool[b].tt & IREP_TT_SFLAG) {
|
||||
sym = mrb_intern_static(mrb, irep->pool[b].u.str, len);
|
||||
}
|
||||
else {
|
||||
sym = mrb_intern(mrb, pool[b].u.str, len);
|
||||
sym = mrb_intern(mrb, irep->pool[b].u.str, len);
|
||||
}
|
||||
regs[a] = mrb_symbol_value(sym);
|
||||
NEXT;
|
||||
@@ -2836,13 +2819,13 @@ RETRY_TRY_BLOCK:
|
||||
CASE(OP_STRING, BB) {
|
||||
mrb_int len;
|
||||
|
||||
mrb_assert((pool[b].tt&IREP_TT_NFLAG)==0);
|
||||
len = pool[b].tt >> 2;
|
||||
if (pool[b].tt & IREP_TT_SFLAG) {
|
||||
regs[a] = mrb_str_new_static(mrb, pool[b].u.str, len);
|
||||
mrb_assert((irep->pool[b].tt&IREP_TT_NFLAG)==0);
|
||||
len = irep->pool[b].tt >> 2;
|
||||
if (irep->pool[b].tt & IREP_TT_SFLAG) {
|
||||
regs[a] = mrb_str_new_static(mrb, irep->pool[b].u.str, len);
|
||||
}
|
||||
else {
|
||||
regs[a] = mrb_str_new(mrb, pool[b].u.str, len);
|
||||
regs[a] = mrb_str_new(mrb, irep->pool[b].u.str, len);
|
||||
}
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
NEXT;
|
||||
@@ -2937,16 +2920,17 @@ RETRY_TRY_BLOCK:
|
||||
CASE(OP_CLASS, BB) {
|
||||
struct RClass *c = 0, *baseclass;
|
||||
mrb_value base, super;
|
||||
mrb_sym id = syms[b];
|
||||
mrb_sym id = irep->syms[b];
|
||||
|
||||
base = regs[a];
|
||||
super = regs[a+1];
|
||||
if (mrb_nil_p(base)) {
|
||||
baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
|
||||
baseclass = MRB_PROC_TARGET_CLASS(ci->proc);
|
||||
if (!baseclass) baseclass = mrb->object_class;
|
||||
base = mrb_obj_value(baseclass);
|
||||
}
|
||||
c = mrb_vm_define_class(mrb, base, super, id);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = mrb_obj_value(c);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
NEXT;
|
||||
@@ -2955,15 +2939,16 @@ RETRY_TRY_BLOCK:
|
||||
CASE(OP_MODULE, BB) {
|
||||
struct RClass *cls = 0, *baseclass;
|
||||
mrb_value base;
|
||||
mrb_sym id = syms[b];
|
||||
mrb_sym id = irep->syms[b];
|
||||
|
||||
base = regs[a];
|
||||
if (mrb_nil_p(base)) {
|
||||
baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
|
||||
baseclass = MRB_PROC_TARGET_CLASS(ci->proc);
|
||||
if (!baseclass) baseclass = mrb->object_class;
|
||||
base = mrb_obj_value(baseclass);
|
||||
}
|
||||
cls = mrb_vm_define_module(mrb, base, id);
|
||||
ci = mrb->c->ci;
|
||||
regs[a] = mrb_obj_value(cls);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
NEXT;
|
||||
@@ -2978,19 +2963,17 @@ RETRY_TRY_BLOCK:
|
||||
/* prepare closure */
|
||||
p = mrb_proc_new(mrb, nirep);
|
||||
p->c = NULL;
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)proc);
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)ci->proc);
|
||||
MRB_PROC_SET_TARGET_CLASS(p, mrb_class_ptr(recv));
|
||||
p->flags |= MRB_PROC_SCOPE;
|
||||
|
||||
/* prepare call stack */
|
||||
cipush(mrb, a, 0, mrb_class_ptr(recv), p, NULL, 0, 0);
|
||||
ci = cipush(mrb, a, 0, mrb_class_ptr(recv), p, NULL, 0, 0);
|
||||
|
||||
irep = p->body.irep;
|
||||
pool = irep->pool;
|
||||
syms = irep->syms;
|
||||
stack_extend(mrb, irep->nregs);
|
||||
stack_clear(regs+1, irep->nregs-1);
|
||||
pc = irep->iseq;
|
||||
ci->pc = irep->iseq;
|
||||
JUMP;
|
||||
}
|
||||
|
||||
@@ -2998,11 +2981,12 @@ RETRY_TRY_BLOCK:
|
||||
struct RClass *target = mrb_class_ptr(regs[a]);
|
||||
struct RProc *p = mrb_proc_ptr(regs[a+1]);
|
||||
mrb_method_t m;
|
||||
mrb_sym mid = syms[b];
|
||||
mrb_sym mid = irep->syms[b];
|
||||
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
mrb_define_method_raw(mrb, target, mid, m);
|
||||
mrb_method_added(mrb, target, mid);
|
||||
ci = mrb->c->ci;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
regs[a] = mrb_symbol_value(mid);
|
||||
NEXT;
|
||||
@@ -3025,22 +3009,26 @@ RETRY_TRY_BLOCK:
|
||||
struct RClass *target = check_target_class(mrb);
|
||||
|
||||
if (!target) goto L_RAISE;
|
||||
mrb_alias_method(mrb, target, syms[a], syms[b]);
|
||||
mrb_method_added(mrb, target, syms[a]);
|
||||
mrb_alias_method(mrb, target, irep->syms[a], irep->syms[b]);
|
||||
mrb_method_added(mrb, target, irep->syms[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_UNDEF, B) {
|
||||
struct RClass *target = check_target_class(mrb);
|
||||
|
||||
if (!target) goto L_RAISE;
|
||||
mrb_undef_method_id(mrb, target, syms[a]);
|
||||
mrb_undef_method_id(mrb, target, irep->syms[a]);
|
||||
ci = mrb->c->ci;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_DEBUG, Z) {
|
||||
const mrb_code *pc = ci->pc;
|
||||
FETCH_BBB();
|
||||
ci->pc = pc;
|
||||
#ifdef MRB_USE_DEBUG_HOOK
|
||||
mrb->debug_op_hook(mrb, irep, pc, regs);
|
||||
mrb->debug_op_hook(mrb, irep, ci->pc, regs);
|
||||
#else
|
||||
#ifndef MRB_NO_STDIO
|
||||
printf("OP_DEBUG %d %d %d\n", a, b, c);
|
||||
@@ -3052,42 +3040,42 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_ERR, B) {
|
||||
size_t len = pool[a].tt >> 2;
|
||||
size_t len = irep->pool[a].tt >> 2;
|
||||
mrb_value exc;
|
||||
|
||||
mrb_assert((pool[a].tt&IREP_TT_NFLAG)==0);
|
||||
exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, pool[a].u.str, len);
|
||||
mrb_assert((irep->pool[a].tt&IREP_TT_NFLAG)==0);
|
||||
exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, irep->pool[a].u.str, len);
|
||||
RAISE_EXC(mrb, exc);
|
||||
}
|
||||
|
||||
CASE(OP_EXT1, Z) {
|
||||
const mrb_code *pc = ci->pc;
|
||||
insn = READ_B();
|
||||
switch (insn) {
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#include <mruby/ops.h>
|
||||
#undef OPCODE
|
||||
}
|
||||
pc--;
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_EXT2, Z) {
|
||||
const mrb_code *pc = ci->pc;
|
||||
insn = READ_B();
|
||||
switch (insn) {
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#include <mruby/ops.h>
|
||||
#undef OPCODE
|
||||
}
|
||||
pc--;
|
||||
NEXT;
|
||||
}
|
||||
CASE(OP_EXT3, Z) {
|
||||
const mrb_code *pc = ci->pc;
|
||||
insn = READ_B();
|
||||
switch (insn) {
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
||||
#include <mruby/ops.h>
|
||||
#undef OPCODE
|
||||
}
|
||||
pc--;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
@@ -3100,7 +3088,7 @@ RETRY_TRY_BLOCK:
|
||||
v = mrb_break_value_get(brk);
|
||||
}
|
||||
CHECKPOINT_MAIN(RBREAK_TAG_STOP) {
|
||||
UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_STOP, mrb->c->ci, v);
|
||||
UNWIND_ENSURE(mrb, ci, ci->pc, RBREAK_TAG_STOP, ci, v);
|
||||
}
|
||||
CHECKPOINT_END(RBREAK_TAG_STOP);
|
||||
mrb->jmp = prev_jmp;
|
||||
@@ -3118,11 +3106,10 @@ RETRY_TRY_BLOCK:
|
||||
MRB_CATCH(&c_jmp) {
|
||||
mrb_assert(mrb->exc != NULL);
|
||||
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
ci = mrb->c->ci;
|
||||
while (ci > mrb->c->cibase && ci->cci == CINFO_DIRECT) {
|
||||
ci = cipop(mrb);
|
||||
}
|
||||
pc = ci->pc;
|
||||
goto RETRY_TRY_BLOCK;
|
||||
}
|
||||
MRB_END_EXC(&c_jmp);
|
||||
|
||||
Reference in New Issue
Block a user