Merge master.

This commit is contained in:
Hiroshi Mimaki
2020-08-06 17:38:20 +09:00
31 changed files with 680 additions and 310 deletions
+35 -39
View File
@@ -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
+1
View File
@@ -43,3 +43,4 @@ of this list.
YAMAMOTO Masaya
KOBAYASHI Shuji
RIZAL Reckordp
Rory O'Connell
+29 -24
View File
@@ -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
- 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 2017 32bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.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
- 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 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
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
+1
View File
@@ -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
+1
View File
@@ -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);
+5 -13
View File
@@ -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)
+1
View File
@@ -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);
+5
View File
@@ -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
@@ -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);
}
+10
View File
@@ -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
+242
View File
@@ -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)
{
}
+63
View File
@@ -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
+2 -1
View File
@@ -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;
}
+1 -30
View File
@@ -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
+60 -24
View File
@@ -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);
printstr(mrb, argv);
if (mrb_string_p(s)) {
printstr(mrb, RSTRING_PTR(s), RSTRING_LEN(s));
}
return s;
}
return 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;
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;
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
+28
View File
@@ -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);
+1 -13
View File
@@ -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|
+5 -1
View File
@@ -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
+5 -3
View File
@@ -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];
+23 -6
View File
@@ -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;
}
+4 -3
View File
@@ -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:
+20 -17
View File
@@ -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);
+22 -2
View File
@@ -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);
+38 -16
View File
@@ -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)
+1
View File
@@ -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;
-2
View File
@@ -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)
{
+1
View File
@@ -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);
+18 -3
View File
@@ -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
+30 -100
View File
@@ -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;
+3 -3
View File
@@ -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|
+11 -1
View File
@@ -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