summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gc.c16
-rw-r--r--src/kernel.c6
-rw-r--r--src/proc.c2
-rw-r--r--src/vm.c47
4 files changed, 42 insertions, 29 deletions
diff --git a/src/gc.c b/src/gc.c
index c83ce9df8..c703428b5 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -593,8 +593,9 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
}
/* mark fibers */
- if (c->prev && c->prev->fib) {
- mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib);
+ mrb_gc_mark(mrb, (struct RBasic*)c->fib);
+ if (c->prev) {
+ mark_context(mrb, c->prev);
}
}
@@ -646,7 +647,9 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
struct REnv *e = (struct REnv*)obj;
mrb_int i, len;
- if (MRB_ENV_STACK_SHARED_P(e)) break;
+ if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->fib) {
+ mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib);
+ }
len = MRB_ENV_STACK_LEN(e);
for (i=0; i<len; i++) {
mrb_gc_mark_value(mrb, e->stack[i]);
@@ -769,7 +772,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
while (ce <= ci) {
struct REnv *e = ci->env;
if (e && !is_dead(&mrb->gc, e) &&
- e->tt == MRB_TT_ENV && !MRB_ENV_STACK_SHARED_P(e)) {
+ e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
mrb_env_unshare(mrb, e);
}
ci--;
@@ -879,13 +882,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err);
#endif
- mark_context(mrb, mrb->root_c);
- if (mrb->root_c->fib) {
- mrb_gc_mark(mrb, (struct RBasic*)mrb->root_c->fib);
- }
if (mrb->root_c != mrb->c) {
mark_context(mrb, mrb->c);
}
+ mark_context(mrb, mrb->root_c);
}
static size_t
diff --git a/src/kernel.c b/src/kernel.c
index ce304fd99..c1300ed70 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -158,7 +158,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
ci = 0; /* no callinfo available */
}
else {
- ci = mrb->c->cibase + e->cioff;
+ ci = e->cxt.c->cibase + e->cioff;
bp = ci[1].stackent + 1;
}
}
@@ -1165,8 +1165,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
while (e) {
if (MRB_ENV_STACK_SHARED_P(e) &&
- !MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) {
- irep = mrb->c->cibase[e->cioff].proc->body.irep;
+ !MRB_PROC_CFUNC_P(e->cxt.c->cibase[e->cioff].proc)) {
+ irep = e->cxt.c->cibase[e->cioff].proc->body.irep;
if (irep->lv) {
for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) {
diff --git a/src/proc.c b/src/proc.c
index 3955c0a1a..ee4a493cd 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -41,7 +41,7 @@ env_new(mrb_state *mrb, int nlocals)
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
MRB_SET_ENV_STACK_LEN(e, nlocals);
- e->mid = mrb->c->ci->mid;
+ e->cxt.c = mrb->c;
e->cioff = mrb->c->ci - mrb->c->cibase;
e->stack = mrb->c->stack;
diff --git a/src/vm.c b/src/vm.c
index adc345439..47ad9a9cc 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -118,16 +118,16 @@ static inline void
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
{
mrb_callinfo *ci = mrb->c->cibase;
+ ptrdiff_t off;
if (newbase == oldbase) return;
+ off = newbase - oldbase;
while (ci <= mrb->c->ci) {
struct REnv *e = ci->env;
if (e && MRB_ENV_STACK_SHARED_P(e)) {
- ptrdiff_t off = e->stack - oldbase;
-
- e->stack = newbase + off;
+ e->stack += off;
}
- ci->stackent = newbase + (ci->stackent - oldbase);
+ ci->stackent += off;
ci++;
}
}
@@ -201,8 +201,8 @@ is_strict(mrb_state *mrb, struct REnv *e)
{
int cioff = e->cioff;
- if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc &&
- MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) {
+ if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->cibase[cioff].proc &&
+ MRB_PROC_STRICT_P(e->cxt.c->cibase[cioff].proc)) {
return TRUE;
}
return FALSE;
@@ -257,15 +257,17 @@ MRB_API void
mrb_env_unshare(mrb_state *mrb, struct REnv *e)
{
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
- mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
ptrdiff_t cioff = e->cioff;
+ mrb_value *p;
if (!MRB_ENV_STACK_SHARED_P(e)) return;
MRB_ENV_UNSHARE_STACK(e);
if (!e->c) {
/* save block argument position (negated) */
- e->cioff = -mrb->c->cibase[cioff].argc-1;
+ e->cioff = -e->cxt.c->cibase[cioff].argc-1;
}
+ e->cxt.mid = e->cxt.c->cibase[cioff].mid;
+ p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
if (len > 0) {
stack_copy(p, e->stack, len);
}
@@ -292,27 +294,28 @@ static void
ecall(mrb_state *mrb, int i)
{
struct RProc *p;
- mrb_callinfo *ci;
+ mrb_callinfo *ci = mrb->c->ci;
mrb_value *self = mrb->c->stack;
struct RObject *exc;
int cioff;
if (i<0) return;
- if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
+ if (ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
}
p = mrb->c->ensure[i];
if (!p) return;
mrb->c->ensure[i] = NULL;
- if (mrb->c->ci->eidx > i)
- mrb->c->ci->eidx = i;
- cioff = mrb->c->ci - mrb->c->cibase;
+ if (ci->eidx > i)
+ ci->eidx = i;
+ cioff = ci - mrb->c->cibase;
ci = cipush(mrb);
ci->stackent = mrb->c->stack;
ci->mid = ci[-1].mid;
ci->acc = CI_ACC_SKIP;
ci->argc = 0;
ci->proc = p;
+ ci->env = p->env;
ci->nregs = p->body.irep->nregs;
ci->target_class = p->target_class;
mrb->c->stack = mrb->c->stack + ci[-1].nregs;
@@ -1057,7 +1060,6 @@ RETRY_TRY_BLOCK:
/* A B C R(A) := uvget(B,C) */
mrb_value *regs_a = regs + GETARG_A(i);
int up = GETARG_C(i);
-
struct REnv *e = uvenv(mrb, up);
if (!e) {
@@ -1235,6 +1237,10 @@ RETRY_TRY_BLOCK:
bidx = a+n+1;
}
if (GET_OPCODE(i) != OP_SENDB) {
+ if (bidx >= mrb->c->ci->nregs) {
+ stack_extend(mrb, bidx+1);
+ mrb->c->ci->nregs = bidx+1;
+ }
SET_NIL_VALUE(regs[bidx]);
}
else {
@@ -1362,9 +1368,15 @@ RETRY_TRY_BLOCK:
ci->target_class = m->target_class;
ci->proc = m;
if (m->env) {
- if (m->env->mid) {
- ci->mid = m->env->mid;
+ mrb_sym mid;
+
+ if (MRB_ENV_STACK_SHARED_P(m->env)) {
+ mid = m->env->cxt.c->cibase[m->env->cioff].mid;
+ }
+ else {
+ mid = m->env->cxt.mid;
}
+ if (mid) ci->mid = mid;
if (!m->env->stack) {
m->env->stack = mrb->c->stack;
}
@@ -1989,7 +2001,8 @@ RETRY_TRY_BLOCK:
if (lv == 0) stack = regs + 1;
else {
struct REnv *e = uvenv(mrb, lv-1);
- if (!e || e->mid == 0) {
+ if (!e || e->cioff == 0 ||
+ (!MRB_ENV_STACK_SHARED_P(e) && e->cxt.mid == 0)) {
localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
}