summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml74
-rw-r--r--AUTHORS1
-rw-r--r--appveyor.yml55
-rw-r--r--include/mruby/gc.h1
-rw-r--r--include/mruby/hash.h1
-rw-r--r--include/mruby/khash.h18
-rw-r--r--include/mruby/variable.h1
-rw-r--r--mrbgems/mruby-io/src/io.c5
-rw-r--r--mrbgems/mruby-objectspace/src/mruby_objectspace.c23
-rw-r--r--mrbgems/mruby-os-memsize/mrbgem.rake10
-rw-r--r--mrbgems/mruby-os-memsize/src/memsize.c242
-rw-r--r--mrbgems/mruby-os-memsize/test/memsize.rb63
-rw-r--r--mrbgems/mruby-pack/src/pack.c3
-rw-r--r--mrbgems/mruby-print/mrblib/print.rb31
-rw-r--r--mrbgems/mruby-print/src/print.c84
-rw-r--r--mrbgems/mruby-random/src/random.c28
-rw-r--r--mrbgems/mruby-test/mrbgem.rake14
-rw-r--r--mrblib/array.rb6
-rw-r--r--src/array.c8
-rw-r--r--src/class.c29
-rw-r--r--src/etc.c7
-rw-r--r--src/gc.c37
-rw-r--r--src/hash.c24
-rw-r--r--src/kernel.c54
-rw-r--r--src/object.c1
-rw-r--r--src/state.c2
-rw-r--r--src/string.c1
-rw-r--r--src/variable.c21
-rw-r--r--src/vm.c130
-rw-r--r--tasks/benchmark.rake6
-rw-r--r--tasks/mrbgems.rake12
31 files changed, 681 insertions, 311 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 81deb4515..335c0cdf6 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 -m -j4 all test
- env:
- MRUBY_CONFIG: travis_config.rb
+ - name: build
+ run: rake -m
+ - name: test
+ run: rake test
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 -m -j4 all test
- env:
- MRUBY_CONFIG: travis_config.rb
- CC: gcc
- CXX: g++
+ - name: build
+ run: rake -m
+ - name: test
+ run: rake test
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 -m -j4 all test
- env:
- MRUBY_CONFIG: travis_config.rb
- CC: clang
- CXX: clang++
+ - name: build
+ run: rake -m
+ - name: test
+ run: rake test
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 -m -j4 all test
- env:
- MRUBY_CONFIG: travis_config.rb
+ - name: build
+ run: rake -m
+ - name: test
+ run: rake test
Windows-MinGW:
runs-on: windows-latest
@@ -57,8 +65,8 @@ 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' test
env:
MRUBY_CONFIG: travis_config.rb
CFLAGS: -g -O1 -Wall -Wundef
@@ -82,25 +90,13 @@ 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
+ run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -E 'STDOUT.sync=true' -m
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
+ - 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
- # 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"
+ MRUBY_CONFIG: travis_config.rb
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
diff --git a/appveyor.yml b/appveyor.yml
index e135383e1..e963ea035 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,39 +1,44 @@
version: "{build}"
-os: Visual Studio 2017
-
shallow_clone: true
environment:
matrix:
- # Visual Studio 2017 64bit
- - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
-
- # Visual Studio 2017 32bit
- - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
- machine: x86
-
- # Visual Studio 2015 64bit
- - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
- machine: amd64
-
- # Visual Studio 2015 32bit
- - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.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
+
+ - 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
+
+ - 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
+
+ - 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
+
+ - 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
+
+ - 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\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 -m -j4
+ - rake -E STDOUT.sync=true test
diff --git a/include/mruby/gc.h b/include/mruby/gc.h
index 4d9fb60eb..1beffba2a 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);
+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/include/mruby/hash.h b/include/mruby/hash.h
index 0052a1105..04b265ec3 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 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/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)
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-io/src/io.c b/mrbgems/mruby-io/src/io.c
index 505ceb248..b3e192899 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 <winsock.h>
#include <io.h>
+ #include <basetsd.h>
#define open _open
#define close _close
#define dup _dup
@@ -32,6 +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
diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
index b89fb0580..bded3afa8 100644
--- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c
+++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
@@ -2,6 +2,14 @@
#include <mruby/gc.h>
#include <mruby/hash.h>
#include <mruby/class.h>
+#include <mruby/object.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/array.h>
+#include <mruby/variable.h>
+#include <mruby/proc.h>
+#include <mruby/value.h>
+#include <mruby/range.h>
struct os_count_struct {
mrb_int total;
@@ -92,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;
@@ -104,9 +113,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
@@ -121,8 +130,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;
@@ -158,12 +167,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);
}
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..65020c97f
--- /dev/null
+++ b/mrbgems/mruby-os-memsize/src/memsize.c
@@ -0,0 +1,242 @@
+#include <mruby.h>
+#include <mruby/gc.h>
+#include <mruby/hash.h>
+#include <mruby/class.h>
+#include <mruby/object.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/array.h>
+#include <mruby/variable.h>
+#include <mruby/proc.h>
+#include <mruby/value.h>
+#include <mruby/range.h>
+
+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_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)
+{
+ 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);
+ size++; /* NUL terminator */
+ }
+ 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 (obj_is_kind_of_checked(mrb, obj, "UnboundMethod") ||
+ obj_is_kind_of_checked(mrb, obj, "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) -> 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.
+ */
+
+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..6be8f1b06
--- /dev/null
+++ b/mrbgems/mruby-os-memsize/test/memsize.rb
@@ -0,0 +1,63 @@
+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'
+
+ 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-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c
index 3a2c3367a..80de397f4 100644
--- a/mrbgems/mruby-pack/src/pack.c
+++ b/mrbgems/mruby-pack/src/pack.c
@@ -1298,7 +1298,8 @@ 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;
}
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
@@ -4,38 +4,9 @@
# 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..df153d920 100644
--- a/mrbgems/mruby-print/src/print.c
+++ b/mrbgems/mruby-print/src/print.c
@@ -17,39 +17,73 @@
#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;
+}
+
+/* 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;
- printstr(mrb, argv);
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i=0; i<argc; i++) {
+ mrb_value s = mrb_str_to_str(mrb, argv[i]);
+ printstr(mrb, RSTRING_PTR(s), RSTRING_LEN(s));
+ }
+ return mrb_nil_value();
+}
+
+/* 15.3.1.2.11 */
+/* 15.3.1.3.39 */
+static mrb_value
+mrb_puts(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<argc; i++) {
+ 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') {
+ printstr(mrb, "\n", 1);
+ }
+ }
+ if (argc == 0) {
+ printstr(mrb, "\n", 1);
+ }
+ return mrb_nil_value();
}
void
@@ -58,6 +92,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
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
index 515c0707a..10c81b946 100644
--- a/mrbgems/mruby-random/src/random.c
+++ b/mrbgems/mruby-random/src/random.c
@@ -218,6 +218,34 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
mrb_value r = mrb_nil_value();
rand_state *random;
+ /*
+ * MSC compiler bug generating invalid instructions with optimization
+ * 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
+ /* 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<mrb_value*>(v_r - ii);
+#else
+ p_r = (mrb_value*)v_r - ii;
+#endif
+ r = *p_r;
+#endif
+
if (RARRAY_LEN(ary) > 1) {
mrb_get_args(mrb, "|o", &r);
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/mrblib/array.rb b/mrblib/array.rb
index 6535d6d83..8586fbc39 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])
@@ -268,4 +268,8 @@ class Array
def sort(&block)
self.dup.sort!(&block)
end
+
+ def to_a
+ self
+ end
end
diff --git a/src/array.c b/src/array.c
index dae2fbf34..ef8588d31 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;
}
@@ -941,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];
diff --git a/src/class.c b/src/class.c
index 1a36c1333..fc8a38ff9 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;
@@ -1151,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/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:
diff --git a/src/gc.c b/src/gc.c
index 03c561d35..be812c4d3 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -225,14 +225,8 @@ 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) {
- if (mrb->gc.out_of_memory) {
- mrb_raise_nomemory(mrb);
- /* mrb_panic(mrb); */
- }
- else {
- mrb->gc.out_of_memory = TRUE;
- mrb_raise_nomemory(mrb);
- }
+ mrb->gc.out_of_memory = TRUE;
+ mrb_raise_nomemory(mrb);
}
else {
mrb->gc.out_of_memory = FALSE;
@@ -673,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:
@@ -737,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<e; i++) {
- mrb_gc_mark_value(mrb, ARY_PTR(a)[i]);
+ for (i=0; i<e; i++) {
+ mrb_gc_mark_value(mrb, p[i]);
}
}
break;
@@ -1049,10 +1043,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);
}
}
@@ -1064,6 +1057,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);
}
@@ -1082,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);
@@ -1605,6 +1601,13 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo
}
}
+mrb_int
+mrb_objspace_page_slot_size(void)
+{
+ const mrb_int i = sizeof(RVALUE);
+ return i;
+}
+
#ifdef GC_TEST
#ifdef GC_DEBUG
static mrb_value gc_test(mrb_state *, mrb_value);
diff --git a/src/hash.c b/src/hash.c
index d9ee483d5..fd338d53b 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) {
@@ -518,6 +523,20 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p)
}
}
+mrb_int
+mrb_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)
@@ -1053,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);
diff --git a/src/kernel.c b/src/kernel.c
index 8f0c9c7b5..682feb13c 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();
@@ -498,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 */
@@ -535,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)
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/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)
{
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);
diff --git a/src/variable.c b/src/variable.c
index 030aa7b00..f05fcee90 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -349,7 +349,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
@@ -679,7 +679,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;
@@ -711,7 +711,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
@@ -1128,6 +1128,21 @@ 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)
+{
+ 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))
mrb_bool
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;
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|
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