From c9fe903fe15e601900ec17ae40fe82b0d2dc4978 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Sun, 12 Aug 2012 01:59:18 +0900 Subject: now segmented list can be used as instance variable tables by -DMRB_USE_IV_SEGLIST; we still need to measure the performance and memory consumption --- include/mrbconf.h | 5 +- include/mruby.h | 2 +- include/mruby/class.h | 2 +- include/mruby/data.h | 2 +- include/mruby/hash.h | 2 +- include/mruby/object.h | 2 +- include/mruby/variable.h | 13 +- src/class.c | 35 +-- src/error.c | 1 + src/kernel.c | 67 +---- src/variable.c | 712 ++++++++++++++++++++++++++++++++++++----------- 11 files changed, 577 insertions(+), 266 deletions(-) diff --git a/include/mrbconf.h b/include/mrbconf.h index 20f49ec29..693e7da88 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -19,7 +19,10 @@ /* number of object per heap page */ //#define MRB_HEAP_PAGE_SIZE 1024 -/* initial size for IV khash */ +/* use segmented list for IV table */ +//#define MRB_USE_IV_SEGLIST + +/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */ //#define MRB_IV_INITIAL_SIZE 8 /* default size of khash table bucket */ diff --git a/include/mruby.h b/include/mruby.h index 353ff93f4..380c5f24c 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -233,7 +233,7 @@ typedef struct mrb_state { int esize; struct RObject *exc; - struct kh_iv *globals; + struct iv_tbl *globals; struct mrb_irep **irep; size_t irep_len, irep_capa; diff --git a/include/mruby/class.h b/include/mruby/class.h index 2cc90310e..b4a2e9471 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -13,7 +13,7 @@ extern "C" { struct RClass { MRUBY_OBJECT_HEADER; - struct kh_iv *iv; + struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; }; diff --git a/include/mruby/data.h b/include/mruby/data.h index 4c136555c..ca2a04b55 100644 --- a/include/mruby/data.h +++ b/include/mruby/data.h @@ -18,7 +18,7 @@ struct mrb_data_type { struct RData { MRUBY_OBJECT_HEADER; - struct kh_iv *iv; + struct iv_tbl *iv; struct mrb_data_type *type; void *data; }; diff --git a/include/mruby/hash.h b/include/mruby/hash.h index f3755eb25..2b0aeeef2 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -13,7 +13,7 @@ extern "C" { struct RHash { MRUBY_OBJECT_HEADER; - struct kh_iv *iv; + struct iv_tbl *iv; struct kh_ht *ht; }; diff --git a/include/mruby/object.h b/include/mruby/object.h index 4be060078..e42a5f428 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -44,7 +44,7 @@ struct RBasic { struct RObject { MRUBY_OBJECT_HEADER; - struct kh_iv *iv; + struct iv_tbl *iv; }; #define mrb_obj_ptr(v) ((struct RObject*)((v).value.p)) diff --git a/include/mruby/variable.h b/include/mruby/variable.h index e93a77c55..0dac75c5b 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -38,17 +38,21 @@ mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); int mrb_const_defined(mrb_state*, mrb_value, mrb_sym); -mrb_value mrb_obj_iv_get(mrb_state*, struct RObject*, mrb_sym); -void mrb_obj_iv_set(mrb_state*, struct RObject*, mrb_sym, mrb_value); -const char * mrb_class2name(mrb_state *mrb, struct RClass* klass); +mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym); +void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); +int mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym); mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym); void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v); +int mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); +void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id); mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self); mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value); +mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*); +mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer); /* GC functions */ void mrb_gc_mark_gv(mrb_state*); @@ -57,9 +61,6 @@ void mrb_gc_mark_iv(mrb_state*, struct RObject*); size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); void mrb_gc_free_iv(mrb_state*, struct RObject*); -#include "mruby/khash.h" -KHASH_DECLARE(iv, mrb_sym, mrb_value, 1) - #if defined(__cplusplus) } /* extern "C" { */ #endif diff --git a/src/class.c b/src/class.c index ae4d45ff1..8244a8637 100644 --- a/src/class.c +++ b/src/class.c @@ -15,7 +15,6 @@ #include "mruby/array.h" #include "error.h" -KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal); KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal); typedef struct fc_result { @@ -65,30 +64,6 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); } -static mrb_sym -class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) -{ - mrb_value name; - - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); - if (mrb_nil_p(name)) { - khash_t(iv)* h; - khiter_t k; - mrb_value v; - - if (!outer) outer = mrb->object_class; - h = outer->iv; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (!kh_exist(h,k)) continue; - v = kh_value(h,k); - if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { - return kh_key(h,k); - } - } - } - return SYM2ID(name); -} - static void make_metaclass(mrb_state *mrb, struct RClass *c) { @@ -1114,16 +1089,16 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); if (mrb_nil_p(path)) { struct RClass *outer = mrb_class_outer_module(mrb, c); - mrb_sym sym = class_sym(mrb, c, outer); - if (outer && outer != mrb->object_class) { + mrb_sym sym = mrb_class_sym(mrb, c, outer); + if (sym == 0) { + return mrb_nil_value(); + } + else if (outer && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2)); name = mrb_sym2name_len(mrb, sym, &len); mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len)); } - else if (sym == 0) { - return mrb_nil_value(); - } else { name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); diff --git a/src/error.c b/src/error.c index 6fe839cb2..150524f87 100644 --- a/src/error.c +++ b/src/error.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "error.h" #include "mruby/variable.h" #include "mruby/string.h" diff --git a/src/kernel.c b/src/kernel.c index 9dc085a94..4e5931fba 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -32,43 +32,6 @@ struct obj_ivar_tag { void * arg; }; -static mrb_value -inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur) -{ - if (recur) { - mrb_str_cat2(mrb, str, " ..."); - } - else { - khiter_t k; - kh_iv_t *h = RCLASS_IV_TBL(obj); - - if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)){ - mrb_sym id = kh_key(h, k); - mrb_value value = kh_value(h, k); - - /* need not to show internal data */ - if (RSTRING_PTR(str)[0] == '-') { /* first element */ - RSTRING_PTR(str)[0] = '#'; - mrb_str_cat2(mrb, str, " "); - } - else { - mrb_str_cat2(mrb, str, ", "); - } - mrb_str_cat2(mrb, str, mrb_sym2name(mrb, id)); - mrb_str_cat2(mrb, str, "="); - mrb_str_append(mrb, str, mrb_inspect(mrb, value)); - } - } - } - } - mrb_str_cat2(mrb, str, ">"); - RSTRING_PTR(str)[0] = '#'; - - return str; -} - int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { @@ -96,16 +59,7 @@ mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value obj) { if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) { - long len = ROBJECT_NUMIV(obj); - - if (len > 0) { - mrb_value str; - const char *c = mrb_obj_classname(mrb, obj); - - str = mrb_sprintf(mrb, "-<%s:%p", c, (void*)&obj); - return inspect_obj(mrb, obj, str, 0); - } - return mrb_any_to_s(mrb, obj); + return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj)); } else if (mrb_nil_p(obj)) { return mrb_str_new(mrb, "nil", 3); @@ -347,13 +301,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_OBJECT: case MRB_TT_CLASS: case MRB_TT_MODULE: - if (ROBJECT(dest)->iv) { - kh_destroy(iv, ROBJECT(dest)->iv); - ROBJECT(dest)->iv = 0; - } - if (ROBJECT(obj)->iv) { - ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv); - } + mrb_iv_copy(mrb, dest, obj); break; default: @@ -630,19 +578,12 @@ check_iv_name(mrb_state *mrb, mrb_sym id) mrb_value mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) { - khiter_t k; - kh_iv_t *h = RCLASS_IV_TBL(self); mrb_sym mid; mrb_get_args(mrb, "n", &mid); check_iv_name(mrb, mid); - - if (h) { - k = kh_get(iv, h, mid); - if (k != kh_end(h)) { - return mrb_true_value(); - } - } + if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid)) + return mrb_true_value(); return mrb_false_value(); } diff --git a/src/variable.c b/src/variable.c index 8b94f5bbb..3f08849a7 100644 --- a/src/variable.c +++ b/src/variable.c @@ -6,29 +6,374 @@ #include "mruby.h" #include "mruby/class.h" -#include "mruby/khash.h" #include "mruby/variable.h" #include "error.h" #include "mruby/array.h" +#include "mruby/string.h" #include "mruby/proc.h" +#ifndef MRB_USE_IV_SEGLIST +#include "mruby/khash.h" +#endif #ifdef ENABLE_REGEXP #include "re.h" #endif +typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); + +#ifdef MRB_USE_IV_SEGLIST + +#ifndef MRB_SEGMENT_SIZE +#define MRB_SEGMENT_SIZE 4 +#endif + +typedef struct segment +{ + mrb_sym key[MRB_SEGMENT_SIZE]; + mrb_value val[MRB_SEGMENT_SIZE]; + struct segment *next; +} segment; + +typedef struct iv_tbl { + segment *rootseg; + int size; + int last_len; +} iv_tbl; + +static iv_tbl* +iv_new(mrb_state *mrb) +{ + iv_tbl *t; + + t = mrb_malloc(mrb, sizeof(iv_tbl)); + if (t) { + t->size = 0; + t->rootseg = NULL; + t->last_len = 0; + } + return t; +} + +static void +iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) +{ + segment *seg = t->rootseg; + segment *prev = NULL; + segment *matched_seg = NULL; + int matched_idx = 0; + int i; + + while (seg) { + for (i=0; ikey[i]; + /* found room in last segment after last_len */ + if (!seg->next && i >= t->last_len) { + seg->key[i] = sym; + seg->val[i] = val; + t->last_len = i+1; + t->size++; + return; + } + if (key == 0 && !matched_seg) { + matched_seg = seg; + matched_idx = i; + } + else if (key == sym) { + seg->val[i] = val; + return; + } + } + prev = seg; + seg = seg->next; + } + + /* not found */ + t->size++; + if (matched_seg) { + matched_seg->key[matched_idx] = sym; + matched_seg->val[matched_idx] = val; + return; + } + + seg = mrb_malloc(mrb, sizeof(segment)); + if (!seg) return; + seg->next = NULL; + seg->key[0] = sym; + seg->val[0] = val; + t->last_len = 1; + if (prev) { + prev->next = seg; + } + else { + t->rootseg = seg; + } + return; +} + +static int +iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + segment *seg; + int i; + + seg = t->rootseg; + while (seg) { + for (i=0; ikey[i]; + + if (!seg->next && i >= t->last_len) { + return 0; + } + if (key == sym) { + if (vp) *vp = seg->val[i]; + return 1; + } + } + seg = seg->next; + } + return 0; +} + +static int +iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + segment *seg; + int i; + + seg = t->rootseg; + while (seg) { + for (i=0; ikey[i]; + + if (!seg->next && i >= t->last_len) { + return 0; + } + if (key == sym) { + t->size--; + seg->key[i] = 0; + if (vp) *vp = seg->val[i]; + return 1; + } + } + seg = seg->next; + } + return 0; +} + +static int +iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) +{ + segment *seg; + int i, n; + + seg = t->rootseg; + while (seg) { + for (i=0; ikey[i]; + + /* no value in last segment after last_len */ + if (!seg->next && i >= t->last_len) { + return 0; + } + if (key != 0) { + n =(*func)(mrb, key, seg->val[i], p); + if (n > 0) return 0; + if (n < 0) { + t->size--; + seg->key[i] = 0; + } + } + } + seg = seg->next; + } + return 1; +} + +static int +iv_size(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + int size = 0; + + if (!t) return 0; + if (t->size > 0) return t->size; + seg = t->rootseg; + while (seg) { + if (seg->next == NULL) { + size += t->last_len; + return size; + } + seg = seg->next; + size += MRB_SEGMENT_SIZE; + } + /* empty iv_tbl */ + return 0; +} + +static iv_tbl* +iv_copy(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + iv_tbl *t2; + + int i; + + seg = t->rootseg; + t2 = iv_new(mrb); + + while (seg != NULL) { + for (i=0; ikey[i]; + mrb_value val = seg->val[i]; + + iv_put(mrb, t2, key, val); + if ((seg->next == NULL) && (i >= t->last_len)) { + return t2; + } + } + seg = seg->next; + } + return t2; +} + +static void +iv_free(mrb_state *mrb, iv_tbl *t) +{ + segment *seg; + + seg = t->rootseg; + while (seg) { + segment *p = seg; + seg = seg->next; + mrb_free(mrb, p); + } + mrb_free(mrb, t); +} + +#else + +#include "mruby/khash.h" + #ifndef MRB_IV_INITIAL_SIZE #define MRB_IV_INITIAL_SIZE 8 #endif +KHASH_DECLARE(iv, mrb_sym, mrb_value, 1) +KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal); + +typedef struct iv_tbl { + khash_t(iv) h; +} iv_tbl; + +static iv_tbl* +iv_new(mrb_state *mrb) +{ + return (iv_tbl*)kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); +} + static void -mark_tbl(mrb_state *mrb, struct kh_iv *h) +iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + + k = kh_put(iv, h, sym); + kh_value(h, k) = val; +} + +static int +iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { + khash_t(iv) *h = &t->h; khiter_t k; - if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) - mrb_gc_mark_value(mrb, kh_value(h, k)); + k = kh_get(iv, h, sym); + if (k != kh_end(h)) { + if (vp) *vp = kh_value(h, k); + return 1; + } + return 0; +} + +static int +iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + + if (h) { + k = kh_get(iv, h, sym); + if (k != kh_end(h)) { + mrb_value val = kh_value(h, k); + kh_del(iv, h, k); + if (vp) *vp = val; + return 1; + } + } + return 0; +} + +static int +iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) +{ + khash_t(iv) *h = &t->h; + khiter_t k; + int n; + + if (h) { + for (k = kh_begin(h); k != kh_end(h); k++) { + if (kh_exist(h, k)){ + n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p); + if (n > 0) return 0; + if (n < 0) { + kh_del(iv, h, k); + } + } + } + } + return 1; +} + +static int +iv_size(mrb_state *mrb, iv_tbl *t) +{ + khash_t(iv) *h = &t->h; + + if (!h) return 0; + return kh_size(h); +} + +static iv_tbl* +iv_copy(mrb_state *mrb, iv_tbl *t) +{ + return (iv_tbl*)kh_copy(iv, mrb, &t->h); +} + +static void +iv_free(mrb_state *mrb, iv_tbl *t) +{ + kh_destroy(iv, &t->h); +} + +#endif + +#ifndef MRB_IV_INITIAL_SIZE +#define MRB_IV_INITIAL_SIZE 8 +#endif + +static int +iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_gc_mark_value(mrb, v); + return 0; +} + +static void +mark_tbl(mrb_state *mrb, iv_tbl *t) +{ + if (t) { + iv_foreach(mrb, t, iv_mark_i, 0); + } } void @@ -40,7 +385,8 @@ mrb_gc_mark_gv(mrb_state *mrb) void mrb_gc_free_gv(mrb_state *mrb) { - kh_destroy(iv, mrb->globals); + if (mrb->globals) + iv_free(mrb, mrb->globals); } void @@ -52,16 +398,15 @@ mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj) size_t mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj) { - struct kh_iv *h = obj->iv; - - if (!h) return 0; - return kh_size(h); + return iv_size(mrb, obj->iv); } void mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj) { - kh_destroy(iv, obj->iv); + if (obj->iv) { + iv_free(mrb, obj->iv); + } } mrb_value @@ -75,26 +420,6 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v) { } -static mrb_value -ivget(mrb_state *mrb, struct kh_iv *h, mrb_sym sym) -{ - khiter_t k; - - k = kh_get(iv, h, sym); - if (k != kh_end(h)) - return kh_value(h, k); - return mrb_nil_value(); -} - -mrb_value -mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) -{ - if (!obj->iv) { - return mrb_nil_value(); - } - return ivget(mrb, obj->iv, sym); -} - static int obj_iv_p(mrb_value obj) { @@ -110,6 +435,16 @@ obj_iv_p(mrb_value obj) } } +mrb_value +mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) +{ + mrb_value v; + + if (obj->iv && iv_get(mrb, obj->iv, sym, &v)) + return v; + return mrb_nil_value(); +} + mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) { @@ -119,54 +454,110 @@ mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) return mrb_nil_value(); } -static void -ivset(mrb_state *mrb, struct kh_iv *h, mrb_sym sym, mrb_value v) +void +mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) { - khiter_t k; + iv_tbl *t = obj->iv; - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + if (!t) { + t = obj->iv = iv_new(mrb); + } + mrb_write_barrier(mrb, (struct RBasic*)obj); + iv_put(mrb, t, sym, v); } void -mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) +mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) { - khash_t(iv) *h; - - if (!obj->iv) { - h = obj->iv = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); + if (obj_iv_p(obj)) { + mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); } else { - h = obj->iv; + mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable"); } - mrb_write_barrier(mrb, (struct RBasic*)obj); - ivset(mrb, h, sym, v); +} + +int +mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) +{ + iv_tbl *t; + + t = obj->iv; + if (t) { + return iv_get(mrb, t, sym, NULL); + } + return 0; +} + +int +mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) +{ + if (!obj_iv_p(obj)) return 0; + return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym); } void -mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) /* mrb_ivar_set */ +mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src) { - if (obj_iv_p(obj)) { - mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); + struct RObject *d = mrb_obj_ptr(dest); + struct RObject *s = mrb_obj_ptr(src); + + if (d->iv) { + iv_free(mrb, d->iv); + d->iv = 0; } + if (s->iv) { + d->iv = iv_copy(mrb, s->iv); + } +} + +static int +inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value str = *(mrb_value*)p; + const char *s; + int len; + + /* need not to show internal data */ + if (RSTRING_PTR(str)[0] == '-') { /* first element */ + RSTRING_PTR(str)[0] = '#'; + mrb_str_cat2(mrb, str, " "); + } + else { + mrb_str_cat2(mrb, str, ", "); + } + s = mrb_sym2name_len(mrb, sym, &len); + mrb_str_cat(mrb, str, s, len); + mrb_str_cat(mrb, str, "=", 1); + mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + return 0; } mrb_value -mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) +mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) { - mrb_value val; + iv_tbl *t = obj->iv; + int len = iv_size(mrb, t); + if (len > 0) { + const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); + mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj); + + iv_foreach(mrb, t, inspect_i, &str); + return str; + } + return mrb_any_to_s(mrb, mrb_obj_value(obj)); +} + +mrb_value +mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) +{ if (obj_iv_p(obj)) { - khash_t(iv) *h = mrb_obj_ptr(obj)->iv; - khiter_t k; - - if (h) { - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - val = kh_value(h, k); - kh_del(iv, h, k); - return val; - } + iv_tbl *t = mrb_obj_ptr(obj)->iv; + mrb_value val; + + if (iv_del(mrb, t, sym, &val)) { + return val; } } return mrb_undef_value(); @@ -186,6 +577,21 @@ mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) mrb_iv_set(mrb, mrb->stack[0], sym, v); } +static int +iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + const char* s; + int len; + + ary = *(mrb_value*)p; + s = mrb_sym2name_len(mrb, sym, &len); + if (len > 1 && s[0] == '@') { + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + } + return 0; +} + /* 15.3.1.3.23 */ /* * call-seq: @@ -207,25 +613,10 @@ mrb_value mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) { mrb_value ary; - kh_iv_t *h; - khint_t i; - int len; - const char* p; ary = mrb_ary_new(mrb); if (obj_iv_p(self)) { - h = ROBJECT_IVPTR(self); - if (h) { - for (i=0;i 1 && *p == '@') { - if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF) - mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, len)); - } - } - } - } + iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary); } return ary; } @@ -238,11 +629,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { - khash_t(iv) *h = c->iv; - khiter_t k = kh_get(iv, h, sym); + iv_tbl *t = c->iv; + mrb_value v; - if (k != kh_end(h)) - return kh_value(h, k); + if (iv_get(mrb, t, sym, &v)) + return v; } c = c->super; } @@ -253,43 +644,34 @@ void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { struct RClass *c = mrb->ci->proc->target_class; - khash_t(iv) *h; - khiter_t k; if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + iv_tbl *t = c->iv; + + if (iv_get(mrb, t, sym, NULL)) { + iv_put(mrb, t, sym, v); return; } } c = c->super; } c = mrb->ci->target_class; - h = c->iv; - if (!h) { - c->iv = h = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE); + if (!c->iv) { + c->iv = iv_new(mrb); } - k = kh_put(iv, h, sym); - kh_value(h, k) = v; + iv_put(mrb, c->iv, sym, v); } int mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { - khiter_t k; struct RClass *m = mrb_class_ptr(mod); - struct kh_iv *h = m->iv; + iv_tbl *t = m->iv; - if (!h) return 0; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) - return 1; - return 0; + if (!t) return 0; + return iv_get(mrb, t, sym, NULL); } static void @@ -309,19 +691,17 @@ static mrb_value const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) { struct RClass *c = base; - khash_t(iv) *h; - khiter_t k; + mrb_value v; + iv_tbl *t; int retry = 0; mrb_sym cm; L_RETRY: while (c) { if (c->iv) { - h = c->iv; - k = kh_get(iv, h, sym); - if (k != kh_end(h)) { - return kh_value(h, k); - } + t = c->iv; + if (iv_get(mrb, t, sym, &v)) + return v; } c = c->super; } @@ -374,13 +754,13 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) struct RClass *c = mrb->ci->proc->target_class; if (!c) c = mrb->ci->target_class; - mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); + mrb_iv_set(mrb, mrb_obj_value(c), sym, v); } void mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) { - mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern(mrb, name), v); + mrb_iv_set(mrb, mrb_obj_value(mod), mrb_intern(mrb, name), v); } void @@ -392,24 +772,38 @@ mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val) mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym) { + mrb_value v; + if (!mrb->globals) { return mrb_nil_value(); } - return ivget(mrb, mrb->globals, sym); + if (iv_get(mrb, mrb->globals, sym, &v)) + return v; + return mrb_nil_value(); } void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { - khash_t(iv) *h; + iv_tbl *t; if (!mrb->globals) { - h = mrb->globals = kh_init(iv, mrb); + t = mrb->globals = iv_new(mrb); } else { - h = mrb->globals; + t = mrb->globals; } - ivset(mrb, h, sym, v); + iv_put(mrb, t, sym, v); +} + +static int +gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + mrb_value ary; + + ary = *(mrb_value*)p; + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + return 0; } /* 15.3.1.2.4 */ @@ -425,73 +819,34 @@ mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self) { - char buf[3]; - khint_t i; - struct kh_iv *h = mrb->globals; + iv_tbl *t = mrb->globals; mrb_value ary = mrb_ary_new(mrb); + int i; + char buf[3]; - if (h) { - for (i=0;i < kh_end(h);i++) { - if (kh_exist(h, i)) { - mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i))); - } - } + if (t) { + iv_foreach(mrb, t, gv_i, &ary); } buf[0] = '$'; buf[2] = 0; for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); - mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf))); + buf[1] = (char)(i + '0'); + mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2))); } return ary; } -int -mrb_st_lookup(struct kh_iv *table, mrb_sym id, khiter_t *value) -{ - khash_t(iv) *h; - khiter_t k; - - if (table) { - h = (khash_t(iv)*)table; - k = kh_get(iv, h, id); - if (k != kh_end(h)) { - if (value != 0) *value = k;//kh_value(h, k); - return 1;/* TRUE */ - } - return 0;/* FALSE */ - } - else { - return 0;/* FALSE */ - } -} - -static int -kiv_lookup(khash_t(iv)* table, mrb_sym key, mrb_value *value) -{ - khash_t(iv) *h=table; - khiter_t k; - - k = kh_get(iv, h, key); - if (k != kh_end(h)) { - *value = kh_value(h, k); - return 1; - } - return 0; -} - static int mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse) { - mrb_value value; struct RClass * tmp; int mod_retry = 0; tmp = klass; retry: while (tmp) { - if (tmp->iv && kiv_lookup(tmp->iv, id, &value)) { - return (int)1/*Qtrue*/; + if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) { + return 1; } if (!recurse && (klass != mrb->object_class)) break; tmp = tmp->super; @@ -525,3 +880,38 @@ mrb_class_obj_get(mrb_state *mrb, const char *name) return mrb_class_ptr(mrb_const_get(mrb, mod, sym)); } +struct csym_arg { + struct RClass *c; + mrb_sym sym; +}; + +static int +csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) +{ + struct csym_arg *a = (struct csym_arg*)p; + struct RClass *c = a->c; + + if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { + a->sym = sym; + return 1; /* stop iteration*/ + } + return 0; +} + +mrb_sym +mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) +{ + mrb_value name; + + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); + if (mrb_nil_p(name)) { + struct csym_arg arg; + + arg.c = c; + arg.sym = 0; + + iv_foreach(mrb, outer->iv, csym_i, &arg); + return arg.sym; + } + return SYM2ID(name); +} -- cgit v1.2.3