summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authordearblue <[email protected]>2021-01-10 10:50:22 +0900
committerdearblue <[email protected]>2021-01-10 13:23:43 +0900
commitced89c25ffc9ac748dc2dd336cce24d080ebf419 (patch)
treec72aa35170876cf2904315a43a383127f796ce34
parent16baea06771f38fea810ad1eaf3239086442c258 (diff)
downloadmruby-ced89c25ffc9ac748dc2dd336cce24d080ebf419.tar.gz
mruby-ced89c25ffc9ac748dc2dd336cce24d080ebf419.zip
Unified `pc` and `err` of `mrb_callinfo`
This enhances self-containment. - Changed the `mrb_callinfo::pc` field to point to itself. Previously it indicated the return destination of the previous call level. `mrb_callinfo::pc` will now hold the address to its own `proc->body.irep->iseq`. - Removed `mrb_callinfo::err` field. This is because `mrb_callinfo::pc - 1` is semantically the same as the previous `err`. - The `pc0` and `pc_save` variables in `mrb_vm_exec()` are no longer needed and have been deleted. - It removes the argument because `cipush()` doesn't need to save the previous `pc`.
-rw-r--r--include/mruby.h3
-rw-r--r--include/mruby/proc.h7
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c3
-rw-r--r--src/backtrace.c16
-rw-r--r--src/vm.c77
5 files changed, 45 insertions, 61 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 3f78e66c6..b54e4f98e 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -152,8 +152,7 @@ typedef struct {
mrb_sym mid;
const struct RProc *proc;
mrb_value *stack;
- const mrb_code *pc; /* return address */
- const mrb_code *err; /* error position */
+ const mrb_code *pc; /* current address on iseq of this proc */
int16_t argc;
int16_t acc;
union {
diff --git a/include/mruby/proc.h b/include/mruby/proc.h
index b4d0927a9..be45a06d8 100644
--- a/include/mruby/proc.h
+++ b/include/mruby/proc.h
@@ -136,6 +136,13 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
MRB_API mrb_value mrb_load_proc(mrb_state *mrb, const struct RProc *proc);
+static inline void
+mrb_vm_ci_proc_set(mrb_callinfo *ci, const struct RProc *p)
+{
+ ci->proc = p;
+ ci->pc = (p && !MRB_PROC_CFUNC_P(p)) ? p->body.irep->iseq : NULL;
+}
+
static inline struct RClass *
mrb_vm_ci_target_class(const mrb_callinfo *ci)
{
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
index d75f864c1..7fd755843 100644
--- a/mrbgems/mruby-fiber/src/fiber.c
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -119,9 +119,8 @@ fiber_init(mrb_state *mrb, mrb_value self)
/* adjust return callinfo */
ci = c->ci;
mrb_vm_ci_target_class_set(ci, MRB_PROC_TARGET_CLASS(p));
- ci->proc = p;
+ mrb_vm_ci_proc_set(ci, p);
mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
- ci->pc = p->body.irep->iseq;
ci->stack = c->stbase;
ci[1] = ci[0];
c->ci++; /* push dummy callinfo */
diff --git a/src/backtrace.c b/src/backtrace.c
index 1006f2f86..508fe99e9 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -29,7 +29,7 @@ mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc);
mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
static void
-each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data)
+each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *data)
{
ptrdiff_t i;
@@ -50,15 +50,11 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr
irep = ci->proc->body.irep;
if (!irep) continue;
- if (mrb->c->cibase[i].err) {
- pc = mrb->c->cibase[i].err;
- }
- else if (i+1 <= ciidx) {
- if (!mrb->c->cibase[i + 1].pc) continue;
- pc = &mrb->c->cibase[i+1].pc[-1];
+ if (mrb->c->cibase[i].pc) {
+ pc = &mrb->c->cibase[i].pc[-1];
}
else {
- pc = pc0;
+ continue;
}
loc.lineno = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
@@ -159,12 +155,12 @@ packed_backtrace(mrb_state *mrb)
int size;
void *ptr;
- each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len);
+ each_backtrace(mrb, ciidx, count_backtrace_i, &len);
size = len * sizeof(struct backtrace_location);
ptr = mrb_malloc(mrb, size);
backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
backtrace->flags = (uint32_t)len;
- each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr);
+ each_backtrace(mrb, ciidx, pack_backtrace_i, &ptr);
return mrb_obj_value(backtrace);
}
diff --git a/src/vm.c b/src/vm.c
index 7a2ec29d7..bbe812997 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -262,7 +262,7 @@ top_proc(mrb_state *mrb, const struct RProc *proc)
#define CI_ACC_RESUMED -3
static inline mrb_callinfo*
-cipush(mrb_state *mrb, const mrb_code *pc, mrb_int push_stacks, mrb_int acc,
+cipush(mrb_state *mrb, mrb_int push_stacks, mrb_int acc,
struct RClass *target_class, const struct RProc *proc, mrb_sym mid, mrb_int argc)
{
struct mrb_context *c = mrb->c;
@@ -277,13 +277,11 @@ cipush(mrb_state *mrb, const mrb_code *pc, mrb_int push_stacks, mrb_int acc,
}
ci = ++c->ci;
ci->mid = mid;
- ci->proc = proc;
+ mrb_vm_ci_proc_set(ci, proc);
ci->stack = ci[-1].stack + push_stacks;
- ci->pc = pc;
ci->argc = argc;
ci->acc = acc;
ci->u.target_class = target_class;
- ci->err = 0;
return ci;
}
@@ -446,7 +444,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
}
- ci = cipush(mrb, NULL, n, 0, c, NULL, mid, argc);
+ ci = cipush(mrb, n, 0, c, NULL, mid, argc);
if (argc < 0) argc = 1;
if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
voff = argv - mrb->c->stbase;
@@ -462,7 +460,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
if (MRB_METHOD_PROC_P(m)) {
struct RProc *p = MRB_METHOD_PROC(m);
- ci->proc = p;
+ mrb_vm_ci_proc_set(ci, p);
if (!MRB_PROC_CFUNC_P(p)) {
mrb_stack_extend(mrb, p->body.irep->nregs + argc);
}
@@ -504,7 +502,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
mrb_int keep, nregs;
mrb->c->ci->stack[0] = self;
- ci->proc = p;
+ mrb_vm_ci_proc_set(ci, p);
if (MRB_PROC_CFUNC_P(p)) {
return MRB_PROC_CFUNC(p)(mrb, self);
}
@@ -519,7 +517,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
stack_clear(mrb->c->ci->stack+keep, nregs-keep);
}
- cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0);
+ cipush(mrb, 0, 0, NULL, NULL, 0, 0);
return self;
}
@@ -583,7 +581,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
if (MRB_METHOD_CFUNC_P(m)) {
if (MRB_METHOD_PROC_P(m)) {
- ci->proc = MRB_METHOD_PROC(m);
+ mrb_vm_ci_proc_set(ci, MRB_METHOD_PROC(m));
}
return MRB_METHOD_CFUNC(m)(mrb, self);
}
@@ -606,7 +604,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
}
ci->u.target_class = c;
p = mrb_proc_ptr(blk);
- ci->proc = p;
+ mrb_vm_ci_proc_set(ci, p);
ci->argc = 1;
ci->mid = ci[-1].mid;
if (MRB_PROC_CFUNC_P(p)) {
@@ -622,7 +620,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
mrb->c->ci->stack[0] = self;
mrb->c->ci->stack[1] = self;
stack_clear(mrb->c->ci->stack+2, nregs-2);
- ci = cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0);
+ ci = cipush(mrb, 0, 0, NULL, NULL, 0, 0);
return self;
}
@@ -698,7 +696,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
}
p = mrb_proc_ptr(b);
- ci = cipush(mrb, NULL, n, CI_ACC_SKIP, c, p, mid, 0 /* dummy */);
+ ci = cipush(mrb, n, CI_ACC_SKIP, c, p, mid, 0 /* dummy */);
if (argc >= CALL_MAXARGS) {
ci->argc = -1;
n = 3;
@@ -928,8 +926,6 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb
} while (0); \
} while (0)
-#define ERR_PC_SET(mrb) mrb->c->ci->err = pc0;
-#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
#ifdef MRB_USE_DEBUG_HOOK
#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
#else
@@ -951,7 +947,7 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb
#ifndef DIRECT_THREADED
#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) {
-#define CASE(insn,ops) case insn: pc0=pc++; FETCH_ ## ops (); pc_save = pc;
+#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc;
#define NEXT goto L_END_DISPATCH
#define JUMP NEXT
#define END_DISPATCH L_END_DISPATCH:;}}
@@ -959,7 +955,7 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb
#else
#define INIT_DISPATCH JUMP; return mrb_nil_value();
-#define CASE(insn,ops) L_ ## insn: pc0=pc++; FETCH_ ## ops (); pc_save = pc;
+#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc;
#define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn]
#define JUMP NEXT
@@ -1014,8 +1010,6 @@ MRB_API mrb_value
mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
{
/* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
- const mrb_code *pc0 = pc;
- const mrb_code *volatile pc_save = pc;
const mrb_irep *irep = proc->body.irep;
const mrb_pool_value *pool = irep->pool;
const mrb_sym *syms = irep->syms;
@@ -1050,7 +1044,7 @@ RETRY_TRY_BLOCK:
goto L_RAISE;
}
mrb->jmp = &c_jmp;
- mrb->c->ci->proc = proc;
+ mrb_vm_ci_proc_set(mrb->c->ci, proc);
#define regs (mrb->c->ci->stack)
INIT_DISPATCH {
@@ -1197,9 +1191,7 @@ RETRY_TRY_BLOCK:
CASE(OP_GETCV, BB) {
mrb_value val;
- ERR_PC_SET(mrb);
val = mrb_vm_cv_get(mrb, syms[b]);
- ERR_PC_CLR(mrb);
regs[a] = val;
NEXT;
}
@@ -1213,9 +1205,7 @@ RETRY_TRY_BLOCK:
mrb_value val;
mrb_sym sym = syms[b];
- ERR_PC_SET(mrb);
val = mrb_vm_const_get(mrb, sym);
- ERR_PC_CLR(mrb);
regs[a] = val;
NEXT;
}
@@ -1228,9 +1218,7 @@ RETRY_TRY_BLOCK:
CASE(OP_GETMCNST, BB) {
mrb_value val;
- ERR_PC_SET(mrb);
val = mrb_const_get(mrb, regs[a], syms[b]);
- ERR_PC_CLR(mrb);
regs[a] = val;
NEXT;
}
@@ -1432,7 +1420,6 @@ RETRY_TRY_BLOCK:
m = mrb_method_search_vm(mrb, &cls, missing);
if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1);
- ERR_PC_SET(mrb);
mrb_method_missing(mrb, mid, recv, args);
}
if (argc >= 0) {
@@ -1448,13 +1435,13 @@ RETRY_TRY_BLOCK:
}
/* push callinfo */
- ci = cipush(mrb, pc, a, a, cls, NULL, mid, argc);
+ ci = cipush(mrb, a, a, cls, NULL, mid, argc);
if (MRB_METHOD_CFUNC_P(m)) {
if (MRB_METHOD_PROC_P(m)) {
struct RProc *p = MRB_METHOD_PROC(m);
- ci->proc = p;
+ mrb_vm_ci_proc_set(ci, p);
recv = p->body.func(mrb, recv);
}
else if (MRB_METHOD_NOARG_P(m) &&
@@ -1490,13 +1477,13 @@ RETRY_TRY_BLOCK:
}
mrb->c->ci->stack[0] = recv;
/* pop stackpos */
+ ci = cipop(mrb);
pc = ci->pc;
- cipop(mrb);
JUMP;
}
else {
/* setup environment for calling method */
- proc = ci->proc = MRB_METHOD_PROC(m);
+ mrb_vm_ci_proc_set(ci, (proc = MRB_METHOD_PROC(m)));
irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
@@ -1514,7 +1501,7 @@ RETRY_TRY_BLOCK:
/* replace callinfo */
ci = mrb->c->ci;
ci->u.target_class = MRB_PROC_TARGET_CLASS(m);
- ci->proc = m;
+ mrb_vm_ci_proc_set(ci, m);
if (MRB_PROC_ENV_P(m)) {
ci->mid = MRB_PROC_ENV(m)->mid;
}
@@ -1526,9 +1513,8 @@ RETRY_TRY_BLOCK:
mrb_gc_arena_shrink(mrb, ai);
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- ci = mrb->c->ci;
+ ci = cipop(mrb);
pc = ci->pc;
- cipop(mrb);
regs[ci->acc] = recv;
irep = mrb->c->ci->proc->body.irep;
pool = irep->pool;
@@ -1622,7 +1608,6 @@ RETRY_TRY_BLOCK:
m = mrb_method_search_vm(mrb, &cls, missing);
if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1);
- ERR_PC_SET(mrb);
mrb_method_missing(mrb, mid, recv, args);
}
mid = missing;
@@ -1638,7 +1623,7 @@ RETRY_TRY_BLOCK:
}
/* push callinfo */
- ci = cipush(mrb, pc, a, 0, cls, NULL, mid, argc);
+ ci = cipush(mrb, a, 0, cls, NULL, mid, argc);
/* prepare stack */
mrb->c->ci->stack[0] = recv;
@@ -1647,7 +1632,7 @@ RETRY_TRY_BLOCK:
mrb_value v;
if (MRB_METHOD_PROC_P(m)) {
- ci->proc = MRB_METHOD_PROC(m);
+ mrb_vm_ci_proc_set(ci, MRB_METHOD_PROC(m));
}
v = MRB_METHOD_CFUNC(m)(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
@@ -1668,8 +1653,8 @@ RETRY_TRY_BLOCK:
}
}
mrb->c->ci->stack[0] = v;
+ ci = cipop(mrb);
pc = ci->pc;
- cipop(mrb);
JUMP;
}
else {
@@ -1677,7 +1662,7 @@ RETRY_TRY_BLOCK:
ci->acc = a;
/* setup environment for calling method */
- proc = ci->proc = MRB_METHOD_PROC(m);
+ mrb_vm_ci_proc_set(ci, (proc = MRB_METHOD_PROC(m)));
irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
@@ -1968,7 +1953,7 @@ RETRY_TRY_BLOCK:
mrb->jmp = prev_jmp;
MRB_THROW(prev_jmp);
}
- pc = ci[1].pc;
+ pc = ci[0].pc;
if (ci == mrb->c->cibase) {
ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL);
if (ch == NULL) {
@@ -2048,8 +2033,8 @@ RETRY_TRY_BLOCK:
UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN_BLOCK, proc, v);
}
CHECKPOINT_END(RBREAK_TAG_RETURN_BLOCK);
- pc = ci->pc;
ci = cipop(mrb);
+ pc = ci->pc;
}
proc = ci->proc;
mrb->exc = NULL; /* clear break object */
@@ -2172,8 +2157,8 @@ RETRY_TRY_BLOCK:
UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK_UPPER, proc, v);
}
CHECKPOINT_END(RBREAK_TAG_BREAK_UPPER);
- pc = ci->pc;
ci = cipop(mrb);
+ pc = ci->pc;
}
CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_INTARGET) {
/* do nothing */
@@ -2207,7 +2192,7 @@ RETRY_TRY_BLOCK:
mrb->jmp = prev_jmp;
return v;
}
- pc = ci[1].pc;
+ pc = ci[0].pc;
DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid)));
proc = mrb->c->ci->proc;
irep = proc->body.irep;
@@ -2741,7 +2726,7 @@ RETRY_TRY_BLOCK:
p->flags |= MRB_PROC_SCOPE;
/* prepare call stack */
- cipush(mrb, pc, a, a, mrb_class_ptr(recv), p, 0, 0);
+ cipush(mrb, a, a, mrb_class_ptr(recv), p, 0, 0);
irep = p->body.irep;
pool = irep->pool;
@@ -2812,7 +2797,6 @@ RETRY_TRY_BLOCK:
mrb_assert((pool[a].tt&IREP_TT_NFLAG)==0);
exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, pool[a].u.str, len);
- ERR_PC_SET(mrb);
mrb_exc_set(mrb, exc);
goto L_RAISE;
}
@@ -2831,7 +2815,6 @@ RETRY_TRY_BLOCK:
}
CHECKPOINT_END(RBREAK_TAG_STOP);
L_STOP:
- ERR_PC_CLR(mrb);
mrb->jmp = prev_jmp;
if (mrb->exc) {
mrb_assert(mrb->exc->tt == MRB_TT_EXCEPTION);
@@ -2849,7 +2832,7 @@ RETRY_TRY_BLOCK:
ci = cipop(mrb);
}
exc_catched = TRUE;
- pc = pc_save;
+ pc = ci->pc;
goto RETRY_TRY_BLOCK;
}
MRB_END_EXC(&c_jmp);
@@ -2878,7 +2861,7 @@ mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int st
mrb_vm_ci_env_set(mrb->c->ci, NULL);
return mrb_vm_run(mrb, proc, self, stack_keep);
}
- cipush(mrb, NULL, 0, CI_ACC_SKIP, mrb->object_class, NULL, 0, 0);
+ cipush(mrb, 0, CI_ACC_SKIP, mrb->object_class, NULL, 0, 0);
v = mrb_vm_run(mrb, proc, self, stack_keep);
return v;