From 0d4227ac04832a3bb4010d701ebda2c97c034da6 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Sun, 12 May 2013 18:42:21 +1000 Subject: Implemented ObjectSpace.count_objects to count the number of allocated objects for each type --- src/gc.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hash.c | 4 +-- 2 files changed, 104 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gc.c b/src/gc.c index b6493b859..6e3ba1d0e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1141,6 +1141,103 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) return mrb_bool_value(enable); } +/* + * call-seq: + * ObjectSpace.count_objects([result_hash]) -> hash + * + * Counts objects for each type. + * + * It returns a hash, such as: + * { + * :TOTAL=>10000, + * :FREE=>3011, + * :MRB_TT_OBJECT=>6, + * :MRB_TT_CLASS=>404, + * # ... + * } + * + * If the optional argument +result_hash+ is given, + * it is overwritten and returned. This is intended to avoid probe effect. + * + */ + +mrb_value os_count_objects(mrb_state *mrb, mrb_value self) +{ + size_t counts[MRB_TT_MAXDEFINE+1]; + size_t freed = 0; + size_t total = 0; + size_t i; + mrb_value hash; + struct heap_page* page = mrb->heaps; + + if (mrb_get_args(mrb, "|H", &hash) == 0) { + hash = mrb_hash_new(mrb); + } + + if (!mrb_test(mrb_hash_empty_p(mrb, hash))) { + mrb_hash_clear(mrb, hash); + } + + for (i = 0; i <= MRB_TT_MAXDEFINE; i++) { + counts[i] = 0; + } + + while (page != NULL) { + RVALUE *p, *pend; + + p = page->objects; + pend = p + MRB_HEAP_PAGE_SIZE; + for (;p < pend; p++) { + if (p->as.basic.flags) { + counts[mrb_type(p->as.basic)]++; + } + else { + freed++; + } + } + total += MRB_HEAP_PAGE_SIZE; + page = page->next; + } + + mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "TOTAL")), mrb_fixnum_value(total)); + mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "FREE")), mrb_fixnum_value(freed)); + + for (i = 0; i < MRB_TT_MAXDEFINE; i++) { + mrb_value type; + switch (i) { +#define COUNT_TYPE(t) case (t): type = mrb_symbol_value(mrb_intern_cstr(mrb, #t)); break; + COUNT_TYPE(MRB_TT_FALSE); + COUNT_TYPE(MRB_TT_FREE); + COUNT_TYPE(MRB_TT_TRUE); + COUNT_TYPE(MRB_TT_FIXNUM); + COUNT_TYPE(MRB_TT_SYMBOL); + COUNT_TYPE(MRB_TT_UNDEF); + COUNT_TYPE(MRB_TT_FLOAT); + COUNT_TYPE(MRB_TT_VOIDP); + COUNT_TYPE(MRB_TT_OBJECT); + COUNT_TYPE(MRB_TT_CLASS); + COUNT_TYPE(MRB_TT_MODULE); + COUNT_TYPE(MRB_TT_ICLASS); + COUNT_TYPE(MRB_TT_SCLASS); + COUNT_TYPE(MRB_TT_PROC); + COUNT_TYPE(MRB_TT_ARRAY); + COUNT_TYPE(MRB_TT_HASH); + COUNT_TYPE(MRB_TT_STRING); + COUNT_TYPE(MRB_TT_RANGE); + COUNT_TYPE(MRB_TT_EXCEPTION); + COUNT_TYPE(MRB_TT_FILE); + COUNT_TYPE(MRB_TT_ENV); + COUNT_TYPE(MRB_TT_DATA); +#undef COUNT_TYPE + default: type = mrb_fixnum_value(i); break; + } + if (counts[i]) + mrb_hash_set(mrb, hash, type, mrb_fixnum_value(counts[i])); + } + + return hash; +} + #ifdef GC_TEST #ifdef GC_DEBUG static mrb_value gc_test(mrb_state *, mrb_value); @@ -1151,6 +1248,8 @@ void mrb_init_gc(mrb_state *mrb) { struct RClass *gc; + struct RClass *os; + gc = mrb_define_module(mrb, "GC"); mrb_define_class_method(mrb, gc, "start", gc_start, MRB_ARGS_NONE()); @@ -1167,6 +1266,9 @@ mrb_init_gc(mrb_state *mrb) mrb_define_class_method(mrb, gc, "test", gc_test, MRB_ARGS_NONE()); #endif #endif + + os = mrb_define_module(mrb, "ObjectSpace"); + mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_ANY()); } #ifdef GC_TEST diff --git a/src/hash.c b/src/hash.c index 882dd3121..5d78a6ea7 100644 --- a/src/hash.c +++ b/src/hash.c @@ -651,7 +651,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) * */ -static mrb_value +mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); @@ -768,7 +768,7 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self) * {}.empty? #=> true * */ -static mrb_value +mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); -- cgit v1.2.3 From 279fce05ae34bd05a01c8b377a5f1b13b701cf83 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Sun, 12 May 2013 19:49:56 +1000 Subject: ObjectSpace.count_objects was incorrectly checking if an object was already freed. Amended the count_objects test to ensure the correct distinction --- src/gc.c | 15 +++++++++------ test/t/objectspace.rb | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gc.c b/src/gc.c index 6e3ba1d0e..375bbfd22 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1168,6 +1168,7 @@ mrb_value os_count_objects(mrb_state *mrb, mrb_value self) size_t total = 0; size_t i; mrb_value hash; + RVALUE *free; struct heap_page* page = mrb->heaps; if (mrb_get_args(mrb, "|H", &hash) == 0) { @@ -1188,13 +1189,15 @@ mrb_value os_count_objects(mrb_state *mrb, mrb_value self) p = page->objects; pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { - if (p->as.basic.flags) { - counts[mrb_type(p->as.basic)]++; - } - else { - freed++; - } + counts[mrb_type(p->as.basic)]++; } + + free = (RVALUE*)page->freelist; + while (free) { + freed++; + free = (RVALUE*)free->as.free.next; + } + total += MRB_HEAP_PAGE_SIZE; page = page->next; } diff --git a/test/t/objectspace.rb b/test/t/objectspace.rb index bf79da902..06319dcbb 100644 --- a/test/t/objectspace.rb +++ b/test/t/objectspace.rb @@ -16,4 +16,20 @@ assert('ObjectSpace.count_objects') do h0 = {:MRB_TT_FOO=>1000} h = ObjectSpace.count_objects(h0) assert_false(h0.has_key?(:MRB_TT_FOO)) + + GC.start + h_after = {} + h_before = ObjectSpace.count_objects + + objs = [] + 1000.times do + objs << {} + end + objs = nil + ObjectSpace.count_objects(h) + GC.start + ObjectSpace.count_objects(h_after) + + assert_equal(h_before[:MRB_TT_HASH] + 1000, h[:MRB_TT_HASH]) + assert_equal(h_before[:MRB_TT_HASH], h_after[:MRB_TT_HASH]) end \ No newline at end of file -- cgit v1.2.3 From a71bf5e3df961605aeb2712bb472bf3b0f1c0dd3 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Sun, 12 May 2013 19:51:51 +1000 Subject: Change in formatting for os_count_objects to be consistent with other functions. --- src/gc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gc.c b/src/gc.c index 375bbfd22..7add82eba 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1161,7 +1161,8 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) * */ -mrb_value os_count_objects(mrb_state *mrb, mrb_value self) +mrb_value +os_count_objects(mrb_state *mrb, mrb_value self) { size_t counts[MRB_TT_MAXDEFINE+1]; size_t freed = 0; -- cgit v1.2.3 From 222918deae84ae8dda26aa769bf3cc6b68e3aeec Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Fri, 17 May 2013 07:21:33 +1000 Subject: First implementation of ObjectSpace moved outside of gc.c --- include/mruby/gc.h | 53 ++++++++++ mrbgems/mruby-objectspace/README.md | 4 + mrbgems/mruby-objectspace/mrbgem.rake | 4 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 111 +++++++++++++++++++++ mrbgems/mruby-objectspace/test/objectspace.rb | 34 +++++++ src/gc.c | 114 +--------------------- test/t/objectspace.rb | 35 ------- 7 files changed, 210 insertions(+), 145 deletions(-) create mode 100644 include/mruby/gc.h create mode 100644 mrbgems/mruby-objectspace/README.md create mode 100644 mrbgems/mruby-objectspace/mrbgem.rake create mode 100644 mrbgems/mruby-objectspace/src/mruby_objectspace.c create mode 100644 mrbgems/mruby-objectspace/test/objectspace.rb delete mode 100644 test/t/objectspace.rb (limited to 'src') diff --git a/include/mruby/gc.h b/include/mruby/gc.h new file mode 100644 index 000000000..00564c4fa --- /dev/null +++ b/include/mruby/gc.h @@ -0,0 +1,53 @@ +/* +** gc.c - garbage collector for mruby +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_GC_H +#define MRUBY_GC_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "mruby.h" +#include "mruby/array.h" +#include "mruby/class.h" +#include "mruby/data.h" +#include "mruby/hash.h" +#include "mruby/proc.h" +#include "mruby/range.h" +#include "mruby/string.h" +#include "mruby/variable.h" + +struct free_obj { + MRB_OBJECT_HEADER; + struct RBasic *next; +}; + +struct RVALUE { + union { + struct free_obj free; + struct RBasic basic; + struct RObject object; + struct RClass klass; + struct RString string; + struct RArray array; + struct RHash hash; + struct RRange range; + struct RData data; + struct RProc proc; + } as; +}; + +typedef struct RVALUE RVALUE; + +typedef int each_object_callback(RVALUE *obj, void *data); +void mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void *data); + +#if defined(__cplusplus) +} /* extern "C" { */ +#endif + +#endif /* MRUBY_GC_H */ diff --git a/mrbgems/mruby-objectspace/README.md b/mrbgems/mruby-objectspace/README.md new file mode 100644 index 000000000..7669c9d7f --- /dev/null +++ b/mrbgems/mruby-objectspace/README.md @@ -0,0 +1,4 @@ +MRuby ObjectSpace Implementation +========= + +Currently only supports count_objects \ No newline at end of file diff --git a/mrbgems/mruby-objectspace/mrbgem.rake b/mrbgems/mruby-objectspace/mrbgem.rake new file mode 100644 index 000000000..100df4cdc --- /dev/null +++ b/mrbgems/mruby-objectspace/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-objectspace') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c new file mode 100644 index 000000000..2d064044d --- /dev/null +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include + +/* + * call-seq: + * ObjectSpace.count_objects([result_hash]) -> hash + * + * Counts objects for each type. + * + * It returns a hash, such as: + * { + * :TOTAL=>10000, + * :FREE=>3011, + * :MRB_TT_OBJECT=>6, + * :MRB_TT_CLASS=>404, + * # ... + * } + * + * If the optional argument +result_hash+ is given, + * it is overwritten and returned. This is intended to avoid probe effect. + * + */ + +struct os_count_struct { + size_t total; + size_t counts[MRB_TT_MAXDEFINE+1]; +}; + +void os_count_object_type(RVALUE *obj, void *data) +{ + struct os_count_struct* obj_count; + obj_count = (struct os_count_struct*)(data); + obj_count->counts[mrb_type(obj->as.basic)]++; + obj_count->total++; +} + +mrb_value +os_count_objects(mrb_state *mrb, mrb_value self) +{ + struct os_count_struct obj_count; + size_t freed = 0; + size_t i; + mrb_value hash; + struct heap_page* page = mrb->heaps; + + if (mrb_get_args(mrb, "|H", &hash) == 0) { + hash = mrb_hash_new(mrb); + } + + if (!mrb_test(mrb_hash_empty_p(mrb, hash))) { + mrb_hash_clear(mrb, hash); + } + + for (i = 0; i <= MRB_TT_MAXDEFINE; i++) { + obj_count.counts[i] = 0; + } + + mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count); + + mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total)); + mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "FREE")), mrb_fixnum_value(freed)); + + for (i = 0; i < MRB_TT_MAXDEFINE; i++) { + mrb_value type; + switch (i) { +#define COUNT_TYPE(t) case (t): type = mrb_symbol_value(mrb_intern_cstr(mrb, #t)); break; + COUNT_TYPE(MRB_TT_FALSE); + COUNT_TYPE(MRB_TT_FREE); + COUNT_TYPE(MRB_TT_TRUE); + COUNT_TYPE(MRB_TT_FIXNUM); + COUNT_TYPE(MRB_TT_SYMBOL); + COUNT_TYPE(MRB_TT_UNDEF); + COUNT_TYPE(MRB_TT_FLOAT); + COUNT_TYPE(MRB_TT_VOIDP); + COUNT_TYPE(MRB_TT_OBJECT); + COUNT_TYPE(MRB_TT_CLASS); + COUNT_TYPE(MRB_TT_MODULE); + COUNT_TYPE(MRB_TT_ICLASS); + COUNT_TYPE(MRB_TT_SCLASS); + COUNT_TYPE(MRB_TT_PROC); + COUNT_TYPE(MRB_TT_ARRAY); + COUNT_TYPE(MRB_TT_HASH); + COUNT_TYPE(MRB_TT_STRING); + COUNT_TYPE(MRB_TT_RANGE); + COUNT_TYPE(MRB_TT_EXCEPTION); + COUNT_TYPE(MRB_TT_FILE); + COUNT_TYPE(MRB_TT_ENV); + COUNT_TYPE(MRB_TT_DATA); +#undef COUNT_TYPE + default: type = mrb_fixnum_value(i); break; + } + if (obj_count.counts[i]) + mrb_hash_set(mrb, hash, type, mrb_fixnum_value(obj_count.counts[i])); + } + + return hash; +} + +void +mrb_mruby_objectspace_gem_init(mrb_state* mrb) { + struct RClass *os; + os = mrb_define_module(mrb, "ObjectSpace"); + mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_ANY()); +} + +void +mrb_mruby_objectspace_gem_final(mrb_state* mrb) { + // finalizer +} diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb new file mode 100644 index 000000000..dbf3bcbb8 --- /dev/null +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -0,0 +1,34 @@ +assert('ObjectSpace.count_objects') do + h = {} + ObjectSpace.count_objects(h) + assert_kind_of(Hash, h) + assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) + assert_true(h.values.all? {|x| x.is_a?(Integer) }) + + h = ObjectSpace.count_objects + assert_kind_of(Hash, h) + assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) + assert_true(h.values.all? {|x| x.is_a?(Integer) }) + + assert_raise(TypeError) { ObjectSpace.count_objects(1) } + + h0 = {:MRB_TT_FOO=>1000} + h = ObjectSpace.count_objects(h0) + assert_false(h0.has_key?(:MRB_TT_FOO)) + + GC.start + h_after = {} + h_before = ObjectSpace.count_objects + + objs = [] + 1000.times do + objs << {} + end + objs = nil + ObjectSpace.count_objects(h) + GC.start + ObjectSpace.count_objects(h_after) + + assert_equal(h_before[:MRB_TT_HASH] + 1000, h[:MRB_TT_HASH]) + assert_equal(h_before[:MRB_TT_HASH], h_after[:MRB_TT_HASH]) +end \ No newline at end of file diff --git a/src/gc.c b/src/gc.c index 7add82eba..199551c55 100644 --- a/src/gc.c +++ b/src/gc.c @@ -20,6 +20,7 @@ #include "mruby/range.h" #include "mruby/string.h" #include "mruby/variable.h" +#include "mruby/gc.h" /* = Tri-color Incremental Garbage Collection @@ -72,26 +73,6 @@ */ -struct free_obj { - MRB_OBJECT_HEADER; - struct RBasic *next; -}; - -typedef struct { - union { - struct free_obj free; - struct RBasic basic; - struct RObject object; - struct RClass klass; - struct RString string; - struct RArray array; - struct RHash hash; - struct RRange range; - struct RData data; - struct RProc proc; - } as; -} RVALUE; - #ifdef GC_PROFILE #include #include @@ -1141,105 +1122,22 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) return mrb_bool_value(enable); } -/* - * call-seq: - * ObjectSpace.count_objects([result_hash]) -> hash - * - * Counts objects for each type. - * - * It returns a hash, such as: - * { - * :TOTAL=>10000, - * :FREE=>3011, - * :MRB_TT_OBJECT=>6, - * :MRB_TT_CLASS=>404, - * # ... - * } - * - * If the optional argument +result_hash+ is given, - * it is overwritten and returned. This is intended to avoid probe effect. - * - */ - -mrb_value -os_count_objects(mrb_state *mrb, mrb_value self) +void +mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void *data) { - size_t counts[MRB_TT_MAXDEFINE+1]; - size_t freed = 0; - size_t total = 0; - size_t i; - mrb_value hash; - RVALUE *free; struct heap_page* page = mrb->heaps; - if (mrb_get_args(mrb, "|H", &hash) == 0) { - hash = mrb_hash_new(mrb); - } - - if (!mrb_test(mrb_hash_empty_p(mrb, hash))) { - mrb_hash_clear(mrb, hash); - } - - for (i = 0; i <= MRB_TT_MAXDEFINE; i++) { - counts[i] = 0; - } - while (page != NULL) { RVALUE *p, *pend; p = page->objects; pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { - counts[mrb_type(p->as.basic)]++; + callback(p, data); } - free = (RVALUE*)page->freelist; - while (free) { - freed++; - free = (RVALUE*)free->as.free.next; - } - - total += MRB_HEAP_PAGE_SIZE; page = page->next; } - - mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "TOTAL")), mrb_fixnum_value(total)); - mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "FREE")), mrb_fixnum_value(freed)); - - for (i = 0; i < MRB_TT_MAXDEFINE; i++) { - mrb_value type; - switch (i) { -#define COUNT_TYPE(t) case (t): type = mrb_symbol_value(mrb_intern_cstr(mrb, #t)); break; - COUNT_TYPE(MRB_TT_FALSE); - COUNT_TYPE(MRB_TT_FREE); - COUNT_TYPE(MRB_TT_TRUE); - COUNT_TYPE(MRB_TT_FIXNUM); - COUNT_TYPE(MRB_TT_SYMBOL); - COUNT_TYPE(MRB_TT_UNDEF); - COUNT_TYPE(MRB_TT_FLOAT); - COUNT_TYPE(MRB_TT_VOIDP); - COUNT_TYPE(MRB_TT_OBJECT); - COUNT_TYPE(MRB_TT_CLASS); - COUNT_TYPE(MRB_TT_MODULE); - COUNT_TYPE(MRB_TT_ICLASS); - COUNT_TYPE(MRB_TT_SCLASS); - COUNT_TYPE(MRB_TT_PROC); - COUNT_TYPE(MRB_TT_ARRAY); - COUNT_TYPE(MRB_TT_HASH); - COUNT_TYPE(MRB_TT_STRING); - COUNT_TYPE(MRB_TT_RANGE); - COUNT_TYPE(MRB_TT_EXCEPTION); - COUNT_TYPE(MRB_TT_FILE); - COUNT_TYPE(MRB_TT_ENV); - COUNT_TYPE(MRB_TT_DATA); -#undef COUNT_TYPE - default: type = mrb_fixnum_value(i); break; - } - if (counts[i]) - mrb_hash_set(mrb, hash, type, mrb_fixnum_value(counts[i])); - } - - return hash; } #ifdef GC_TEST @@ -1252,7 +1150,6 @@ void mrb_init_gc(mrb_state *mrb) { struct RClass *gc; - struct RClass *os; gc = mrb_define_module(mrb, "GC"); @@ -1270,9 +1167,6 @@ mrb_init_gc(mrb_state *mrb) mrb_define_class_method(mrb, gc, "test", gc_test, MRB_ARGS_NONE()); #endif #endif - - os = mrb_define_module(mrb, "ObjectSpace"); - mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_ANY()); } #ifdef GC_TEST diff --git a/test/t/objectspace.rb b/test/t/objectspace.rb deleted file mode 100644 index 06319dcbb..000000000 --- a/test/t/objectspace.rb +++ /dev/null @@ -1,35 +0,0 @@ - -assert('ObjectSpace.count_objects') do - h = {} - ObjectSpace.count_objects(h) - assert_kind_of(Hash, h) - assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) - assert_true(h.values.all? {|x| x.is_a?(Integer) }) - - h = ObjectSpace.count_objects - assert_kind_of(Hash, h) - assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) - assert_true(h.values.all? {|x| x.is_a?(Integer) }) - - assert_raise(TypeError) { ObjectSpace.count_objects(1) } - - h0 = {:MRB_TT_FOO=>1000} - h = ObjectSpace.count_objects(h0) - assert_false(h0.has_key?(:MRB_TT_FOO)) - - GC.start - h_after = {} - h_before = ObjectSpace.count_objects - - objs = [] - 1000.times do - objs << {} - end - objs = nil - ObjectSpace.count_objects(h) - GC.start - ObjectSpace.count_objects(h_after) - - assert_equal(h_before[:MRB_TT_HASH] + 1000, h[:MRB_TT_HASH]) - assert_equal(h_before[:MRB_TT_HASH], h_after[:MRB_TT_HASH]) - end \ No newline at end of file -- cgit v1.2.3 From f62cc5b1eebb29d244977c6030c04d9cb8ebefba Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Fri, 17 May 2013 07:41:13 +1000 Subject: Changed the object_count so that it only iterates over the RBasic object, not the full RVALUE known by the GC --- include/mruby/gc.h | 33 ++--------------------- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 24 ++++++++++++----- mrbgems/mruby-objectspace/test/objectspace.rb | 11 ++++++++ src/gc.c | 22 ++++++++++++++- 4 files changed, 52 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 00564c4fa..552321be2 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -12,38 +12,9 @@ extern "C" { #endif #include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/data.h" -#include "mruby/hash.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" +#include "mruby/value.h" -struct free_obj { - MRB_OBJECT_HEADER; - struct RBasic *next; -}; - -struct RVALUE { - union { - struct free_obj free; - struct RBasic basic; - struct RObject object; - struct RClass klass; - struct RString string; - struct RArray array; - struct RHash hash; - struct RRange range; - struct RData data; - struct RProc proc; - } as; -}; - -typedef struct RVALUE RVALUE; - -typedef int each_object_callback(RVALUE *obj, void *data); +typedef int 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); #if defined(__cplusplus) diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 2d064044d..cf3cf631f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -1,7 +1,9 @@ +#include + #include #include #include -#include +#include /* * call-seq: @@ -25,22 +27,30 @@ struct os_count_struct { size_t total; + size_t freed; size_t counts[MRB_TT_MAXDEFINE+1]; }; -void os_count_object_type(RVALUE *obj, void *data) +void os_count_object_type(mrb_state *mrb, struct RBasic obj, void *data) { struct os_count_struct* obj_count; obj_count = (struct os_count_struct*)(data); - obj_count->counts[mrb_type(obj->as.basic)]++; - obj_count->total++; + obj_count->counts[mrb_type(obj)]++; + if (is_dead(mrb, &obj)) + { + obj_count->freed++; + } + else + { + obj_count->total++; + } + } mrb_value os_count_objects(mrb_state *mrb, mrb_value self) { struct os_count_struct obj_count; - size_t freed = 0; size_t i; mrb_value hash; struct heap_page* page = mrb->heaps; @@ -56,11 +66,13 @@ os_count_objects(mrb_state *mrb, mrb_value self) for (i = 0; i <= MRB_TT_MAXDEFINE; i++) { obj_count.counts[i] = 0; } + obj_count.total = 0; + obj_count.freed = 0; mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count); mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total)); - mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "FREE")), mrb_fixnum_value(freed)); + mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, "FREE")), mrb_fixnum_value(obj_count.freed)); for (i = 0; i < MRB_TT_MAXDEFINE; i++) { mrb_value type; diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index dbf3bcbb8..4a362740c 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -5,6 +5,11 @@ assert('ObjectSpace.count_objects') do assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) assert_true(h.values.all? {|x| x.is_a?(Integer) }) + assert_true(h.has_key?(:TOTAL)) + assert_true(h.has_key?(:FREE)) + + p h.inspect + h = ObjectSpace.count_objects assert_kind_of(Hash, h) assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) @@ -12,6 +17,8 @@ assert('ObjectSpace.count_objects') do assert_raise(TypeError) { ObjectSpace.count_objects(1) } + p h.inspect + h0 = {:MRB_TT_FOO=>1000} h = ObjectSpace.count_objects(h0) assert_false(h0.has_key?(:MRB_TT_FOO)) @@ -31,4 +38,8 @@ assert('ObjectSpace.count_objects') do assert_equal(h_before[:MRB_TT_HASH] + 1000, h[:MRB_TT_HASH]) assert_equal(h_before[:MRB_TT_HASH], h_after[:MRB_TT_HASH]) + + p h.inspect + p h_after.inspect + end \ No newline at end of file diff --git a/src/gc.c b/src/gc.c index 199551c55..f824ee9d4 100644 --- a/src/gc.c +++ b/src/gc.c @@ -73,6 +73,26 @@ */ +struct free_obj { + MRB_OBJECT_HEADER; + struct RBasic *next; +}; + +typedef struct { + union { + struct free_obj free; + struct RBasic basic; + struct RObject object; + struct RClass klass; + struct RString string; + struct RArray array; + struct RHash hash; + struct RRange range; + struct RData data; + struct RProc proc; + } as; +} RVALUE; + #ifdef GC_PROFILE #include #include @@ -1133,7 +1153,7 @@ mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void * p = page->objects; pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { - callback(p, data); + callback(mrb, p->as.basic, data); } page = page->next; -- cgit v1.2.3 From 40d63f7740e4b020a2126ddb386760c6fd51c999 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Fri, 17 May 2013 08:02:24 +1000 Subject: Changed the each_object callback so that a pointer is passed for the object, instead of the struct. --- include/mruby/gc.h | 12 ++---------- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 6 +++--- src/gc.c | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 552321be2..0c19275ba 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -1,5 +1,5 @@ /* -** gc.c - garbage collector for mruby +** gc.h - garbage collector for mruby ** ** See Copyright Notice in mruby.h */ @@ -7,18 +7,10 @@ #ifndef MRUBY_GC_H #define MRUBY_GC_H -#if defined(__cplusplus) -extern "C" { -#endif - #include "mruby.h" #include "mruby/value.h" -typedef int each_object_callback(mrb_state *mrb, struct RBasic obj, void *data); +typedef int 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); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif - #endif /* MRUBY_GC_H */ diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index cf3cf631f..10934c83f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -31,12 +31,12 @@ struct os_count_struct { size_t counts[MRB_TT_MAXDEFINE+1]; }; -void os_count_object_type(mrb_state *mrb, struct RBasic obj, void *data) +void os_count_object_type(mrb_state *mrb, struct RBasic* obj, void *data) { struct os_count_struct* obj_count; obj_count = (struct os_count_struct*)(data); - obj_count->counts[mrb_type(obj)]++; - if (is_dead(mrb, &obj)) + obj_count->counts[obj->tt]++; + if (is_dead(mrb, obj)) { obj_count->freed++; } diff --git a/src/gc.c b/src/gc.c index f824ee9d4..9dcc3f4b2 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1153,7 +1153,7 @@ mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void * p = page->objects; pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { - callback(mrb, p->as.basic, data); + callback(mrb, &p->as.basic, data); } page = page->next; -- cgit v1.2.3 From 4acfadfee147138372ce01f29079948b7adca3d9 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Sat, 18 May 2013 10:55:41 +1000 Subject: Fixed the each object callback to be more consistent with other callbacks. --- include/mruby/gc.h | 2 +- src/gc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 0c19275ba..2f7dc73cf 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -10,7 +10,7 @@ #include "mruby.h" #include "mruby/value.h" -typedef int each_object_callback(mrb_state *mrb, struct RBasic* obj, void *data); +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); #endif /* MRUBY_GC_H */ diff --git a/src/gc.c b/src/gc.c index 9dcc3f4b2..2e5678f7d 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1153,7 +1153,7 @@ mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void * p = page->objects; pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { - callback(mrb, &p->as.basic, data); + (*callback)(mrb, &p->as.basic, data); } page = page->next; -- cgit v1.2.3