summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-11-20 06:21:22 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-11-20 18:33:41 +0900
commit8f2c62407c0659d84126545e19505a851059e750 (patch)
tree7a073d389fc2f5fc7c14f86ffa96d0145bff9f82
parent6c06e77446f3cca4a92b3df8d0a5fe568c5fdc65 (diff)
downloadmruby-8f2c62407c0659d84126545e19505a851059e750.tar.gz
mruby-8f2c62407c0659d84126545e19505a851059e750.zip
Add `MRB_METHOD_TABLE_INLINE` option.
Now the method tables (in classes/modules and caches) keeps C function pointers without wrapping in `struct RProc` objects. For the sake of portability, `mrb_method_t` is represented by the struct and union, but if the most significant bit of the pointer is not used by the platform, `mrb_method_t` should be packed in `uintptr_t` to reduce memory usage. `MRB_METHOD_TABLE_INLINE` is turned on by default for linux.
-rw-r--r--include/mrbconf.h7
-rw-r--r--include/mruby.h19
-rw-r--r--include/mruby/class.h6
-rw-r--r--include/mruby/proc.h36
-rw-r--r--mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c8
-rw-r--r--mrbgems/mruby-proc-ext/test/proc.c14
-rw-r--r--mrbgems/mruby-struct/src/struct.c7
-rw-r--r--src/class.c88
-rw-r--r--src/kernel.c18
-rw-r--r--src/proc.c19
-rw-r--r--src/vm.c98
11 files changed, 205 insertions, 115 deletions
diff --git a/include/mrbconf.h b/include/mrbconf.h
index c4f6f38cd..96ab6b77f 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -36,6 +36,13 @@
/* size of the method cache (need to be the power of 2) */
//#define MRB_METHOD_CACHE_SIZE (1<<7)
+/* add -DMRB_METHOD_TABLE_INLINE unless platform uses MSB of pointers */
+//#define MRB_METHOD_TABLE_INLINE
+/* turn MRB_METHOD_TABLE_INLINE on for linux by default */
+#if !defined(MRB_METHOD_TABLE_INLINE) && defined(__linux__)
+# define MRB_METHOD_TABLE_INLINE
+#endif
+
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
//#define MRB_INT16
diff --git a/include/mruby.h b/include/mruby.h
index 1413d604e..5c8d38200 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -170,11 +170,25 @@ struct mrb_context {
# define MRB_METHOD_CACHE_SIZE (1<<7)
#endif
+typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value);
+
+#ifdef MRB_METHOD_TABLE_INLINE
+typedef uintptr_t mrb_method_t;
+#else
+typedef struct {
+ mrb_bool func_p;
+ union {
+ struct RProc *proc;
+ mrb_func_t func;
+ };
+} mrb_method_t;
+#endif
+
#ifdef MRB_METHOD_CACHE
struct mrb_cache_entry {
struct RClass *c;
mrb_sym mid;
- struct RProc *m;
+ mrb_method_t m;
};
#endif
@@ -257,9 +271,6 @@ typedef struct mrb_state {
mrb_int atexit_stack_len;
} mrb_state;
-
-typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
-
/**
* Defines a new class.
*
diff --git a/include/mruby/class.h b/include/mruby/class.h
index 1e1d3c136..ea35d8e17 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -74,12 +74,12 @@ MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
-MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
+MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
-MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
-MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
+MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
+MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
diff --git a/include/mruby/proc.h b/include/mruby/proc.h
index b33e9e1a2..d2b676bd0 100644
--- a/include/mruby/proc.h
+++ b/include/mruby/proc.h
@@ -55,8 +55,9 @@ struct RProc {
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
#define MRB_ASPEC_BLOCK(a) ((a) & 1)
-#define MRB_PROC_CFUNC 128
-#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0)
+#define MRB_PROC_CFUNC_FL 128
+#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)
+#define MRB_PROC_CFUNC(p) (p)->body.func
#define MRB_PROC_STRICT 256
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
#define MRB_PROC_ORPHAN 512
@@ -64,7 +65,7 @@ struct RProc {
#define MRB_PROC_ENVSET 1024
#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)
-#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class )
+#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class)
#define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\
if (MRB_PROC_ENV_P(p)) {\
(p)->e.env->c = (tc);\
@@ -95,8 +96,35 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
/* old name */
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
+#ifdef MRB_METHOD_TABLE_INLINE
+
+#define MRB_METHOD_FUNC_FL ((uintptr_t)1U<<(sizeof(uintptr_t)*8-1))
+#define MRB_METHOD_FUNC_P(m) ((uintptr_t)(m)&MRB_METHOD_FUNC_FL)
+#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL)))
+#define MRB_METHOD_FROM_FUNC(m,fn) m=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL))
+#define MRB_METHOD_FROM_PROC(m,pr) m=(mrb_method_t)(struct RProc*)(pr)
+#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
+#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
+#define MRB_METHOD_UNDEF_P(m) ((m)==0)
+
+#else
+
+#define MRB_METHOD_FUNC_P(m) ((m).func_p)
+#define MRB_METHOD_FUNC(m) ((m).func)
+#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).func_p=TRUE;(m).func=(fn);}while(0)
+#define MRB_METHOD_FROM_PROC(m,pr) do{(m).func_p=FALSE;(m).proc=(pr);}while(0)
+#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
+#define MRB_METHOD_PROC(fn) ((m).proc)
+#define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL)
+
+#endif /* MRB_METHOD_TABLE_INLINE */
+
+#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
+#define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL))
+
+
#include <mruby/khash.h>
-KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE)
+KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE)
MRB_END_DECL
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
index dead4b2a8..43e538ab4 100644
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -117,7 +117,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
{
const char* class_name;
const char* method_name;
- struct RProc* m;
+ mrb_method_t m;
struct RClass* sc;
const char* sn;
mrb_sym ssym;
@@ -136,10 +136,10 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
}
else if (method_p->class_name != NULL) {
m = mrb_method_search_vm(mrb, &class_obj, method_sym);
- if (m == NULL) {
+ if (MRB_METHOD_UNDEF_P(m)) {
return MRB_DEBUG_OK;
}
- if (MRB_PROC_CFUNC_P(m)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
*isCfunc = TRUE;
}
@@ -151,7 +151,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
sc = mrb_class_get(mrb, method_p->class_name);
ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
m = mrb_method_search_vm(mrb, &sc, ssym);
- if (m == NULL) {
+ if (MRB_METHOD_UNDEF_P(m)) {
return MRB_DEBUG_OK;
}
diff --git a/mrbgems/mruby-proc-ext/test/proc.c b/mrbgems/mruby-proc-ext/test/proc.c
index a77b68e9d..7072fe2e9 100644
--- a/mrbgems/mruby-proc-ext/test/proc.c
+++ b/mrbgems/mruby-proc-ext/test/proc.c
@@ -13,10 +13,13 @@ proc_new_cfunc_with_env(mrb_state *mrb, mrb_value self)
{
mrb_sym n;
mrb_value n_val;
+ mrb_method_t m;
+ struct RProc *p;
mrb_get_args(mrb, "n", &n);
n_val = mrb_symbol_value(n);
- mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
- mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val));
+ p = mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, mrb_class_ptr(self), n, m);
return self;
}
@@ -33,9 +36,12 @@ cfunc_env_get(mrb_state *mrb, mrb_value self)
{
mrb_sym n;
mrb_value *argv; mrb_int argc;
+ mrb_method_t m;
+ struct RProc *p;
mrb_get_args(mrb, "na", &n, &argv, &argc);
- mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
- mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv));
+ p = mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, mrb_class_ptr(self), n, m);
return self;
}
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index 1d2e62583..8de4b6c52 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -189,11 +189,14 @@ make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c
const char *name = mrb_sym2name_len(mrb, id, NULL);
if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
+ mrb_method_t m;
mrb_value at = mrb_fixnum_value(i);
struct RProc *aref = mrb_proc_new_cfunc_with_env(mrb, mrb_struct_ref, 1, &at);
struct RProc *aset = mrb_proc_new_cfunc_with_env(mrb, mrb_struct_set_m, 1, &at);
- mrb_define_method_raw(mrb, c, id, aref);
- mrb_define_method_raw(mrb, c, mrb_id_attrset(mrb, id), aset);
+ MRB_METHOD_FROM_PROC(m, aref);
+ mrb_define_method_raw(mrb, c, id, m);
+ MRB_METHOD_FROM_PROC(m, aset);
+ mrb_define_method_raw(mrb, c, mrb_id_attrset(mrb, id), m);
mrb_gc_arena_restore(mrb, ai);
}
}
diff --git a/src/class.c b/src/class.c
index fb394cc89..c65038b87 100644
--- a/src/class.c
+++ b/src/class.c
@@ -16,7 +16,7 @@
#include <mruby/data.h>
#include <mruby/istruct.h>
-KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
+KHASH_DEFINE(mt, mrb_sym, mrb_method_t, TRUE, kh_int_hash_func, kh_int_hash_equal)
void
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
@@ -27,9 +27,11 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
if (!h) return;
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
- struct RProc *m = kh_value(h, k);
- if (m) {
- mrb_gc_mark(mrb, (struct RBasic*)m);
+ mrb_method_t m = kh_value(h, k);
+
+ if (MRB_METHOD_PROC_P(m)) {
+ struct RProc *p = MRB_METHOD_PROC(m);
+ mrb_gc_mark(mrb, (struct RBasic*)p);
}
}
}
@@ -419,7 +421,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
}
MRB_API void
-mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
+mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_t m)
{
khash_t(mt) *h;
khiter_t k;
@@ -434,8 +436,11 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro
}
if (!h) h = c->mt = kh_init(mt, mrb);
k = kh_put(mt, mrb, h, mid);
- kh_value(h, k) = p;
- if (p) {
+ kh_value(h, k) = m;
+ if (MRB_METHOD_PROC_P(m) && !MRB_METHOD_UNDEF_P(m)) {
+ struct RProc *p = MRB_METHOD_PROC(m);
+
+ p->flags |= MRB_PROC_SCOPE;
p->c = NULL;
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p);
MRB_PROC_SET_TARGET_CLASS(p, c);
@@ -447,13 +452,11 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro
MRB_API void
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
{
- struct RProc *p;
+ mrb_method_t m;
int ai = mrb_gc_arena_save(mrb);
- p = mrb_proc_new_cfunc(mrb, func);
- MRB_PROC_SET_TARGET_CLASS(p, c);
- p->flags |= MRB_PROC_SCOPE;
- mrb_define_method_raw(mrb, c, mid, p);
+ MRB_METHOD_FROM_FUNC(m, func);
+ mrb_define_method_raw(mrb, c, mid, m);
mrb_gc_arena_restore(mrb, ai);
}
@@ -1383,11 +1386,11 @@ mc_clear_by_id(mrb_state *mrb, struct RClass *c, mrb_sym mid)
}
#endif
-MRB_API struct RProc*
+MRB_API mrb_method_t
mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
{
khiter_t k;
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c = *cp;
#ifdef MRB_METHOD_CACHE
struct RClass *oc = c;
@@ -1406,7 +1409,7 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
k = kh_get(mt, mrb, h, mid);
if (k != kh_end(h)) {
m = kh_value(h, k);
- if (!m) break;
+ if (MRB_METHOD_UNDEF_P(m)) break;
*cp = c;
#ifdef MRB_METHOD_CACHE
mc->c = oc;
@@ -1418,16 +1421,17 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
}
c = c->super;
}
- return NULL; /* no method */
+ MRB_METHOD_FROM_PROC(m, NULL);
+ return m; /* no method */
}
-MRB_API struct RProc*
+MRB_API mrb_method_t
mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
{
- struct RProc *m;
+ mrb_method_t m;
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
@@ -1458,6 +1462,8 @@ mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
for (i=0; i<argc; i++) {
mrb_value name, str;
mrb_sym method, sym;
+ struct RProc *p;
+ mrb_method_t m;
method = to_sym(mrb, argv[i]);
name = mrb_sym2str(mrb, method);
@@ -1467,8 +1473,9 @@ mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
sym = mrb_intern_str(mrb, str);
mrb_iv_check(mrb, sym);
name = mrb_symbol_value(sym);
- mrb_define_method_raw(mrb, c, method,
- mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
+ p = mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, c, method, m);
mrb_gc_arena_restore(mrb, ai);
}
return mrb_nil_value();
@@ -1498,6 +1505,8 @@ mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
for (i=0; i<argc; i++) {
mrb_value name, str, attr;
mrb_sym method, sym;
+ struct RProc *p;
+ mrb_method_t m;
method = to_sym(mrb, argv[i]);
@@ -1516,8 +1525,9 @@ mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
mrb_str_cat_lit(mrb, str, "=");
method = mrb_intern_str(mrb, str);
- mrb_define_method_raw(mrb, c, method,
- mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
+ p = mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, c, method, m);
mrb_gc_arena_restore(mrb, ai);
}
return mrb_nil_value();
@@ -1560,15 +1570,16 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv)
mrb_value *argv;
mrb_int argc;
mrb_sym init;
- struct RProc *p;
+ mrb_method_t m;
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
obj = mrb_instance_alloc(mrb, cv);
init = mrb_intern_lit(mrb, "initialize");
- p = mrb_method_search(mrb, mrb_class(mrb, obj), init);
- if (MRB_PROC_CFUNC_P(p)) {
- if (p->body.func != mrb_bob_init) {
- p->body.func(mrb, obj);
+ m = mrb_method_search(mrb, mrb_class(mrb, obj), init);
+ if (MRB_METHOD_CFUNC_P(m)) {
+ mrb_func_t f = MRB_METHOD_CFUNC(m);
+ if (f != mrb_bob_init) {
+ f(mrb, obj);
}
}
else {
@@ -1703,10 +1714,10 @@ mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
MRB_API mrb_bool
mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
{
- struct RProc *m;
+ mrb_method_t m;
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
return FALSE;
}
return TRUE;
@@ -1846,7 +1857,7 @@ mrb_obj_class(mrb_state *mrb, mrb_value obj)
MRB_API void
mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
{
- struct RProc *m = mrb_method_search(mrb, c, b);
+ mrb_method_t m = mrb_method_search(mrb, c, b);
mrb_define_method_raw(mrb, c, a, m);
}
@@ -1940,7 +1951,10 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
}
else {
- mrb_define_method_raw(mrb, c, a, NULL);
+ mrb_method_t m;
+
+ MRB_METHOD_FROM_PROC(m, NULL);
+ mrb_define_method_raw(mrb, c, a, m);
}
}
@@ -1976,6 +1990,7 @@ mod_define_method(mrb_state *mrb, mrb_value self)
{
struct RClass *c = mrb_class_ptr(self);
struct RProc *p;
+ mrb_method_t m;
mrb_sym mid;
mrb_value proc = mrb_undef_value();
mrb_value blk;
@@ -1998,7 +2013,8 @@ mod_define_method(mrb_state *mrb, mrb_value self)
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mrb_proc_copy(p, mrb_proc_ptr(blk));
p->flags |= MRB_PROC_STRICT;
- mrb_define_method_raw(mrb, c, mid, p);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, c, mid, m);
return mrb_symbol_value(mid);
}
@@ -2379,7 +2395,7 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
mrb_value *argv;
mrb_int argc, i;
mrb_sym mid;
- struct RProc *method_rproc;
+ mrb_method_t m;
struct RClass *rclass;
int ai;
@@ -2399,11 +2415,11 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
mid = mrb_symbol(argv[i]);
rclass = mrb_class_ptr(mod);
- method_rproc = mrb_method_search(mrb, rclass, mid);
+ m = mrb_method_search(mrb, rclass, mid);
prepare_singleton_class(mrb, (struct RBasic*)rclass);
ai = mrb_gc_arena_save(mrb);
- mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
+ mrb_define_method_raw(mrb, rclass->c, mid, m);
mrb_gc_arena_restore(mrb, ai);
}
diff --git a/src/kernel.c b/src/kernel.c
index 4a20e18c1..1ac49ed04 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -31,8 +31,14 @@ typedef enum {
MRB_API mrb_bool
mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func)
{
- struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mid);
- if (MRB_PROC_CFUNC_P(me) && (me->body.func == func))
+ mrb_method_t m = mrb_method_search(mrb, mrb_class(mrb, obj), mid);
+ struct RProc *p;
+
+ if (MRB_METHOD_UNDEF_P(m)) return FALSE;
+ if (MRB_METHOD_FUNC_P(m))
+ return MRB_METHOD_FUNC(m) == func;
+ p = MRB_METHOD_PROC(m);
+ if (MRB_PROC_CFUNC_P(p) && (MRB_PROC_CFUNC(p) == func))
return TRUE;
return FALSE;
}
@@ -677,7 +683,9 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
khash_t(mt) *h = klass->mt;
if (!h || kh_size(h) == 0) return;
for (i=0;i<kh_end(h);i++) {
- if (kh_exist(h, i) && kh_value(h, i)) {
+ if (kh_exist(h, i)) {
+ mrb_method_t m = kh_value(h, i);
+ if (MRB_METHOD_UNDEF_P(m)) continue;
kh_put(st, mrb, set, kh_key(h, i));
}
}
@@ -1134,6 +1142,7 @@ static mrb_value
mod_define_singleton_method(mrb_state *mrb, mrb_value self)
{
struct RProc *p;
+ mrb_method_t m;
mrb_sym mid;
mrb_value blk = mrb_nil_value();
@@ -1144,7 +1153,8 @@ mod_define_singleton_method(mrb_state *mrb, mrb_value self)
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mrb_proc_copy(p, mrb_proc_ptr(blk));
p->flags |= MRB_PROC_STRICT;
- mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, m);
return mrb_symbol_value(mid);
}
diff --git a/src/proc.c b/src/proc.c
index 69a9c0299..bd93de618 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -99,7 +99,7 @@ mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
p->body.func = func;
- p->flags |= MRB_PROC_CFUNC;
+ p->flags |= MRB_PROC_CFUNC_FL;
p->upper = 0;
p->e.target_class = 0;
@@ -141,11 +141,12 @@ MRB_API mrb_value
mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
{
struct RProc *p = mrb->c->ci->proc;
- struct REnv *e = MRB_PROC_ENV(p);
+ struct REnv *e;
- if (!MRB_PROC_CFUNC_P(p)) {
+ if (!p || !MRB_PROC_CFUNC_P(p)) {
mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
}
+ e = MRB_PROC_ENV(p);
if (!e) {
mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
}
@@ -216,12 +217,6 @@ mrb_proc_cfunc_p(struct RProc *p)
return MRB_PROC_CFUNC_P(p);
}
-mrb_value
-mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
-{
- return (p->body.func)(mrb, self);
-}
-
/* 15.2.17.4.2 */
static mrb_value
mrb_proc_arity(mrb_state *mrb, mrb_value self)
@@ -293,7 +288,8 @@ proc_lambda(mrb_state *mrb, mrb_value self)
void
mrb_init_proc(mrb_state *mrb)
{
- struct RProc *m;
+ struct RProc *p;
+ mrb_method_t m;
mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
static const mrb_irep mrb_irep_zero = { 0 };
@@ -307,7 +303,8 @@ mrb_init_proc(mrb_state *mrb)
mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
- m = mrb_proc_new(mrb, call_irep);
+ p = mrb_proc_new(mrb, call_irep);
+ MRB_METHOD_FROM_PROC(m, p);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
diff --git a/src/vm.c b/src/vm.c
index 8dfabdafe..170cb832d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -400,7 +400,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
mrb->jmp = 0;
}
else {
- struct RProc *p;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
int n;
@@ -414,12 +414,12 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
}
c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, mid);
- if (!p) {
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
- p = mrb_method_search_vm(mrb, &c, missing);
- if (!p) {
+ m = mrb_method_search_vm(mrb, &c, missing);
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_method_missing(mrb, mid, self, args);
}
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
@@ -432,7 +432,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
}
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = p;
ci->stackent = mrb->c->stack;
ci->argc = (int)argc;
ci->target_class = c;
@@ -440,7 +439,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
voff = argv - mrb->c->stbase;
}
- if (MRB_PROC_CFUNC_P(p)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
ci->nregs = (int)(argc + 2);
stack_extend(mrb, ci->nregs);
}
@@ -452,6 +451,8 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
argc = 1;
}
else {
+ struct RProc *p = MRB_METHOD_PROC(m);
+ ci->proc = p;
if (argc < 0) argc = 1;
ci->nregs = (int)(p->body.irep->nregs + argc);
stack_extend(mrb, ci->nregs);
@@ -465,18 +466,18 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
}
mrb->c->stack[argc+1] = blk;
- if (MRB_PROC_CFUNC_P(p)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
int ai = mrb_gc_arena_save(mrb);
ci->acc = CI_ACC_DIRECT;
- val = p->body.func(mrb, self);
+ val = MRB_METHOD_CFUNC(m)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
cipop(mrb);
mrb_gc_arena_restore(mrb, ai);
}
else {
ci->acc = CI_ACC_SKIP;
- val = mrb_run(mrb, p, self);
+ val = mrb_run(mrb, MRB_METHOD_PROC(m), self);
}
}
mrb_gc_protect(mrb, val);
@@ -499,7 +500,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
ci->proc = p;
ci->target_class = MRB_PROC_TARGET_CLASS(p);
if (MRB_PROC_CFUNC_P(p)) {
- return p->body.func(mrb, self);
+ return MRB_PROC_CFUNC(p)(mrb, self);
}
ci->nregs = p->body.irep->nregs;
if (ci->argc < 0) keep = 3;
@@ -547,7 +548,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_sym name;
mrb_value block, *argv, *regs;
mrb_int argc, i, len;
- struct RProc *p;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
@@ -559,9 +560,8 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
}
c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, name);
-
- if (!p) { /* call method_mising */
+ m = mrb_method_search_vm(mrb, &c, name);
+ if (MRB_METHOD_UNDEF_P(m)) { /* call method_mising */
goto funcall;
}
@@ -579,7 +579,10 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_ary_shift(mrb, regs[0]);
}
- return mrb_exec_irep(mrb, self, p);
+ if (MRB_METHOD_CFUNC_P(m)) {
+ return MRB_METHOD_CFUNC(m)(mrb, self);
+ }
+ return mrb_exec_irep(mrb, self, MRB_METHOD_PROC(m));
}
static mrb_value
@@ -606,7 +609,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;
mrb->c->stack[2] = mrb_nil_value();
- return p->body.func(mrb, self);
+ return MRB_PROC_CFUNC(p)(mrb, self);
}
ci->nregs = p->body.irep->nregs;
stack_extend(mrb, (ci->nregs < 3) ? 3 : ci->nregs);
@@ -725,7 +728,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
mrb->c->stack[argc+1] = mrb_nil_value();
if (MRB_PROC_CFUNC_P(p)) {
- val = p->body.func(mrb, self);
+ val = MRB_PROC_CFUNC(p)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
}
else {
@@ -1376,7 +1379,7 @@ RETRY_TRY_BLOCK:
int n = GETARG_C(i);
int argc = (n == CALL_MAXARGS) ? -1 : n;
int bidx = (argc < 0) ? a+2 : a+n+1;
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
@@ -1400,10 +1403,10 @@ RETRY_TRY_BLOCK:
}
c = mrb_class(mrb, recv);
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
ERR_PC_SET(mrb, pc);
mrb_method_missing(mrb, mid, recv, args);
@@ -1423,7 +1426,6 @@ RETRY_TRY_BLOCK:
/* push callinfo */
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = m;
ci->stackent = mrb->c->stack;
ci->target_class = c;
ci->argc = argc;
@@ -1434,9 +1436,17 @@ RETRY_TRY_BLOCK:
/* prepare stack */
mrb->c->stack += a;
- if (MRB_PROC_CFUNC_P(m)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
ci->nregs = (argc < 0) ? 3 : n+2;
- recv = m->body.func(mrb, recv);
+ if (MRB_METHOD_PROC_P(m)) {
+ struct RProc *p = MRB_METHOD_PROC(m);
+
+ ci->proc = p;
+ recv = p->body.func(mrb, recv);
+ }
+ else {
+ recv = MRB_METHOD_FUNC(m)(mrb, recv);
+ }
mrb_gc_arena_restore(mrb, ai);
mrb_gc_arena_shrink(mrb, ai);
if (mrb->exc) goto L_RAISE;
@@ -1471,8 +1481,8 @@ RETRY_TRY_BLOCK:
}
else {
/* setup environment for calling method */
- proc = mrb->c->ci->proc = m;
- irep = m->body.irep;
+ proc = ci->proc = MRB_METHOD_PROC(m);
+ irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
@@ -1511,7 +1521,7 @@ RETRY_TRY_BLOCK:
/* prepare stack */
if (MRB_PROC_CFUNC_P(m)) {
- recv = m->body.func(mrb, recv);
+ recv = MRB_PROC_CFUNC(m)(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
mrb_gc_arena_shrink(mrb, ai);
if (mrb->exc) goto L_RAISE;
@@ -1560,7 +1570,7 @@ RETRY_TRY_BLOCK:
int n = GETARG_C(i);
int argc = (n == CALL_MAXARGS) ? -1 : n;
int bidx = (argc < 0) ? a+2 : a+n+1;
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
@@ -1584,10 +1594,10 @@ RETRY_TRY_BLOCK:
}
c = ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
ERR_PC_SET(mrb, pc);
mrb_method_missing(mrb, mid, recv, args);
@@ -1607,7 +1617,6 @@ RETRY_TRY_BLOCK:
/* push callinfo */
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = m;
ci->stackent = mrb->c->stack;
ci->target_class = c;
ci->pc = pc + 1;
@@ -1617,10 +1626,10 @@ RETRY_TRY_BLOCK:
mrb->c->stack += a;
mrb->c->stack[0] = recv;
- if (MRB_PROC_CFUNC_P(m)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
mrb_value v;
ci->nregs = (argc < 0) ? 3 : n+2;
- v = m->body.func(mrb, recv);
+ v = MRB_METHOD_CFUNC(m)(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
ci = mrb->c->ci;
@@ -1649,8 +1658,8 @@ RETRY_TRY_BLOCK:
ci->acc = a;
/* setup environment for calling method */
- ci->proc = m;
- irep = m->body.irep;
+ proc = ci->proc = MRB_METHOD_PROC(m);
+ irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
@@ -1934,7 +1943,7 @@ RETRY_TRY_BLOCK:
/* Fall through to OP_R_NORMAL otherwise */
if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) {
mrb_callinfo *cibase = mrb->c->cibase;
- dst = top_proc(mrb, proc);
+ dst = top_proc(mrb, proc);
if (MRB_PROC_ENV_P(dst)) {
struct REnv *e = MRB_PROC_ENV(dst);
@@ -2075,7 +2084,7 @@ RETRY_TRY_BLOCK:
int a = GETARG_A(i);
int b = GETARG_B(i);
int n = GETARG_C(i);
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
mrb_value recv;
@@ -2084,11 +2093,11 @@ RETRY_TRY_BLOCK:
recv = regs[a];
c = mrb_class(mrb, recv);
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value sym = mrb_symbol_value(mid);
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args;
if (n == CALL_MAXARGS) {
@@ -2124,15 +2133,16 @@ RETRY_TRY_BLOCK:
/* move stack */
value_move(mrb->c->stack, &regs[a], ci->argc+1);
- if (MRB_PROC_CFUNC_P(m)) {
- mrb_value v = m->body.func(mrb, recv);
+ if (MRB_METHOD_CFUNC_P(m)) {
+ mrb_value v = MRB_METHOD_CFUNC(m)(mrb, recv);
mrb->c->stack[0] = v;
mrb_gc_arena_restore(mrb, ai);
goto L_RETURN;
}
else {
/* setup environment for calling method */
- irep = m->body.irep;
+ struct RProc *p = MRB_METHOD_PROC(m);
+ irep = p->body.irep;
pool = irep->pool;
syms = irep->syms;
if (ci->argc < 0) {
@@ -2824,8 +2834,10 @@ RETRY_TRY_BLOCK:
int a = GETARG_A(i);
struct RClass *c = mrb_class_ptr(regs[a]);
struct RProc *p = mrb_proc_ptr(regs[a+1]);
+ mrb_method_t m;
- mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], m);
mrb_gc_arena_restore(mrb, ai);
NEXT;
}