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(+) 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(-) 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(-) 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 6d5652114e2105b1e9d81b353b3c9335ca3b4dd5 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 13:18:05 -0700 Subject: update CI settings for Windows --- .github/workflows/build.yml | 3 --- appveyor.yml | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81deb4515..1c6fa34b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -101,6 +101,3 @@ jobs: rake -E "STDOUT.sync=true" -m -j4 test env: MRUBY_CONFIG: appveyor_config.rb - # TODO(take-cheeze): Re-enable /O2 - CFLAGS: "/c /nologo /W3 /we4013 /Zi /MD /D_CRT_SECURE_NO_WARNINGS" - CXXFLAGS: "/c /nologo /W3 /Zi /MD /EHs /D_CRT_SECURE_NO_WARNINGS" diff --git a/appveyor.yml b/appveyor.yml index e135383e1..876e1edb0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,18 @@ version: "{build}" -os: Visual Studio 2017 +os: Visual Studio 2019 shallow_clone: true environment: matrix: + # Visual Studio 2019 64bit + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat + + # Visual Studio 2019 32bit + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat + machine: x86 + # Visual Studio 2017 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat @@ -25,15 +32,14 @@ environment: - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat machine: amd64 - init: - call "%visualcpp%" %machine% - # For using Rubyinstaller's Ruby 2.4 64bit - - set PATH=C:\Ruby24-x64\bin;%PATH% + # For using Rubyins4aller's Ruby 2.6 64bit + # 2.6 is the highest supported Ruby version across all historical + # Visual Studio AppVeyor images. Ruby 2.7 is only on the 2019 image. + - set PATH=C:\Ruby26-x64\bin;%PATH% - ruby --version - build_script: - set MRUBY_CONFIG=appveyor_config.rb - - rake -m - - rake -E $stdout.sync=true test + - rake -E "$stdout.sync=true" -m -j4 test -- 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(-) 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 b59283a03f9f2fed85c6426af9358eb8c8e5b09c Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:05:02 -0700 Subject: per-machine appveyor os config --- appveyor.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 876e1edb0..3afc9c98d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,37 +1,46 @@ version: "{build}" -os: Visual Studio 2019 - shallow_clone: true environment: matrix: # Visual Studio 2019 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat + os: Visual Studio 2019 # Visual Studio 2019 32bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat + os: Visual Studio 2019 machine: x86 # Visual Studio 2017 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat + os: Visual Studio 2017 # Visual Studio 2017 32bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat + os: Visual Studio 2017 machine: x86 # Visual Studio 2015 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat + os: Visual Studio 2015 machine: amd64 # Visual Studio 2015 32bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat + os: Visual Studio 2015 machine: x86 # Visual Studio 2013 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat + os: Visual Studio 2013 machine: amd64 + # Visual Studio 2013 32bit + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat + os: Visual Studio 2013 + machine: x86 init: - call "%visualcpp%" %machine% # For using Rubyins4aller's Ruby 2.6 64bit -- cgit v1.2.3 From 206f7ce272ec15f2d156ad26275fa1e03d720ab0 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:21:15 -0700 Subject: simplify appveyor config --- appveyor.yml | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3afc9c98d..08aa4b4ad 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,43 +6,38 @@ environment: matrix: # Visual Studio 2019 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat - os: Visual Studio 2019 + appveyor_build_worker_image: Visual Studio 2019 # Visual Studio 2019 32bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat - os: Visual Studio 2019 - machine: x86 + appveyor_build_worker_image: Visual Studio 2019 # Visual Studio 2017 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat - os: Visual Studio 2017 + appveyor_build_worker_image: Visual Studio 2017 # Visual Studio 2017 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat - os: Visual Studio 2017 - machine: x86 + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat + appveyor_build_worker_image: Visual Studio 2017 # Visual Studio 2015 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - os: Visual Studio 2015 - machine: amd64 + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvars64.bat + appveyor_build_worker_image: Visual Studio 2015 # Visual Studio 2015 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - os: Visual Studio 2015 - machine: x86 + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvars32.bat + appveyor_build_worker_image: Visual Studio 2015 # Visual Studio 2013 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - os: Visual Studio 2013 - machine: amd64 + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvars64.bat + appveyor_build_worker_image: Visual Studio 2013 # Visual Studio 2013 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - os: Visual Studio 2013 - machine: x86 + - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvars32.bat + appveyor_build_worker_image: Visual Studio 2013 + init: - - call "%visualcpp%" %machine% + - call "%visualcpp%" # For using Rubyins4aller's Ruby 2.6 64bit # 2.6 is the highest supported Ruby version across all historical # Visual Studio AppVeyor images. Ruby 2.7 is only on the 2019 image. -- cgit v1.2.3 From 0ed623c44261da33edfb6e14c6c5cc26fb33e17a Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:38:11 -0700 Subject: name appveyor jobs, fix <=2015 config --- appveyor.yml | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 08aa4b4ad..cbbc774b2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,40 +4,44 @@ shallow_clone: true environment: matrix: - # Visual Studio 2019 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat + - job_name: Visual Studio 2019 64bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat appveyor_build_worker_image: Visual Studio 2019 - # Visual Studio 2019 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat + - job_name: Visual Studio 2019 32bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat appveyor_build_worker_image: Visual Studio 2019 - # Visual Studio 2017 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat + - job_name: Visual Studio 2017 64bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat appveyor_build_worker_image: Visual Studio 2017 - # Visual Studio 2017 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat + - job_name: Visual Studio 2017 32bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat appveyor_build_worker_image: Visual Studio 2017 - # Visual Studio 2015 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvars64.bat + - job_name: Visual Studio 2015 64bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat appveyor_build_worker_image: Visual Studio 2015 + machine: x86_amd64 - # Visual Studio 2015 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvars32.bat + - job_name: Visual Studio 2015 32bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat appveyor_build_worker_image: Visual Studio 2015 + machine: x86 - # Visual Studio 2013 64bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvars64.bat + - job_name: Visual Studio 2013 64bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat appveyor_build_worker_image: Visual Studio 2013 + machine: x86_amd64 - # Visual Studio 2013 32bit - - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvars32.bat + - job_name: Visual Studio 2013 32bit + visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat appveyor_build_worker_image: Visual Studio 2013 + machine: x86 init: - - call "%visualcpp%" + - call "%visualcpp%" "%machine%" # For using Rubyins4aller's Ruby 2.6 64bit # 2.6 is the highest supported Ruby version across all historical # Visual Studio AppVeyor images. Ruby 2.7 is only on the 2019 image. -- cgit v1.2.3 From ce167d70b77a21baac6686ccb568eaad00bee35f Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:44:13 -0700 Subject: fix quoting --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cbbc774b2..522735abe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,7 +41,7 @@ environment: machine: x86 init: - - call "%visualcpp%" "%machine%" + - call "%visualcpp%" %machine% # For using Rubyins4aller's Ruby 2.6 64bit # 2.6 is the highest supported Ruby version across all historical # Visual Studio AppVeyor images. Ruby 2.7 is only on the 2019 image. -- cgit v1.2.3 From 5b9f7c0b933d4e4fbe67305075872a28574fa76c Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:59:13 -0700 Subject: use 2015 image for 2013 builds, ruby 2 not on 2013 image --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 522735abe..454c0f545 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,12 +32,12 @@ environment: - job_name: Visual Studio 2013 64bit visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - appveyor_build_worker_image: Visual Studio 2013 + appveyor_build_worker_image: Visual Studio 2015 machine: x86_amd64 - job_name: Visual Studio 2013 32bit visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - appveyor_build_worker_image: Visual Studio 2013 + appveyor_build_worker_image: Visual Studio 2015 machine: x86 init: -- cgit v1.2.3 From ba9f81db8b8b1bdf80f87559fe80bd37ddd0188f Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Mon, 29 Jun 2020 16:16:55 -0700 Subject: VS2013 32-bit does not work --- appveyor.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 454c0f545..ac77222d6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,11 +35,6 @@ environment: appveyor_build_worker_image: Visual Studio 2015 machine: x86_amd64 - - job_name: Visual Studio 2013 32bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - appveyor_build_worker_image: Visual Studio 2015 - machine: x86 - init: - call "%visualcpp%" %machine% # For using Rubyins4aller's Ruby 2.6 64bit -- cgit v1.2.3 From 97319697c8f9f6ff27b32589947e1918e3015503 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 2 Jul 2020 10:41:03 +0900 Subject: Cancel 9cdf439 Should not free the pointer in `realloc` since it can cause use-after-free problem. --- src/gc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gc.c b/src/gc.c index 6c83911d5..e1892080f 100644 --- a/src/gc.c +++ b/src/gc.c @@ -225,7 +225,6 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len) p2 = mrb_realloc_simple(mrb, p, len); if (len == 0) return p2; if (p2 == NULL) { - mrb_free(mrb, p); mrb->gc.out_of_memory = TRUE; mrb_raise_nomemory(mrb); } -- cgit v1.2.3 From 57469584704a5e65e655e05ac48d9a09e246f0c5 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sat, 4 Jul 2020 20:33:38 -0700 Subject: fix object_id of true, false, and undef all 0 --- src/etc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/etc.c b/src/etc.c index 785f49357..74b9ab03b 100644 --- a/src/etc.c +++ b/src/etc.c @@ -107,10 +107,11 @@ mrb_obj_id(mrb_value obj) return MakeID(0); /* not define */ case MRB_TT_FALSE: if (mrb_nil_p(obj)) - return MakeID(1); - return MakeID(0); + return MakeID(4); + else + return MakeID(0); case MRB_TT_TRUE: - return MakeID(1); + return MakeID(2); case MRB_TT_SYMBOL: return MakeID(mrb_symbol(obj)); case MRB_TT_FIXNUM: -- cgit v1.2.3 From 4f189b2be91f577359bea5be8e5c504e1a4eb1d8 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 20:55:56 -0700 Subject: remove vs2013, separate build and test commands --- appveyor.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ac77222d6..93c40dbb1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,11 +30,6 @@ environment: appveyor_build_worker_image: Visual Studio 2015 machine: x86 - - job_name: Visual Studio 2013 64bit - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - appveyor_build_worker_image: Visual Studio 2015 - machine: x86_amd64 - init: - call "%visualcpp%" %machine% # For using Rubyins4aller's Ruby 2.6 64bit @@ -45,4 +40,5 @@ init: build_script: - set MRUBY_CONFIG=appveyor_config.rb - - rake -E "$stdout.sync=true" -m -j4 test + - rake -E "$stdout.sync=true" -m -j4 + - rake test -- cgit v1.2.3 From 5c7adf0534ce2c9683308d7ada8ee93cd01a1b01 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 20:59:49 -0700 Subject: separate build and test steps, remove MSC --- .github/workflows/build.yml | 51 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c6fa34b4..392ec7c1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,10 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build and test - run: rake -m -j4 all test + - name: build + run: rake -m -j4 all + - name: test + run: rake test env: MRUBY_CONFIG: travis_config.rb @@ -20,8 +22,10 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf gcc g++ - - name: build and test - run: rake -m -j4 all test + - name: build + run: rake -m -j4 all + - name: test + run: rake test env: MRUBY_CONFIG: travis_config.rb CC: gcc @@ -33,8 +37,10 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build and test - run: rake -m -j4 all test + - name: build + run: rake -m -j4 all + - name: test + run: rake test env: MRUBY_CONFIG: travis_config.rb CC: clang @@ -46,8 +52,10 @@ jobs: - uses: actions/checkout@v1 - name: brew run: brew install ruby gperf - - name: build and test - run: rake -m -j4 all test + - name: build + run: rake -m -j4 all + - name: test + run: rake test env: MRUBY_CONFIG: travis_config.rb @@ -57,8 +65,10 @@ jobs: - uses: actions/checkout@v1 - name: chocolatey run: choco install -y ruby gperf - - name: build and test - run: rake -E '$stdout.sync=true' -j4 test + - name: build + run: rake -E '$stdout.sync=true' -m -j4 + - name: test + run: rake -E 'STDOUT.sync=true' test env: MRUBY_CONFIG: travis_config.rb CFLAGS: -g -O1 -Wall -Wundef @@ -82,22 +92,11 @@ jobs: - name: Set ENV run: | echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' - - name: build and test + - name: build shell: cmd - run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' test - env: - MRUBY_CONFIG: travis_config.rb - - Windows-VC: - runs-on: windows-latest - steps: - - uses: actions/checkout@v1 - - name: chocolatey - run: choco install -y ruby gperf - - name: build and test + run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' + - name: test shell: cmd - run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - rake -E "STDOUT.sync=true" -m -j4 test + run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' test env: - MRUBY_CONFIG: appveyor_config.rb + MRUBY_CONFIG: travis_config.rb -- cgit v1.2.3 From 4d393d5d09f73064fed931f2cbb2347fb03373d1 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 21:05:27 -0700 Subject: use correct config file --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 392ec7c1c..8e990dc85 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -99,4 +99,4 @@ jobs: shell: cmd run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' test env: - MRUBY_CONFIG: travis_config.rb + MRUBY_CONFIG: appveyor_config.rb -- cgit v1.2.3 From b3dace6ae3d28417bf7061a560671734a5568de5 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 21:12:04 -0700 Subject: use verbose test output. use correct config file this time --- .github/workflows/build.yml | 10 +++++----- appveyor.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e990dc85..8f6f73c61 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - name: build run: rake -m -j4 all - name: test - run: rake test + run: rake test -v env: MRUBY_CONFIG: travis_config.rb @@ -25,7 +25,7 @@ jobs: - name: build run: rake -m -j4 all - name: test - run: rake test + run: rake test -v env: MRUBY_CONFIG: travis_config.rb CC: gcc @@ -40,7 +40,7 @@ jobs: - name: build run: rake -m -j4 all - name: test - run: rake test + run: rake test -v env: MRUBY_CONFIG: travis_config.rb CC: clang @@ -55,7 +55,7 @@ jobs: - name: build run: rake -m -j4 all - name: test - run: rake test + run: rake test -v env: MRUBY_CONFIG: travis_config.rb @@ -99,4 +99,4 @@ jobs: shell: cmd run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' test env: - MRUBY_CONFIG: appveyor_config.rb + MRUBY_CONFIG: travis_config.rb diff --git a/appveyor.yml b/appveyor.yml index 93c40dbb1..888261855 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,4 +41,4 @@ init: build_script: - set MRUBY_CONFIG=appveyor_config.rb - rake -E "$stdout.sync=true" -m -j4 - - rake test + - rake test -v -- cgit v1.2.3 From b75974689089396ed22c8ef3ecd80355b40bf80f Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 5 Jul 2020 21:37:20 -0700 Subject: try not separating build and test steps --- .github/workflows/build.yml | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8f6f73c61..91a82b4db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,10 +9,8 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build - run: rake -m -j4 all - - name: test - run: rake test -v + - name: build and test + run: rake -v test env: MRUBY_CONFIG: travis_config.rb @@ -22,10 +20,8 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf gcc g++ - - name: build - run: rake -m -j4 all - - name: test - run: rake test -v + - name: build and test + run: rake -v test env: MRUBY_CONFIG: travis_config.rb CC: gcc @@ -37,10 +33,8 @@ jobs: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build - run: rake -m -j4 all - - name: test - run: rake test -v + - name: build and test + run: rake -v test env: MRUBY_CONFIG: travis_config.rb CC: clang @@ -52,10 +46,8 @@ jobs: - uses: actions/checkout@v1 - name: brew run: brew install ruby gperf - - name: build - run: rake -m -j4 all - - name: test - run: rake test -v + - name: build and test + run: rake -v test env: MRUBY_CONFIG: travis_config.rb @@ -66,9 +58,7 @@ jobs: - name: chocolatey run: choco install -y ruby gperf - name: build - run: rake -E '$stdout.sync=true' -m -j4 - - name: test - run: rake -E 'STDOUT.sync=true' test + run: rake -E 'STDOUT.sync=true' -v test env: MRUBY_CONFIG: travis_config.rb CFLAGS: -g -O1 -Wall -Wundef @@ -92,11 +82,8 @@ jobs: - name: Set ENV run: | echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' - - name: build - shell: cmd - run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' - - name: test + - name: build and test shell: cmd - run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' test + run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' -v test env: MRUBY_CONFIG: travis_config.rb -- cgit v1.2.3 From 01a8d8498fc3c1b107b303661d06b858858fce26 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 6 Jul 2020 23:11:51 +0900 Subject: Avoid infinite loop when converting objects to strings. --- src/object.c | 1 + src/string.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/object.c b/src/object.c index db9dfb568..7257f402d 100644 --- a/src/object.c +++ b/src/object.c @@ -338,6 +338,7 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char if (mrb_type(val) == type) return val; v = convert_type(mrb, val, tname, method, TRUE); if (mrb_type(v) != type) { + if (type == MRB_TT_STRING) return mrb_any_to_s(mrb, val); mrb_raisef(mrb, E_TYPE_ERROR, "%v cannot be converted to %s by #%s", val, tname, method); } return v; diff --git a/src/string.c b/src/string.c index f1ffbe43d..78c41c5f3 100644 --- a/src/string.c +++ b/src/string.c @@ -1121,6 +1121,7 @@ mrb_str_to_str(mrb_state *mrb, mrb_value str) return mrb_sym_str(mrb, mrb_symbol(str)); case MRB_TT_FIXNUM: return mrb_fixnum_to_str(mrb, str, 10); + case MRB_TT_SCLASS: case MRB_TT_CLASS: case MRB_TT_MODULE: return mrb_mod_to_s(mrb, str); -- cgit v1.2.3 From 3a79d6051506da5a830d3272b3075440debf2733 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Tue, 7 Jul 2020 11:18:44 -0700 Subject: fix rake -m for separating build and test steps --- .github/workflows/build.yml | 55 ++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 91a82b4db..934460b73 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,51 +5,59 @@ on: [push, pull_request] jobs: Ubuntu-1604: runs-on: ubuntu-16.04 + env: + MRUBY_CONFIG: travis_config.rb steps: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build and test - run: rake -v test - env: - MRUBY_CONFIG: travis_config.rb + - name: build + run: rake -m + - name: test + run: rake test -v Ubuntu-1804-gcc: runs-on: ubuntu-18.04 + env: + MRUBY_CONFIG: travis_config.rb + CC: gcc + CXX: g++ steps: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf gcc g++ - - name: build and test - run: rake -v test - env: - MRUBY_CONFIG: travis_config.rb - CC: gcc - CXX: g++ + - name: build + run: rake -m + - name: test + run: rake test -v Ubuntu-1804-clang: runs-on: ubuntu-18.04 + env: + MRUBY_CONFIG: travis_config.rb + CC: clang + CXX: clang++ steps: - uses: actions/checkout@v1 - name: apt run: sudo apt install ruby gperf - - name: build and test - run: rake -v test - env: - MRUBY_CONFIG: travis_config.rb - CC: clang - CXX: clang++ + - name: build + run: rake -m + - name: test + run: rake test -v macOS: runs-on: macos-latest + env: + MRUBY_CONFIG: travis_config.rb steps: - uses: actions/checkout@v1 - name: brew run: brew install ruby gperf - - name: build and test - run: rake -v test - env: - MRUBY_CONFIG: travis_config.rb + - name: build + run: rake -m + - name: test + run: rake test -v Windows-MinGW: runs-on: windows-latest @@ -82,7 +90,12 @@ jobs: - name: Set ENV run: | echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' - - name: build and test + - name: build + shell: cmd + run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' -m + env: + MRUBY_CONFIG: travis_config.rb + - name: test shell: cmd run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' -v test env: -- cgit v1.2.3 From 8a44903992475bf11f375f7a732e933d2a628fc5 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Tue, 7 Jul 2020 17:34:26 -0700 Subject: remove verbose test output --- .github/workflows/build.yml | 12 ++++++------ appveyor.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 934460b73..335c0cdf6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: build run: rake -m - name: test - run: rake test -v + run: rake test Ubuntu-1804-gcc: runs-on: ubuntu-18.04 @@ -29,7 +29,7 @@ jobs: - name: build run: rake -m - name: test - run: rake test -v + run: rake test Ubuntu-1804-clang: runs-on: ubuntu-18.04 @@ -44,7 +44,7 @@ jobs: - name: build run: rake -m - name: test - run: rake test -v + run: rake test macOS: runs-on: macos-latest @@ -57,7 +57,7 @@ jobs: - name: build run: rake -m - name: test - run: rake test -v + run: rake test Windows-MinGW: runs-on: windows-latest @@ -66,7 +66,7 @@ jobs: - name: chocolatey run: choco install -y ruby gperf - name: build - run: rake -E 'STDOUT.sync=true' -v test + run: rake -E 'STDOUT.sync=true' test env: MRUBY_CONFIG: travis_config.rb CFLAGS: -g -O1 -Wall -Wundef @@ -97,6 +97,6 @@ jobs: MRUBY_CONFIG: travis_config.rb - name: test shell: cmd - run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' -v test + run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' test env: MRUBY_CONFIG: travis_config.rb diff --git a/appveyor.yml b/appveyor.yml index 888261855..93c40dbb1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,4 +41,4 @@ init: build_script: - set MRUBY_CONFIG=appveyor_config.rb - rake -E "$stdout.sync=true" -m -j4 - - rake test -v + - rake test -- 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(+) 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(-) 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(+) 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(-) 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 28e39419a589763fc2357de84d91979f2b113cd1 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 11 Jul 2020 16:12:48 +0900 Subject: Remove the prototype declaration `mrb_free_backtrace()` This function is removed by 9644ad5. --- src/state.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/state.c b/src/state.c index 533bdaa0b..790f7ca13 100644 --- a/src/state.c +++ b/src/state.c @@ -164,8 +164,6 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) mrb_free(mrb, irep); } -void mrb_free_backtrace(mrb_state *mrb); - MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c) { -- 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(+) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 4bf050a192072938cea8a5c28b0bd85f5ece43aa Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Tue, 14 Jul 2020 21:30:36 +0900 Subject: Set `STDOUT.sync=true` when testing on AppVeyor [skip travis] This issue is a correction error at 5a682bfc. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 93c40dbb1..e963ea035 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,5 +40,5 @@ init: build_script: - set MRUBY_CONFIG=appveyor_config.rb - - rake -E "$stdout.sync=true" -m -j4 - - rake test + - rake -m -j4 + - rake -E STDOUT.sync=true test -- 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(-) 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(-) 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(-) 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 5dc87f77d4f33edb53111e9e0fe2881065edee12 Mon Sep 17 00:00:00 2001 From: dearblue Date: Thu, 16 Jul 2020 23:11:30 +0900 Subject: Fixed shift width for `MRB_ENV_SET_BIDX()` ref c07f24cd1 and close #5035 --- include/mruby/proc.h | 2 +- test/t/kernel.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/mruby/proc.h b/include/mruby/proc.h index ef5357d5d..12013c3ae 100644 --- a/include/mruby/proc.h +++ b/include/mruby/proc.h @@ -34,7 +34,7 @@ struct REnv { #define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED) #define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0) #define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff) -#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<10)) +#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8)) void mrb_env_unshare(mrb_state*, struct REnv*); diff --git a/test/t/kernel.rb b/test/t/kernel.rb index b7291a000..606150147 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -116,6 +116,13 @@ assert('Kernel#block_given?', '15.3.1.3.6') do "block" end end + + def bg_try_in_block + -> { block_given? }[] + end + + assert_false bg_try_in_block + assert_true bg_try_in_block{} end assert('Kernel#class', '15.3.1.3.7') do -- 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 1952004d5a4a3c0758036baca6158aa51e93d4d3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 Jul 2020 16:15:47 +0900 Subject: Use `proc->env` to check `block_given?` if possible; fix #5039 This bug has been there since mruby 1.4.0 (2018-04). --- src/kernel.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/kernel.c b/src/kernel.c index 8f0c9c7b5..a74f8a8ed 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -99,6 +99,18 @@ mrb_obj_id_m(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(mrb_obj_id(self)); } +static int +env_bidx(struct REnv *e) +{ + int bidx; + + /* use saved block arg position */ + bidx = MRB_ENV_BIDX(e); + /* bidx may be useless (e.g. define_method) */ + if (bidx >= MRB_ENV_LEN(e)) return -1; + return bidx; +} + /* 15.3.1.2.2 */ /* 15.3.1.2.5 */ /* 15.3.1.3.6 */ @@ -129,6 +141,8 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) mrb_callinfo *ci = &mrb->c->ci[-1]; mrb_callinfo *cibase = mrb->c->cibase; mrb_value *bp; + int bidx; + struct REnv *e = NULL; struct RProc *p; if (ci <= cibase) { @@ -139,29 +153,36 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) /* search method/class/module proc */ while (p) { if (MRB_PROC_SCOPE_P(p)) break; + e = MRB_PROC_ENV(p); p = p->upper; } if (p == NULL) return mrb_false_value(); + if (e) { + bidx = env_bidx(e); + if (bidx < 0) return mrb_false_value(); + bp = &e->stack[bidx]; + goto block_given; + } /* search ci corresponding to proc */ while (cibase < ci) { if (ci->proc == p) break; ci--; } if (ci == cibase) { - return mrb_false_value(); + /* proc is closure */ + if (!MRB_PROC_ENV_P(p)) return mrb_false_value(); + e = MRB_PROC_ENV(p); + bidx = env_bidx(e); + if (bidx < 0) return mrb_false_value(); + bp = &e->stack[bidx]; } else if (ci->env) { - struct REnv *e = ci->env; - int bidx; - + e = ci->env; /* top-level does not have block slot (always false) */ - if (e->stack == mrb->c->stbase) - return mrb_false_value(); - /* use saved block arg position */ - bidx = MRB_ENV_BIDX(e); + if (e->stack == mrb->c->stbase) return mrb_false_value(); + bidx = env_bidx(e); /* bidx may be useless (e.g. define_method) */ - if (bidx >= MRB_ENV_LEN(e)) - return mrb_false_value(); + if (bidx < 0) return mrb_false_value(); bp = &e->stack[bidx]; } else { @@ -173,6 +194,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) bp++; } } + block_given: if (mrb_nil_p(*bp)) return mrb_false_value(); return mrb_true_value(); -- 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(-) 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(+) 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(-) 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(-) 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(-) 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 d023adcb12191de7d8ae8144f100db46db887e1a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 19 Jul 2020 07:45:16 +0900 Subject: Add new specifier `c` to `mrb_get_args`. `C` retrieves a `mrb_value` that refers a class/module. `c` retrieves a `struct RClass*` pointer to a class/module. --- src/class.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/class.c b/src/class.c index 1a36c1333..30dc4c17a 100644 --- a/src/class.c +++ b/src/class.c @@ -587,6 +587,7 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil z: String [char*] NUL terminated string; z! gives NULL for nil a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil + c: Class/Module [strcut RClass*] f: Fixnum/Float [mrb_float] i: Fixnum/Float [mrb_int] b: boolean [mrb_bool] @@ -713,6 +714,22 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'c': + { + struct RClass **p; + + p = va_arg(ap, struct RClass**); + if (i < argc) { + mrb_value ss; + + ss = argv[i++]; + if (!class_ptr_p(ss)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss); + } + *p = mrb_class_ptr(ss); + } + } + break; case 'S': { mrb_value *p; -- 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 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 0685784119376ef9b1ec3eff7197ab6108c033c2 Mon Sep 17 00:00:00 2001 From: Rory OConnell <19547+RoryO@users.noreply.github.com> Date: Sun, 19 Jul 2020 15:40:29 -0700 Subject: Adding to authors --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 366149fb0..83a0772a6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,3 +43,4 @@ of this list. YAMAMOTO Masaya KOBAYASHI Shuji RIZAL Reckordp + Rory O'Connell -- 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(-) 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 6334949ba69363cb909a57d6871895bd6d98bb6b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 Jul 2020 12:47:35 +0900 Subject: Fix the VM stack handling bug in 'mrb_yield_with_class()`; fix #5042 --- src/vm.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/vm.c b/src/vm.c index 136ea2fcf..f74be7edd 100644 --- a/src/vm.c +++ b/src/vm.c @@ -754,16 +754,25 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value ci = cipush(mrb); ci->mid = mid; ci->proc = p; - ci->stackent = mrb->c->stack; - ci->argc = (int)argc; ci->target_class = c; ci->acc = CI_ACC_SKIP; - n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs; - mrb->c->stack = mrb->c->stack + n; + ci->stackent = mrb->c->stack; + mrb->c->stack += n; + if (argc >= CALL_MAXARGS) { + ci->argc = -1; + n = 3; + } + else { + ci->argc = (int)argc; + n = argc + 2; + } mrb_stack_extend(mrb, n); - mrb->c->stack[0] = self; - if (argc > 0) { + if (ci->argc < 0) { + mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv); + argc = 1; + } + else if (argc > 0) { stack_copy(mrb->c->stack+1, argv, argc); } mrb->c->stack[argc+1] = mrb_nil_value(); -- 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(-) 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(-) 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 670622f45dae813e6e80759b9389309abf98ec8a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 Jul 2020 15:55:51 +0900 Subject: Skip unnecessary `mark_context` if `mrb->c == mrb->root_c`. --- src/gc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gc.c b/src/gc.c index fd4fb2406..135d7416d 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1076,7 +1076,9 @@ final_marking_phase(mrb_state *mrb, mrb_gc *gc) } mrb_gc_mark_gv(mrb); mark_context(mrb, mrb->c); - mark_context(mrb, mrb->root_c); + if (mrb->c != mrb->root_c) { + mark_context(mrb, mrb->root_c); + } mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); gc_mark_gray_list(mrb, gc); mrb_assert(gc->gray_list == NULL); -- cgit v1.2.3 From 914da3d7121613d6e440c700a23b97445bd81308 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:18:45 +0900 Subject: Small comment fix in `mrblib/array.c`. --- mrblib/array.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrblib/array.rb b/mrblib/array.rb index 6535d6d83..6bcc8c482 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -12,7 +12,7 @@ class Array # ISO 15.2.12.5.10 # def each(&block) # return to_enum :each unless block - + # # idx = 0 # while idx < length # block.call(self[idx]) -- cgit v1.2.3 From 0bb4d10ca7dacaeb5873cfd2e61423e8a4222350 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:19:25 +0900 Subject: Define `Array#to_a` to avoid unnecessary loops. --- mrblib/array.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mrblib/array.rb b/mrblib/array.rb index 6bcc8c482..8586fbc39 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -268,4 +268,8 @@ class Array def sort(&block) self.dup.sort!(&block) end + + def to_a + self + end end -- cgit v1.2.3 From 5533c2983373a9fca5a97074ebe9258841ce4d00 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:21:05 +0900 Subject: Use `mrb_field_write_barrier` instead of `mrb_write_barrier` for `push`. When the array is very big, the simpler `mrb_write_barrier` causes calling `gc_mark_children` for big arrays repeatedly. That would hinder performance very badly. --- src/array.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/array.c b/src/array.c index dae2fbf34..eb94fc6c7 100644 --- a/src/array.c +++ b/src/array.c @@ -522,8 +522,10 @@ mrb_ary_push_m(mrb_state *mrb, mrb_value self) } array_copy(ARY_PTR(a)+len, argv, alen); ARY_SET_LEN(a, len2); - mrb_write_barrier(mrb, (struct RBasic*)a); - + while (alen--) { + mrb_field_write_barrier_value(mrb, (struct RBasic*)a, *argv); + argv++; + } return self; } -- cgit v1.2.3 From 097f525817d0825f12780adfc8542bb7f3db1302 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:23:10 +0900 Subject: Avoid using `mrb_ary_modify` from the internal function. `mrb_ary_modify` calls `mrb_write_barrier`, so can cause the same problem of the past `push`. It is provided for use-level API. --- src/array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/array.c b/src/array.c index eb94fc6c7..ef8588d31 100644 --- a/src/array.c +++ b/src/array.c @@ -943,7 +943,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self) mrb_value v1, v2, v3; mrb_int i, len; - mrb_ary_modify(mrb, mrb_ary_ptr(self)); + ary_modify(mrb, mrb_ary_ptr(self)); if (mrb_get_argc(mrb) == 2) { mrb_value *vs = mrb_get_argv(mrb); v1 = vs[0]; v2 = vs[1]; -- cgit v1.2.3 From c99bb756c4d57df5466d4ff0b4749397041aab1a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:25:01 +0900 Subject: Move `gray_list` update from `gc_mark_children`. The responsibility moved to caller to avoid confusion. Currently the function is called from only 2 places, so it is relatively easy to ensure not to update `gray_list` in the caller. But the assumption may change in the future. --- src/gc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gc.c b/src/gc.c index 135d7416d..d21b7f9fc 100644 --- a/src/gc.c +++ b/src/gc.c @@ -667,7 +667,6 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { mrb_assert(is_gray(obj)); paint_black(obj); - gc->gray_list = obj->gcnext; mrb_gc_mark(mrb, (struct RBasic*)obj->c); switch (obj->tt) { case MRB_TT_ICLASS: @@ -1043,10 +1042,9 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) static void gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) { while (gc->gray_list) { - if (is_gray(gc->gray_list)) - gc_mark_children(mrb, gc, gc->gray_list); - else - gc->gray_list = gc->gray_list->gcnext; + struct RBasic *obj = gc->gray_list; + gc->gray_list = obj->gcnext; + gc_mark_children(mrb, gc, obj); } } @@ -1058,6 +1056,7 @@ incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) while (gc->gray_list && tried_marks < limit) { struct RBasic *obj = gc->gray_list; + gc->gray_list = obj->gcnext; gc_mark_children(mrb, gc, obj); tried_marks += gc_gray_counts(mrb, gc, obj); } -- cgit v1.2.3 From 491aa1bfe5809146eec85b7d2915f3d389eb59b5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Jul 2020 14:28:24 +0900 Subject: Use more local variables. To make debugging easy, and to improve the performance little bit. --- src/gc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gc.c b/src/gc.c index d21b7f9fc..e92516ca7 100644 --- a/src/gc.c +++ b/src/gc.c @@ -730,10 +730,11 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) case MRB_TT_ARRAY: { struct RArray *a = (struct RArray*)obj; - size_t i, e; + size_t i, e=ARY_LEN(a); + mrb_value *p = ARY_PTR(a); - for (i=0,e=ARY_LEN(a); i Date: Wed, 22 Jul 2020 14:31:07 +0900 Subject: Use more `mrb_field_write_barrier` for instance variables. --- src/variable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/variable.c b/src/variable.c index 0755f7d92..0c94f412e 100644 --- a/src/variable.c +++ b/src/variable.c @@ -350,7 +350,7 @@ mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value obj->iv = iv_new(mrb); } iv_put(mrb, obj->iv, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)obj); + mrb_field_write_barrier_value(mrb, (struct RBasic*)obj, v); } MRB_API void @@ -680,7 +680,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) if (iv_get(mrb, t, sym, NULL)) { mrb_check_frozen(mrb, c); iv_put(mrb, t, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); return; } c = c->super; @@ -712,7 +712,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) } iv_put(mrb, c->iv, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); } MRB_API void -- 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(-) 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 e7599050dc7055bc013b4114401e62670bf86828 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 23 Jul 2020 07:06:35 +0900 Subject: Fix a bug with `ht_index` called with `size==0`; fix #5046 It happens when a hash made empty calls `rehash`. --- src/hash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hash.c b/src/hash.c index 79b61d8b2..9a690bf1a 100644 --- a/src/hash.c +++ b/src/hash.c @@ -174,6 +174,11 @@ ht_index(mrb_state *mrb, htable *t) segment *seg; size_t i; + if (size == 0) { + t->index = NULL; + mrb_free(mrb, index); + return; + } /* allocate index table */ if (index && index->size >= UPPER_BOUND(index->capa)) { size = index->capa+1; @@ -194,7 +199,7 @@ ht_index(mrb_state *mrb, htable *t) index->table[i] = NULL; } - /* rebuld index */ + /* rebuild index */ mask = HT_MASK(index); seg = t->rootseg; while (seg) { -- 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(+) 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(+) 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(-) 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(-) 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 ccd5f203bf1e7c54cb08fc9eecfe2772277b5a58 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 22 Jul 2020 00:18:28 +0900 Subject: Improve prototype for `mrb_objspace_page_slot_size()`; ref #5032 If it qualify a return type that is not a pointer with `const`, the compiler ignores it. --- include/mruby/gc.h | 2 +- src/gc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 3b2ded9d4..1beffba2a 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -21,7 +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_int mrb_objspace_page_slot_size(void); MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); #ifndef MRB_GC_ARENA_SIZE diff --git a/src/gc.c b/src/gc.c index fd4fb2406..fa7f30889 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1599,8 +1599,8 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo } } -const mrb_int -mrb_objspace_page_slot_size() +mrb_int +mrb_objspace_page_slot_size(void) { const mrb_int i = sizeof(RVALUE); return i; -- cgit v1.2.3 From f868d7d357d7456f15fa4c1d0219784aa1c8c2c6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 24 Jul 2020 13:13:06 +0900 Subject: Change the logic to calculate object (`iv_tbl`) size; #5045 --- src/variable.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/variable.c b/src/variable.c index 8b4bdf0ce..f05fcee90 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1131,9 +1131,16 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) mrb_int mrb_obj_iv_tbl_memsize(mrb_state* mrb, mrb_value obj) { - 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); + size_t nseg = 0; + segment *seg; + + if (mrb_obj_ptr(obj)->iv == NULL) return 0; + seg = mrb_obj_ptr(obj)->iv->rootseg; + while (seg) { + nseg++; + seg = seg->next; + } + return sizeof(iv_tbl) + sizeof(segment)*nseg; } #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) -- cgit v1.2.3 From 0c88c717861a4ec182e41f2c290ec0ef31029967 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sat, 25 Jul 2020 16:59:02 +0900 Subject: Use type tag for hash code in `ht_hash_func()` The function corresponding to `ht_hash_func()` was as follows in the days of khash implementation (before d78acc7a). ```c mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) { enum mrb_vtype t = mrb_type(key); ... switch (t) { ... default: hv = mrb_funcall(mrb, key, "hash", 0); h = (khint_t)t ^ (khint_t)mrb_fixnum(hv); break; } ... } ``` When switched to the segmented list implementation (d78acc7a), this function was changed as follows. ```c sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key) { enum mrb_vtype tt = mrb_type(key); ... switch (tt) { ... default: hv = mrb_funcall(mrb, key, "hash", 0); h = (size_t)t ^ (size_t)mrb_fixnum(hv); break; } ... } ``` Since the argument `t` was added, the variable for type tag was changed from `t` to `tt`, but the variable used in the expression of `h` remained `t`. Probably this is an omission of change, so fixed it. --- src/hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hash.c b/src/hash.c index 9a690bf1a..128836fce 100644 --- a/src/hash.c +++ b/src/hash.c @@ -73,7 +73,7 @@ ht_hash_func(mrb_state *mrb, htable *t, mrb_value key) default: hv = mrb_funcall(mrb, key, "hash", 0); - h = (size_t)t ^ (size_t)mrb_fixnum(hv); + h = (size_t)tt ^ (size_t)mrb_fixnum(hv); break; } if (index && (index != t->index || capa != index->capa)) { -- 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(-) 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 d96be5c1b2304c21ab9f15023a96e21b9ea279c6 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 29 Apr 2020 18:02:17 +0900 Subject: Extend the `cipush()` and `cipop()` functions - Returns the updated call info. - Unify the processing around `cipush()`. - `cipop()` restores the stack. --- src/vm.c | 130 +++++++++++++++------------------------------------------------ 1 file changed, 30 insertions(+), 100 deletions(-) diff --git a/src/vm.c b/src/vm.c index f74be7edd..79bb3ed60 100644 --- a/src/vm.c +++ b/src/vm.c @@ -269,14 +269,13 @@ top_proc(mrb_state *mrb, struct RProc *proc) #define CI_ACC_RESUMED -3 static inline mrb_callinfo* -cipush(mrb_state *mrb) +cipush(mrb_state *mrb, const mrb_code *pc, int push_stacks, int acc, + struct RClass *target_class, struct RProc *proc, mrb_sym mid, int argc) { struct mrb_context *c = mrb->c; static const mrb_callinfo ci_zero = { 0 }; mrb_callinfo *ci = c->ci; - int ridx = ci->ridx; - if (ci + 1 == c->ciend) { ptrdiff_t size = ci - c->cibase; @@ -286,8 +285,16 @@ cipush(mrb_state *mrb) } ci = ++c->ci; *ci = ci_zero; - ci->epos = mrb->c->eidx; - ci->ridx = ridx; + ci->mid = mid; + ci->proc = proc; + ci->stackent = c->stack; + ci->epos = c->eidx; + ci->ridx = ci[-1].ridx; + ci->pc = pc; + ci->argc = argc; + ci->acc = acc; + ci->target_class = target_class; + c->stack += push_stacks; return ci; } @@ -313,14 +320,16 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e) } } -static inline void +static inline mrb_callinfo* cipop(mrb_state *mrb) { struct mrb_context *c = mrb->c; struct REnv *env = c->ci->env; + mrb->c->stack = c->ci->stackent; c->ci--; if (env) mrb_env_unshare(mrb, env); + return c->ci; } void mrb_exc_set(mrb_state *mrb, mrb_value exc); @@ -356,16 +365,9 @@ ecall(mrb_state *mrb) nregs = ci->proc->body.irep->nregs; } cioff = ci - c->cibase; - ci = cipush(mrb); - ci->stackent = mrb->c->stack; - ci->mid = ci[-1].mid; - ci->acc = CI_ACC_SKIP; - ci->argc = 0; - ci->proc = p; - ci->target_class = MRB_PROC_TARGET_CLASS(p); + ci = cipush(mrb, NULL, nregs, CI_ACC_SKIP, MRB_PROC_TARGET_CLASS(p), p, ci->mid, 0); env = MRB_PROC_ENV(p); mrb_assert(env); - c->stack += nregs; exc = mrb->exc; mrb->exc = 0; if (exc) { mrb_gc_protect(mrb, mrb_obj_value(exc)); @@ -447,7 +449,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc } MRB_CATCH(&c_jmp) { /* error */ while (nth_ci < (mrb->c->ci - mrb->c->cibase)) { - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } mrb->jmp = 0; @@ -486,12 +487,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) { mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->argc = (int)argc; - ci->target_class = c; - mrb->c->stack = mrb->c->stack + n; + ci = cipush(mrb, NULL, n, 0, c, NULL, mid, argc); if (argc < 0) argc = 1; if (mrb->c->stbase <= argv && argv < mrb->c->stend) { voff = argv - mrb->c->stbase; @@ -524,7 +520,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc if (MRB_METHOD_CFUNC_P(m)) { ci->acc = CI_ACC_DIRECT; val = MRB_METHOD_CFUNC(m)(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } else { @@ -565,11 +560,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) stack_clear(mrb->c->stack+keep, nregs-keep); } - ci = cipush(mrb); - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; + cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0); return self; } @@ -671,11 +662,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) mrb->c->stack[0] = self; mrb->c->stack[1] = self; stack_clear(mrb->c->stack+2, nregs-2); - ci = cipush(mrb); - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; + ci = cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0); return self; } @@ -751,13 +738,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } p = mrb_proc_ptr(b); - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->target_class = c; - ci->acc = CI_ACC_SKIP; - ci->stackent = mrb->c->stack; - mrb->c->stack += n; + ci = cipush(mrb, NULL, n, CI_ACC_SKIP, c, p, mid, 0 /* dummy */); if (argc >= CALL_MAXARGS) { ci->argc = -1; n = 3; @@ -779,7 +760,6 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value if (MRB_PROC_CFUNC_P(p)) { val = MRB_PROC_CFUNC(p)(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } else { @@ -1328,15 +1308,7 @@ RETRY_TRY_BLOCK: mrb->c->ensure[epos+n] = NULL; if (proc == NULL) continue; irep = proc->body.irep; - ci = cipush(mrb); - ci->mid = ci[-1].mid; - ci->argc = 0; - ci->proc = proc; - ci->stackent = mrb->c->stack; - ci->target_class = target_class; - ci->pc = pc; - ci->acc = nregs; - mrb->c->stack += ci->acc; + ci = cipush(mrb, pc, nregs, nregs, target_class, proc, ci->mid, 0); mrb_stack_extend(mrb, irep->nregs); regs[0] = self; pc = irep->iseq; @@ -1418,17 +1390,7 @@ RETRY_TRY_BLOCK: } /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->target_class = cls; - ci->argc = argc; - - ci->pc = pc; - ci->acc = a; - - /* prepare stack */ - mrb->c->stack += a; + ci = cipush(mrb, pc, a, a, cls, NULL, mid, argc); if (MRB_METHOD_CFUNC_P(m)) { if (MRB_METHOD_PROC_P(m)) { @@ -1470,7 +1432,6 @@ RETRY_TRY_BLOCK: } mrb->c->stack[0] = recv; /* pop stackpos */ - mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); JUMP; @@ -1508,10 +1469,9 @@ RETRY_TRY_BLOCK: if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->c->ci; - mrb->c->stack = ci->stackent; - regs[ci->acc] = recv; pc = ci->pc; cipop(mrb); + regs[ci->acc] = recv; irep = mrb->c->ci->proc->body.irep; pool = irep->pool; syms = irep->syms; @@ -1617,15 +1577,9 @@ RETRY_TRY_BLOCK: } /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->target_class = cls; - ci->pc = pc; - ci->argc = argc; + ci = cipush(mrb, pc, a, 0, cls, NULL, mid, argc); /* prepare stack */ - mrb->c->stack += a; mrb->c->stack[0] = recv; if (MRB_METHOD_CFUNC_P(m)) { @@ -1652,8 +1606,6 @@ RETRY_TRY_BLOCK: } } mrb->c->stack[0] = v; - /* pop stackpos */ - mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); JUMP; @@ -1954,13 +1906,11 @@ RETRY_TRY_BLOCK: goto L_RESCUE; } while (ci[0].ridx == ci[-1].ridx) { - cipop(mrb); - mrb->c->stack = ci->stackent; - if (ci->acc == CI_ACC_SKIP && prev_jmp) { + ci = cipop(mrb); + if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } - ci = mrb->c->ci; if (ci == mrb->c->cibase) { if (ci->ridx == 0) { L_FTOP: /* fiber top */ @@ -2142,15 +2092,13 @@ RETRY_TRY_BLOCK: return v; } acc = ci->acc; - mrb->c->stack = ci->stackent; - cipop(mrb); + ci = cipop(mrb); if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) { mrb_gc_arena_restore(mrb, ai); mrb->jmp = prev_jmp; return v; } - pc = ci->pc; - ci = mrb->c->ci; + pc = ci[1].pc; DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid))); proc = mrb->c->ci->proc; irep = proc->body.irep; @@ -2664,7 +2612,6 @@ RETRY_TRY_BLOCK: } CASE(OP_EXEC, BB) { - mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; mrb_irep *nirep = irep->reps[b]; @@ -2677,19 +2624,7 @@ RETRY_TRY_BLOCK: p->flags |= MRB_PROC_SCOPE; /* prepare call stack */ - ci = cipush(mrb); - ci->pc = pc; - ci->acc = a; - ci->mid = 0; - ci->stackent = mrb->c->stack; - ci->argc = 0; - ci->target_class = mrb_class_ptr(recv); - - /* prepare stack */ - mrb->c->stack += a; - - /* setup block to call */ - ci->proc = p; + cipush(mrb, pc, a, a, mrb_class_ptr(recv), p, 0, 0); irep = p->body.irep; pool = irep->pool; @@ -2834,7 +2769,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { - mrb_callinfo *ci; mrb_value v; if (!mrb->c->cibase) { @@ -2844,11 +2778,7 @@ mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int sta mrb->c->ci->env = NULL; return mrb_vm_run(mrb, proc, self, stack_keep); } - ci = cipush(mrb); - ci->stackent = mrb->c->stack; - ci->mid = 0; - ci->acc = CI_ACC_SKIP; - ci->target_class = mrb->object_class; + cipush(mrb, NULL, 0, CI_ACC_SKIP, mrb->object_class, NULL, 0, 0); v = mrb_vm_run(mrb, proc, self, stack_keep); return v; -- 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(+) 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 0a505dcfd6f7abd107e72b0b2a4cab561928f756 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 31 Jul 2020 18:14:02 +0900 Subject: Simplify `khash.h`. - Remove ` kh_put_prepare` function used only internally - Remove `n_occupied` member from `kh_` struct --- include/mruby/khash.h | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/include/mruby/khash.h b/include/mruby/khash.h index 9f3f1a2cc..4884ba73c 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -61,7 +61,6 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; typedef struct kh_##name { \ khint_t n_buckets; \ khint_t size; \ - khint_t n_occupied; \ uint8_t *ed_flags; \ khkey_t *keys; \ khval_t *vals; \ @@ -73,7 +72,6 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \ khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \ khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \ - void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \ void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \ void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); @@ -103,7 +101,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \ uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \ if (!p) { return 1; } \ - h->size = h->n_occupied = 0; \ + h->size = 0; \ h->keys = (khkey_t *)p; \ h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \ h->ed_flags = p+len*sz; \ @@ -143,7 +141,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) (void)mrb; \ if (h && h->ed_flags) { \ kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \ - h->size = h->n_occupied = 0; \ + h->size = 0; \ } \ } \ khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \ @@ -184,16 +182,12 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) mrb_free(mrb, old_keys); \ } \ } \ - void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \ - { \ - if (h->n_occupied >= khash_upper_bound(h)) { \ - kh_resize_##name(mrb, h, h->n_buckets*2); \ - } \ - } \ khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \ { \ khint_t k, del_k, step = 0; \ - kh_put_prepare_##name(mrb, h); \ + if (h->size >= khash_upper_bound(h)) { \ + kh_resize_##name(mrb, h, h->n_buckets*2); \ + } \ k = __hash_func(mrb,key) & khash_mask(h); \ del_k = kh_end(h); \ while (!__ac_isempty(h->ed_flags, k)) { \ @@ -221,7 +215,6 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) h->keys[k] = key; \ h->ed_flags[k/4] &= ~__m_empty[k%4]; \ h->size++; \ - h->n_occupied++; \ if (ret) *ret = 1; \ return k; \ } \ @@ -256,7 +249,6 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) #define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h) #define kh_clear(name, mrb, h) kh_clear_##name(mrb, h) #define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s) -#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h) #define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL) #define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r) #define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k) -- cgit v1.2.3 From faed5054f8a1503b8b755ea5be8575fc8b68e110 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 3 Aug 2020 15:53:50 +0900 Subject: Initialized local variables in `mrb_hash_shift()`. --- src/hash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hash.c b/src/hash.c index 128836fce..fd338d53b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1072,7 +1072,8 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) mrb_hash_modify(mrb, hash); if (t && t->size > 0) { - mrb_value del_key, del_val; + mrb_value del_key = mrb_nil_value(); + mrb_value del_val = mrb_nil_value(); ht_shift(mrb, t, &del_key, &del_val); mrb_gc_protect(mrb, del_key); -- 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(-) 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(-) 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 From fde95a7db59c84971252831d9ebfa1ce79d134af Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 4 Aug 2020 21:54:47 +0900 Subject: Improve `rake benchmark` - Use POSIX format instead of GNU extension for `time` command. For example FreeBSD's `time(1)` does not have GNU extensions available. - Sort `benchmark/bm_*.rb`. This is because the order of the bar graph cannot be uniquely determined depending on the result of `Dir.glob`. --- tasks/benchmark.rake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/benchmark.rake b/tasks/benchmark.rake index 84e69ebee..6352f5c17 100644 --- a/tasks/benchmark.rake +++ b/tasks/benchmark.rake @@ -5,7 +5,7 @@ end $dat_files = [] def bm_files - Dir.glob("#{MRUBY_ROOT}/benchmark/bm_*.rb") + Dir.glob("#{MRUBY_ROOT}/benchmark/bm_*.rb").sort end def build_config_name @@ -67,8 +67,8 @@ MRuby.each_target do |target| puts "..." data = (0...MRuby::BENCHMARK_REPEAT).map do |n| - str = %x{(time -f "%e %S %U" #{mruby_bin} #{bm_file}) 2>&1 >/dev/null} - str.split(' ').map(&:to_f) + str = %x{(time -p #{mruby_bin} #{bm_file}) 2>&1 >/dev/null} + str.scan(/\d+\.\d+$/).map(&:to_f) # [real, user, sys] end File.open(task.name, "w") do |f| -- cgit v1.2.3