void test_mrb_write_barrier(void) { mrb_state *mrb = mrb_open(); struct RBasic *obj; puts("test_mrb_write_barrier"); obj = mrb_basic_ptr(mrb_ary_new(mrb)); paint_black(obj); puts(" in GC_STATE_MARK"); mrb->gc_state = GC_STATE_MARK; mrb_write_barrier(mrb, obj); gc_assert(is_gray(obj)); gc_assert(mrb->variable_gray_list == obj); puts(" fail with gray"); paint_gray(obj); mrb_write_barrier(mrb, obj); gc_assert(is_gray(obj)); mrb_close(mrb); }
mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value v) { struct RBasic *obj; switch (mrb_type(v)) { case MRB_TT_FALSE: if (mrb_nil_p(v)) return mrb_obj_value(mrb->nil_class); return mrb_obj_value(mrb->false_class); case MRB_TT_TRUE: return mrb_obj_value(mrb->true_class); case MRB_TT_VOIDP: return mrb_obj_value(mrb->object_class); case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: case MRB_TT_FLOAT: mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); return mrb_nil_value(); /* not reached */ default: break; } obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); return mrb_obj_value(obj->c); }
struct RClass* mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { struct RClass *klass = mrb_basic_ptr(obj)->c; if (klass->tt != MRB_TT_SCLASS) return klass; else { /* copy singleton(unnamed) class */ struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); 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) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj); } 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 RClass* mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { struct RClass *klass = mrb_basic_ptr(obj)->c; if (klass->tt != MRB_TT_SCLASS) return klass; else { /* copy singleton(unnamed) class */ struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); switch (mrb_type(obj)) { case MRB_TT_CLASS: case MRB_TT_SCLASS: break; default: clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); break; } clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj); } 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; } }
void test_mrb_write_barrier(void) { mrb_state *mrb = mrb_open(); struct RBasic *obj; mrb_gc *gc = &mrb->gc; puts("test_mrb_write_barrier"); obj = mrb_basic_ptr(mrb_ary_new(mrb)); paint_black(obj); puts(" in MRB_GC_STATE_MARK"); gc->state = MRB_GC_STATE_MARK; mrb_write_barrier(mrb, obj); mrb_assert(is_gray(obj)); mrb_assert(gc->atomic_gray_list == obj); puts(" fail with gray"); paint_gray(obj); mrb_write_barrier(mrb, obj); mrb_assert(is_gray(obj)); mrb_close(mrb); }
static void mark_context_stack(mrb_state *mrb, struct mrb_context *c) { size_t i; size_t e; mrb_value nil; if (c->stack == NULL) return; e = c->stack - c->stbase; if (c->ci) { e += ci_nregs(c->ci); } if (c->stbase + e > c->stend) e = c->stend - c->stbase; for (i=0; i<e; i++) { mrb_value v = c->stbase[i]; if (!mrb_immediate_p(v)) { mrb_gc_mark(mrb, mrb_basic_ptr(v)); } } e = c->stend - c->stbase; nil = mrb_nil_value(); for (; i<e; i++) { c->stbase[i] = nil; } }
static void mark_context_stack(mrb_state *mrb, struct mrb_context *c) { size_t i; size_t e; 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_value v = c->stbase[i]; if (!mrb_immediate_p(v)) { if (mrb_basic_ptr(v)->tt == MRB_TT_FREE) { c->stbase[i] = mrb_nil_value(); } else { mrb_gc_mark(mrb, mrb_basic_ptr(v)); } } } }
void test_add_gray_list(void) { mrb_state *mrb = mrb_open(); struct RBasic *obj1, *obj2; puts("test_add_gray_list"); change_gen_gc_mode(mrb, FALSE); mrb_assert(mrb->gray_list == NULL); obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); add_gray_list(mrb, obj1); mrb_assert(mrb->gray_list == obj1); mrb_assert(is_gray(obj1)); obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); add_gray_list(mrb, obj2); mrb_assert(mrb->gray_list == obj2); mrb_assert(mrb->gray_list->gcnext == obj1); mrb_assert(is_gray(obj2)); mrb_close(mrb); }
static mrb_value mrb_obj_frozen(mrb_state *mrb, mrb_value self) { struct RBasic *b; switch (mrb_type(self)) { case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: case MRB_TT_SYMBOL: case MRB_TT_FLOAT: return mrb_true_value(); default: break; } b = mrb_basic_ptr(self); if (!MRB_FROZEN_P(b)) { return mrb_false_value(); } return mrb_true_value(); }
static mrb_value mrb_obj_freeze(mrb_state *mrb, mrb_value self) { struct RBasic *b; switch (mrb_type(self)) { case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: case MRB_TT_SYMBOL: case MRB_TT_FLOAT: return self; default: break; } b = mrb_basic_ptr(self); if (!MRB_FROZEN_P(b)) { MRB_SET_FROZEN_FLAG(b); } return self; }
static mrb_value mrb_sce_init(mrb_state *mrb, mrb_value self) { mrb_value c, e2c, m, str; mrb_int n; int argc, no_errno = 0; char buf[20]; argc = mrb_get_args(mrb, "o|i", &m, &n); if (argc == 1) { if (mrb_type(m) == MRB_TT_FIXNUM) { n = mrb_fixnum(m); m = mrb_nil_value(); } else { no_errno = 1; } } if (!no_errno) { e2c = mrb_const_get(mrb, mrb_obj_value(mrb_module_get(mrb, "Errno")), mrb_intern_lit(mrb, "Errno2class")); c = mrb_hash_fetch(mrb, e2c, mrb_fixnum_value(n), mrb_nil_value()); if (!mrb_nil_p(c)) { mrb_basic_ptr(self)->c = mrb_class_ptr(c); str = mrb_str_new_cstr(mrb, strerror(n)); } else { mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "errno"), mrb_fixnum_value(n)); str = mrb_str_new_cstr(mrb, "Unknown error: "); snprintf(buf, sizeof(buf), "%d", (int)n); mrb_str_cat2(mrb, str, buf); } } else { str = mrb_str_new_cstr(mrb, "unknown error"); } if (!mrb_nil_p(m)) { mrb_str_cat2(mrb, str, " - "); mrb_str_append(mrb, str, m); } mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "mesg"), str); return self; }
void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_special_const_p(obj)) return; gc_protect(mrb, mrb_basic_ptr(obj)); }
void test_mrb_field_write_barrier(void) { mrb_state *mrb = mrb_open(); struct RBasic *obj, *value; puts("test_mrb_field_write_barrier"); mrb->is_generational_gc_mode = FALSE; obj = mrb_basic_ptr(mrb_ary_new(mrb)); value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value")); paint_black(obj); paint_partial_white(mrb,value); puts(" in GC_STATE_MARK"); mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier(mrb, obj, value); mrb_assert(is_gray(value)); puts(" in GC_STATE_SWEEP"); paint_partial_white(mrb,value); mrb->gc_state = GC_STATE_SWEEP; mrb_field_write_barrier(mrb, obj, value); mrb_assert(obj->color & mrb->current_white_part); mrb_assert(value->color & mrb->current_white_part); puts(" fail with black"); mrb->gc_state = GC_STATE_MARK; paint_white(obj); paint_partial_white(mrb,value); mrb_field_write_barrier(mrb, obj, value); mrb_assert(obj->color & mrb->current_white_part); puts(" fail with gray"); mrb->gc_state = GC_STATE_MARK; paint_black(obj); paint_gray(value); mrb_field_write_barrier(mrb, obj, value); mrb_assert(is_gray(value)); { puts("test_mrb_field_write_barrier_value"); obj = mrb_basic_ptr(mrb_ary_new(mrb)); mrb_value value = mrb_str_new_lit(mrb, "value"); paint_black(obj); paint_partial_white(mrb, mrb_basic_ptr(value)); mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier_value(mrb, obj, value); mrb_assert(is_gray(mrb_basic_ptr(value))); } mrb_close(mrb); }
/* mrb_gc_protect() leaves the object in the arena */ MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_immediate_p(obj)) return; gc_protect(mrb, mrb_basic_ptr(obj)); }
static mrb_value mrb_sce_errno(mrb_state *mrb, mrb_value self) { struct RClass *c; mrb_sym sym; c = mrb_class(mrb, self); sym = mrb_intern_lit(mrb, "Errno"); #if MRUBY_RELEASE_NO < 10000 if (mrb_const_defined_at(mrb, c, sym)) { #else if (mrb_const_defined_at(mrb, mrb_obj_value(c), sym)) { #endif return mrb_const_get(mrb, mrb_obj_value(c), sym); } else { sym = mrb_intern_lit(mrb, "errno"); return mrb_attr_get(mrb, self, sym); } } static mrb_value mrb_sce_to_s(mrb_state *mrb, mrb_value self) { return mrb_attr_get(mrb, self, mrb_intern_lit(mrb, "mesg")); } static mrb_value mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls) { struct RClass *cl, *sce; mrb_value e, msg; mrb_int no; int argc; char name[8]; sce = mrb_class_get(mrb, "SystemCallError"); argc = mrb_get_args(mrb, "i|S", &no, &msg); if (argc == 1) { e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 1, mrb_fixnum_value(no)); } else { e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 2, msg, mrb_fixnum_value(no)); } if (mrb_obj_class(mrb, e) == sce) { snprintf(name, sizeof(name), "E%03ld", (long)no); cl = mrb_define_class_under(mrb, mrb_module_get(mrb, "Errno"), name, sce); mrb_define_const(mrb, cl, "Errno", mrb_fixnum_value(no)); mrb_basic_ptr(e)->c = cl; } mrb_exc_raise(mrb, e); return mrb_nil_value(); /* NOTREACHED */ } static mrb_value mrb_exxx_init(mrb_state *mrb, mrb_value self) { mrb_value m, no, str; no = mrb_const_get(mrb, mrb_obj_value(mrb_class(mrb, self)), mrb_intern_lit(mrb, "Errno")); str = mrb_str_new_cstr(mrb, strerror(mrb_fixnum(no))); m = mrb_nil_value(); mrb_get_args(mrb, "|S", &m); if (!mrb_nil_p(m)) { mrb_str_cat2(mrb, str, " - "); mrb_str_append(mrb, str, m); } mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "mesg"), str); return self; }