summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-05-20 17:54:07 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-05-20 17:54:07 +0900
commit5c0b9b703c9d1a08d7219b057b809bda4bc89f8a (patch)
treeab610a2988ef928c02bfc50e31aedc5a707f008e
parent35ee85164dd19143d4b47a34f13ad2bb71fed369 (diff)
downloadmruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.tar.gz
mruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.zip
primary mruby fiber implementation
-rw-r--r--include/mruby.h29
-rw-r--r--include/mruby/gc.h1
-rw-r--r--include/mruby/value.h11
-rw-r--r--mrbgems/default.gembox3
-rw-r--r--mrbgems/mruby-fiber/mrbgem.rake4
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c179
-rw-r--r--mrbgems/mruby-struct/src/struct.c4
-rw-r--r--src/backtrace.c6
-rw-r--r--src/class.c12
-rw-r--r--src/error.c6
-rw-r--r--src/gc.c95
-rw-r--r--src/kernel.c10
-rw-r--r--src/proc.c18
-rw-r--r--src/state.c21
-rw-r--r--src/variable.c22
-rw-r--r--src/vm.c315
16 files changed, 508 insertions, 228 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 9fe70e5b8..73c38cf1d 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -61,16 +61,8 @@ typedef struct {
struct REnv *env;
} mrb_callinfo;
-enum gc_state {
- GC_STATE_NONE = 0,
- GC_STATE_MARK,
- GC_STATE_SWEEP
-};
-
-typedef struct mrb_state {
- void *jmp;
-
- mrb_allocf allocf;
+struct mrb_context {
+ struct mrb_context *prev;
mrb_value *stack;
mrb_value *stbase, *stend;
@@ -82,10 +74,24 @@ typedef struct mrb_state {
int rsize;
struct RProc **ensure;
int esize;
+};
+
+enum gc_state {
+ GC_STATE_NONE = 0,
+ GC_STATE_MARK,
+ GC_STATE_SWEEP
+};
+
+typedef struct mrb_state {
+ void *jmp;
+
+ mrb_allocf allocf;
+
+ struct mrb_context *c;
+ struct mrb_context *root_c;
struct RObject *exc;
struct iv_tbl *globals;
-
struct mrb_irep **irep;
size_t irep_len, irep_capa;
@@ -140,7 +146,6 @@ typedef struct mrb_state {
struct RClass *eStandardError_class;
void *ud; /* auxiliary data */
-
} mrb_state;
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
diff --git a/include/mruby/gc.h b/include/mruby/gc.h
index 2f7dc73cf..7afa24b48 100644
--- a/include/mruby/gc.h
+++ b/include/mruby/gc.h
@@ -12,5 +12,6 @@
typedef void (each_object_callback)(mrb_state *mrb, struct RBasic* obj, void *data);
void mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void *data);
+void mrb_free_context(mrb_state *mrb, struct mrb_context *c);
#endif /* MRUBY_GC_H */
diff --git a/include/mruby/value.h b/include/mruby/value.h
index 0ce59e06a..fa2a68ac8 100644
--- a/include/mruby/value.h
+++ b/include/mruby/value.h
@@ -34,7 +34,8 @@ enum mrb_vtype {
MRB_TT_FILE, /* 19 */
MRB_TT_ENV, /* 20 */
MRB_TT_DATA, /* 21 */
- MRB_TT_MAXDEFINE /* 22 */
+ MRB_TT_FIBER, /* 22 */
+ MRB_TT_MAXDEFINE /* 23 */
};
typedef struct mrb_value {
@@ -92,7 +93,8 @@ enum mrb_vtype {
MRB_TT_FILE, /* 20 */
MRB_TT_ENV, /* 21 */
MRB_TT_DATA, /* 22 */
- MRB_TT_MAXDEFINE /* 23 */
+ MRB_TT_FIBER, /* 23 */
+ MRB_TT_MAXDEFINE /* 24 */
};
#ifdef MRB_ENDIAN_BIG
@@ -202,6 +204,11 @@ struct RObject {
#define mrb_immediate_p(x) (mrb_type(x) <= MRB_TT_VOIDP)
#define mrb_special_const_p(x) mrb_immediate_p(x)
+struct RFiber {
+ MRB_OBJECT_HEADER;
+ struct mrb_context *cxt;
+};
+
static inline mrb_value
mrb_fixnum_value(mrb_int i)
{
diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox
index a53b07d8a..1c6732d48 100644
--- a/mrbgems/default.gembox
+++ b/mrbgems/default.gembox
@@ -44,6 +44,9 @@ MRuby::GemBox.new do |conf|
# Use ObjectSpace class
conf.gem :core => "mruby-objectspace"
+ # Use Fiber class
+ conf.gem :core => "mruby-fiber"
+
# Generate mirb command
conf.gem :core => "mruby-bin-mirb"
diff --git a/mrbgems/mruby-fiber/mrbgem.rake b/mrbgems/mruby-fiber/mrbgem.rake
new file mode 100644
index 000000000..cb258adcb
--- /dev/null
+++ b/mrbgems/mruby-fiber/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-fiber') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mruby developers'
+end
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
new file mode 100644
index 000000000..01410e4b3
--- /dev/null
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -0,0 +1,179 @@
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "mruby/proc.h"
+
+#define FIBER_STACK_INIT_SIZE 64
+#define FIBER_CI_INIT_SIZE 8
+
+/*
+ * call-seq:
+ * Fiber.new{...} -> obj
+ *
+ * Creates an fiber, whose execution is suspend until it explicitly
+ * resumed using <code>Fibder#resume</code> method.
+ * <code>resume</code>. Arguments passed to resume will be the value of
+ * the <code>Fiber.yield</code> expression or will be passed as block
+ * parameters to the fiber's block if this is the first <code>resume</code>.
+ *
+ * Alternatively, when resume is called it evaluates to the arguments passed
+ * to the next <code>Fiber.yield</code> statement inside the fiber's block
+ * or to the block value if it runs to completion without any
+ * <code>Fiber.yield</code>
+ */
+static mrb_value
+fiber_init(mrb_state *mrb, mrb_value self)
+{
+ static const struct mrb_context mrb_context_zero = { 0 };
+ struct RFiber *f = (struct RFiber*)self.value.p;
+ struct mrb_context *c;
+ struct RProc *p;
+ mrb_callinfo *ci;
+ mrb_value blk;
+
+ mrb_get_args(mrb, "&", &blk);
+
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
+ }
+ p = mrb_proc_ptr(blk);
+ if (MRB_PROC_CFUNC_P(p)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber from C defined method");
+ }
+
+ f->cxt = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
+ *f->cxt = mrb_context_zero;
+
+ /* initialize VM stack */
+ c = f->cxt;
+ c->stbase = (mrb_value *)mrb_calloc(mrb, FIBER_STACK_INIT_SIZE, sizeof(mrb_value));
+ c->stend = c->stbase + FIBER_STACK_INIT_SIZE;
+ c->stack = c->stbase;
+
+ /* copy receiver from a block */
+ c->stack[0] = mrb->c->stack[0];
+
+ /* initialize callinfo stack */
+ c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo));
+ c->ciend = c->cibase + FIBER_CI_INIT_SIZE;
+ c->ci = c->cibase;
+
+ /* adjust return callinfo */
+ ci = c->ci;
+ ci->target_class = p->target_class;
+ ci->proc = p;
+ ci->pc = p->body.irep->iseq;
+ ci->nregs = p->body.irep->nregs;
+ ci[1] = ci[0];
+ c->ci++; /* push dummy callinfo */
+
+ return self;
+}
+
+static struct mrb_context*
+fiber_check(mrb_state *mrb, mrb_value fib)
+{
+ struct RFiber *f = (struct RFiber*)fib.value.p;
+
+ if (!f->cxt) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized Fiber");
+ }
+ return f->cxt;
+}
+
+static mrb_value
+fiber_result(mrb_state *mrb, mrb_value *a, int len)
+{
+ if (len == 0) return mrb_nil_value();
+ if (len == 1) return a[0];
+ return mrb_ary_new_from_values(mrb, len, a);
+}
+
+/*
+ * call-seq:
+ * fiber.resume(args, ...) -> obj
+ *
+ * Resumes the fiber from the point at which the last <code>Fiber.yield</code>
+ * was called, or starts running it if it is the first call to
+ * <code>resume</code>. Arguments passed to resume will be the value of
+ * the <code>Fiber.yield</code> expression or will be passed as block
+ * parameters to the fiber's block if this is the first <code>resume</code>.
+ *
+ * Alternatively, when resume is called it evaluates to the arguments passed
+ * to the next <code>Fiber.yield</code> statement inside the fiber's block
+ * or to the block value if it runs to completion without any
+ * <code>Fiber.yield</code>
+ */
+static mrb_value
+fiber_resume(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_context *c = fiber_check(mrb, self);
+ mrb_value *a;
+ int len;
+
+ mrb_get_args(mrb, "*", &a, &len);
+ if (!c->prev) { /* first call */
+ mrb_value *b = c->stack+1;
+ mrb_value *e = b + len;
+
+ while (b<e) {
+ *b++ = *a++;
+ }
+ c->ci->argc = len;
+ c->prev = mrb->c;
+ mrb->c = c;
+
+ return c->ci->proc->env->stack[0];
+ }
+ if (c->ci == c->cibase) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "resuming dead Fiber");
+ }
+ c->prev = mrb->c;
+ mrb->c = c;
+ return fiber_result(mrb, a, len);
+}
+
+/*
+ * call-seq:
+ * Fiber.yield(args, ...) -> obj
+ *
+ * Yields control back to the context that resumed the fiber, passing
+ * along any arguments that were passed to it. The fiber will resume
+ * processing at this point when <code>resume</code> is called next.
+ * Any arguments passed to the next <code>resume</code> will be the
+ * value that this <code>Fiber.yield</code> expression evaluates to.
+ */
+static mrb_value
+fiber_yield(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_context *c = mrb->c;
+ mrb_value *a;
+ int len;
+
+ if (!c->prev) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "can't yield from root Fiber");
+ }
+ mrb_get_args(mrb, "*", &a, &len);
+
+ mrb->c = c->prev;
+ return fiber_result(mrb, a, len);
+}
+
+void
+mrb_mruby_fiber_gem_init(mrb_state* mrb)
+{
+ struct RClass *c;
+
+ c = mrb_define_class(mrb, "Fiber", mrb->object_class);
+ MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER);
+
+ mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY());
+
+ mrb_define_class_method(mrb, c, "yield", fiber_yield, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_fiber_gem_final(mrb_state* mrb)
+{
+}
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index 2775471fe..a2731ca54 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -132,7 +132,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
static mrb_value
mrb_struct_ref(mrb_state *mrb, mrb_value obj)
{
- return mrb_struct_getmember(mrb, obj, mrb->ci->mid);
+ return mrb_struct_getmember(mrb, obj, mrb->c->ci->mid);
}
static mrb_value mrb_struct_ref0(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[0];}
@@ -191,7 +191,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
mrb_value members, slot, *ptr, *ptr_members;
/* get base id */
- name = mrb_sym2name_len(mrb, mrb->ci->mid, &len);
+ name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &len);
mid = mrb_intern2(mrb, name, len-1); /* omit last "=" */
members = mrb_struct_members(mrb, obj);
diff --git a/src/backtrace.c b/src/backtrace.c
index 3fadb9552..f6e3e2eb0 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -19,11 +19,11 @@ mrb_print_backtrace(mrb_state *mrb)
printf("trace:\n");
ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx")));
- if (ciidx >= mrb->ciend - mrb->cibase)
+ if (ciidx >= mrb->c->ciend - mrb->c->cibase)
ciidx = 10; /* ciidx is broken... */
for (i = ciidx; i >= 0; i--) {
- ci = &mrb->cibase[i];
+ ci = &mrb->c->cibase[i];
filename = "(unknown)";
line = -1;
@@ -38,7 +38,7 @@ mrb_print_backtrace(mrb_state *mrb)
mrb_code *pc;
if (i+1 <= ciidx) {
- pc = mrb->cibase[i+1].pc;
+ pc = mrb->c->cibase[i+1].pc;
}
else {
pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc")));
diff --git a/src/class.c b/src/class.c
index e756cf562..4264129b6 100644
--- a/src/class.c
+++ b/src/class.c
@@ -391,14 +391,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
char c;
int i = 0;
- mrb_value *sp = mrb->stack + 1;
+ mrb_value *sp = mrb->c->stack + 1;
va_list ap;
- int argc = mrb->ci->argc;
+ int argc = mrb->c->ci->argc;
int opt = 0;
va_start(ap, format);
if (argc < 0) {
- struct RArray *a = mrb_ary_ptr(mrb->stack[1]);
+ struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
argc = a->len;
sp = a->ptr;
@@ -620,11 +620,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p, *bp;
p = va_arg(ap, mrb_value*);
- if (mrb->ci->argc < 0) {
- bp = mrb->stack + 2;
+ if (mrb->c->ci->argc < 0) {
+ bp = mrb->c->stack + 2;
}
else {
- bp = mrb->stack + mrb->ci->argc + 1;
+ bp = mrb->c->stack + mrb->c->ci->argc + 1;
}
*p = *bp;
}
diff --git a/src/error.c b/src/error.c
index 1ac42455c..bd3afd2e1 100644
--- a/src/error.c
+++ b/src/error.c
@@ -189,12 +189,12 @@ exc_equal(mrb_state *mrb, mrb_value exc)
static void
exc_debug_info(mrb_state *mrb, struct RObject *exc)
{
- mrb_callinfo *ci = mrb->ci;
+ mrb_callinfo *ci = mrb->c->ci;
mrb_code *pc = ci->pc;
- mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase));
ci--;
- while (ci >= mrb->cibase) {
+ while (ci >= mrb->c->cibase) {
if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
mrb_irep *irep = ci->proc->body.irep;
diff --git a/src/gc.c b/src/gc.c
index 2e5678f7d..4837d5207 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -387,6 +387,35 @@ add_gray_list(mrb_state *mrb, struct RBasic *obj)
}
static void
+mark_context(mrb_state *mrb, struct mrb_context *c)
+{
+ size_t i;
+ size_t e;
+ mrb_callinfo *ci;
+
+ /* mark stack */
+ e = c->stack - c->stbase;
+ if (c->ci) e += c->ci->nregs;
+ if (c->stbase + e > c->stend) e = c->stend - c->stbase;
+ for (i=0; i<e; i++) {
+ mrb_gc_mark_value(mrb, c->stbase[i]);
+ }
+ /* mark ensure stack */
+ e = (c->ci) ? c->ci->eidx : 0;
+ for (i=0; i<e; i++) {
+ mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
+ }
+ /* mark closure */
+ for (ci = c->cibase; ci <= c->ci; ci++) {
+ if (!ci) continue;
+ mrb_gc_mark(mrb, (struct RBasic*)ci->env);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->proc);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->target_class);
+ }
+ if (c->prev) mark_context(mrb, c->prev);
+}
+
+static void
gc_mark_children(mrb_state *mrb, struct RBasic *obj)
{
gc_assert(is_gray(obj));
@@ -438,6 +467,15 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
}
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ mark_context(mrb, c);
+ ((struct RFiber*)obj)->cxt = NULL;
+ }
+ break;
+
case MRB_TT_ARRAY:
{
struct RArray *a = (struct RArray*)obj;
@@ -517,6 +555,14 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
}
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ mrb_free_context(mrb, c);
+ }
+ break;
+
case MRB_TT_ARRAY:
if (obj->flags & MRB_ARY_SHARED)
mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
@@ -557,9 +603,7 @@ static void
root_scan_phase(mrb_state *mrb)
{
int j;
- size_t i;
- size_t e;
- mrb_callinfo *ci;
+ size_t i, e;
if (!is_minor_gc(mrb)) {
mrb->gray_list = 0;
@@ -577,25 +621,8 @@ root_scan_phase(mrb_state *mrb)
mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
- /* mark stack */
- e = mrb->stack - mrb->stbase;
- if (mrb->ci) e += mrb->ci->nregs;
- if (mrb->stbase + e > mrb->stend) e = mrb->stend - mrb->stbase;
- for (i=0; i<e; i++) {
- mrb_gc_mark_value(mrb, mrb->stbase[i]);
- }
- /* mark ensure stack */
- e = (mrb->ci) ? mrb->ci->eidx : 0;
- for (i=0; i<e; i++) {
- mrb_gc_mark(mrb, (struct RBasic*)mrb->ensure[i]);
- }
- /* mark closure */
- for (ci = mrb->cibase; ci <= mrb->ci; ci++) {
- if (!ci) continue;
- mrb_gc_mark(mrb, (struct RBasic*)ci->env);
- mrb_gc_mark(mrb, (struct RBasic*)ci->proc);
- mrb_gc_mark(mrb, (struct RBasic*)ci->target_class);
- }
+
+ mark_context(mrb, mrb->c);
/* mark irep pool */
if (mrb->irep) {
size_t len = mrb->irep_len;
@@ -643,6 +670,30 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
children += (int)obj->flags;
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+ size_t i;
+ mrb_callinfo *ci;
+
+ /* mark stack */
+ i = c->stack - c->stbase;
+ if (c->ci) i += c->ci->nregs;
+ if (c->stbase + i > c->stend) i = c->stend - c->stbase;
+ children += i;
+
+ /* mark ensure stack */
+ children += (c->ci) ? c->ci->eidx : 0;
+
+ /* mark closure */
+ if (c->cibase) {
+ for (i=0, ci = c->cibase; ci <= c->ci; i++, ci++)
+ ;
+ }
+ children += i;
+ }
+ break;
+
case MRB_TT_ARRAY:
{
struct RArray *a = (struct RArray*)obj;
diff --git a/src/kernel.c b/src/kernel.c
index 033ce283a..af4806378 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -214,19 +214,19 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
{
- mrb_callinfo *ci = mrb->ci;
+ mrb_callinfo *ci = mrb->c->ci;
mrb_value *bp;
mrb_bool given_p;
- bp = mrb->stbase + ci->stackidx + 1;
+ bp = mrb->c->stbase + ci->stackidx + 1;
ci--;
- if (ci <= mrb->cibase) {
+ if (ci <= mrb->c->cibase) {
given_p = 0;
}
else {
/* block_given? called within block; check upper scope */
if (ci->proc->env && ci->proc->env->stack) {
- given_p = !(ci->proc->env->stack == mrb->stbase ||
+ given_p = !(ci->proc->env->stack == mrb->c->stbase ||
mrb_nil_p(ci->proc->env->stack[1]));
}
else {
@@ -894,7 +894,7 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
/* fall through */
default:
exc = mrb_make_exception(mrb, argc, a);
- mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc));
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->c->ci->pc));
mrb_exc_raise(mrb, exc);
break;
}
diff --git a/src/proc.c b/src/proc.c
index ce2728779..e21a37736 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -19,7 +19,7 @@ mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
struct RProc *p;
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
- p->target_class = (mrb->ci) ? mrb->ci->target_class : 0;
+ p->target_class = (mrb->c->ci) ? mrb->c->ci->target_class : 0;
p->body.irep = irep;
p->env = 0;
@@ -31,16 +31,16 @@ closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
{
struct REnv *e;
- if (!mrb->ci->env) {
- e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->ci->proc->env);
+ if (!mrb->c->ci->env) {
+ e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
e->flags= (unsigned int)nlocals;
- e->mid = mrb->ci->mid;
- e->cioff = mrb->ci - mrb->cibase;
- e->stack = mrb->stack;
- mrb->ci->env = e;
+ e->mid = mrb->c->ci->mid;
+ e->cioff = mrb->c->ci - mrb->c->cibase;
+ e->stack = mrb->c->stack;
+ mrb->c->ci->env = e;
}
else {
- e = mrb->ci->env;
+ e = mrb->c->ci->env;
}
p->env = e;
}
@@ -50,7 +50,7 @@ mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
{
struct RProc *p = mrb_proc_new(mrb, irep);
- closure_setup(mrb, p, mrb->ci->proc->body.irep->nlocals);
+ closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
return p;
}
diff --git a/src/state.c b/src/state.c
index b34fbd025..76b506d3e 100644
--- a/src/state.c
+++ b/src/state.c
@@ -25,6 +25,7 @@ mrb_state*
mrb_open_allocf(mrb_allocf f, void *ud)
{
static const mrb_state mrb_state_zero = { 0 };
+ static const struct mrb_context mrb_context_zero = { 0 };
mrb_state *mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
if (mrb == NULL) return NULL;
@@ -34,7 +35,11 @@ mrb_open_allocf(mrb_allocf f, void *ud)
mrb->current_white_part = MRB_GC_WHITE_A;
mrb_init_heap(mrb);
+ mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
+ *mrb->c = mrb_context_zero;
+ mrb->root_c = mrb->c;
mrb_init_core(mrb);
+
return mrb;
}
@@ -107,6 +112,17 @@ mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
}
void
+mrb_free_context(mrb_state *mrb, struct mrb_context *c)
+{
+ if (!c) return;
+ mrb_free(mrb, c->stbase);
+ mrb_free(mrb, c->cibase);
+ mrb_free(mrb, c->rescue);
+ mrb_free(mrb, c->ensure);
+ mrb_free(mrb, c);
+}
+
+void
mrb_close(mrb_state *mrb)
{
size_t i;
@@ -115,14 +131,11 @@ mrb_close(mrb_state *mrb)
/* free */
mrb_gc_free_gv(mrb);
- mrb_free(mrb, mrb->stbase);
- mrb_free(mrb, mrb->cibase);
for (i=0; i<mrb->irep_len; i++) {
mrb_irep_free(mrb, mrb->irep[i]);
}
mrb_free(mrb, mrb->irep);
- mrb_free(mrb, mrb->rescue);
- mrb_free(mrb, mrb->ensure);
+ mrb_free_context(mrb, mrb->root_c);
mrb_free_symtbl(mrb);
mrb_free_heap(mrb);
mrb_alloca_free(mrb);
diff --git a/src/variable.c b/src/variable.c
index 9ffc2ac92..2610c5d7a 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -579,14 +579,14 @@ mrb_value
mrb_vm_iv_get(mrb_state *mrb, mrb_sym sym)
{
/* get self */
- return mrb_iv_get(mrb, mrb->stack[0], sym);
+ return mrb_iv_get(mrb, mrb->c->stack[0], sym);
}
void
mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
/* get self */
- mrb_iv_set(mrb, mrb->stack[0], sym, v);
+ mrb_iv_set(mrb, mrb->c->stack[0], sym, v);
}
static int
@@ -763,9 +763,9 @@ mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
mrb_value
mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
{
- struct RClass *c = mrb->ci->proc->target_class;
+ struct RClass *c = mrb->c->ci->proc->target_class;
- if (!c) c = mrb->ci->target_class;
+ if (!c) c = mrb->c->ci->target_class;
return mrb_mod_cv_get(mrb, c, sym);
}
@@ -773,9 +773,9 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
void
mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
- struct RClass *c = mrb->ci->proc->target_class;
+ struct RClass *c = mrb->c->ci->proc->target_class;
- if (!c) c = mrb->ci->target_class;
+ if (!c) c = mrb->c->ci->target_class;
while (c) {
if (c->iv) {
iv_tbl *t = c->iv;
@@ -788,7 +788,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
}
c = c->super;
}
- c = mrb->ci->target_class;
+ c = mrb->c->ci->target_class;
if (!c->iv) {
c->iv = iv_new(mrb);
}
@@ -868,9 +868,9 @@ mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
mrb_value
mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
{
- struct RClass *c = mrb->ci->proc->target_class;
+ struct RClass *c = mrb->c->ci->proc->target_class;
- if (!c) c = mrb->ci->target_class;
+ if (!c) c = mrb->c->ci->target_class;
if (c) {
struct RClass *c2;
mrb_value v;
@@ -900,9 +900,9 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
void
mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
- struct RClass *c = mrb->ci->proc->target_class;
+ struct RClass *c = mrb->c->ci->proc->target_class;
- if (!c) c = mrb->ci->target_class;
+ if (!c) c = mrb->c->ci->target_class;
mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
}
diff --git a/src/vm.c b/src/vm.c
index 4794323c7..31fdfe816 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -88,24 +88,26 @@ stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
static void
stack_init(mrb_state *mrb)
{
+ struct mrb_context *c = mrb->c;
+
/* assert(mrb->stack == NULL); */
- mrb->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
- mrb->stend = mrb->stbase + STACK_INIT_SIZE;
- mrb->stack = mrb->stbase;
-
- /* assert(mrb->ci == NULL); */
- mrb->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
- mrb->ciend = mrb->cibase + CALLINFO_INIT_SIZE;
- mrb->ci = mrb->cibase;
- mrb->ci->target_class = mrb->object_class;
+ c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
+ c->stend = c->stbase + STACK_INIT_SIZE;
+ c->stack = c->stbase;
+
+ /* assert(ci == NULL); */
+ c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
+ c->ciend = c->cibase + CALLINFO_INIT_SIZE;
+ c->ci = c->cibase;
+ c->ci->target_class = mrb->object_class;
}
static inline void
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
{
- mrb_callinfo *ci = mrb->cibase;
+ mrb_callinfo *ci = mrb->c->cibase;
- while (ci <= mrb->ci) {
+ while (ci <= mrb->c->ci) {
struct REnv *e = ci->env;
if (e && e->cioff >= 0) {
ptrdiff_t off = e->stack - oldbase;
@@ -121,13 +123,13 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
static void
stack_extend(mrb_state *mrb, int room, int keep)
{
- if (mrb->stack + room >= mrb->stend) {
+ if (mrb->c->stack + room >= mrb->c->stend) {
int size, off;
- mrb_value *oldbase = mrb->stbase;
+ mrb_value *oldbase = mrb->c->stbase;
- size = mrb->stend - mrb->stbase;
- off = mrb->stack - mrb->stbase;
+ size = mrb->c->stend - mrb->c->stbase;
+ off = mrb->c->stack - mrb->c->stbase;
/* do not leave uninitialized malloc region */
if (keep > size) keep = size;
@@ -140,10 +142,10 @@ stack_extend(mrb_state *mrb, int room, int keep)
else
size += room;
- mrb->stbase = (mrb_value *)mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size);
- mrb->stack = mrb->stbase + off;
- mrb->stend = mrb->stbase + size;
- envadjust(mrb, oldbase, mrb->stbase);
+ mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
+ mrb->c->stack = mrb->c->stbase + off;
+ mrb->c->stend = mrb->c->stbase + size;
+ envadjust(mrb, oldbase, mrb->c->stbase);
/* Raise an exception if the new stack size will be too large,
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
if (size > MRB_STACK_MAX) {
@@ -153,7 +155,7 @@ stack_extend(mrb_state *mrb, int room, int keep)
if (room > keep) {
#ifndef MRB_NAN_BOXING
- stack_clear(&(mrb->stack[keep]), room - keep);
+ stack_clear(&(mrb->c->stack[keep]), room - keep);
#else
int i;
for (i=keep; i<room; i++) {
@@ -166,7 +168,7 @@ stack_extend(mrb_state *mrb, int room, int keep)
static inline struct REnv*
uvenv(mrb_state *mrb, int up)
{
- struct REnv *e = mrb->ci->proc->env;
+ struct REnv *e = mrb->c->ci->proc->env;
while (up--) {
if (!e) return 0;
@@ -180,8 +182,8 @@ is_strict(mrb_state *mrb, struct REnv *e)
{
int cioff = e->cioff;
- if (cioff >= 0 && mrb->cibase[cioff].proc &&
- MRB_PROC_STRICT_P(mrb->cibase[cioff].proc)) {
+ if (cioff >= 0 && mrb->c->cibase[cioff].proc &&
+ MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) {
return 1;
}
return 0;
@@ -203,29 +205,34 @@ top_env(mrb_state *mrb, struct RProc *proc)
static mrb_callinfo*
cipush(mrb_state *mrb)
{
- int eidx = mrb->ci->eidx;
- int ridx = mrb->ci->ridx;
+ struct mrb_context *c = mrb->c;
+ mrb_callinfo *ci = c->ci;
+
+ int eidx = ci->eidx;
+ int ridx = ci->ridx;
- if (mrb->ci + 1 == mrb->ciend) {
- size_t size = mrb->ci - mrb->cibase;
+ if (ci + 1 == c->ciend) {
+ size_t size = ci - c->cibase;
- mrb->cibase = (mrb_callinfo *)mrb_realloc(mrb, mrb->cibase, sizeof(mrb_callinfo)*size*2);
- mrb->ci = mrb->cibase + size;
- mrb->ciend = mrb->cibase + size * 2;
+ c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
+ ci = c->cibase + size;
+ c->ciend = c->cibase + size * 2;
}
- mrb->ci++;
- mrb->ci->nregs = 2; /* protect method_missing arg and block */
- mrb->ci->eidx = eidx;
- mrb->ci->ridx = ridx;
- mrb->ci->env = 0;
- return mrb->ci;
+ ci = ++c->ci;
+ ci->nregs = 2; /* protect method_missing arg and block */
+ ci->eidx = eidx;
+ ci->ridx = ridx;
+ ci->env = 0;
+ return ci;
}
static void
cipop(mrb_state *mrb)
{
- if (mrb->ci->env) {
- struct REnv *e = mrb->ci->env;
+ struct mrb_context *c = mrb->c;
+
+ if (c->ci->env) {
+ struct REnv *e = c->ci->env;
size_t len = (size_t)e->flags;
mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
@@ -234,7 +241,7 @@ cipop(mrb_state *mrb)
e->stack = p;
}
- mrb->ci--;
+ c->ci--;
}
static void
@@ -242,23 +249,23 @@ ecall(mrb_state *mrb, int i)
{
struct RProc *p;
mrb_callinfo *ci;
- mrb_value *self = mrb->stack;
+ mrb_value *self = mrb->c->stack;
struct RObject *exc;
- p = mrb->ensure[i];
+ p = mrb->c->ensure[i];
if (!p) return;
ci = cipush(mrb);
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
ci->mid = ci[-1].mid;
ci->acc = -1;
ci->argc = 0;
ci->proc = p;
ci->nregs = p->body.irep->nregs;
ci->target_class = p->target_class;
- mrb->stack = mrb->stack + ci[-1].nregs;
+ mrb->c->stack = mrb->c->stack + ci[-1].nregs;
exc = mrb->exc; mrb->exc = 0;
mrb_run(mrb, p, *self);
- mrb->ensure[i] = NULL;
+ mrb->c->ensure[i] = NULL;
if (!mrb->exc) mrb->exc = exc;
}
@@ -308,11 +315,11 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
if (!mrb->jmp) {
jmp_buf c_jmp;
- mrb_callinfo *old_ci = mrb->ci;
+ mrb_callinfo *old_ci = mrb->c->ci;
if (setjmp(c_jmp) != 0) { /* error */
- while (old_ci != mrb->ci) {
- mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ while (old_ci != mrb->c->ci) {
+ mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx;
cipop(mrb);
}
mrb->jmp = 0;
@@ -332,10 +339,10 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
mrb_callinfo *ci;
int n;
- if (!mrb->stack) {
+ if (!mrb->c->stack) {
stack_init(mrb);
}
- n = mrb->ci->nregs;
+ n = mrb->c->ci->nregs;
if (argc < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
}
@@ -350,7 +357,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
ci = cipush(mrb);
ci->mid = mid;
ci->proc = p;
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
ci->argc = argc;
ci->target_class = p->target_class;
if (MRB_PROC_CFUNC_P(p)) {
@@ -360,25 +367,25 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
ci->nregs = p->body.irep->nregs + n;
}
ci->acc = -1;
- mrb->stack = mrb->stack + n;
+ mrb->c->stack = mrb->c->stack + n;
stack_extend(mrb, ci->nregs, 0);
- mrb->stack[0] = self;
+ mrb->c->stack[0] = self;
if (undef) {
- mrb->stack[1] = mrb_symbol_value(undef);
- stack_copy(mrb->stack+2, argv, argc-1);
+ mrb->c->stack[1] = mrb_symbol_value(undef);
+ stack_copy(mrb->c->stack+2, argv, argc-1);
}
else if (argc > 0) {
- stack_copy(mrb->stack+1, argv, argc);
+ stack_copy(mrb->c->stack+1, argv, argc);
}
- mrb->stack[argc+1] = blk;
+ mrb->c->stack[argc+1] = blk;
if (MRB_PROC_CFUNC_P(p)) {
int ai = mrb_gc_arena_save(mrb);
val = p->body.func(mrb, self);
mrb_gc_arena_restore(mrb, ai);
mrb_gc_protect(mrb, val);
- mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx;
cipop(mrb);
}
else {
@@ -398,9 +405,9 @@ mrb_value
mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c)
{
struct RProc *p;
- mrb_sym mid = mrb->ci->mid;
+ mrb_sym mid = mrb->c->ci->mid;
mrb_callinfo *ci;
- int n = mrb->ci->nregs;
+ int n = mrb->c->ci->nregs;
mrb_value val;
if (mrb_nil_p(b)) {
@@ -410,7 +417,7 @@ mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_v
ci = cipush(mrb);
ci->mid = mid;
ci->proc = p;
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
ci->argc = argc;
ci->target_class = c;
if (MRB_PROC_CFUNC_P(p)) {
@@ -420,18 +427,18 @@ mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_v
ci->nregs = p->body.irep->nregs + 1;
}
ci->acc = -1;
- mrb->stack = mrb->stack + n;
+ mrb->c->stack = mrb->c->stack + n;
stack_extend(mrb, ci->nregs, 0);
- mrb->stack[0] = self;
+ mrb->c->stack[0] = self;
if (argc > 0) {
- stack_copy(mrb->stack+1, argv, argc);
+ stack_copy(mrb->c->stack+1, argv, argc);
}
- mrb->stack[argc+1] = mrb_nil_value();
+ mrb->c->stack[argc+1] = mrb_nil_value();
if (MRB_PROC_CFUNC_P(p)) {
val = p->body.func(mrb, self);
- mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx;
cipop(mrb);
}
else {
@@ -445,7 +452,7 @@ mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv)
{
struct RProc *p = mrb_proc_ptr(b);
- return mrb_yield_internal(mrb, b, argc, argv, mrb->stack[0], p->target_class);
+ return mrb_yield_internal(mrb, b, argc, argv, mrb->c->stack[0], p->target_class);
}
mrb_value
@@ -453,7 +460,7 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
{
struct RProc *p = mrb_proc_ptr(b);
- return mrb_yield_internal(mrb, b, 1, &arg, mrb->stack[0], p->target_class);
+ return mrb_yield_internal(mrb, b, 1, &arg, mrb->c->stack[0], p->target_class);
}
typedef enum {
@@ -484,14 +491,14 @@ argnum_error(mrb_state *mrb, int num)
mrb_value exc;
mrb_value str;
- if (mrb->ci->mid) {
+ if (mrb->c->ci->mid) {
str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
- mrb_sym2str(mrb, mrb->ci->mid),
- mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
+ mrb_sym2str(mrb, mrb->c->ci->mid),
+ mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
}
else {
str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
- mrb_fixnum_value(mrb->ci->argc), mrb_fixnum_value(num));
+ mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num));
}
exc = mrb_exc_new3(mrb, E_ARGUMENT_ERROR, str);
mrb->exc = mrb_obj_ptr(exc);
@@ -577,13 +584,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
goto L_RAISE;
}
- if (!mrb->stack) {
+ if (!mrb->c->stack) {
stack_init(mrb);
}
stack_extend(mrb, irep->nregs, irep->nregs);
- mrb->ci->proc = proc;
- mrb->ci->nregs = irep->nregs + 1;
- regs = mrb->stack;
+ mrb->c->ci->proc = proc;
+ mrb->c->ci->nregs = irep->nregs + 1;
+ regs = mrb->c->stack;
regs[0] = self;
INIT_DISPATCH {
@@ -769,12 +776,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_ONERR) {
/* sBx pc+=sBx on exception */
- if (mrb->rsize <= mrb->ci->ridx) {
- if (mrb->rsize == 0) mrb->rsize = 16;
- else mrb->rsize *= 2;
- mrb->rescue = (mrb_code **)mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize);
+ if (mrb->c->rsize <= mrb->c->ci->ridx) {
+ if (mrb->c->rsize == 0) mrb->c->rsize = 16;
+ else mrb->c->rsize *= 2;
+ mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize);
}
- mrb->rescue[mrb->ci->ridx++] = pc + GETARG_sBx(i);
+ mrb->c->rescue[mrb->c->ci->ridx++] = pc + GETARG_sBx(i);
NEXT;
}
@@ -789,7 +796,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int a = GETARG_A(i);
while (a--) {
- mrb->ci->ridx--;
+ mrb->c->ci->ridx--;
}
NEXT;
}
@@ -806,12 +813,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
p = mrb_closure_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]);
/* push ensure_stack */
- if (mrb->esize <= mrb->ci->eidx) {
- if (mrb->esize == 0) mrb->esize = 16;
- else mrb->esize *= 2;
- mrb->ensure = (struct RProc **)mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize);
+ if (mrb->c->esize <= mrb->c->ci->eidx) {
+ if (mrb->c->esize == 0) mrb->c->esize = 16;
+ else mrb->c->esize *= 2;
+ mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
}
- mrb->ensure[mrb->ci->eidx++] = p;
+ mrb->c->ensure[mrb->c->ci->eidx++] = p;
mrb_gc_arena_restore(mrb, ai);
NEXT;
}
@@ -822,7 +829,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int a = GETARG_A(i);
for (n=0; n<a; n++) {
- ecall(mrb, --mrb->ci->eidx);
+ ecall(mrb, --mrb->c->ci->eidx);
}
mrb_gc_arena_restore(mrb, ai);
NEXT;
@@ -880,7 +887,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci = cipush(mrb);
ci->mid = mid;
ci->proc = m;
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
if (n == CALL_MAXARGS) {
ci->argc = -1;
}
@@ -898,7 +905,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->acc = a;
/* prepare stack */
- mrb->stack += a;
+ mrb->c->stack += a;
if (MRB_PROC_CFUNC_P(m)) {
if (n == CALL_MAXARGS) {
@@ -908,17 +915,24 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->nregs = n + 2;
}
result = m->body.func(mrb, recv);
- mrb->stack[0] = result;
+ mrb->c->stack[0] = result;
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- regs = mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ ci = mrb->c->ci;
+ if (!MRB_PROC_CFUNC_P(ci[-1].proc)) {
+ irep = ci[-1].proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ }
+ regs = mrb->c->stack = mrb->c->stbase + ci->stackidx;
+ pc = ci->pc;
cipop(mrb);
- NEXT;
+ JUMP;
}
else {
/* setup environment for calling method */
- proc = mrb->ci->proc = m;
+ proc = mrb->c->ci->proc = m;
irep = m->body.irep;
pool = irep->pool;
syms = irep->syms;
@@ -929,7 +943,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
}
- regs = mrb->stack;
+ regs = mrb->c->stack;
pc = irep->iseq;
JUMP;
}
@@ -943,11 +957,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_CALL) {
/* A R(A) := self.call(frame.argc, frame.argv) */
mrb_callinfo *ci;
- mrb_value recv = mrb->stack[0];
+ mrb_value recv = mrb->c->stack[0];
struct RProc *m = mrb_proc_ptr(recv);
/* replace callinfo */
- ci = mrb->ci;
+ ci = mrb->c->ci;
ci->target_class = m->target_class;
ci->proc = m;
if (m->env) {
@@ -955,7 +969,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->mid = m->env->mid;
}
if (!m->env->stack) {
- m->env->stack = mrb->stack;
+ m->env->stack = mrb->c->stack;
}
}
@@ -965,12 +979,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- ci = mrb->ci;
- regs = mrb->stack = mrb->stbase + ci->stackidx;
+ ci = mrb->c->ci;
+ regs = mrb->c->stack = mrb->c->stbase + ci->stackidx;
regs[ci->acc] = recv;
pc = ci->pc;
cipop(mrb);
- irep = mrb->ci->proc->body.irep;
+ irep = mrb->c->ci->proc->body.irep;
pool = irep->pool;
syms = irep->syms;
JUMP;
@@ -980,7 +994,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
proc = m;
irep = m->body.irep;
if (!irep) {
- mrb->stack[0] = mrb_nil_value();
+ mrb->c->stack[0] = mrb_nil_value();
goto L_RETURN;
}
pool = irep->pool;
@@ -992,7 +1006,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
}
- regs = mrb->stack;
+ regs = mrb->c->stack;
regs[0] = m->env->stack[0];
pc = m->body.irep->iseq;
JUMP;
@@ -1002,7 +1016,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_SUPER) {
/* A B C R(A) := super(R(A+1),... ,R(A+C-1)) */
mrb_value recv;
- mrb_callinfo *ci = mrb->ci;
+ mrb_callinfo *ci = mrb->c->ci;
struct RProc *m;
struct RClass *c;
mrb_sym mid = ci->mid;
@@ -1010,7 +1024,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int n = GETARG_C(i);
recv = regs[0];
- c = mrb->ci->target_class->super;
+ c = mrb->c->ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
if (!m) {
mid = mrb_intern2(mrb, "method_missing", 14);
@@ -1028,7 +1042,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci = cipush(mrb);
ci->mid = mid;
ci->proc = m;
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
if (n == CALL_MAXARGS) {
ci->argc = -1;
}
@@ -1039,15 +1053,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->pc = pc + 1;
/* prepare stack */
- mrb->stack += a;
- mrb->stack[0] = recv;
+ mrb->c->stack += a;
+ mrb->c->stack[0] = recv;
if (MRB_PROC_CFUNC_P(m)) {
- mrb->stack[0] = m->body.func(mrb, recv);
+ mrb->c->stack[0] = m->body.func(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- regs = mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ regs = mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx;
cipop(mrb);
NEXT;
}
@@ -1067,7 +1081,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
}
- regs = mrb->stack;
+ regs = mrb->c->stack;
pc = irep->iseq;
JUMP;
}
@@ -1138,7 +1152,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int kd = (ax>>1)&0x1;
int b = (ax>>0)& 0x1;
*/
- int argc = mrb->ci->argc;
+ int argc = mrb->c->ci->argc;
mrb_value *argv = regs+1;
mrb_value *argv0 = argv;
int len = m1 + o + r + m2;
@@ -1150,7 +1164,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
argc = ary->len;
mrb_gc_protect(mrb, regs[1]);
}
- if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) {
+ if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
if (argc >= 0) {
if (argc < m1 + m2 || (r == 0 && argc > len)) {
argnum_error(mrb, m1+m2);
@@ -1162,7 +1176,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
argc = mrb_ary_ptr(argv[0])->len;
argv = mrb_ary_ptr(argv[0])->ptr;
}
- mrb->ci->argc = len;
+ mrb->c->ci->argc = len;
if (argc < len) {
regs[len+1] = *blk; /* move block */
if (argv0 != argv) {
@@ -1219,11 +1233,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
int eidx;
L_RAISE:
- ci = mrb->ci;
+ ci = mrb->c->ci;
mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc));
- mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase));
+ mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase));
eidx = ci->eidx;
- if (ci == mrb->cibase) {
+ if (ci == mrb->c->cibase) {
if (ci->ridx == 0) goto L_STOP;
goto L_RESCUE;
}
@@ -1232,8 +1246,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
- ci = mrb->ci;
- mrb->stack = mrb->stbase + ci[1].stackidx;
+ ci = mrb->c->ci;
+ mrb->c->stack = mrb->c->stbase + ci[1].stackidx;
if (ci[1].acc < 0 && prev_jmp) {
mrb->jmp = prev_jmp;
longjmp(*(jmp_buf*)mrb->jmp, 1);
@@ -1241,9 +1255,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
while (eidx > ci->eidx) {
ecall(mrb, --eidx);
}
- if (ci == mrb->cibase) {
+ if (ci == mrb->c->cibase) {
if (ci->ridx == 0) {
- regs = mrb->stack = mrb->stbase;
+ regs = mrb->c->stack = mrb->c->stbase;
goto L_STOP;
}
break;
@@ -1253,12 +1267,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
irep = ci->proc->body.irep;
pool = irep->pool;
syms = irep->syms;
- regs = mrb->stack = mrb->stbase + ci[1].stackidx;
- pc = mrb->rescue[--ci->ridx];
+ regs = mrb->c->stack = mrb->c->stbase + ci[1].stackidx;
+ pc = mrb->c->rescue[--ci->ridx];
}
else {
- mrb_callinfo *ci = mrb->ci;
- int acc, eidx = mrb->ci->eidx;
+ mrb_callinfo *ci = mrb->c->ci;
+ int acc, eidx = mrb->c->ci->eidx;
mrb_value v = regs[GETARG_A(i)];
switch (GETARG_B(i)) {
@@ -1271,45 +1285,48 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
- ci = mrb->cibase + e->cioff;
- if (ci == mrb->cibase) {
+ ci = mrb->c->cibase + e->cioff;
+ if (ci == mrb->c->cibase) {
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
- mrb->ci = ci;
+ mrb->c->ci = ci;
break;
}
case OP_R_NORMAL:
- if (ci == mrb->cibase) {
- localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
- goto L_RAISE;
+ if (ci == mrb->c->cibase) {
+ if (!mrb->c->prev) { /* toplevel return */
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ mrb->c = mrb->c->prev; /* automatic yield at the end */
}
- ci = mrb->ci;
+ ci = mrb->c->ci;
break;
case OP_R_BREAK:
if (proc->env->cioff < 0) {
localjump_error(mrb, LOCALJUMP_ERROR_BREAK);
goto L_RAISE;
}
- ci = mrb->ci = mrb->cibase + proc->env->cioff + 1;
+ ci = mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1;
break;
default:
/* cannot happen */
break;
}
- while (eidx > mrb->ci[-1].eidx) {
+ while (eidx > mrb->c->ci[-1].eidx) {
ecall(mrb, --eidx);
}
cipop(mrb);
acc = ci->acc;
pc = ci->pc;
- regs = mrb->stack = mrb->stbase + ci->stackidx;
+ regs = mrb->c->stack = mrb->c->stbase + ci->stackidx;
if (acc < 0) {
mrb->jmp = prev_jmp;
return v;
}
DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid)));
- proc = mrb->ci->proc;
+ proc = mrb->c->ci->proc;
irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
@@ -1347,7 +1364,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
/* replace callinfo */
- ci = mrb->ci;
+ ci = mrb->c->ci;
ci->mid = mid;
ci->target_class = m->target_class;
if (n == CALL_MAXARGS) {
@@ -1358,10 +1375,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
/* move stack */
- value_move(mrb->stack, &regs[a], ci->argc+1);
+ value_move(mrb->c->stack, &regs[a], ci->argc+1);
if (MRB_PROC_CFUNC_P(m)) {
- mrb->stack[0] = m->body.func(mrb, recv);
+ mrb->c->stack[0] = m->body.func(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
goto L_RETURN;
}
@@ -1376,7 +1393,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
}
- regs = mrb->stack;
+ regs = mrb->c->stack;
pc = irep->iseq;
}
JUMP;
@@ -1854,7 +1871,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
base = regs[a];
super = regs[a+1];
if (mrb_nil_p(base)) {
- base = mrb_obj_value(mrb->ci->target_class);
+ base = mrb_obj_value(mrb->c->ci->target_class);
}
c = mrb_vm_define_class(mrb, base, super, id);
regs[a] = mrb_obj_value(c);
@@ -1871,7 +1888,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
base = regs[a];
if (mrb_nil_p(base)) {
- base = mrb_obj_value(mrb->ci->target_class);
+ base = mrb_obj_value(mrb->c->ci->target_class);
}
c = mrb_vm_define_module(mrb, base, id);
regs[a] = mrb_obj_value(c);
@@ -1891,23 +1908,23 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->pc = pc + 1;
ci->acc = a;
ci->mid = 0;
- ci->stackidx = mrb->stack - mrb->stbase;
+ ci->stackidx = mrb->c->stack - mrb->c->stbase;
ci->argc = 0;
ci->target_class = mrb_class_ptr(recv);
/* prepare stack */
- mrb->stack += a;
+ mrb->c->stack += a;
p = mrb_proc_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]);
p->target_class = ci->target_class;
ci->proc = p;
if (MRB_PROC_CFUNC_P(p)) {
- mrb->stack[0] = p->body.func(mrb, recv);
+ mrb->c->stack[0] = p->body.func(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
/* pop stackpos */
- regs = mrb->stack = mrb->stbase + mrb->ci->stackidx;
+ regs = mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx;
cipop(mrb);
NEXT;
}
@@ -1917,7 +1934,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
syms = irep->syms;
stack_extend(mrb, irep->nregs, 1);
ci->nregs = irep->nregs;
- regs = mrb->stack;
+ regs = mrb->c->stack;
pc = irep->iseq;
JUMP;
}
@@ -1942,13 +1959,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_TCLASS) {
/* A B R(A) := target_class */
- if (!mrb->ci->target_class) {
+ if (!mrb->c->ci->target_class) {
static const char msg[] = "no target class or module";
mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1);
mrb->exc = mrb_obj_ptr(exc);
goto L_RAISE;
}
- regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class);
+ regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class);
NEXT;
}
@@ -1974,7 +1991,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* stop VM */
L_STOP:
{
- int n = mrb->ci->eidx;
+ int n = mrb->c->ci->eidx;
while (n--) {
ecall(mrb, n);