primary mruby fiber implementation

parent 35ee8516
......@@ -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);
......
......@@ -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 */
......@@ -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)
{
......
......@@ -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"
......
MRuby::Gem::Specification.new('mruby-fiber') do |spec|
spec.license = 'MIT'
spec.authors = 'mruby developers'
end
#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)
{
}
......@@ -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);
......
......@@ -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")));
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -386,6 +386,35 @@ add_gray_list(mrb_state *mrb, struct RBasic *obj)
mrb->gray_list = 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)
{
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......@@ -106,6 +111,17 @@ mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep)
mrb_free(mrb, 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)
{
......@@ -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);
......
......@@ -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);
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment