diff options
| -rw-r--r-- | include/mruby.h | 20 | ||||
| -rw-r--r-- | mrbgems/mruby-class-ext/test/module.rb | 26 | ||||
| -rw-r--r-- | src/class.c | 9 | ||||
| -rw-r--r-- | src/gc.c | 28 | ||||
| -rw-r--r-- | src/vm.c | 63 | ||||
| -rw-r--r-- | test/t/module.rb | 22 |
6 files changed, 109 insertions, 59 deletions
diff --git a/include/mruby.h b/include/mruby.h index 592ab1f04..18f54fd2f 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1036,11 +1036,27 @@ MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val); MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj); MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2); +static inline int mrb_gc_arena_save(mrb_state*); +static inline void mrb_gc_arena_restore(mrb_state*,int); + +static inline int +mrb_gc_arena_save(mrb_state *mrb) +{ + return mrb->gc.arena_idx; +} + +static inline void +mrb_gc_arena_restore(mrb_state *mrb, int idx) +{ + mrb->gc.arena_idx = idx; +} + +MRB_API int mrb_gc_arena_save(mrb_state*); +MRB_API void mrb_gc_arena_restore(mrb_state*,int); + MRB_API void mrb_garbage_collect(mrb_state*); MRB_API void mrb_full_gc(mrb_state*); MRB_API void mrb_incremental_gc(mrb_state *); -MRB_API int mrb_gc_arena_save(mrb_state*); -MRB_API void mrb_gc_arena_restore(mrb_state*,int); MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*); #define mrb_gc_mark_value(mrb,val) do {\ if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \ diff --git a/mrbgems/mruby-class-ext/test/module.rb b/mrbgems/mruby-class-ext/test/module.rb index 64b755278..65abde108 100644 --- a/mrbgems/mruby-class-ext/test/module.rb +++ b/mrbgems/mruby-class-ext/test/module.rb @@ -1,12 +1,26 @@ assert 'Module#name' do - module A - class B - end + module Outer + class Inner; end + const_set :SetInner, Class.new end - assert_nil A::B.singleton_class.name - assert_equal 'Fixnum', Fixnum.name - assert_equal 'A::B', A::B.name + assert_equal 'Outer', Outer.name + assert_equal 'Outer::Inner', Outer::Inner.name + assert_equal 'Outer::SetInner', Outer::SetInner.name + + outer = Module.new do + const_set :SetInner, Class.new + end + Object.const_set :SetOuter, outer + + assert_equal 'SetOuter', SetOuter.name + assert_equal 'SetOuter::SetInner', SetOuter::SetInner.name + + mod = Module.new + cls = Class.new + + assert_nil mod.name + assert_nil cls.name end assert 'Module#singleton_class?' do diff --git a/src/class.c b/src/class.c index e4e177f04..41a0fbad8 100644 --- a/src/class.c +++ b/src/class.c @@ -2178,7 +2178,14 @@ mrb_mod_const_set(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "no", &id, &value); check_const_name_sym(mrb, id); - mrb_const_set(mrb, mod, id, value); + if ((mrb_type(value) == MRB_TT_CLASS || mrb_type(value) == MRB_TT_MODULE) + && !mrb_obj_iv_defined(mrb, mrb_obj_ptr(value), mrb_intern_lit(mrb, "__classid__"))) { + /* name unnamed classes/modules */ + setup_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(value), id); + } + else { + mrb_const_set(mrb, mod, id, value); + } return value; } @@ -1243,34 +1243,6 @@ mrb_garbage_collect(mrb_state *mrb) mrb_full_gc(mrb); } -MRB_API int -mrb_gc_arena_save(mrb_state *mrb) -{ - return mrb->gc.arena_idx; -} - -MRB_API void -mrb_gc_arena_restore(mrb_state *mrb, int idx) -{ - mrb_gc *gc = &mrb->gc; - -#ifndef MRB_GC_FIXED_ARENA - int capa = gc->arena_capa; - - if (idx < capa / 4) { - capa >>= 2; - if (capa < MRB_GC_ARENA_SIZE) { - capa = MRB_GC_ARENA_SIZE; - } - if (capa != gc->arena_capa) { - gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa); - gc->arena_capa = capa; - } - } -#endif - gc->arena_idx = idx; -} - /* * Field write barrier * Paint obj(Black) -> value(White) to obj(Black) -> value(Gray). @@ -65,7 +65,28 @@ The value below allows about 60000 recursive calls in the simplest case. */ # define DEBUG(x) #endif -#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) + +#ifndef MRB_GC_FIXED_ARENA +static void +mrb_gc_arena_shrink(mrb_state *mrb, int idx) +{ + mrb_gc *gc = &mrb->gc; + int capa = gc->arena_capa; + + if (idx < capa / 4) { + capa >>= 2; + if (capa < MRB_GC_ARENA_SIZE) { + capa = MRB_GC_ARENA_SIZE; + } + if (capa != gc->arena_capa) { + gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa); + gc->arena_capa = capa; + } + } +} +#else +#define mrb_gc_arena_shrink(mrb,idx) +#endif #define CALL_MAXARGS 127 @@ -1271,7 +1292,7 @@ RETRY_TRY_BLOCK: } mrb->c->ensure[mrb->c->eidx++] = p; mrb->c->ensure[mrb->c->eidx] = NULL; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -1283,7 +1304,7 @@ RETRY_TRY_BLOCK: for (n=0; n<a && mrb->c->eidx > epos; n++) { ecall(mrb, --mrb->c->eidx); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); } NEXT; } @@ -1395,6 +1416,7 @@ RETRY_TRY_BLOCK: } result = m->body.func(mrb, recv); mrb_gc_arena_restore(mrb, ai); + mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; ci = mrb->c->ci; if (GET_OPCODE(i) == OP_SENDB) { @@ -1481,6 +1503,7 @@ RETRY_TRY_BLOCK: if (MRB_PROC_CFUNC_P(m)) { recv = m->body.func(mrb, recv); mrb_gc_arena_restore(mrb, ai); + mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->c->ci; @@ -1716,7 +1739,7 @@ RETRY_TRY_BLOCK: rest->len = m1+len+m2; } regs[a+1] = stack[m1+r+m2]; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2006,7 +2029,7 @@ RETRY_TRY_BLOCK: ci = mrb->c->ci; } if (ci->acc < 0) { - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); mrb->c->vmexec = FALSE; mrb->exc = (struct RObject*)break_new(mrb, proc, v); mrb->jmp = prev_jmp; @@ -2040,7 +2063,7 @@ RETRY_TRY_BLOCK: ecall(mrb, --mrb->c->eidx); } if (mrb->c->vmexec && !mrb->c->ci->target_class) { - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); mrb->c->vmexec = FALSE; mrb->jmp = prev_jmp; return v; @@ -2050,7 +2073,7 @@ RETRY_TRY_BLOCK: mrb->c->stack = ci->stackent; cipop(mrb); if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) { - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); mrb->jmp = prev_jmp; return v; } @@ -2062,7 +2085,7 @@ RETRY_TRY_BLOCK: syms = irep->syms; regs[acc] = v; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); } JUMP; } @@ -2231,7 +2254,7 @@ RETRY_TRY_BLOCK: default: goto L_SEND; } - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2549,7 +2572,7 @@ RETRY_TRY_BLOCK: int c = GETARG_C(i); mrb_value v = mrb_ary_new_from_values(mrb, c, ®s[b]); regs[a] = v; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2559,7 +2582,7 @@ RETRY_TRY_BLOCK: int b = GETARG_B(i); mrb_value splat = mrb_ary_splat(mrb, regs[b]); mrb_ary_concat(mrb, regs[a], splat); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2634,7 +2657,7 @@ RETRY_TRY_BLOCK: idx++; } } - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2642,7 +2665,7 @@ RETRY_TRY_BLOCK: /* A Bx R(A) := str_new(Lit(Bx)) */ mrb_value str = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); regs[GETARG_A(i)] = str; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2664,7 +2687,7 @@ RETRY_TRY_BLOCK: b+=2; } regs[GETARG_A(i)] = hash; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2681,7 +2704,7 @@ RETRY_TRY_BLOCK: } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; regs[GETARG_A(i)] = mrb_obj_value(p); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2708,7 +2731,7 @@ RETRY_TRY_BLOCK: } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2728,7 +2751,7 @@ RETRY_TRY_BLOCK: } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2776,14 +2799,14 @@ RETRY_TRY_BLOCK: struct RProc *p = mrb_proc_ptr(regs[a+1]); mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } CASE(OP_SCLASS) { /* A B R(A) := R(B).singleton_class */ regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2803,7 +2826,7 @@ RETRY_TRY_BLOCK: int b = GETARG_B(i); mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); regs[GETARG_A(i)] = val; - ARENA_RESTORE(mrb, ai); + mrb_gc_arena_restore(mrb, ai); NEXT; } diff --git a/test/t/module.rb b/test/t/module.rb index cfdca8503..419b0bfd5 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -787,10 +787,28 @@ end # @!endgroup prepend assert('Module#to_s') do - module Test4to_sModules + module Outer + class Inner; end + const_set :SetInner, Class.new + end + + assert_equal 'Outer', Outer.to_s + assert_equal 'Outer::Inner', Outer::Inner.to_s + assert_equal 'Outer::SetInner', Outer::SetInner.to_s + + outer = Module.new do + const_set :SetInner, Class.new end + Object.const_set :SetOuter, outer + + assert_equal 'SetOuter', SetOuter.to_s + assert_equal 'SetOuter::SetInner', SetOuter::SetInner.to_s + + mod = Module.new + cls = Class.new - assert_equal 'Test4to_sModules', Test4to_sModules.to_s + assert_equal "#<Module:0x", mod.to_s[0,11] + assert_equal "#<Class:0x", cls.to_s[0,10] end assert('Module#inspect') do |
