void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { struct RClass *ins_pos; ins_pos = c; while (m) { struct RClass *p = c, *ic; int superclass_seen = 0; if (c->mt == m->mt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); } while (p) { if (c != p && p->tt == MRB_TT_CLASS) { superclass_seen = 1; } else if (p->mt == m->mt){ if (p->tt == MRB_TT_ICLASS && !superclass_seen) { ins_pos = p; } goto skip; } p = p->super; } ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); if (m->tt == MRB_TT_ICLASS) { ic->c = m->c; } else { ic->c = m; } ic->mt = m->mt; ic->iv = m->iv; ic->super = ins_pos->super; ins_pos->super = ic; mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic); ins_pos = ic; skip: m = m->super; } }
/* * call-seq: * obj.clone -> an_object * * Produces a shallow copy of <i>obj</i>---the instance variables of * <i>obj</i> are copied, but not the objects they reference. Copies * the frozen state of <i>obj</i>. See also the discussion * under <code>Object#dup</code>. * * class Klass * attr_accessor :str * end * s1 = Klass.new #=> #<Klass:0x401b3a38> * s1.str = "Hello" #=> "Hello" * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> * s2.str[1,4] = "i" #=> "i" * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">" * * This method may have class-specific behavior. If so, that * behavior will be documented under the #+initialize_copy+ method of * the class. * * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone. */ MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self) { struct RObject *p; mrb_value clone; if (mrb_immediate_p(self)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self); } if (mrb_type(self) == MRB_TT_SCLASS) { mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); } p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); p->c = mrb_singleton_class_clone(mrb, self); mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c); clone = mrb_obj_value(p); init_copy(mrb, clone, self); return clone; }
static void make_metaclass(mrb_state *mrb, struct RClass *c) { struct RClass *sc; if (c->c->tt == MRB_TT_SCLASS) { return; } sc = mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); sc->mt = 0; if (!c->super) { sc->super = mrb->class_class; } else { sc->super = c->super->c; } c->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)sc->super); }
struct RProc * mrb_proc_new(mrb_state *mrb, mrb_irep *irep) { struct RProc *p; mrb_callinfo *ci = mrb->c->ci; p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); p->target_class = 0; if (ci) { if (ci->proc) p->target_class = ci->proc->target_class; if (!p->target_class) p->target_class = ci->target_class; } p->body.irep = irep; p->env = 0; mrb_irep_incref(mrb, irep); return p; }
struct RProc * mrb_closure_new(mrb_state *mrb, mrb_irep *irep) { struct RProc *p = mrb_proc_new(mrb, irep); struct REnv *e; if (!mrb->ci->env) { e = mrb_obj_alloc(mrb, MRB_TT_ENV, mrb->ci->proc->env); e->flags= (unsigned int)irep->nlocals; e->mid = mrb->ci->mid; e->cioff = mrb->ci - mrb->cibase; e->stack = mrb->stack; mrb->ci->env = e; } else { e = mrb->ci->env; } p->env = e; return p; }
mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv) { struct RClass *c = mrb_class_ptr(cv); struct RObject *o; enum mrb_vtype ttype = MRB_INSTANCE_TT(c); mrb_value obj, blk; mrb_value *argv; int argc; if (c->tt == MRB_TT_SCLASS) mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); if (ttype == 0) ttype = MRB_TT_OBJECT; o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); obj = mrb_obj_value(o); mrb_get_args(mrb, "*&", &argv, &argc, &blk); mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk); return obj; }
static struct RArray* ary_new_capa(mrb_state *mrb, mrb_int capa) { struct RArray *a; mrb_int blen; if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } blen = capa * sizeof(mrb_value) ; if (blen < capa) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); a->ptr = (mrb_value *)mrb_malloc(mrb, blen); a->aux.capa = capa; a->len = 0; return a; }
/* Soon: struct RProc *mrbb_closure_new(mrb_state* mrb, mrb_func_t cfunc, unsigned int nlocals) { struct RProc *p = mrb_closure_new_cfunc(mrb, cfunc); p->flags |= MRB_PROC_MRBCFUNC; return p; } */ struct RProc *mrbb_closure_new(mrb_state* mrb, mrb_func_t cfunc, unsigned int nlocals) { struct RProc *p = mrbb_proc_new(mrb, cfunc); // stolen from mrb_closure_new() struct REnv *e; if (!mrb->ci->env) { e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->ci->proc->env); e->flags= nlocals; e->mid = mrb->ci->mid; e->cioff = mrb->ci - mrb->cibase; e->stack = mrb->stack; mrb->ci->env = e; } else { e = mrb->ci->env; } p->env = e; return p; }
static mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash) { struct RHash* ret; khash_t(ht) *h, *ret_h; khiter_t k, ret_k; mrb_value ifnone, vret; h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); ret->ht = kh_init(ht, mrb); if (h && kh_size(h) > 0) { ret_h = ret->ht; for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)) { int ai = mrb_gc_arena_save(mrb); ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h, k))); mrb_gc_arena_restore(mrb, ai); kh_val(ret_h, ret_k).v = kh_val(h, k).v; kh_val(ret_h, ret_k).n = kh_size(ret_h)-1; } } } if (MRB_RHASH_DEFAULT_P(hash)) { ret->flags |= MRB_HASH_DEFAULT; } if (MRB_RHASH_PROCDEFAULT_P(hash)) { ret->flags |= MRB_HASH_PROC_DEFAULT; } vret = mrb_obj_value(ret); ifnone = RHASH_IFNONE(hash); if (!mrb_nil_p(ifnone)) { mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone); } return vret; }
/* * call-seq: * lambda { |...| block } -> a_proc * * Equivalent to <code>Proc.new</code>, except the resulting Proc objects * check the number of parameters passed when called. */ static mrb_value proc_lambda(mrb_state *mrb, mrb_value self) { mrb_value blk; struct RProc *p; mrb_get_args(mrb, "&", &blk); if (mrb_nil_p(blk)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); } if (mrb_type(blk) != MRB_TT_PROC) { mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); } p = mrb_proc_ptr(blk); if (!MRB_PROC_STRICT_P(p)) { struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c); mrb_proc_copy(p2, p); p2->flags |= MRB_PROC_STRICT; return mrb_obj_value(p2); } return blk; }
static mrb_value read_string_value(MarshalContext *ctx) { mrb_state *mrb = ctx->mrb; int len = read_fixnum(ctx); struct RString *str = (struct RString*) mrb_obj_alloc (mrb, MRB_TT_STRING, mrb->string_class); str->c = mrb->string_class; str->len = len; str->aux.capa = len; str->ptr = (char*) mrb_malloc(mrb, len+1); ctx->readData(str->ptr, len); str->ptr[len] = '\0'; mrb_value str_obj = mrb_obj_value(str); return str_obj; }
struct RProc * mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t f, mrb_int argc, const mrb_value *argv) { struct RProc *p; struct REnv *e; int ai, i; p = mrb_proc_new_cfunc(mrb, f); ai = mrb_gc_arena_save(mrb); e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL); p->env = e; mrb_gc_arena_restore(mrb, ai); MRB_ENV_UNSHARE_STACK(e); MRB_ENV_STACK_LEN(e) = argc; e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); for (i = 0; i < argc; ++i) { e->stack[i] = argv[i]; } return p; }
struct RClass* mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { struct RClass *klass = RBASIC(obj)->c; //if (!FL_TEST(klass, FL_SINGLETON)) //return klass; if (klass->tt != MRB_TT_SCLASS) return klass; else { //struct clone_method_data data; /* copy singleton(unnamed) class */ //VALUE clone = class_alloc(RBASIC(klass)->flags, 0); struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); //clone->super = objklass->super; if ((mrb_type(obj) == MRB_TT_CLASS) || (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */ clone->c = clone; } else { clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); } clone->super = klass->super; if (klass->iv) { clone->iv = klass->iv; } if (klass->mt) { clone->mt = kh_copy(mt, mrb, klass->mt); } else { clone->mt = kh_init(mt, mrb); } clone->tt = MRB_TT_SCLASS; return clone; } }
static struct RArray* ary_new_capa(mrb_state *mrb, mrb_int capa) { struct RArray *a; size_t blen; if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } blen = capa * sizeof(mrb_value); a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); if (capa <= MRB_ARY_EMBED_LEN_MAX) { ARY_SET_EMBED_LEN(a, 0); } else { a->as.heap.ptr = (mrb_value *)mrb_malloc(mrb, blen); a->as.heap.aux.capa = capa; a->as.heap.len = 0; } return a; }
MRB_API mrb_value mrb_sample_buffer_slice(mrb_state *mrb, mrb_value sample_buffer, mrb_int len, mrb_int offset) { mrb_value buf; mrb_sample_buffer *b = 0, *other = 0; if (len <= 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "Length must be positive"); if (offset < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "Offset can not be negative"); other = mrb_sample_buffer_check(mrb, sample_buffer); if (len > other->len - offset) mrb_raise(mrb, E_ARGUMENT_ERROR, "Slice must be completely inside the buffer"); buf = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_DATA, mrb_class_get(mrb, "SampleBuffer"))); b = mrb_sample_buffer_alloc(mrb); b->shared = other->shared; mrb_shared_sample_buffer_ref(mrb, other->shared); b->len = len; b->offset = offset; mrb_data_init(buf, b, &mrb_sample_buffer_type); return buf; }
MRB_API mrb_value mrb_sample_buffer_new_zero(mrb_state *mrb, mrb_int len, mrb_int offset) { mrb_value buf; mrb_sample_buffer *b = 0; mrb_int i; if (len <= 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "Length must be positive"); if (offset < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "Offset can not be negative"); buf = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_DATA, mrb_class_get(mrb, "SampleBuffer"))); b = mrb_sample_buffer_alloc(mrb); b->shared = mrb_shared_sample_buffer_alloc(mrb, len); b->shared->offset = offset; b->len = len; b->offset = 0; for (i = 0; i < len; ++i) { b->shared->buffer[i] = 0; } mrb_data_init(buf, b, &mrb_sample_buffer_type); return buf; }
mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash) { struct RHash* ret; khash_t(ht) *h, *ret_h; khiter_t k, ret_k; h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); ret->ht = kh_init(ht, mrb); if (kh_size(h) > 0) { ret_h = ret->ht; for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h,k)) { ret_k = kh_put(ht, ret_h, KEY(kh_key(h,k))); kh_val(ret_h, ret_k) = kh_val(h,k); } } } return mrb_obj_value(ret); }
int load_irep(struct VM *vm, char **pos) { char *p = *pos; int i; p += 4; int sz = get_int_4(p); p += 4; if( !check_str_4(p, "0000") ){ return LOAD_FILE_IREP_ERROR_VERSION; } p += 4; int cnt = 0; while( cnt < sz ){ int sz2 = get_int_4(p); p += 4; // new irep mrb_irep *irep = new_irep(); if( irep == 0 ){ return LOAD_FILE_IREP_ERROR_ALLOCATION; } // add irep into vm->irep (at tail) // TODO: Optimize this process if( vm->irep == 0 ){ vm->irep = irep; } else { mrb_irep *p = vm->irep; while( p->next != 0 ){ p = p->next; } p->next = irep; } irep->next = 0; // nlocals,nregs,rlen irep->nlocals = get_int_2(p); p += 2; irep->nregs = get_int_2(p); p += 2; irep->rlen = get_int_2(p); p += 2; irep->ilen = get_int_4(p); p += 4; // padding (align=4 ?) p = (char *)( ( (unsigned long)p + 3 ) & ~3L ); // code irep->code = (uint8_t *)p; p += irep->ilen * 4; // pool irep->ptr_to_pool = 0; int plen = get_int_4(p); p += 4; for( i=0 ; i<plen ; i++ ){ int tt = (int)*p++; int obj_size = get_int_2(p); p += 2; mrb_object *ptr = mrb_obj_alloc(MRB_TT_FALSE); if( ptr == 0 ){ return LOAD_FILE_IREP_ERROR_ALLOCATION; } switch( tt ){ #if MRUBYC_USE_FLOAT case 2: { // IREP_TT_FLOAT char buf[obj_size+1]; memcpy(buf, p, obj_size); buf[obj_size] = '\0'; sscanf(buf, "%lf", &ptr->value.d); ptr->tt = MRB_TT_FLOAT; } break; #endif default: break; } if( irep->ptr_to_pool == 0 ){ irep->ptr_to_pool = ptr; } else { mrb_object *pp = irep->ptr_to_pool; while( pp->next != 0 ) pp = pp->next; pp->next = ptr; } p += obj_size; } // syms irep->ptr_to_sym = (uint8_t*)p; int slen = get_int_4(p); p += 4; for( i=0 ; i<slen ; i++ ){ int s = get_int_2(p); p += 2; p += s+1; } // cnt cnt += sz2 + 8; } /* TODO: size */ *pos += sz; return NO_ERROR; }
static struct RProc* create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line) { mrbc_context *cxt; struct mrb_parser_state *p; struct RProc *proc; struct REnv *e; struct mrb_context *c = mrb->c; if (!mrb_nil_p(binding)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil."); } cxt = mrbc_context_new(mrb); cxt->lineno = line; if (!file) { file = "(eval)"; } mrbc_filename(mrb, cxt, file); cxt->capture_errors = TRUE; cxt->no_optimize = TRUE; p = mrb_parse_nstring(mrb, s, len, cxt); /* only occur when memory ran out */ if (!p) { mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state."); } if (0 < p->nerr) { /* parse error */ char buf[256]; int n; n = snprintf(buf, sizeof(buf), "line %d: %s\n", p->error_buffer[0].lineno, p->error_buffer[0].message); mrb_parser_free(p); mrbc_context_free(mrb, cxt); mrb_exc_raise(mrb, mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); } proc = mrb_generate_code(mrb, p); if (proc == NULL) { /* codegen error */ mrb_parser_free(p); mrbc_context_free(mrb, cxt); mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error"); } if (c->ci[-1].proc->target_class) { proc->target_class = c->ci[-1].proc->target_class; } e = c->ci[-1].proc->env; if (!e) e = c->ci[-1].env; e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e); e->mid = c->ci[-1].mid; e->cioff = c->ci - c->cibase - 1; e->stack = c->ci->stackent; MRB_SET_ENV_STACK_LEN(e, c->ci[-1].proc->body.irep->nlocals); c->ci->env = e; proc->env = e; patch_irep(mrb, proc->body.irep, 0); mrb_parser_free(p); mrbc_context_free(mrb, cxt); return proc; }
static struct RProc* create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line) { mrbc_context *cxt; struct mrb_parser_state *p; struct RProc *proc; struct REnv *e; mrb_callinfo *ci = &mrb->c->ci[-1]; /* callinfo of eval caller */ struct RClass *target_class = NULL; int bidx; if (!mrb_nil_p(binding)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil."); } cxt = mrbc_context_new(mrb); cxt->lineno = (short)line; mrbc_filename(mrb, cxt, file ? file : "(eval)"); cxt->capture_errors = TRUE; cxt->no_optimize = TRUE; p = mrb_parse_nstring(mrb, s, len, cxt); /* only occur when memory ran out */ if (!p) { mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state."); } if (0 < p->nerr) { /* parse error */ mrb_value str; if (file) { str = mrb_format(mrb, " file %S line %S: %S", mrb_str_new_cstr(mrb, file), mrb_fixnum_value(p->error_buffer[0].lineno), mrb_str_new_cstr(mrb, p->error_buffer[0].message)); } else { str = mrb_format(mrb, " line %S: %S", mrb_fixnum_value(p->error_buffer[0].lineno), mrb_str_new_cstr(mrb, p->error_buffer[0].message)); } mrb_parser_free(p); mrbc_context_free(mrb, cxt); mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str)); } proc = mrb_generate_code(mrb, p); if (proc == NULL) { /* codegen error */ mrb_parser_free(p); mrbc_context_free(mrb, cxt); mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error"); } target_class = MRB_PROC_TARGET_CLASS(ci->proc); if (!MRB_PROC_CFUNC_P(ci->proc)) { if (ci->env) { e = ci->env; } else { e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)target_class); e->mid = ci->mid; e->stack = ci[1].stackent; e->cxt = mrb->c; MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals); bidx = ci->argc; if (ci->argc < 0) bidx = 2; else bidx += 1; MRB_ENV_SET_BIDX(e, bidx); ci->env = e; } proc->e.env = e; proc->flags |= MRB_PROC_ENVSET; mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e); } proc->upper = ci->proc; mrb->c->ci->target_class = target_class; patch_irep(mrb, proc->body.irep, 0, proc->body.irep); /* mrb_codedump_all(mrb, proc); */ mrb_parser_free(p); mrbc_context_free(mrb, cxt); return proc; }
static struct RObject * method_object_alloc(mrb_state *mrb, struct RClass *mclass) { return (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mclass); }
// based on https://gist.github.com/3066997 static mrb_value migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) { mrb_value nv; switch (mrb_type(v)) { case MRB_TT_OBJECT: case MRB_TT_EXCEPTION: { struct RObject *o = mrb_obj_ptr(v); mrb_value path = mrb_class_path(mrb, o->c); struct RClass *c; if (mrb_nil_p(path)) { mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate class"); } c = mrb_class_get(mrb2, RSTRING_PTR(path)); nv = mrb_obj_value(mrb_obj_alloc(mrb2, mrb_type(v), c)); } migrate_simple_iv(mrb, v, mrb2, nv); break; case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: nv = v; break; case MRB_TT_SYMBOL: nv = mrb_symbol_value(migrate_sym(mrb, mrb_symbol(v), mrb2)); break; case MRB_TT_FLOAT: nv = mrb_float_value(mrb2, mrb_float(v)); break; case MRB_TT_STRING: nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v)); break; case MRB_TT_RANGE: { struct RRange *r = mrb_range_ptr(v); nv = mrb_range_new(mrb2, migrate_simple_value(mrb, r->edges->beg, mrb2), migrate_simple_value(mrb, r->edges->end, mrb2), r->excl); } break; case MRB_TT_ARRAY: { struct RArray *a0, *a1; int i; a0 = mrb_ary_ptr(v); nv = mrb_ary_new_capa(mrb2, a0->len); a1 = mrb_ary_ptr(nv); for (i=0; i<a0->len; i++) { int ai = mrb_gc_arena_save(mrb2); a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2); a1->len++; mrb_gc_arena_restore(mrb2, ai); } } break; case MRB_TT_HASH: { mrb_value ka; int i, l; nv = mrb_hash_new(mrb2); ka = mrb_hash_keys(mrb, v); l = RARRAY_LEN(ka); for (i = 0; i < l; i++) { int ai = mrb_gc_arena_save(mrb2); mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2); mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2); mrb_hash_set(mrb2, nv, k, o); mrb_gc_arena_restore(mrb2, ai); } } migrate_simple_iv(mrb, v, mrb2, nv); break; case MRB_TT_DATA: if (!is_safe_migratable_datatype(DATA_TYPE(v))) mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object"); nv = v; DATA_PTR(nv) = DATA_PTR(v); DATA_TYPE(nv) = DATA_TYPE(v); migrate_simple_iv(mrb, v, mrb2, nv); break; default: mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object"); break; } return nv; }