diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-05-20 17:54:07 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-05-20 17:54:07 +0900 |
| commit | 5c0b9b703c9d1a08d7219b057b809bda4bc89f8a (patch) | |
| tree | ab610a2988ef928c02bfc50e31aedc5a707f008e | |
| parent | 35ee85164dd19143d4b47a34f13ad2bb71fed369 (diff) | |
| download | mruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.tar.gz mruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.zip | |
primary mruby fiber implementation
| -rw-r--r-- | include/mruby.h | 29 | ||||
| -rw-r--r-- | include/mruby/gc.h | 1 | ||||
| -rw-r--r-- | include/mruby/value.h | 11 | ||||
| -rw-r--r-- | mrbgems/default.gembox | 3 | ||||
| -rw-r--r-- | mrbgems/mruby-fiber/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-fiber/src/fiber.c | 179 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/src/struct.c | 4 | ||||
| -rw-r--r-- | src/backtrace.c | 6 | ||||
| -rw-r--r-- | src/class.c | 12 | ||||
| -rw-r--r-- | src/error.c | 6 | ||||
| -rw-r--r-- | src/gc.c | 95 | ||||
| -rw-r--r-- | src/kernel.c | 10 | ||||
| -rw-r--r-- | src/proc.c | 18 | ||||
| -rw-r--r-- | src/state.c | 21 | ||||
| -rw-r--r-- | src/variable.c | 22 | ||||
| -rw-r--r-- | src/vm.c | 315 |
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; @@ -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); } @@ -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, ®s[a], ci->argc+1); + value_move(mrb->c->stack, ®s[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); |
