From db296e95939ed856abb564135d2e6f586cf1888e Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 26 Jun 2020 15:13:04 -0700 Subject: work around MSC optimization generating non functional code --- mrbgems/mruby-random/src/random.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 515c0707a..6f31b15a6 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -210,9 +210,16 @@ random_m_srand(mrb_state *mrb, mrb_value self) * Shuffles elements in self in place. */ +#if defined _MSC_VER && _MSC_VER >= 1900 +#pragma optimize( "", off ) +#endif static mrb_value mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { + /* + * MSC compiler generating invalid instructions with optimization + * enabled + */ mrb_int i; mrb_value max; mrb_value r = mrb_nil_value(); -- cgit v1.2.3 From b8d896e56ab382b89c4980c0dc0efaca23f3a2c9 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 26 Jun 2020 21:16:17 -0700 Subject: Narrower scope working around MSC bug --- mrbgems/mruby-random/src/random.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 6f31b15a6..f1834848d 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -210,18 +210,18 @@ random_m_srand(mrb_state *mrb, mrb_value self) * Shuffles elements in self in place. */ -#if defined _MSC_VER && _MSC_VER >= 1900 -#pragma optimize( "", off ) -#endif static mrb_value mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { + mrb_int i; + mrb_value max; /* * MSC compiler generating invalid instructions with optimization * enabled */ - mrb_int i; - mrb_value max; +#if defined _MSC_VER && _MSC_VER >= 1923 + volatile +#endif mrb_value r = mrb_nil_value(); rand_state *random; -- cgit v1.2.3 From b1017b26513c5773b30b88b0675ab070356fb2a8 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 26 Jun 2020 21:44:31 -0700 Subject: Reduce scope of volatile keyword for MSC bug --- mrbgems/mruby-random/src/random.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index f1834848d..55bea5713 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -215,15 +215,18 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { mrb_int i; mrb_value max; + mrb_value r = mrb_nil_value(); + rand_state *random; + /* - * MSC compiler generating invalid instructions with optimization + * MSC compiler bug generating invalid instructions with optimization * enabled */ #if defined _MSC_VER && _MSC_VER >= 1923 - volatile + volatile mrb_value rr; + rr = r; + r = rr; #endif - mrb_value r = mrb_nil_value(); - rand_state *random; if (RARRAY_LEN(ary) > 1) { mrb_get_args(mrb, "|o", &r); -- cgit v1.2.3 From 3cf48713a2d39e624e9b755bfcfae6fb51a861c9 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 14:25:59 -0700 Subject: Work around more MSC optimzer bugs --- mrbgems/mruby-random/src/random.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 55bea5713..10c81b946 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -220,12 +220,30 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) /* * MSC compiler bug generating invalid instructions with optimization - * enabled + * enabled. MSC errantly uses a hardcoded value with optimizations on + * when using a fixed value from a union. + * Creating a temp volatile variable and reassigning back to the original + * value tricks the compiler to not perform this optimization; */ #if defined _MSC_VER && _MSC_VER >= 1923 - volatile mrb_value rr; - rr = r; - r = rr; + /* C++ will not cast away volatile easily, so we cannot do something like + * volatile mrb_value rr = r; r = (mrb_value)rr; with C++. + * That cast does work with C. + * We also have to trick the compiler to not optimize away the const_cast entirely + * by creating and manipulating an intermediate volatile pointer. + */ + volatile mrb_value *v_r; + volatile mrb_int ii; + mrb_value *p_r; + v_r = &r; + ii = 2; + v_r = v_r + 2; +#if defined __cplusplus + p_r = const_cast(v_r - ii); +#else + p_r = (mrb_value*)v_r - ii; +#endif + r = *p_r; #endif if (RARRAY_LEN(ary) > 1) { -- cgit v1.2.3 From 338c8538c92a1f3c4117fb920855a610cfaefc25 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Thu, 9 Jul 2020 18:52:31 -0700 Subject: Initial ObjectSpace.memsize_of implementation --- mrbgems/mruby-objectspace/mrbgem.rake | 4 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 201 ++++++++++++++++++++++ mrbgems/mruby-objectspace/test/objectspace.rb | 76 ++++++++ 3 files changed, 281 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/mrbgem.rake b/mrbgems/mruby-objectspace/mrbgem.rake index fa35136a1..101e24275 100644 --- a/mrbgems/mruby-objectspace/mrbgem.rake +++ b/mrbgems/mruby-objectspace/mrbgem.rake @@ -2,4 +2,8 @@ MRuby::Gem::Specification.new('mruby-objectspace') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' spec.summary = 'ObjectSpace class' + + spec.add_test_dependency('mruby-metaprog') + spec.add_test_dependency('mruby-method') + spec.add_test_dependency('mruby-fiber') end diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b89fb0580..fe7e929c8 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -2,6 +2,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include struct os_count_struct { mrb_int total; @@ -168,12 +176,205 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } +static void os_memsize_of_object(mrb_state*,mrb_value,mrb_bool,mrb_int*); + +static int +os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) +{ + mrb_int *cb_data = (mrb_int *)data; + mrb_int recurse = *(&cb_data[0]); + mrb_int* total = &cb_data[1]; + + os_memsize_of_object(mrb, obj, (mrb_bool)(recurse), total); + return 0; +} + +static void +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) +{ + /* need iv segment table size */ + if(recurse) { + mrb_int r = (mrb_int)recurse; + mrb_int *cb_data[2] = { &r, t }; + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, t); + } +} + +static void +os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep, mrb_int* t) +{ + mrb_int i; + (*t) += (irep->slen * sizeof(mrb_sym)) + + (irep->plen * sizeof(mrb_code)) + + (irep->ilen * sizeof(mrb_code)); + + for(i = 0; i < irep->rlen; i++) { + os_memsize_of_irep(state, irep->reps[i], t); + } +} + +static void +os_memsize_of_method(mrb_state* mrb, mrb_value method_obj, mrb_int* t) +{ + mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), + mrb_intern_lit(mrb, "_proc")); + struct RProc *proc = mrb_proc_ptr(proc_value); + + (*t) += sizeof(struct RProc); + if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); +} + +static void +os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) +{ + mrb_value method_list; + mrb_int i; + if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return; + method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); + for(i = 0; i < RARRAY_LEN(method_list); i++) { + mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, + mrb_ary_ref(mrb, method_list, i)); + os_memsize_of_method(mrb, method, t); + } +} + +static void +os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t) +{ + switch(obj.tt) { + case MRB_TT_STRING: + (*t) += RSTRING_LEN(obj); + break; + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_EXCEPTION: + case MRB_TT_SCLASS: + case MRB_TT_ICLASS: + case MRB_TT_OBJECT: { + os_memsize_of_ivars(mrb, obj, recurse, t); + if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { + os_memsize_of_method(mrb, obj, t); + } + else { + os_memsize_of_methods(mrb, obj, t); + } + break; + } + case MRB_TT_HASH: { + struct htable* htable = RHASH_TBL(obj); + /* Need htable & segment struct defs */ + break; + } + case MRB_TT_ARRAY: { + mrb_int len, i; + len = RARRAY_LEN(obj); + /* Arrays that do not fit within an RArray perform a heap allocation + * storing an array of pointers to the original objects*/ + if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; + + if(recurse) { + for(i = 0; i < len; i++) { + os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); + } + } + break; + } + case MRB_TT_PROC: { + struct RProc* proc = mrb_proc_ptr(obj); + (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); + if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + break; + } + case MRB_TT_DATA: + if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { + (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); + } + break; + #ifndef MRB_WITHOUT_FLOAT + case MRB_TT_FLOAT: + #ifdef MRB_WORD_BOXING + (*t) += sizeof(struct RFloat); + #endif + break; + #endif + case MRB_TT_RANGE: + #ifndef MRB_RANGE_EMBED + (*t) += sizeof(struct mrb_range_edges); + #endif + break; + case MRB_TT_FIBER: + struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); + (*t) += sizeof(struct mrb_context); + break; + /* zero heap size types. + * immediate VM stack values, contained within mrb_state, mrb_heap_page, + * or on C stack */ + case MRB_TT_TRUE: + case MRB_TT_FALSE: + case MRB_TT_FIXNUM: + case MRB_TT_BREAK: + case MRB_TT_CPTR: + case MRB_TT_SYMBOL: + case MRB_TT_FREE: + case MRB_TT_UNDEF: + case MRB_TT_ENV: + case MRB_TT_ISTRUCT: + /* never used, silences compiler warning + * not having a default: clause lets the compiler tell us when there is a new + * TT not accounted for */ + case MRB_TT_MAXDEFINE: + break; + } +} + +/* + * call-seq: + * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric + * + * Returns the amount of heap memory allocated for object in size_t units. + * Not all objects cause additional heap allocations beyond their object pointer + * in the heap page and may return 0. + * + * The return value depends on the definition of size_t on that platform, + * therefore the value is not comparable across platform types. + * + * Immediate values such as integers, booleans, symbols and unboxed float numbers + * return 0. Additionally special objects which are small enough to fit inside an + * object * pointer, termed embedded objects, also return 0. Strings and arrays + * below a compile-time defined size may be embedded. + * + * Setting recurse: true descends into instance variables, array members, + * and hash values recursively, calculating the child objects and adding to + * the final sum. + * + */ + +static mrb_value +os_memsize_of(mrb_state *mrb, mrb_value self) +{ + mrb_int total; + mrb_value obj; + mrb_bool recurse; + const char *kw_names[1] = { "recurse" }; + mrb_value kw_values[1]; + const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; + + mrb_get_args(mrb, "o:", &obj, &kwargs); + recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value()) ? TRUE : FALSE; + + total = 0; + os_memsize_of_object(mrb, obj, recurse, &total); + + return mrb_fixnum_value(total); +} + void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); } void diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index 9c44c2157..d26fd5a9e 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -1,3 +1,4 @@ +# coding: utf-8 assert('ObjectSpace.count_objects') do h = {} f = Fiber.new {} if Object.const_defined?(:Fiber) @@ -58,3 +59,78 @@ end assert 'Check class pointer of ObjectSpace.each_object.' do assert_nothing_raised { ObjectSpace.each_object { |obj| !obj } } end + +assert 'ObjectSpace.memsize_of' do + # immediate literals + int_size = ObjectSpace.memsize_of 1 + assert_equal int_size, 0, 'int zero' + + sym_size = ObjectSpace.memsize_of :foo + assert_equal sym_size, 0, 'sym zero' + + assert_equal ObjectSpace.memsize_of(true), int_size + assert_equal ObjectSpace.memsize_of(false), int_size + + float_size = if Object.const_defined? :Float + ObjectSpace.memsize_of 1.0 + else + nil + end + + # need some way of asking if floats are boxed + assert_equal float_size, 0 if float_size + + assert_not_equal ObjectSpace.memsize_of('a'), 0, 'memsize of str' + + if __ENCODING__ == "UTF-8" + assert_not_equal ObjectSpace.memsize_of("こんにちは世界"), 0, 'memsize of utf8 str' + end + + assert_not_equal ObjectSpace.memsize_of(0..1), 0, 'range not zero' + + # class defs + class_obj_size = ObjectSpace.memsize_of Class + assert_not_equal class_obj_size, 0, 'Class obj not zero' + + empty_class_def_size = ObjectSpace.memsize_of Class.new + + # need access to struct iv_tbl + # assert_not_equal empty_class_def_size, 0, 'Class def not zero' + + class_without_methods = Class.new do + @a = 1 + @b = 2 + end + class_total_size = empty_class_def_size + (int_size * 2) + assert_equal ObjectSpace.memsize_of(class_without_methods), class_total_size, 'class without methods size' + + module_without_methods = Module.new do + @a = 1 + @b = 2 + end + module_total_size = empty_class_def_size + (int_size * 2) + assert_equal ObjectSpace.memsize_of(module_without_methods), module_total_size, 'module without methods size' + + proc_size = ObjectSpace.memsize_of Proc.new { x = 1; x } + assert_not_equal proc_size, 0 + + class_with_methods = Class.new do + def foo + a = 0 + a + 1 + end + end + + m_size = ObjectSpace.memsize_of class_with_methods.instance_method(:foo) + assert_not_equal m_size, 0, 'method size not zero' + + # collections + assert_equal ObjectSpace.memsize_of([]), 0, 'empty array size zero' + assert_not_equal ObjectSpace.memsize_of(Array.new(16)), 0, 'array size non zero' + + # fiber + assert_not_equal ObjectSpace.memsize_of(Fiber.new {}), 0, 'fiber non zero' + + skip 'No hash table support yet' + assert_equal ObjectSpace.memsize_of({}), 0, 'empty hash size zero' +end -- cgit v1.2.3 From 37d662868807615a2b8f0f3e3939f592e2b43835 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 10 Jul 2020 00:57:45 -0700 Subject: fix case scopes and variable names --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index fe7e929c8..c0bc2b807 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -196,7 +196,7 @@ os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) if(recurse) { mrb_int r = (mrb_int)recurse; mrb_int *cb_data[2] = { &r, t }; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, t); + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, cb_data); } } @@ -261,8 +261,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_HASH: { - struct htable* htable = RHASH_TBL(obj); - /* Need htable & segment struct defs */ + /*struct htable* htable = RHASH_TBL(obj); + * Need htable & segment struct defs */ break; } case MRB_TT_ARRAY: { @@ -302,10 +302,11 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t (*t) += sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: - struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); + case MRB_TT_FIBER: { + /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ (*t) += sizeof(struct mrb_context); break; + } /* zero heap size types. * immediate VM stack values, contained within mrb_state, mrb_heap_page, * or on C stack */ -- cgit v1.2.3 From 308c6c8311dec0ff9add28af3665e6a7ef5a8c51 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 20:00:21 -0700 Subject: Need typedef of ssize_t for msc compiler --- mrbgems/mruby-io/src/io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 505ceb248..073f7c107 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -18,6 +18,7 @@ #if defined(_WIN32) || defined(_WIN64) #include #include + #include #define open _open #define close _close #define dup _dup @@ -32,6 +33,7 @@ typedef long fsuseconds_t; typedef int fmode_t; typedef int mrb_io_read_write_size; + typedef SSIZE_T ssize_t; #ifndef O_TMPFILE #define O_TMPFILE O_TEMPORARY -- cgit v1.2.3 From bb23faae65bc32779f9b9a60d717cef9299638b7 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 10 Jul 2020 21:06:29 -0700 Subject: downcase windows include file for mingw compatability --- mrbgems/mruby-io/src/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 073f7c107..0d7543578 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -18,7 +18,7 @@ #if defined(_WIN32) || defined(_WIN64) #include #include - #include + #include #define open _open #define close _close #define dup _dup -- cgit v1.2.3 From 5df95e8d7bd86911828d0e44473b599885cd6c15 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 12 Jul 2020 17:09:40 +0900 Subject: Fix `ssize_t` for mingw; ref #5030 Legacy MinGW and MinGW-w64 had own `ssize_t`. --- mrbgems/mruby-io/src/io.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 0d7543578..b3e192899 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -33,7 +33,10 @@ typedef long fsuseconds_t; typedef int fmode_t; typedef int mrb_io_read_write_size; + #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) && \ + !defined(__have_typedef_ssize_t) typedef SSIZE_T ssize_t; + #endif #ifndef O_TMPFILE #define O_TMPFILE O_TEMPORARY -- cgit v1.2.3 From 41e3220539ff0150bb09968b243ce6ed96b6fe0e Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:56:27 -0700 Subject: All values use page slot size in calculation --- include/mruby/gc.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 +++++++++++----- src/gc.c | 7 +++++++ 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'mrbgems') diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 4d9fb60eb..3b2ded9d4 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -21,6 +21,7 @@ struct mrb_state; #define MRB_EACH_OBJ_BREAK 1 typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); +const mrb_int mrb_objspace_page_slot_size(); MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); #ifndef MRB_GC_ARENA_SIZE diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index c0bc2b807..791bf68fe 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -251,6 +251,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_SCLASS: case MRB_TT_ICLASS: case MRB_TT_OBJECT: { + (*t) += mrb_objspace_page_slot_size(); os_memsize_of_ivars(mrb, obj, recurse, t); if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { os_memsize_of_method(mrb, obj, t); @@ -270,6 +271,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t len = RARRAY_LEN(obj); /* Arrays that do not fit within an RArray perform a heap allocation * storing an array of pointers to the original objects*/ + (*t) += mrb_objspace_page_slot_size(); if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; if(recurse) { @@ -280,12 +282,14 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_PROC: { + (*t) += mrb_objspace_page_slot_size(); struct RProc* proc = mrb_proc_ptr(obj); (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); break; } case MRB_TT_DATA: + (*t) += mrb_objspace_page_slot_size(); if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); } @@ -293,23 +297,25 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING - (*t) += sizeof(struct RFloat); + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct RFloat); #endif break; #endif case MRB_TT_RANGE: #ifndef MRB_RANGE_EMBED - (*t) += sizeof(struct mrb_range_edges); + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct mrb_range_edges); #endif break; case MRB_TT_FIBER: { /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ (*t) += sizeof(struct mrb_context); + case MRB_TT_ISTRUCT: + (*t) += mrb_objspace_page_slot_size(); break; - } /* zero heap size types. - * immediate VM stack values, contained within mrb_state, mrb_heap_page, - * or on C stack */ + * immediate VM stack values, contained within mrb_state, or on C stack */ case MRB_TT_TRUE: case MRB_TT_FALSE: case MRB_TT_FIXNUM: diff --git a/src/gc.c b/src/gc.c index e1892080f..fd4fb2406 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1599,6 +1599,13 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo } } +const mrb_int +mrb_objspace_page_slot_size() +{ + const mrb_int i = sizeof(RVALUE); + return i; +} + #ifdef GC_TEST #ifdef GC_DEBUG static mrb_value gc_test(mrb_state *, mrb_value); -- cgit v1.2.3 From e7bd7d0eaf677f62d86f27c2e9a917faa5a7d419 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:58:50 -0700 Subject: Use size of hash's table in calculation --- include/mruby/hash.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 9 ++++++--- src/hash.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'mrbgems') diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 0052a1105..cd53f6aeb 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -23,6 +23,7 @@ struct RHash { #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) +mrb_int os_memsize_of_hash_table(mrb_value obj); MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 791bf68fe..b0a3e0d89 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -262,8 +262,12 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_HASH: { - /*struct htable* htable = RHASH_TBL(obj); - * Need htable & segment struct defs */ + (*t) += mrb_objspace_page_slot_size() + + os_memsize_of_hash_table(obj); + if(recurse) { + os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); + os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); + } break; } case MRB_TT_ARRAY: { @@ -325,7 +329,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_FREE: case MRB_TT_UNDEF: case MRB_TT_ENV: - case MRB_TT_ISTRUCT: /* never used, silences compiler warning * not having a default: clause lets the compiler tell us when there is a new * TT not accounted for */ diff --git a/src/hash.c b/src/hash.c index 4d5310903..7c90758c0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -518,6 +518,20 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p) } } +mrb_int +os_memsize_of_hash_table(mrb_value obj) +{ + struct htable *h = mrb_hash_ptr(obj)->ht; + mrb_int segkv_size = 0; + + if(h->index) segkv_size = (sizeof(struct segkv) * h->index->capa); + + return sizeof(htable) + + sizeof(segindex) + + (sizeof(segment) * h->size) + + segkv_size; +} + /* Iterates over the hash table. */ MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p) -- cgit v1.2.3 From 6f945a09b4a09828667da6d4bad85b8ef50baf9c Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 15:59:24 -0700 Subject: Use object iv table size in calculation --- include/mruby/variable.h | 1 + mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- src/variable.c | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/include/mruby/variable.h b/include/mruby/variable.h index 6e918cf57..5559f6606 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -35,6 +35,7 @@ mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym); void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value); mrb_value mrb_vm_const_get(mrb_state*, mrb_sym); void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value); +mrb_int mrb_obj_iv_tbl_memsize(mrb_state*, mrb_value); MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b0a3e0d89..e48ac5b11 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -192,7 +192,7 @@ os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) static void os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) { - /* need iv segment table size */ + (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); if(recurse) { mrb_int r = (mrb_int)recurse; mrb_int *cb_data[2] = { &r, t }; diff --git a/src/variable.c b/src/variable.c index 030aa7b00..0755f7d92 100644 --- a/src/variable.c +++ b/src/variable.c @@ -4,6 +4,7 @@ ** See Copyright Notice in mruby.h */ +#include #include #include #include @@ -1128,6 +1129,14 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) return path; } +mrb_int +mrb_obj_iv_tbl_memsize(mrb_state* mrb, mrb_value obj) +{ + return sizeof(iv_tbl) + + (sizeof(segment) * ceil(iv_size(mrb, mrb_obj_ptr(obj)->iv)/ + MRB_IV_SEGMENT_SIZE)); +} + #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) mrb_bool -- cgit v1.2.3 From 5184263bdcdef9e467cf67b71be46368bc5409d2 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 16:00:14 -0700 Subject: Calculating sizes of VM components for a Fiber --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 27 ++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index e48ac5b11..0ffce2fbc 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -312,9 +312,30 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: { - /* struct RFiber* fiber = (struct RFiber*)mrb_ptr(obj); */ - (*t) += sizeof(struct mrb_context); + case MRB_TT_FIBER: + struct RFiber* f = (struct RFiber *)mrb_ptr(obj); + mrb_callinfo *ci_p = f->cxt->cibase; + ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; + ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; + mrb_int i = 0; + + while(ci_p < f->cxt->ciend) { + if(ci_p->proc) os_memsize_of_irep(mrb, ci_p->proc->body.irep, t); + ci_p++; + } + + for(i = 0; i <= f->cxt->esize; i++) { + os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + } + + (*t) += mrb_objspace_page_slot_size() + + sizeof(struct RFiber) + + sizeof(struct mrb_context) + + sizeof(struct RProc *) * f->cxt->esize + + sizeof(uint16_t *) * f->cxt->rsize + + stack_size + + ci_size; + break; case MRB_TT_ISTRUCT: (*t) += mrb_objspace_page_slot_size(); break; -- cgit v1.2.3 From 5759256ff8b7edbaeefa50b37404453afdd86a0b Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 16:00:49 -0700 Subject: Update tests for new calculations --- mrbgems/mruby-objectspace/test/objectspace.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index d26fd5a9e..60626e6bf 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -93,9 +93,7 @@ assert 'ObjectSpace.memsize_of' do assert_not_equal class_obj_size, 0, 'Class obj not zero' empty_class_def_size = ObjectSpace.memsize_of Class.new - - # need access to struct iv_tbl - # assert_not_equal empty_class_def_size, 0, 'Class def not zero' + assert_not_equal empty_class_def_size, 0, 'Class def not zero' class_without_methods = Class.new do @a = 1 @@ -125,12 +123,15 @@ assert 'ObjectSpace.memsize_of' do assert_not_equal m_size, 0, 'method size not zero' # collections - assert_equal ObjectSpace.memsize_of([]), 0, 'empty array size zero' - assert_not_equal ObjectSpace.memsize_of(Array.new(16)), 0, 'array size non zero' + assert_not_equal ObjectSpace.memsize_of([]), 0, 'empty array size not zero' + assert_not_equal ObjectSpace.memsize_of(Array.new(16)), 0, 'array size not zero' # fiber - assert_not_equal ObjectSpace.memsize_of(Fiber.new {}), 0, 'fiber non zero' + assert_not_equal ObjectSpace.memsize_of(Fiber.new {}), 0, 'fiber not zero' + + #hash + assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' + + # recursion - skip 'No hash table support yet' - assert_equal ObjectSpace.memsize_of({}), 0, 'empty hash size zero' end -- cgit v1.2.3 From ad4402159119d61d3a0b0a997b219bc1a0f4f196 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 16:43:59 -0700 Subject: C89 compiler mode fixes --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 0ffce2fbc..f28336b95 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -286,8 +286,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t break; } case MRB_TT_PROC: { - (*t) += mrb_objspace_page_slot_size(); struct RProc* proc = mrb_proc_ptr(obj); + (*t) += mrb_objspace_page_slot_size(); (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); break; @@ -312,7 +312,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t sizeof(struct mrb_range_edges); #endif break; - case MRB_TT_FIBER: + case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); mrb_callinfo *ci_p = f->cxt->cibase; ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; @@ -336,6 +336,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t stack_size + ci_size; break; + } case MRB_TT_ISTRUCT: (*t) += mrb_objspace_page_slot_size(); break; -- cgit v1.2.3 From 0e5394638bd6f8fa8c52fa4f75c4c1799adb70e0 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 13 Jul 2020 17:05:03 -0700 Subject: Validate ensure stack presense before calculating --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index f28336b95..d5ffa83f1 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -324,8 +324,10 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t ci_p++; } - for(i = 0; i <= f->cxt->esize; i++) { - os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + if(f->cxt->esize) { + for(i = 0; i <= f->cxt->esize; i++) { + os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + } } (*t) += mrb_objspace_page_slot_size() + -- cgit v1.2.3 From 49896a4d28f1fa054c95ccb7ec97c610fb75b3d2 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Tue, 14 Jul 2020 19:55:23 +0900 Subject: Fix `${build_dir}/mrbgems/gem_init.c` generation condition; ref #5010 The `${build_dir}/mrbgems/gem_init.c` generation condition has been changed at #5010, but it is somewhat insufficient, for example, there was a problem with `rake && rake test`, which was also regenerated in `rake test`. --- mrbgems/mruby-test/mrbgem.rake | 14 +------------- tasks/mrbgems.rake | 12 +++++++++++- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake index 97189a67b..ced252ae6 100644 --- a/mrbgems/mruby-test/mrbgem.rake +++ b/mrbgems/mruby-test/mrbgem.rake @@ -146,20 +146,8 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| end end - # store the last gem selection and make the re-build - # of the test gem depending on a change to the gem - # selection - active_gems_path = "#{build_dir}/active_gems_path.lst" - active_gem_list = File.read active_gems_path if File.exist? active_gems_path - current_gem_list = build.gems.map(&:name).join("\n") - task active_gems_path do |_t| - mkdir_p File.dirname(active_gems_path) - File.write active_gems_path, current_gem_list - end - file clib => active_gems_path if active_gem_list != current_gem_list - file mlib => clib - file clib => [build.mrbcfile, __FILE__] do |_t| + file clib => ["#{build.build_dir}/mrbgems/active_gems.txt", build.mrbcfile, __FILE__] do |_t| _pp "GEN", "*.rb", "#{clib.relative_path}" mkdir_p File.dirname(clib) open(clib, 'w') do |f| diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index c814a16db..0a3ae652d 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -5,9 +5,10 @@ MRuby.each_target do gems.check self # loader all gems + active_gems_txt = "#{build_dir}/mrbgems/active_gems.txt" self.libmruby_objs << objfile("#{build_dir}/mrbgems/gem_init") file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"] - file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__, *Dir.glob("#{build_dir}/mrbgems/mruby-*/*.c")] do |t| + file "#{build_dir}/mrbgems/gem_init.c" => [active_gems_txt, MRUBY_CONFIG, __FILE__] do |t| mkdir_p "#{build_dir}/mrbgems" open(t.name, 'w') do |f| gem_func_gems = gems.select { |g| g.generate_functions } @@ -49,6 +50,15 @@ MRuby.each_target do f.puts %Q[}] end end + file active_gems_txt => :generate_active_gems_txt + task :generate_active_gems_txt do |t| + def t.timestamp; Time.at(0) end + active_gems = gems.sort_by(&:name).inject(""){|s, g| s << "#{g.name}\n"} + if !File.exist?(active_gems_txt) || File.read(active_gems_txt) != active_gems + mkdir_p File.dirname(active_gems_txt) + File.write(active_gems_txt, active_gems) + end + end end # legal documents -- cgit v1.2.3 From 4d32c671a70cd066010cf502ab13ab8f78357d0e Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Tue, 14 Jul 2020 23:30:35 -0700 Subject: Finishing out memsize_of recursion --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 39 +++++++----- mrbgems/mruby-objectspace/test/objectspace.rb | 73 ++++++++++++++++++++++- 2 files changed, 93 insertions(+), 19 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d5ffa83f1..7088e166f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -176,27 +176,28 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static void os_memsize_of_object(mrb_state*,mrb_value,mrb_bool,mrb_int*); +static void os_memsize_of_object(mrb_state*,mrb_value,mrb_value,mrb_int*); + +struct os_memsize_cb_data { + mrb_int *t; + mrb_value recurse; +}; static int os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) { - mrb_int *cb_data = (mrb_int *)data; - mrb_int recurse = *(&cb_data[0]); - mrb_int* total = &cb_data[1]; - - os_memsize_of_object(mrb, obj, (mrb_bool)(recurse), total); + struct os_memsize_cb_data *cb_data = (struct os_memsize_cb_data *)(data); + os_memsize_of_object(mrb, obj, cb_data->recurse, cb_data->t); return 0; } static void -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int *t) +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int *t) { (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); - if(recurse) { - mrb_int r = (mrb_int)recurse; - mrb_int *cb_data[2] = { &r, t }; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, cb_data); + if(!mrb_nil_p(recurse)) { + struct os_memsize_cb_data cb_data = {t, recurse}; + mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, &cb_data); } } @@ -239,8 +240,14 @@ os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) } static void -os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t) +os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* t) { + if(!mrb_nil_p(recurse)) { + const mrb_value obj_id = mrb_fixnum_value(mrb_obj_id(obj)); + if(mrb_hash_key_p(mrb, recurse, obj_id)) return; + mrb_hash_set(mrb, recurse, obj_id, mrb_true_value()); + } + switch(obj.tt) { case MRB_TT_STRING: (*t) += RSTRING_LEN(obj); @@ -264,7 +271,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t case MRB_TT_HASH: { (*t) += mrb_objspace_page_slot_size() + os_memsize_of_hash_table(obj); - if(recurse) { + if(!mrb_nil_p(recurse)) { os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); } @@ -278,7 +285,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_bool recurse, mrb_int* t (*t) += mrb_objspace_page_slot_size(); if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; - if(recurse) { + if(!mrb_nil_p(recurse)) { for(i = 0; i < len; i++) { os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); } @@ -388,13 +395,13 @@ os_memsize_of(mrb_state *mrb, mrb_value self) { mrb_int total; mrb_value obj; - mrb_bool recurse; + mrb_value recurse; const char *kw_names[1] = { "recurse" }; mrb_value kw_values[1]; const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value()) ? TRUE : FALSE; + recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value())? mrb_hash_new(mrb) : mrb_nil_value(); total = 0; os_memsize_of_object(mrb, obj, recurse, &total); diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index 60626e6bf..610cdfbfa 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -123,15 +123,82 @@ assert 'ObjectSpace.memsize_of' do assert_not_equal m_size, 0, 'method size not zero' # collections - assert_not_equal ObjectSpace.memsize_of([]), 0, 'empty array size not zero' - assert_not_equal ObjectSpace.memsize_of(Array.new(16)), 0, 'array size not zero' + empty_array_size = ObjectSpace.memsize_of [] + assert_not_equal empty_array_size, 0, 'empty array size not zero' + assert_operator empty_array_size, :<, ObjectSpace.memsize_of(Array.new(16)), 'large array size greater than embed' # fiber - assert_not_equal ObjectSpace.memsize_of(Fiber.new {}), 0, 'fiber not zero' + empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) + assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' + assert_operator empty_fiber_size, :<, ObjectSpace.memsize_of(Fiber.new { yield; 1 }), 'Fiber code size growth' #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' # recursion + foo_str = 'foo' * 10 + bar_str = 'bar' * 10 + caz_str = 'caz' * 10 + fbc_ary = [foo_str, bar_str, caz_str] + assert_operator ObjectSpace.memsize_of(fbc_ary), + :<, + ObjectSpace.memsize_of(fbc_ary, recurse: true), + 'basic array recursion' + + big_ary = [ 'a' * 10, + [ 'b' * 10, + [ 'c' * 10, + [ 'd' * 10, + [ 'e' * 10, + [ 'f' * 10, + ['g' * 10] + ] * 10, + ] * 10, + ] * 10, + ] * 10, + ] * 10, + ] * 10 + assert_operator ObjectSpace.memsize_of(big_ary), + :<, + ObjectSpace.memsize_of(big_ary, recurse: true), + 'large array recursion' + + assert_nothing_raised 'infinite array recursion' do + ObjectSpace.memsize_of(fbc_ary.push(fbc_ary)) + end + + basic_hsh = {a: [foo_str, bar_str], b: caz_str, 'c' => {}} + assert_operator ObjectSpace.memsize_of(basic_hsh), + :<, + ObjectSpace.memsize_of(basic_hsh, recurse: true), + 'hash recursion with basic keys' + + weird_keys = {big_ary => foo_str} + assert_operator ObjectSpace.memsize_of(weird_keys), + :<, + ObjectSpace.memsize_of(weird_keys, recurse: true), + 'hash recursion with collection as key' + + basic_hsh.store('d', basic_hsh) + assert_nothing_raised 'hash value recursion' do + ObjectSpace.memsize_of basic_hsh, recurse: true + end + + foo_klass = Class.new do + def bar= b + @bar = b + end + end + fk_one = foo_klass.new + fk_one.bar = fbc_ary + assert_operator ObjectSpace.memsize_of(fk_one), + :<, + ObjectSpace.memsize_of(fk_one, recurse: true), + 'basic ivar recursion' + + fk_one.bar = fk_one + assert_nothing_raised 'ivar infinite recursion' do + ObjectSpace.memsize_of(fk_one, recurse: true) + end end -- cgit v1.2.3 From 38b0759108882c4d791cc4cf1a5989fb8e5d533d Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Tue, 14 Jul 2020 23:43:10 -0700 Subject: Clarify memsize_of documentation --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 7088e166f..9fbfd0d54 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -373,20 +373,24 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric * * Returns the amount of heap memory allocated for object in size_t units. - * Not all objects cause additional heap allocations beyond their object pointer - * in the heap page and may return 0. * * The return value depends on the definition of size_t on that platform, * therefore the value is not comparable across platform types. * * Immediate values such as integers, booleans, symbols and unboxed float numbers * return 0. Additionally special objects which are small enough to fit inside an - * object * pointer, termed embedded objects, also return 0. Strings and arrays - * below a compile-time defined size may be embedded. + * object pointer, termed embedded objects, will return the size of the object pointer. + * Strings and arrays below a compile-time defined size may be embedded. * * Setting recurse: true descends into instance variables, array members, - * and hash values recursively, calculating the child objects and adding to - * the final sum. + * hash keys and hash values recursively, calculating the child objects and adding to + * the final sum. It avoids infinite recursion and over counting objects by + * internally tracking discovered object ids. + * + * MRB_TT_DATA objects aren't calculated beyond their original page slot. However, + * if the object implements a memsize method it will call that method and add the + * return value to the total. This provides an opportunity for C based data structures + * to report their memory usage. * */ -- cgit v1.2.3 From f74d370c1574fba53330c032ec6ac4716fee4a07 Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Wed, 15 Jul 2020 19:57:22 -0700 Subject: mrb_ prefix convention --- include/mruby/hash.h | 2 +- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- src/hash.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'mrbgems') diff --git a/include/mruby/hash.h b/include/mruby/hash.h index cd53f6aeb..04b265ec3 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -23,7 +23,7 @@ struct RHash { #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) -mrb_int os_memsize_of_hash_table(mrb_value obj); +mrb_int mrb_os_memsize_of_hash_table(mrb_value obj); MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9fbfd0d54..7892c6a1b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -270,7 +270,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* } case MRB_TT_HASH: { (*t) += mrb_objspace_page_slot_size() + - os_memsize_of_hash_table(obj); + mrb_os_memsize_of_hash_table(obj); if(!mrb_nil_p(recurse)) { os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); diff --git a/src/hash.c b/src/hash.c index 7c90758c0..79b61d8b2 100644 --- a/src/hash.c +++ b/src/hash.c @@ -519,7 +519,7 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p) } mrb_int -os_memsize_of_hash_table(mrb_value obj) +mrb_os_memsize_of_hash_table(mrb_value obj) { struct htable *h = mrb_hash_ptr(obj)->ht; mrb_int segkv_size = 0; -- cgit v1.2.3 From 7f66cf7d66f71d729f9ad1b129d9d817c075b979 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:51:01 +0900 Subject: Fix `memsize_of` for string objects; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 7892c6a1b..a9469203f 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -250,7 +250,10 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* switch(obj.tt) { case MRB_TT_STRING: - (*t) += RSTRING_LEN(obj); + (*t) += mrb_objspace_page_slot_size(); + if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { + (*t) += RSTRING_CAPA(obj); + } break; case MRB_TT_CLASS: case MRB_TT_MODULE: -- cgit v1.2.3 From c6b8b58e0e1ad8a06e28d97bcc5860a14246537b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:52:04 +0900 Subject: Fix `memsize_of` for fiber objects; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index a9469203f..a67697d0d 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -345,8 +345,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* sizeof(struct mrb_context) + sizeof(struct RProc *) * f->cxt->esize + sizeof(uint16_t *) * f->cxt->rsize + - stack_size + - ci_size; + sizeof(mrb_value) * stack_size + + sizeof(mrb_callinfo) * ci_size; break; } case MRB_TT_ISTRUCT: -- cgit v1.2.3 From 60279b2a8ed3f1c802371ecb2450da63e78316bc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:53:24 +0900 Subject: Use `mrb_test` instead of `mrb_obj_eq`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index a67697d0d..8892f40dc 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -408,7 +408,7 @@ os_memsize_of(mrb_state *mrb, mrb_value self) const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = mrb_obj_eq(mrb, kw_values[0], mrb_true_value())? mrb_hash_new(mrb) : mrb_nil_value(); + recurse = (!mrb_undef_p(kw_values[0]) && mrb_test(kw_values[0]))? mrb_hash_new(mrb) : mrb_nil_value(); total = 0; os_memsize_of_object(mrb, obj, recurse, &total); -- cgit v1.2.3 From 2e56da5a78befb93a1e4debe42d783c4b7be4c30 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 10:59:43 +0900 Subject: Remove `MRB_TT_DATA` calculation of `memsize_of`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 8892f40dc..971f81c97 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -304,9 +304,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* } case MRB_TT_DATA: (*t) += mrb_objspace_page_slot_size(); - if(mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "memsize"))) { - (*t) += mrb_fixnum(mrb_funcall(mrb, obj, "memsize", 0)); - } break; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: @@ -390,11 +387,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* * the final sum. It avoids infinite recursion and over counting objects by * internally tracking discovered object ids. * - * MRB_TT_DATA objects aren't calculated beyond their original page slot. However, - * if the object implements a memsize method it will call that method and add the - * return value to the total. This provides an opportunity for C based data structures - * to report their memory usage. - * */ static mrb_value -- cgit v1.2.3 From f00657ead7c3e5f6f9a346d7797a280b5c9f02fa Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 11:15:07 +0900 Subject: Remove recursive `memsize_of`; #5032 This is enhancement from CRuby's `memsize_of`. We need to change the CRuby first for the enhancement. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 134 ++++++++-------------- mrbgems/mruby-objectspace/test/objectspace.rb | 69 +---------- 2 files changed, 51 insertions(+), 152 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 971f81c97..71a7e1b8b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -176,83 +176,66 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static void os_memsize_of_object(mrb_state*,mrb_value,mrb_value,mrb_int*); - -struct os_memsize_cb_data { - mrb_int *t; - mrb_value recurse; -}; - -static int -os_memsize_ivar_cb(mrb_state *mrb, mrb_sym _name, mrb_value obj, void *data) +static mrb_int +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) { - struct os_memsize_cb_data *cb_data = (struct os_memsize_cb_data *)(data); - os_memsize_of_object(mrb, obj, cb_data->recurse, cb_data->t); - return 0; -} - -static void -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int *t) -{ - (*t) += mrb_obj_iv_tbl_memsize(mrb, obj); - if(!mrb_nil_p(recurse)) { - struct os_memsize_cb_data cb_data = {t, recurse}; - mrb_iv_foreach(mrb, obj, os_memsize_ivar_cb, &cb_data); - } + return mrb_obj_iv_tbl_memsize(mrb, obj); } -static void -os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep, mrb_int* t) +static mrb_int +os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep) { - mrb_int i; - (*t) += (irep->slen * sizeof(mrb_sym)) + - (irep->plen * sizeof(mrb_code)) + - (irep->ilen * sizeof(mrb_code)); + mrb_int size, i; + size = (irep->slen * sizeof(mrb_sym)) + + (irep->plen * sizeof(mrb_code)) + + (irep->ilen * sizeof(mrb_code)); for(i = 0; i < irep->rlen; i++) { - os_memsize_of_irep(state, irep->reps[i], t); + size += os_memsize_of_irep(state, irep->reps[i]); } + return size; } -static void -os_memsize_of_method(mrb_state* mrb, mrb_value method_obj, mrb_int* t) +static mrb_int +os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) { + mrb_int size; mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), mrb_intern_lit(mrb, "_proc")); struct RProc *proc = mrb_proc_ptr(proc_value); - (*t) += sizeof(struct RProc); - if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + size = sizeof(struct RProc); + if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); + return size; } -static void -os_memsize_of_methods(mrb_state* mrb, mrb_value obj, mrb_int* t) +static mrb_int +os_memsize_of_methods(mrb_state* mrb, mrb_value obj) { mrb_value method_list; + mrb_int size = 0; mrb_int i; - if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return; + + if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return 0; method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); for(i = 0; i < RARRAY_LEN(method_list); i++) { mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, mrb_ary_ref(mrb, method_list, i)); - os_memsize_of_method(mrb, method, t); + size += os_memsize_of_method(mrb, method); } + return size; } -static void -os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* t) +static mrb_int +os_memsize_of_object(mrb_state* mrb, mrb_value obj) { - if(!mrb_nil_p(recurse)) { - const mrb_value obj_id = mrb_fixnum_value(mrb_obj_id(obj)); - if(mrb_hash_key_p(mrb, recurse, obj_id)) return; - mrb_hash_set(mrb, recurse, obj_id, mrb_true_value()); - } + mrb_int size = 0; switch(obj.tt) { case MRB_TT_STRING: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { - (*t) += RSTRING_CAPA(obj); + size += RSTRING_CAPA(obj); } break; case MRB_TT_CLASS: @@ -261,61 +244,50 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* case MRB_TT_SCLASS: case MRB_TT_ICLASS: case MRB_TT_OBJECT: { - (*t) += mrb_objspace_page_slot_size(); - os_memsize_of_ivars(mrb, obj, recurse, t); + size += mrb_objspace_page_slot_size(); + size += os_memsize_of_ivars(mrb, obj); if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { - os_memsize_of_method(mrb, obj, t); + size += os_memsize_of_method(mrb, obj); } else { - os_memsize_of_methods(mrb, obj, t); + size += os_memsize_of_methods(mrb, obj); } break; } case MRB_TT_HASH: { - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + mrb_os_memsize_of_hash_table(obj); - if(!mrb_nil_p(recurse)) { - os_memsize_of_object(mrb, mrb_hash_keys(mrb, obj), recurse, t); - os_memsize_of_object(mrb, mrb_hash_values(mrb, obj), recurse, t); - } break; } case MRB_TT_ARRAY: { - mrb_int len, i; - len = RARRAY_LEN(obj); + mrb_int len = RARRAY_LEN(obj); /* Arrays that do not fit within an RArray perform a heap allocation * storing an array of pointers to the original objects*/ - (*t) += mrb_objspace_page_slot_size(); - if(len > MRB_ARY_EMBED_LEN_MAX) (*t) += sizeof(mrb_value *) * len; - - if(!mrb_nil_p(recurse)) { - for(i = 0; i < len; i++) { - os_memsize_of_object(mrb, ARY_PTR(mrb_ary_ptr(obj))[i], recurse, t); - } - } + size += mrb_objspace_page_slot_size(); + if(len > MRB_ARY_EMBED_LEN_MAX) size += sizeof(mrb_value *) * len; break; } case MRB_TT_PROC: { struct RProc* proc = mrb_proc_ptr(obj); - (*t) += mrb_objspace_page_slot_size(); - (*t) += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); - if(!MRB_PROC_CFUNC_P(proc)) os_memsize_of_irep(mrb, proc->body.irep, t); + size += mrb_objspace_page_slot_size(); + size += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); + if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); break; } case MRB_TT_DATA: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); break; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct RFloat); #endif break; #endif case MRB_TT_RANGE: #ifndef MRB_RANGE_EMBED - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct mrb_range_edges); #endif break; @@ -327,17 +299,17 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* mrb_int i = 0; while(ci_p < f->cxt->ciend) { - if(ci_p->proc) os_memsize_of_irep(mrb, ci_p->proc->body.irep, t); + if(ci_p->proc) size += os_memsize_of_irep(mrb, ci_p->proc->body.irep); ci_p++; } if(f->cxt->esize) { for(i = 0; i <= f->cxt->esize; i++) { - os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep, t); + size += os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep); } } - (*t) += mrb_objspace_page_slot_size() + + size += mrb_objspace_page_slot_size() + sizeof(struct RFiber) + sizeof(struct mrb_context) + sizeof(struct RProc *) * f->cxt->esize + @@ -347,7 +319,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* break; } case MRB_TT_ISTRUCT: - (*t) += mrb_objspace_page_slot_size(); + size += mrb_objspace_page_slot_size(); break; /* zero heap size types. * immediate VM stack values, contained within mrb_state, or on C stack */ @@ -366,6 +338,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj, mrb_value recurse, mrb_int* case MRB_TT_MAXDEFINE: break; } + return size; } /* @@ -394,17 +367,10 @@ os_memsize_of(mrb_state *mrb, mrb_value self) { mrb_int total; mrb_value obj; - mrb_value recurse; - const char *kw_names[1] = { "recurse" }; - mrb_value kw_values[1]; - const mrb_kwargs kwargs = { 1, kw_values, kw_names, 0, NULL }; - - mrb_get_args(mrb, "o:", &obj, &kwargs); - recurse = (!mrb_undef_p(kw_values[0]) && mrb_test(kw_values[0]))? mrb_hash_new(mrb) : mrb_nil_value(); - total = 0; - os_memsize_of_object(mrb, obj, recurse, &total); + mrb_get_args(mrb, "o", &obj); + total = os_memsize_of_object(mrb, obj); return mrb_fixnum_value(total); } diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index 610cdfbfa..c8f0c4d24 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -1,4 +1,4 @@ -# coding: utf-8 +# coding: cp932 assert('ObjectSpace.count_objects') do h = {} f = Fiber.new {} if Object.const_defined?(:Fiber) @@ -134,71 +134,4 @@ assert 'ObjectSpace.memsize_of' do #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' - - # recursion - foo_str = 'foo' * 10 - bar_str = 'bar' * 10 - caz_str = 'caz' * 10 - fbc_ary = [foo_str, bar_str, caz_str] - assert_operator ObjectSpace.memsize_of(fbc_ary), - :<, - ObjectSpace.memsize_of(fbc_ary, recurse: true), - 'basic array recursion' - - big_ary = [ 'a' * 10, - [ 'b' * 10, - [ 'c' * 10, - [ 'd' * 10, - [ 'e' * 10, - [ 'f' * 10, - ['g' * 10] - ] * 10, - ] * 10, - ] * 10, - ] * 10, - ] * 10, - ] * 10 - assert_operator ObjectSpace.memsize_of(big_ary), - :<, - ObjectSpace.memsize_of(big_ary, recurse: true), - 'large array recursion' - - assert_nothing_raised 'infinite array recursion' do - ObjectSpace.memsize_of(fbc_ary.push(fbc_ary)) - end - - basic_hsh = {a: [foo_str, bar_str], b: caz_str, 'c' => {}} - assert_operator ObjectSpace.memsize_of(basic_hsh), - :<, - ObjectSpace.memsize_of(basic_hsh, recurse: true), - 'hash recursion with basic keys' - - weird_keys = {big_ary => foo_str} - assert_operator ObjectSpace.memsize_of(weird_keys), - :<, - ObjectSpace.memsize_of(weird_keys, recurse: true), - 'hash recursion with collection as key' - - basic_hsh.store('d', basic_hsh) - assert_nothing_raised 'hash value recursion' do - ObjectSpace.memsize_of basic_hsh, recurse: true - end - - foo_klass = Class.new do - def bar= b - @bar = b - end - end - - fk_one = foo_klass.new - fk_one.bar = fbc_ary - assert_operator ObjectSpace.memsize_of(fk_one), - :<, - ObjectSpace.memsize_of(fk_one, recurse: true), - 'basic ivar recursion' - - fk_one.bar = fk_one - assert_nothing_raised 'ivar infinite recursion' do - ObjectSpace.memsize_of(fk_one, recurse: true) - end end -- cgit v1.2.3 From a2b8c08a52867190ea90ba8076a296b368470200 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 09:42:17 +0900 Subject: Add `const` to `irep` pointer in `os_memsize_of_irep`; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 71a7e1b8b..6ac1ab51b 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -183,7 +183,7 @@ os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) } static mrb_int -os_memsize_of_irep(mrb_state* state, struct mrb_irep *irep) +os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep) { mrb_int size, i; size = (irep->slen * sizeof(mrb_sym)) + -- cgit v1.2.3 From 9f52bcfca9c23cba27f0ff50dacb1704057e1042 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 11:50:12 +0900 Subject: Fix `memsize_of` Fibers; #5032 Memory size of a Fiber is calculated by stack size only in CRuby. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 13 ------------- mrbgems/mruby-objectspace/test/objectspace.rb | 1 - 2 files changed, 14 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6ac1ab51b..9ad7ee619 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -293,21 +293,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) break; case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); - mrb_callinfo *ci_p = f->cxt->cibase; ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; - mrb_int i = 0; - - while(ci_p < f->cxt->ciend) { - if(ci_p->proc) size += os_memsize_of_irep(mrb, ci_p->proc->body.irep); - ci_p++; - } - - if(f->cxt->esize) { - for(i = 0; i <= f->cxt->esize; i++) { - size += os_memsize_of_irep(mrb, f->cxt->ensure[i]->body.irep); - } - } size += mrb_objspace_page_slot_size() + sizeof(struct RFiber) + diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index c8f0c4d24..d029a2f43 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -130,7 +130,6 @@ assert 'ObjectSpace.memsize_of' do # fiber empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' - assert_operator empty_fiber_size, :<, ObjectSpace.memsize_of(Fiber.new { yield; 1 }), 'Fiber code size growth' #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' -- cgit v1.2.3 From 495c1a377a63f0f56916c478f616eeb667bb3811 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 12:31:00 +0900 Subject: Fix `memsize_of` to count method table size; #5032 Also avoid `mrb_funcall` to minimize VM recursion. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 29 +++++------------------ 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9ad7ee619..d46c5c2d1 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -205,24 +205,7 @@ os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) struct RProc *proc = mrb_proc_ptr(proc_value); size = sizeof(struct RProc); - if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - return size; -} - -static mrb_int -os_memsize_of_methods(mrb_state* mrb, mrb_value obj) -{ - mrb_value method_list; - mrb_int size = 0; - mrb_int i; - - if(!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "instance_methods"))) return 0; - method_list = mrb_funcall(mrb, obj, "instance_methods", 1, mrb_false_value()); - for(i = 0; i < RARRAY_LEN(method_list); i++) { - mrb_value method = mrb_funcall(mrb, obj, "instance_method", 1, - mrb_ary_ref(mrb, method_list, i)); - size += os_memsize_of_method(mrb, method); - } + if (!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); return size; } @@ -240,18 +223,18 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) break; case MRB_TT_CLASS: case MRB_TT_MODULE: - case MRB_TT_EXCEPTION: case MRB_TT_SCLASS: case MRB_TT_ICLASS: + size += mrb_gc_mark_mt_size(mrb, mrb_class_ptr(obj)) * sizeof(mrb_method_t); + /* fall through */ + case MRB_TT_EXCEPTION: case MRB_TT_OBJECT: { size += mrb_objspace_page_slot_size(); size += os_memsize_of_ivars(mrb, obj); - if(mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod"))) { + if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || + mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ size += os_memsize_of_method(mrb, obj); } - else { - size += os_memsize_of_methods(mrb, obj); - } break; } case MRB_TT_HASH: { -- cgit v1.2.3 From e41f1f5139ef03dac2bd1c0b9a7a4143ddf07f59 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 12:32:54 +0900 Subject: Fix indent of compiler conditions; #5032 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d46c5c2d1..9ac75c710 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -260,19 +260,19 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) case MRB_TT_DATA: size += mrb_objspace_page_slot_size(); break; - #ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: - #ifdef MRB_WORD_BOXING +#ifdef MRB_WORD_BOXING size += mrb_objspace_page_slot_size() + sizeof(struct RFloat); - #endif +#endif break; - #endif +#endif case MRB_TT_RANGE: - #ifndef MRB_RANGE_EMBED +#ifndef MRB_RANGE_EMBED size += mrb_objspace_page_slot_size() + sizeof(struct mrb_range_edges); - #endif +#endif break; case MRB_TT_FIBER: { struct RFiber* f = (struct RFiber *)mrb_ptr(obj); -- cgit v1.2.3 From fe1ec9afdd1dbfd579efe5c9823f554e26d75a2d Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 17 Jul 2020 20:09:44 -0700 Subject: Add ObjectSpace.memsize_of_all --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 25 +++++++++++++++++++++++ mrbgems/mruby-objectspace/test/objectspace.rb | 15 +++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 9ac75c710..6da2a4104 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -344,6 +344,30 @@ os_memsize_of(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(total); } +struct os_memsize_of_all_cb_data { + mrb_int t; + struct RClass *type; +}; + +static int +os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) +{ + struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; + if(obj->c == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + return 0; +} + +static mrb_value +os_memsize_of_all(mrb_state *mrb, mrb_value self) +{ + mrb_value type; + struct os_memsize_of_all_cb_data data = { 0 }; + mrb_get_args(mrb, "C", &type); + data.type = mrb_class_ptr(type); + mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); + return mrb_fixnum_value(data.t); +} + void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { @@ -351,6 +375,7 @@ mrb_mruby_objectspace_gem_init(mrb_state *mrb) mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_REQ(1)); } void diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index d029a2f43..e5783b942 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -1,4 +1,3 @@ -# coding: cp932 assert('ObjectSpace.count_objects') do h = {} f = Fiber.new {} if Object.const_defined?(:Fiber) @@ -134,3 +133,17 @@ assert 'ObjectSpace.memsize_of' do #hash assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' end + +assert 'ObjectSpace.memsize_of_all' do + foo_class = Class.new do + def initialize + @a = 'a' + @b = 'b' + end + end + + foos = Array.new(10) { foo_class.new } + foo_size = ObjectSpace.memsize_of(foos.first) + + assert_equal ObjectSpace.memsize_of_all(foo_class), foo_size * foos.size, 'Memsize of all instance' +end -- cgit v1.2.3 From a79d1ba9ffe4d3c2c092f118c68ca8a0e311af0b Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Fri, 17 Jul 2020 20:21:23 -0700 Subject: Adding memsize_of_all doc --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6da2a4104..f5cc7b753 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -357,6 +357,14 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) return 0; } +/* + * call-seq: + * ObjectSpace.memsize_of_all([klass]) -> Numeric + * + * Return consuming memory size of all living objects of type klass. + * + */ + static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { -- cgit v1.2.3 From ffe8bf6323a6fd9a0b68b3e84745ccc820b2bc49 Mon Sep 17 00:00:00 2001 From: Rory O'Connell <19547+RoryO@users.noreply.github.com> Date: Sat, 18 Jul 2020 13:55:45 -0700 Subject: Avoid singleton classes with mrb_class_real --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index f5cc7b753..b3e8605d7 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,7 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(obj->c == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + if(mrb_class_real(obj->c) == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } -- cgit v1.2.3 From 6d073f8d99f6b4cbc1549f02298a785aba9b9a7a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 06:57:34 +0900 Subject: Fix `memsize_of_all` to count memory of subclass instances; #5040 `ObjectSpace.memsize_of_all` takes a class and count memory size of all instances of the class and its subclasses (if any). --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b3e8605d7..6ae030dff 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,8 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(mrb_class_real(obj->c) == data->type) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + if(mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) + data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } -- cgit v1.2.3 From 5b2763821e1be3709fd70d732ad1ed6c343f649f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 07:42:35 +0900 Subject: Fix `memsize_of_all` to count all objects if no argument given; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6ae030dff..b02e01919 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,17 @@ static int os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) { struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - if(mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) + switch (obj->tt) { + case MRB_TT_FREE: case MRB_TT_ENV: + case MRB_TT_BREAK: case MRB_TT_ICLASS: + /* internal objects that should not be counted */ + return 0; + default: + break; + } + /* skip Proc objects for methods */ + if (obj->c == NULL) return 0; + if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); return 0; } @@ -369,9 +379,9 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { - mrb_value type; + mrb_value type = mrb_nil_value(); struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "C", &type); + mrb_get_args(mrb, "|C", &type); data.type = mrb_class_ptr(type); mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); return mrb_fixnum_value(data.t); -- cgit v1.2.3 From f76defd310c03ace8750abec22938ed3427fceee Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 07:47:07 +0900 Subject: Use `c` specifier for `mrb_get_args`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 12 +++--------- src/class.c | 12 ++++++------ src/kernel.c | 12 ++++++------ 3 files changed, 15 insertions(+), 21 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index b02e01919..16c520732 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -166,12 +166,8 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) static mrb_value os_each_object(mrb_state *mrb, mrb_value self) { - mrb_value cls = mrb_nil_value(); - struct os_each_object_data d; - mrb_get_args(mrb, "&!|C", &d.block, &cls); - - d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls); - d.count = 0; + struct os_each_object_data d = {0}; + mrb_get_args(mrb, "&!|c", &d.block, &d.target_module); mrb_objspace_each_objects(mrb, os_each_object_cb, &d); return mrb_fixnum_value(d.count); } @@ -379,10 +375,8 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) static mrb_value os_memsize_of_all(mrb_state *mrb, mrb_value self) { - mrb_value type = mrb_nil_value(); struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "|C", &type); - data.type = mrb_class_ptr(type); + mrb_get_args(mrb, "|c", &data.type); mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); return mrb_fixnum_value(data.t); } diff --git a/src/class.c b/src/class.c index 30dc4c17a..fc8a38ff9 100644 --- a/src/class.c +++ b/src/class.c @@ -1168,22 +1168,22 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) static mrb_value mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_prepend_module(mrb, c, mrb_class_ptr(mod)); return mod; } static mrb_value mrb_mod_append_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_include_module(mrb, c, mrb_class_ptr(mod)); return mod; } diff --git a/src/kernel.c b/src/kernel.c index a74f8a8ed..682feb13c 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -520,11 +520,11 @@ mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) static mrb_value obj_is_instance_of(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, c)); } /* 15.3.1.3.24 */ @@ -557,11 +557,11 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c)); } KHASH_DECLARE(st, mrb_sym, char, FALSE) -- cgit v1.2.3 From 00337543a5baf0e2cbedd65a697710a557b72041 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 09:11:16 +0900 Subject: Should have updated the arg spec for `memsize_of`&`memsize_of_all`; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 16c520732..d8ce19e82 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -387,8 +387,8 @@ mrb_mruby_objectspace_gem_init(mrb_state *mrb) struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_OPT(1)); } void -- cgit v1.2.3 From 1d2c5c12d373751835097d95e34924a005334cd2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:10:08 +0900 Subject: Reorder members of `struct os_each_object_data` to stop warnings. `mrb_value` may or may not be struct according to configuration. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index d8ce19e82..1b293f019 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -112,9 +112,9 @@ os_count_objects(mrb_state *mrb, mrb_value self) } struct os_each_object_data { - mrb_value block; struct RClass *target_module; mrb_int count; + mrb_value block; }; static int -- cgit v1.2.3 From 71254be076eb25b77840276c910f1b6f43c3bd17 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:11:53 +0900 Subject: Skip `MRB_TT_FREE` and `MRB_TT_BREAK` in `each_object`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 1b293f019..5febe6e3e 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -129,8 +129,8 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) /* filter internal objects */ switch (obj->tt) { - case MRB_TT_ENV: - case MRB_TT_ICLASS: + case MRB_TT_FREE: case MRB_TT_ENV: + case MRB_TT_BREAK: case MRB_TT_ICLASS: return MRB_EACH_OBJ_OK; default: break; -- cgit v1.2.3 From 07b75d927e1e97ad4fe3dd2288ea07343b9a84ee Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 13:15:01 +0900 Subject: Replace 0 by `MRB_EACH_OBJ_OK`; #5040 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 5febe6e3e..4a3b38cee 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -353,7 +353,7 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) case MRB_TT_FREE: case MRB_TT_ENV: case MRB_TT_BREAK: case MRB_TT_ICLASS: /* internal objects that should not be counted */ - return 0; + return MRB_EACH_OBJ_OK; default: break; } @@ -361,7 +361,7 @@ os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) if (obj->c == NULL) return 0; if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); - return 0; + return MRB_EACH_OBJ_OK; } /* -- cgit v1.2.3 From a6f31ad6ce29ab07a2f96f678f66e7923f765642 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 22:41:09 +0900 Subject: Avoid accessing `obj.tt` of `mrb_value`; #5040 The old code compiles only on `MRB_NO_BOXING`. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 4a3b38cee..6804a99ae 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -210,7 +210,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) { mrb_int size = 0; - switch(obj.tt) { + switch(mrb_type(obj)) { case MRB_TT_STRING: size += mrb_objspace_page_slot_size(); if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { -- cgit v1.2.3 From c9ea39843b7fe0aa7a9c110e9140ca3eccb26023 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 22:47:22 +0900 Subject: Remove some tests from `mruby-objectspace` gem; #5040 Those tests succeeds only on some configuration. --- mrbgems/mruby-objectspace/test/objectspace.rb | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index e5783b942..aa7c7dbbf 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -70,23 +70,12 @@ assert 'ObjectSpace.memsize_of' do assert_equal ObjectSpace.memsize_of(true), int_size assert_equal ObjectSpace.memsize_of(false), int_size - float_size = if Object.const_defined? :Float - ObjectSpace.memsize_of 1.0 - else - nil - end - - # need some way of asking if floats are boxed - assert_equal float_size, 0 if float_size - assert_not_equal ObjectSpace.memsize_of('a'), 0, 'memsize of str' if __ENCODING__ == "UTF-8" assert_not_equal ObjectSpace.memsize_of("こんにちは世界"), 0, 'memsize of utf8 str' end - assert_not_equal ObjectSpace.memsize_of(0..1), 0, 'range not zero' - # class defs class_obj_size = ObjectSpace.memsize_of Class assert_not_equal class_obj_size, 0, 'Class obj not zero' -- cgit v1.2.3 From 5f4a27217ea81ac3dd65f39cc3560dc019fe83a6 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 19 Jul 2020 15:36:08 -0700 Subject: Separate `memsize_of` and `memsize_of_all` to a separate gem; #5040 Those methods are originally CRuby specific. Co-authored-by: Yukihiro "Matz" Matsumoto --- mrbgems/mruby-objectspace/mrbgem.rake | 4 - mrbgems/mruby-objectspace/test/objectspace.rb | 78 --------- mrbgems/mruby-os-memsize/mrbgem.rake | 10 ++ mrbgems/mruby-os-memsize/src/memsize.c | 234 ++++++++++++++++++++++++++ mrbgems/mruby-os-memsize/test/memsize.rb | 77 +++++++++ 5 files changed, 321 insertions(+), 82 deletions(-) create mode 100644 mrbgems/mruby-os-memsize/mrbgem.rake create mode 100644 mrbgems/mruby-os-memsize/src/memsize.c create mode 100644 mrbgems/mruby-os-memsize/test/memsize.rb (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/mrbgem.rake b/mrbgems/mruby-objectspace/mrbgem.rake index 101e24275..fa35136a1 100644 --- a/mrbgems/mruby-objectspace/mrbgem.rake +++ b/mrbgems/mruby-objectspace/mrbgem.rake @@ -2,8 +2,4 @@ MRuby::Gem::Specification.new('mruby-objectspace') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' spec.summary = 'ObjectSpace class' - - spec.add_test_dependency('mruby-metaprog') - spec.add_test_dependency('mruby-method') - spec.add_test_dependency('mruby-fiber') end diff --git a/mrbgems/mruby-objectspace/test/objectspace.rb b/mrbgems/mruby-objectspace/test/objectspace.rb index aa7c7dbbf..9c44c2157 100644 --- a/mrbgems/mruby-objectspace/test/objectspace.rb +++ b/mrbgems/mruby-objectspace/test/objectspace.rb @@ -58,81 +58,3 @@ end assert 'Check class pointer of ObjectSpace.each_object.' do assert_nothing_raised { ObjectSpace.each_object { |obj| !obj } } end - -assert 'ObjectSpace.memsize_of' do - # immediate literals - int_size = ObjectSpace.memsize_of 1 - assert_equal int_size, 0, 'int zero' - - sym_size = ObjectSpace.memsize_of :foo - assert_equal sym_size, 0, 'sym zero' - - assert_equal ObjectSpace.memsize_of(true), int_size - assert_equal ObjectSpace.memsize_of(false), int_size - - assert_not_equal ObjectSpace.memsize_of('a'), 0, 'memsize of str' - - if __ENCODING__ == "UTF-8" - assert_not_equal ObjectSpace.memsize_of("こんにちは世界"), 0, 'memsize of utf8 str' - end - - # class defs - class_obj_size = ObjectSpace.memsize_of Class - assert_not_equal class_obj_size, 0, 'Class obj not zero' - - empty_class_def_size = ObjectSpace.memsize_of Class.new - assert_not_equal empty_class_def_size, 0, 'Class def not zero' - - class_without_methods = Class.new do - @a = 1 - @b = 2 - end - class_total_size = empty_class_def_size + (int_size * 2) - assert_equal ObjectSpace.memsize_of(class_without_methods), class_total_size, 'class without methods size' - - module_without_methods = Module.new do - @a = 1 - @b = 2 - end - module_total_size = empty_class_def_size + (int_size * 2) - assert_equal ObjectSpace.memsize_of(module_without_methods), module_total_size, 'module without methods size' - - proc_size = ObjectSpace.memsize_of Proc.new { x = 1; x } - assert_not_equal proc_size, 0 - - class_with_methods = Class.new do - def foo - a = 0 - a + 1 - end - end - - m_size = ObjectSpace.memsize_of class_with_methods.instance_method(:foo) - assert_not_equal m_size, 0, 'method size not zero' - - # collections - empty_array_size = ObjectSpace.memsize_of [] - assert_not_equal empty_array_size, 0, 'empty array size not zero' - assert_operator empty_array_size, :<, ObjectSpace.memsize_of(Array.new(16)), 'large array size greater than embed' - - # fiber - empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) - assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' - - #hash - assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' -end - -assert 'ObjectSpace.memsize_of_all' do - foo_class = Class.new do - def initialize - @a = 'a' - @b = 'b' - end - end - - foos = Array.new(10) { foo_class.new } - foo_size = ObjectSpace.memsize_of(foos.first) - - assert_equal ObjectSpace.memsize_of_all(foo_class), foo_size * foos.size, 'Memsize of all instance' -end diff --git a/mrbgems/mruby-os-memsize/mrbgem.rake b/mrbgems/mruby-os-memsize/mrbgem.rake new file mode 100644 index 000000000..b5c163bba --- /dev/null +++ b/mrbgems/mruby-os-memsize/mrbgem.rake @@ -0,0 +1,10 @@ +MRuby::Gem::Specification.new('mruby-os-memsize') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'ObjectSpace memsize_of method' + + spec.add_dependency('mruby-objectspace') + spec.add_test_dependency('mruby-metaprog') + spec.add_test_dependency('mruby-method') + spec.add_test_dependency('mruby-fiber') +end diff --git a/mrbgems/mruby-os-memsize/src/memsize.c b/mrbgems/mruby-os-memsize/src/memsize.c new file mode 100644 index 000000000..d82c6b7ed --- /dev/null +++ b/mrbgems/mruby-os-memsize/src/memsize.c @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static mrb_int +os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) +{ + return mrb_obj_iv_tbl_memsize(mrb, obj); +} + +static mrb_int +os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep) +{ + mrb_int size, i; + size = (irep->slen * sizeof(mrb_sym)) + + (irep->plen * sizeof(mrb_code)) + + (irep->ilen * sizeof(mrb_code)); + + for(i = 0; i < irep->rlen; i++) { + size += os_memsize_of_irep(state, irep->reps[i]); + } + return size; +} + +static mrb_int +os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) +{ + mrb_int size; + mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), + mrb_intern_lit(mrb, "_proc")); + struct RProc *proc = mrb_proc_ptr(proc_value); + + size = sizeof(struct RProc); + if (!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); + return size; +} + +static mrb_int +os_memsize_of_object(mrb_state* mrb, mrb_value obj) +{ + mrb_int size = 0; + + switch(mrb_type(obj)) { + case MRB_TT_STRING: + size += mrb_objspace_page_slot_size(); + if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { + size += RSTRING_CAPA(obj); + } + break; + case MRB_TT_CLASS: + case MRB_TT_MODULE: + case MRB_TT_SCLASS: + case MRB_TT_ICLASS: + size += mrb_gc_mark_mt_size(mrb, mrb_class_ptr(obj)) * sizeof(mrb_method_t); + /* fall through */ + case MRB_TT_EXCEPTION: + case MRB_TT_OBJECT: { + size += mrb_objspace_page_slot_size(); + size += os_memsize_of_ivars(mrb, obj); + if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || + mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ + size += os_memsize_of_method(mrb, obj); + } + break; + } + case MRB_TT_HASH: { + size += mrb_objspace_page_slot_size() + + mrb_os_memsize_of_hash_table(obj); + break; + } + case MRB_TT_ARRAY: { + mrb_int len = RARRAY_LEN(obj); + /* Arrays that do not fit within an RArray perform a heap allocation + * storing an array of pointers to the original objects*/ + size += mrb_objspace_page_slot_size(); + if(len > MRB_ARY_EMBED_LEN_MAX) size += sizeof(mrb_value *) * len; + break; + } + case MRB_TT_PROC: { + struct RProc* proc = mrb_proc_ptr(obj); + size += mrb_objspace_page_slot_size(); + size += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); + if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); + break; + } + case MRB_TT_DATA: + size += mrb_objspace_page_slot_size(); + break; +#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_FLOAT: +#ifdef MRB_WORD_BOXING + size += mrb_objspace_page_slot_size() + + sizeof(struct RFloat); +#endif + break; +#endif + case MRB_TT_RANGE: +#ifndef MRB_RANGE_EMBED + size += mrb_objspace_page_slot_size() + + sizeof(struct mrb_range_edges); +#endif + break; + case MRB_TT_FIBER: { + struct RFiber* f = (struct RFiber *)mrb_ptr(obj); + ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; + ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; + + size += mrb_objspace_page_slot_size() + + sizeof(struct RFiber) + + sizeof(struct mrb_context) + + sizeof(struct RProc *) * f->cxt->esize + + sizeof(uint16_t *) * f->cxt->rsize + + sizeof(mrb_value) * stack_size + + sizeof(mrb_callinfo) * ci_size; + break; + } + case MRB_TT_ISTRUCT: + size += mrb_objspace_page_slot_size(); + break; + /* zero heap size types. + * immediate VM stack values, contained within mrb_state, or on C stack */ + case MRB_TT_TRUE: + case MRB_TT_FALSE: + case MRB_TT_FIXNUM: + case MRB_TT_BREAK: + case MRB_TT_CPTR: + case MRB_TT_SYMBOL: + case MRB_TT_FREE: + case MRB_TT_UNDEF: + case MRB_TT_ENV: + /* never used, silences compiler warning + * not having a default: clause lets the compiler tell us when there is a new + * TT not accounted for */ + case MRB_TT_MAXDEFINE: + break; + } + return size; +} + +/* + * call-seq: + * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric + * + * Returns the amount of heap memory allocated for object in size_t units. + * + * The return value depends on the definition of size_t on that platform, + * therefore the value is not comparable across platform types. + * + * Immediate values such as integers, booleans, symbols and unboxed float numbers + * return 0. Additionally special objects which are small enough to fit inside an + * object pointer, termed embedded objects, will return the size of the object pointer. + * Strings and arrays below a compile-time defined size may be embedded. + * + * Setting recurse: true descends into instance variables, array members, + * hash keys and hash values recursively, calculating the child objects and adding to + * the final sum. It avoids infinite recursion and over counting objects by + * internally tracking discovered object ids. + * + */ + +static mrb_value +os_memsize_of(mrb_state *mrb, mrb_value self) +{ + mrb_int total; + mrb_value obj; + + mrb_get_args(mrb, "o", &obj); + + total = os_memsize_of_object(mrb, obj); + return mrb_fixnum_value(total); +} + +struct os_memsize_of_all_cb_data { + mrb_int t; + struct RClass *type; +}; + +static int +os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) +{ + struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; + switch (obj->tt) { + case MRB_TT_FREE: case MRB_TT_ENV: + case MRB_TT_BREAK: case MRB_TT_ICLASS: + /* internal objects that should not be counted */ + return MRB_EACH_OBJ_OK; + default: + break; + } + /* skip Proc objects for methods */ + if (obj->c == NULL) return 0; + if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) + data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); + return MRB_EACH_OBJ_OK; +} + +/* + * call-seq: + * ObjectSpace.memsize_of_all([klass]) -> Numeric + * + * Return consuming memory size of all living objects of type klass. + * + */ + +static mrb_value +os_memsize_of_all(mrb_state *mrb, mrb_value self) +{ + struct os_memsize_of_all_cb_data data = { 0 }; + mrb_get_args(mrb, "|c", &data.type); + mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); + return mrb_fixnum_value(data.t); +} + +void +mrb_mruby_os_memsize_gem_init(mrb_state *mrb) +{ + struct RClass *os = mrb_module_get(mrb, "ObjectSpace"); + mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_OPT(1)); +} + +void +mrb_mruby_os_memsize_gem_final(mrb_state *mrb) +{ +} diff --git a/mrbgems/mruby-os-memsize/test/memsize.rb b/mrbgems/mruby-os-memsize/test/memsize.rb new file mode 100644 index 000000000..c6b1b7b2d --- /dev/null +++ b/mrbgems/mruby-os-memsize/test/memsize.rb @@ -0,0 +1,77 @@ +assert 'ObjectSpace.memsize_of' do + # immediate literals + int_size = ObjectSpace.memsize_of 1 + assert_equal int_size, 0, 'int zero' + + sym_size = ObjectSpace.memsize_of :foo + assert_equal sym_size, 0, 'sym zero' + + assert_equal ObjectSpace.memsize_of(true), int_size + assert_equal ObjectSpace.memsize_of(false), int_size + + assert_not_equal ObjectSpace.memsize_of('a'), 0, 'memsize of str' + + if __ENCODING__ == "UTF-8" + assert_not_equal ObjectSpace.memsize_of("縺薙s縺ォ縺。縺ッ荳也阜"), 0, 'memsize of utf8 str' + end + + # class defs + class_obj_size = ObjectSpace.memsize_of Class + assert_not_equal class_obj_size, 0, 'Class obj not zero' + + empty_class_def_size = ObjectSpace.memsize_of Class.new + assert_not_equal empty_class_def_size, 0, 'Class def not zero' + + class_without_methods = Class.new do + @a = 1 + @b = 2 + end + class_total_size = empty_class_def_size + (int_size * 2) + assert_equal ObjectSpace.memsize_of(class_without_methods), class_total_size, 'class without methods size' + + module_without_methods = Module.new do + @a = 1 + @b = 2 + end + module_total_size = empty_class_def_size + (int_size * 2) + assert_equal ObjectSpace.memsize_of(module_without_methods), module_total_size, 'module without methods size' + + proc_size = ObjectSpace.memsize_of Proc.new { x = 1; x } + assert_not_equal proc_size, 0 + + class_with_methods = Class.new do + def foo + a = 0 + a + 1 + end + end + + m_size = ObjectSpace.memsize_of class_with_methods.instance_method(:foo) + assert_not_equal m_size, 0, 'method size not zero' + + # collections + empty_array_size = ObjectSpace.memsize_of [] + assert_not_equal empty_array_size, 0, 'empty array size not zero' + assert_operator empty_array_size, :<, ObjectSpace.memsize_of(Array.new(16)), 'large array size greater than embed' + + # fiber + empty_fiber_size = ObjectSpace.memsize_of(Fiber.new {}) + assert_not_equal empty_fiber_size, 0, 'empty fiber not zero' + + #hash + assert_not_equal ObjectSpace.memsize_of({}), 0, 'empty hash size not zero' +end + +assert 'ObjectSpace.memsize_of_all' do + foo_class = Class.new do + def initialize + @a = 'a' + @b = 'b' + end + end + + foos = Array.new(10) { foo_class.new } + foo_size = ObjectSpace.memsize_of(foos.first) + + assert_equal ObjectSpace.memsize_of_all(foo_class), foo_size * foos.size, 'Memsize of all instance' +end -- cgit v1.2.3 From b1847721e8c53101dcec61cbccb154fba2381b59 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 20 Jul 2020 23:35:17 +0900 Subject: Implement `Kernel#print` and `Kernel#puts` in C. --- mrbgems/mruby-print/mrblib/print.rb | 31 +------------- mrbgems/mruby-print/src/print.c | 81 ++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 54 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-print/mrblib/print.rb b/mrbgems/mruby-print/mrblib/print.rb index cfe14a5e1..6383901ee 100644 --- a/mrbgems/mruby-print/mrblib/print.rb +++ b/mrbgems/mruby-print/mrblib/print.rb @@ -3,39 +3,10 @@ # # ISO 15.3.1 module Kernel - ## - # Invoke method +print+ on STDOUT and passing +*args+ - # - # ISO 15.3.1.2.10 - def print(*args) - i = 0 - len = args.size - while i < len - __printstr__ args[i].to_s - i += 1 - end - end - - ## - # Invoke method +puts+ on STDOUT and passing +*args*+ - # - # ISO 15.3.1.2.11 - def puts(*args) - i = 0 - len = args.size - while i < len - s = args[i].to_s - __printstr__ s - __printstr__ "\n" if (s[-1] != "\n") - i += 1 - end - __printstr__ "\n" if len == 0 - nil - end - ## # Print human readable object description # + # ISO 15.3.1.2.9 # ISO 15.3.1.3.34 def p(*args) i = 0 diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c index 9301dbe55..1ee2e63aa 100644 --- a/mrbgems/mruby-print/src/print.c +++ b/mrbgems/mruby-print/src/print.c @@ -17,39 +17,70 @@ #endif static void -printstr(mrb_state *mrb, mrb_value obj) +printstr(mrb_state *mrb, const char *p, size_t len) { - if (mrb_string_p(obj)) { #if defined(_WIN32) - if (isatty(fileno(stdout))) { - DWORD written; - int mlen = (int)RSTRING_LEN(obj); - char* utf8 = RSTRING_PTR(obj); - int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0); - wchar_t* utf16 = (wchar_t*)mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); - if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) { - utf16[wlen] = 0; - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - utf16, wlen, &written, NULL); - } - mrb_free(mrb, utf16); - } else + if (isatty(fileno(stdout))) { + DWORD written; + int wlen = MultiByteToWideChar(CP_UTF8, 0, p, len, NULL, 0); + wchar_t* utf16 = (wchar_t*)mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); + if (MultiByteToWideChar(CP_UTF8, 0, p, len, utf16, wlen) > 0) { + utf16[wlen] = 0; + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), + utf16, wlen, &written, NULL); + } + mrb_free(mrb, utf16); + } else #endif - fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout); - fflush(stdout); - } + fwrite(p, len, 1, stdout); + fflush(stdout); } -/* 15.3.1.2.9 */ -/* 15.3.1.3.34 */ -mrb_value +static mrb_value mrb_printstr(mrb_state *mrb, mrb_value self) { - mrb_value argv = mrb_get_arg1(mrb); + mrb_value s = mrb_get_arg1(mrb); + + if (mrb_string_p(s)) { + printstr(mrb, RSTRING_PTR(s), RSTRING_LEN(s)); + } + return s; +} - printstr(mrb, argv); +/* 15.3.1.2.10 */ +/* 15.3.1.3.35 */ +static mrb_value +mrb_print(mrb_state *mrb, mrb_value self) +{ + mrb_int argc, i; + mrb_value *argv; - return argv; + mrb_get_args(mrb, "*", &argv, &argc); + for (i=0; i 0 && RSTRING_PTR(s)[len-1] != '\n') { + printstr(mrb, "\n", 1); + } + } + return mrb_nil_value(); } void @@ -58,6 +89,8 @@ mrb_mruby_print_gem_init(mrb_state* mrb) struct RClass *krn; krn = mrb->kernel_module; mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, krn, "print", mrb_print, MRB_ARGS_ANY()); + mrb_define_method(mrb, krn, "puts", mrb_puts, MRB_ARGS_ANY()); } void -- cgit v1.2.3 From 639703cf018f54a5962a19fc8df5bcfa48308238 Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:32:30 +0900 Subject: Remove unnecessory methods in `mruby-objectspace`; ref #5041 The `ObjectSpace#memsize_of` and `ObjectSpace#memsize_of_all` in `mruby-objectspace` ware migrated to `mruby-os-memsize` mrbgem. --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 211 ---------------------- 1 file changed, 211 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6804a99ae..408d3c0af 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -172,223 +172,12 @@ os_each_object(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(d.count); } -static mrb_int -os_memsize_of_ivars(mrb_state* mrb, mrb_value obj) -{ - return mrb_obj_iv_tbl_memsize(mrb, obj); -} - -static mrb_int -os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep) -{ - mrb_int size, i; - size = (irep->slen * sizeof(mrb_sym)) + - (irep->plen * sizeof(mrb_code)) + - (irep->ilen * sizeof(mrb_code)); - - for(i = 0; i < irep->rlen; i++) { - size += os_memsize_of_irep(state, irep->reps[i]); - } - return size; -} - -static mrb_int -os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) -{ - mrb_int size; - mrb_value proc_value = mrb_obj_iv_get(mrb, mrb_obj_ptr(method_obj), - mrb_intern_lit(mrb, "_proc")); - struct RProc *proc = mrb_proc_ptr(proc_value); - - size = sizeof(struct RProc); - if (!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - return size; -} - -static mrb_int -os_memsize_of_object(mrb_state* mrb, mrb_value obj) -{ - mrb_int size = 0; - - switch(mrb_type(obj)) { - case MRB_TT_STRING: - size += mrb_objspace_page_slot_size(); - if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { - size += RSTRING_CAPA(obj); - } - break; - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - case MRB_TT_ICLASS: - size += mrb_gc_mark_mt_size(mrb, mrb_class_ptr(obj)) * sizeof(mrb_method_t); - /* fall through */ - case MRB_TT_EXCEPTION: - case MRB_TT_OBJECT: { - size += mrb_objspace_page_slot_size(); - size += os_memsize_of_ivars(mrb, obj); - if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || - mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ - size += os_memsize_of_method(mrb, obj); - } - break; - } - case MRB_TT_HASH: { - size += mrb_objspace_page_slot_size() + - mrb_os_memsize_of_hash_table(obj); - break; - } - case MRB_TT_ARRAY: { - mrb_int len = RARRAY_LEN(obj); - /* Arrays that do not fit within an RArray perform a heap allocation - * storing an array of pointers to the original objects*/ - size += mrb_objspace_page_slot_size(); - if(len > MRB_ARY_EMBED_LEN_MAX) size += sizeof(mrb_value *) * len; - break; - } - case MRB_TT_PROC: { - struct RProc* proc = mrb_proc_ptr(obj); - size += mrb_objspace_page_slot_size(); - size += MRB_ENV_LEN(proc->e.env) * sizeof(mrb_value); - if(!MRB_PROC_CFUNC_P(proc)) size += os_memsize_of_irep(mrb, proc->body.irep); - break; - } - case MRB_TT_DATA: - size += mrb_objspace_page_slot_size(); - break; -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - size += mrb_objspace_page_slot_size() + - sizeof(struct RFloat); -#endif - break; -#endif - case MRB_TT_RANGE: -#ifndef MRB_RANGE_EMBED - size += mrb_objspace_page_slot_size() + - sizeof(struct mrb_range_edges); -#endif - break; - case MRB_TT_FIBER: { - struct RFiber* f = (struct RFiber *)mrb_ptr(obj); - ptrdiff_t stack_size = f->cxt->stend - f->cxt->stbase; - ptrdiff_t ci_size = f->cxt->ciend - f->cxt->cibase; - - size += mrb_objspace_page_slot_size() + - sizeof(struct RFiber) + - sizeof(struct mrb_context) + - sizeof(struct RProc *) * f->cxt->esize + - sizeof(uint16_t *) * f->cxt->rsize + - sizeof(mrb_value) * stack_size + - sizeof(mrb_callinfo) * ci_size; - break; - } - case MRB_TT_ISTRUCT: - size += mrb_objspace_page_slot_size(); - break; - /* zero heap size types. - * immediate VM stack values, contained within mrb_state, or on C stack */ - case MRB_TT_TRUE: - case MRB_TT_FALSE: - case MRB_TT_FIXNUM: - case MRB_TT_BREAK: - case MRB_TT_CPTR: - case MRB_TT_SYMBOL: - case MRB_TT_FREE: - case MRB_TT_UNDEF: - case MRB_TT_ENV: - /* never used, silences compiler warning - * not having a default: clause lets the compiler tell us when there is a new - * TT not accounted for */ - case MRB_TT_MAXDEFINE: - break; - } - return size; -} - -/* - * call-seq: - * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric - * - * Returns the amount of heap memory allocated for object in size_t units. - * - * The return value depends on the definition of size_t on that platform, - * therefore the value is not comparable across platform types. - * - * Immediate values such as integers, booleans, symbols and unboxed float numbers - * return 0. Additionally special objects which are small enough to fit inside an - * object pointer, termed embedded objects, will return the size of the object pointer. - * Strings and arrays below a compile-time defined size may be embedded. - * - * Setting recurse: true descends into instance variables, array members, - * hash keys and hash values recursively, calculating the child objects and adding to - * the final sum. It avoids infinite recursion and over counting objects by - * internally tracking discovered object ids. - * - */ - -static mrb_value -os_memsize_of(mrb_state *mrb, mrb_value self) -{ - mrb_int total; - mrb_value obj; - - mrb_get_args(mrb, "o", &obj); - - total = os_memsize_of_object(mrb, obj); - return mrb_fixnum_value(total); -} - -struct os_memsize_of_all_cb_data { - mrb_int t; - struct RClass *type; -}; - -static int -os_memsize_of_all_cb(mrb_state *mrb, struct RBasic *obj, void *d) -{ - struct os_memsize_of_all_cb_data *data = (struct os_memsize_of_all_cb_data *)d; - switch (obj->tt) { - case MRB_TT_FREE: case MRB_TT_ENV: - case MRB_TT_BREAK: case MRB_TT_ICLASS: - /* internal objects that should not be counted */ - return MRB_EACH_OBJ_OK; - default: - break; - } - /* skip Proc objects for methods */ - if (obj->c == NULL) return 0; - if (data->type == NULL || mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), data->type)) - data->t += os_memsize_of_object(mrb, mrb_obj_value(obj)); - return MRB_EACH_OBJ_OK; -} - -/* - * call-seq: - * ObjectSpace.memsize_of_all([klass]) -> Numeric - * - * Return consuming memory size of all living objects of type klass. - * - */ - -static mrb_value -os_memsize_of_all(mrb_state *mrb, mrb_value self) -{ - struct os_memsize_of_all_cb_data data = { 0 }; - mrb_get_args(mrb, "|c", &data.type); - mrb_objspace_each_objects(mrb, os_memsize_of_all_cb, &data); - return mrb_fixnum_value(data.t); -} - void mrb_mruby_objectspace_gem_init(mrb_state *mrb) { struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "memsize_of", os_memsize_of, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, os, "memsize_of_all", os_memsize_of_all, MRB_ARGS_OPT(1)); } void -- cgit v1.2.3 From 97f71b5a67d753c0949e31c7a90efb821387c637 Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:37:39 +0900 Subject: Fixed garbled characters; ref #5041 --- mrbgems/mruby-os-memsize/test/memsize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-os-memsize/test/memsize.rb b/mrbgems/mruby-os-memsize/test/memsize.rb index c6b1b7b2d..9e8d41165 100644 --- a/mrbgems/mruby-os-memsize/test/memsize.rb +++ b/mrbgems/mruby-os-memsize/test/memsize.rb @@ -12,7 +12,7 @@ assert 'ObjectSpace.memsize_of' do assert_not_equal ObjectSpace.memsize_of('a'), 0, 'memsize of str' if __ENCODING__ == "UTF-8" - assert_not_equal ObjectSpace.memsize_of("縺薙s縺ォ縺。縺ッ荳也阜"), 0, 'memsize of utf8 str' + assert_not_equal ObjectSpace.memsize_of("こんにちは世界"), 0, 'memsize of utf8 str' end # class defs -- cgit v1.2.3 From 0e9bd248271b9f3d8de42e0fbc932c3148d91787 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 17:50:01 +0900 Subject: Fix `puts` to print newline with empty strings; ref b184772 --- mrbgems/mruby-print/src/print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c index 1ee2e63aa..851aee25e 100644 --- a/mrbgems/mruby-print/src/print.c +++ b/mrbgems/mruby-print/src/print.c @@ -76,7 +76,7 @@ mrb_puts(mrb_state *mrb, mrb_value self) mrb_value s = mrb_str_to_str(mrb, argv[i]); mrb_int len = RSTRING_LEN(s); printstr(mrb, RSTRING_PTR(s), len); - if (len > 0 && RSTRING_PTR(s)[len-1] != '\n') { + if (len == 0 || RSTRING_PTR(s)[len-1] != '\n') { printstr(mrb, "\n", 1); } } -- cgit v1.2.3 From b4f4f5968b7c5e05b91bf7a62a0438b0d4c9133e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 23 Jul 2020 07:10:35 +0900 Subject: `ObjectSpace.count_objects` to support `MRB_TT_ISTRUCT`; #5046 --- mrbgems/mruby-objectspace/src/mruby_objectspace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c index 6804a99ae..de5a4f025 100644 --- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c +++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c @@ -100,6 +100,7 @@ os_count_objects(mrb_state *mrb, mrb_value self) COUNT_TYPE(T_ENV); COUNT_TYPE(T_DATA); COUNT_TYPE(T_FIBER); + COUNT_TYPE(T_ISTRUCT); #undef COUNT_TYPE default: type = mrb_fixnum_value(i); break; -- cgit v1.2.3 From 2b588b8566a50ed33f4f9878aa10fdbe05a3feeb Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:40:37 +0900 Subject: Add NUL terminator to string object size calculation; ref #5032 --- mrbgems/mruby-os-memsize/src/memsize.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-os-memsize/src/memsize.c b/mrbgems/mruby-os-memsize/src/memsize.c index d82c6b7ed..70887a3ae 100644 --- a/mrbgems/mruby-os-memsize/src/memsize.c +++ b/mrbgems/mruby-os-memsize/src/memsize.c @@ -54,6 +54,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) size += mrb_objspace_page_slot_size(); if (!RSTR_EMBED_P(RSTRING(obj)) && !RSTR_SHARED_P(RSTRING(obj))) { size += RSTRING_CAPA(obj); + size++; /* NUL terminator */ } break; case MRB_TT_CLASS: -- cgit v1.2.3 From c9ba761b9e23e720da9200be1c4df103a04e51b2 Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:45:53 +0900 Subject: Support without `mruby-method` for `mruby-os-memsize`; ref #5032 --- mrbgems/mruby-os-memsize/src/memsize.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-os-memsize/src/memsize.c b/mrbgems/mruby-os-memsize/src/memsize.c index 70887a3ae..14f90109d 100644 --- a/mrbgems/mruby-os-memsize/src/memsize.c +++ b/mrbgems/mruby-os-memsize/src/memsize.c @@ -44,6 +44,19 @@ os_memsize_of_method(mrb_state* mrb, mrb_value method_obj) return size; } +static mrb_bool +obj_is_kind_of_checked(mrb_state *mrb, mrb_value obj, const char *classname) +{ + mrb_value objclass = mrb_obj_value(mrb->object_class); + + if (mrb_const_defined(mrb, objclass, mrb_intern_cstr(mrb, classname))) { + struct RClass *klass = mrb_class_get(mrb, classname); + return mrb_obj_is_kind_of(mrb, obj, klass); + } + + return FALSE; +} + static mrb_int os_memsize_of_object(mrb_state* mrb, mrb_value obj) { @@ -67,8 +80,8 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) case MRB_TT_OBJECT: { size += mrb_objspace_page_slot_size(); size += os_memsize_of_ivars(mrb, obj); - if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "UnboundMethod")) || - mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "Method"))){ + if (obj_is_kind_of_checked(mrb, obj, "UnboundMethod") || + obj_is_kind_of_checked(mrb, obj, "Method")) { size += os_memsize_of_method(mrb, obj); } break; -- cgit v1.2.3 From 5c2b11d21581cf472929b21f28f1a388a16f0865 Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 21 Jul 2020 23:55:26 +0900 Subject: Avoid using FPU with `mruby-os-memsize`; ref #5032 And, in the calculation of the instance variable size, the fraction was always rounded down because of division of integers, so fix it. At the same time, test items that are no longer passed due to this change are deleted. --- mrbgems/mruby-os-memsize/test/memsize.rb | 14 -------------- src/variable.c | 7 +++---- 2 files changed, 3 insertions(+), 18 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-os-memsize/test/memsize.rb b/mrbgems/mruby-os-memsize/test/memsize.rb index 9e8d41165..6be8f1b06 100644 --- a/mrbgems/mruby-os-memsize/test/memsize.rb +++ b/mrbgems/mruby-os-memsize/test/memsize.rb @@ -22,20 +22,6 @@ assert 'ObjectSpace.memsize_of' do empty_class_def_size = ObjectSpace.memsize_of Class.new assert_not_equal empty_class_def_size, 0, 'Class def not zero' - class_without_methods = Class.new do - @a = 1 - @b = 2 - end - class_total_size = empty_class_def_size + (int_size * 2) - assert_equal ObjectSpace.memsize_of(class_without_methods), class_total_size, 'class without methods size' - - module_without_methods = Module.new do - @a = 1 - @b = 2 - end - module_total_size = empty_class_def_size + (int_size * 2) - assert_equal ObjectSpace.memsize_of(module_without_methods), module_total_size, 'module without methods size' - proc_size = ObjectSpace.memsize_of Proc.new { x = 1; x } assert_not_equal proc_size, 0 diff --git a/src/variable.c b/src/variable.c index 0755f7d92..8c16b2d4f 100644 --- a/src/variable.c +++ b/src/variable.c @@ -4,7 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include #include #include #include @@ -1132,9 +1131,9 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) mrb_int mrb_obj_iv_tbl_memsize(mrb_state* mrb, mrb_value obj) { - return sizeof(iv_tbl) + - (sizeof(segment) * ceil(iv_size(mrb, mrb_obj_ptr(obj)->iv)/ - MRB_IV_SEGMENT_SIZE)); + size_t ivsize = iv_size(mrb, mrb_obj_ptr(obj)->iv); + size_t ivsegs = (ivsize + MRB_IV_SEGMENT_SIZE - 1) / MRB_IV_SEGMENT_SIZE; + return sizeof(iv_tbl) + (sizeof(segment) * ivsegs); } #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) -- cgit v1.2.3 From 0983c723c51cba5f603e374383d105443abf75a9 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 26 Jul 2020 13:03:28 +0900 Subject: Update document for `ObjectSpace.memsize_of` [ci skip] The `recurse` keyword is removed by f00657ead7c3e5f6f9a346d7797a280b5c9f02fa. --- mrbgems/mruby-os-memsize/src/memsize.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-os-memsize/src/memsize.c b/mrbgems/mruby-os-memsize/src/memsize.c index 14f90109d..65020c97f 100644 --- a/mrbgems/mruby-os-memsize/src/memsize.c +++ b/mrbgems/mruby-os-memsize/src/memsize.c @@ -162,7 +162,7 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) /* * call-seq: - * ObjectSpace.memsize_of(obj, recurse: false) -> Numeric + * ObjectSpace.memsize_of(obj) -> Numeric * * Returns the amount of heap memory allocated for object in size_t units. * @@ -173,12 +173,6 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj) * return 0. Additionally special objects which are small enough to fit inside an * object pointer, termed embedded objects, will return the size of the object pointer. * Strings and arrays below a compile-time defined size may be embedded. - * - * Setting recurse: true descends into instance variables, array members, - * hash keys and hash values recursively, calculating the child objects and adding to - * the final sum. It avoids infinite recursion and over counting objects by - * internally tracking discovered object ids. - * */ static mrb_value -- cgit v1.2.3 From 1517d77e936ed5bbe176eb78c6f3308ef98a6047 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 31 Jul 2020 06:57:05 +0900 Subject: Fix `puts` in `mruby-print` on no argument; 0e9bd24 `puts` should print newline when called without arguments. --- mrbgems/mruby-print/src/print.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mrbgems') diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c index 851aee25e..df153d920 100644 --- a/mrbgems/mruby-print/src/print.c +++ b/mrbgems/mruby-print/src/print.c @@ -80,6 +80,9 @@ mrb_puts(mrb_state *mrb, mrb_value self) printstr(mrb, "\n", 1); } } + if (argc == 0) { + printstr(mrb, "\n", 1); + } return mrb_nil_value(); } -- cgit v1.2.3 From 43443d9377212844b84bc0440a8c35c4adfbb5d6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 3 Aug 2020 19:46:34 +0900 Subject: Should not decrement `count` when `PACK_FLAG_COUNT2`; fix #5057 --- mrbgems/mruby-pack/src/pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index 3a2c3367a..8169a90b5 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -1302,7 +1302,7 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) aidx++; break; } - if (count > 0) { + if (!(flags & PACK_FLAG_COUNT2) && count > 0) { count--; } } -- cgit v1.2.3 From cfb799a18e5adf8166e7ec72e2066da38062df1b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 4 Aug 2020 17:50:09 +0900 Subject: Fix wrong condition for `PACK_DIR_HEX`; ref #5057 --- mrbgems/mruby-pack/src/pack.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems') diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index 8169a90b5..80de397f4 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -1298,11 +1298,12 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) default: break; } - if (dir == PACK_DIR_STR || dir == PACK_DIR_BASE64) { /* always consumes 1 entry */ + if (dir == PACK_DIR_STR || dir == PACK_DIR_BASE64 || dir == PACK_DIR_HEX) { + /* always consumes 1 entry */ aidx++; break; } - if (!(flags & PACK_FLAG_COUNT2) && count > 0) { + if (count > 0) { count--; } } -- cgit v1.2.3