Created
March 14, 2010 00:16
-
-
Save methodmissing/331658 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
methodmissing:rubyenterpriseedition187-248 lourens$ ./orig_ruby -Ilib lazy_mem_bench.rb | |
user system total real | |
Hash.new 0.100000 0.000000 0.100000 ( 0.103147) | |
Hash#[] 0.130000 0.000000 0.130000 ( 0.125913) | |
Hash#size 0.110000 0.000000 0.110000 ( 0.111521) | |
Hash['a','b'].keys 0.170000 0.000000 0.170000 ( 0.177375) | |
Class.new 1.050000 0.010000 1.060000 ( 1.055517) | |
Module.new 0.510000 0.000000 0.510000 ( 0.510009) | |
B.new.extend(A) 1.340000 0.000000 1.340000 ( 1.335759) | |
Allocated 134418009 bytes | |
methodmissing:rubyenterpriseedition187-248 lourens$ ./ruby -Ilib lazy_mem_bench.rb | |
user system total real | |
Hash.new 0.050000 0.000000 0.050000 ( 0.048200) | |
Hash#[] 0.110000 0.000000 0.110000 ( 0.116991) | |
Hash#size 0.100000 0.000000 0.100000 ( 0.099957) | |
Hash['a','b'].keys 0.170000 0.000000 0.170000 ( 0.173603) | |
Class.new 0.960000 0.000000 0.960000 ( 0.960538) | |
Module.new 0.460000 0.000000 0.460000 ( 0.452228) | |
B.new.extend(A) 1.320000 0.000000 1.320000 ( 1.324234) | |
Allocated 89618009 bytes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/array.c b/array.c | |
index 89f74d0..515abec 100644 | |
--- a/array.c | |
+++ b/array.c | |
@@ -2863,7 +2863,7 @@ rb_ary_diff(ary1, ary2) | |
ary3 = rb_ary_new(); | |
for (i=0; i<RARRAY(ary1)->len; i++) { | |
- if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue; | |
+ if (st_lookup(RHASH_TBL(hash), RARRAY(ary1)->ptr[i], 0)) continue; | |
rb_ary_push(ary3, rb_ary_elt(ary1, i)); | |
} | |
return ary3; | |
@@ -2894,7 +2894,7 @@ rb_ary_and(ary1, ary2) | |
for (i=0; i<RARRAY(ary1)->len; i++) { | |
v = vv = rb_ary_elt(ary1, i); | |
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { | |
+ if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) { | |
rb_ary_push(ary3, v); | |
} | |
} | |
@@ -2927,13 +2927,13 @@ rb_ary_or(ary1, ary2) | |
for (i=0; i<RARRAY(ary1)->len; i++) { | |
v = vv = rb_ary_elt(ary1, i); | |
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { | |
+ if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) { | |
rb_ary_push(ary3, v); | |
} | |
} | |
for (i=0; i<RARRAY(ary2)->len; i++) { | |
v = vv = rb_ary_elt(ary2, i); | |
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { | |
+ if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) { | |
rb_ary_push(ary3, v); | |
} | |
} | |
@@ -2963,12 +2963,12 @@ rb_ary_uniq_bang(ary) | |
hash = ary_make_hash(ary, 0); | |
- if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) { | |
+ if (RARRAY(ary)->len == RHASH_TBL(hash)->num_entries) { | |
return Qnil; | |
} | |
for (i=j=0; i<RARRAY(ary)->len; i++) { | |
v = vv = rb_ary_elt(ary, i); | |
- if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) { | |
+ if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) { | |
rb_ary_store(ary, j++, v); | |
} | |
} | |
diff --git a/class.c b/class.c | |
index 054be60..712ffca 100644 | |
--- a/class.c | |
+++ b/class.c | |
@@ -28,7 +28,6 @@ rb_class_boot(super) | |
klass->super = super; | |
klass->iv_tbl = 0; | |
klass->m_tbl = 0; /* safe GC */ | |
- klass->m_tbl = st_init_numtable(); | |
OBJ_INFECT(klass, super); | |
return (VALUE)klass; | |
@@ -91,13 +90,13 @@ rb_mod_init_copy(clone, orig) | |
id = rb_intern("__classid__"); | |
st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0); | |
} | |
- if (RCLASS(orig)->m_tbl) { | |
+ if (RCLASS_M_TBL(orig)) { | |
struct clone_method_data data; | |
data.tbl = RCLASS(clone)->m_tbl = st_init_numtable(); | |
data.klass = (VALUE)clone; | |
- st_foreach(RCLASS(orig)->m_tbl, clone_method, (st_data_t)&data); | |
+ st_foreach(RCLASS_M_TBL(orig), clone_method, (st_data_t)&data); | |
} | |
return clone; | |
@@ -157,7 +156,7 @@ rb_singleton_class_clone(obj) | |
break; | |
} | |
- st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data); | |
+ st_foreach(RCLASS_M_TBL(klass), clone_method, (st_data_t)&data); | |
} | |
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); | |
FL_SET(clone, FL_SINGLETON); | |
@@ -308,7 +307,6 @@ rb_module_new() | |
mdl->super = 0; | |
mdl->iv_tbl = 0; | |
mdl->m_tbl = 0; | |
- mdl->m_tbl = st_init_numtable(); | |
return (VALUE)mdl; | |
} | |
@@ -383,7 +381,7 @@ include_class_new(module, super) | |
RCLASS(module)->iv_tbl = st_init_numtable(); | |
} | |
klass->iv_tbl = RCLASS(module)->iv_tbl; | |
- klass->m_tbl = RCLASS(module)->m_tbl; | |
+ klass->m_tbl = RCLASS_M_TBL(module); | |
klass->super = super; | |
if (TYPE(module) == T_ICLASS) { | |
RBASIC(klass)->klass = RBASIC(module)->klass; | |
@@ -418,13 +416,13 @@ rb_include_module(klass, module) | |
while (module) { | |
int superclass_seen = Qfalse; | |
- if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl) | |
+ if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) | |
rb_raise(rb_eArgError, "cyclic include detected"); | |
/* ignore if the module included already in superclasses */ | |
for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) { | |
switch (BUILTIN_TYPE(p)) { | |
case T_ICLASS: | |
- if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) { | |
+ if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { | |
if (!superclass_seen) { | |
c = p; /* move insertion point */ | |
} | |
@@ -648,7 +646,7 @@ class_instance_method_list(argc, argv, mod, func) | |
list = st_init_numtable(); | |
for (; mod; mod = RCLASS(mod)->super) { | |
- st_foreach(RCLASS(mod)->m_tbl, method_entry, (st_data_t)list); | |
+ st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list); | |
if (BUILTIN_TYPE(mod) == T_ICLASS) continue; | |
if (FL_TEST(mod, FL_SINGLETON)) continue; | |
if (!recur) break; | |
@@ -806,12 +804,12 @@ rb_obj_singleton_methods(argc, argv, obj) | |
klass = CLASS_OF(obj); | |
list = st_init_numtable(); | |
if (klass && FL_TEST(klass, FL_SINGLETON)) { | |
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list); | |
+ st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); | |
klass = RCLASS(klass)->super; | |
} | |
if (RTEST(recur)) { | |
while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { | |
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list); | |
+ st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); | |
klass = RCLASS(klass)->super; | |
} | |
} | |
diff --git a/eval.c b/eval.c | |
index 4ec77d9..c53a26e 100644 | |
--- a/eval.c | |
+++ b/eval.c | |
@@ -396,7 +396,7 @@ rb_clear_cache_for_undef(klass, id) | |
while (ent < end) { | |
if (ent->mid == id && | |
(ent->klass == klass || | |
- RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl)) { | |
+ RCLASS_M_TBL(ent->origin) == RCLASS_M_TBL(klass))) { | |
ent->mid = 0; | |
} | |
ent++; | |
@@ -471,7 +471,7 @@ rb_add_method(klass, mid, node, noex) | |
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); | |
rb_clear_cache_by_id(mid); | |
body = NEW_METHOD(node, NOEX_WITH_SAFE(noex)); | |
- st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body); | |
+ st_insert(RCLASS_M_TBL(klass), mid, (st_data_t)body); | |
if (node && mid != ID_ALLOCATOR && ruby_running) { | |
if (FL_TEST(klass, FL_SINGLETON)) { | |
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid)); | |
@@ -508,7 +508,7 @@ search_method(klass, id, origin) | |
st_data_t body; | |
if (!klass) return 0; | |
- while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) { | |
+ while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { | |
klass = RCLASS(klass)->super; | |
if (!klass) return 0; | |
} | |
@@ -606,11 +606,11 @@ remove_method(klass, mid) | |
if (mid == __id__ || mid == __send__ || mid == init) { | |
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid)); | |
} | |
- if (st_lookup(RCLASS(klass)->m_tbl, mid, &data)) { | |
+ if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) { | |
body = (NODE *)data; | |
if (!body || !body->nd_body) body = 0; | |
else { | |
- st_delete(RCLASS(klass)->m_tbl, &mid, &data); | |
+ st_delete(RCLASS_M_TBL(klass), &mid, &data); | |
} | |
} | |
if (!body) { | |
@@ -2238,13 +2238,13 @@ rb_alias(klass, name, def) | |
} | |
rb_clear_cache_by_id(name); | |
- if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, &data)) { | |
+ if (RTEST(ruby_verbose) && st_lookup(RCLASS_M_TBL(klass), name, &data)) { | |
node = (NODE *)data; | |
if (node->nd_cnt == 0 && node->nd_body) { | |
rb_warning("discarding old %s", rb_id2name(name)); | |
} | |
} | |
- st_insert(RCLASS(klass)->m_tbl, name, | |
+ st_insert(RCLASS_M_TBL(klass), name, | |
(st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), | |
NOEX_WITH_SAFE(orig->nd_noex))); | |
@@ -2905,7 +2905,7 @@ rb_Array(val) | |
ID id = rb_intern("to_a"); | |
if (search_method(CLASS_OF(val), id, &origin) && | |
- RCLASS(origin)->m_tbl != RCLASS(rb_mKernel)->m_tbl) { /* exclude Kernel#to_a */ | |
+ RCLASS_M_TBL(origin) != RCLASS_M_TBL(rb_mKernel)) { /* exclude Kernel#to_a */ | |
val = rb_funcall(val, id, 0); | |
if (TYPE(val) != T_ARRAY) { | |
rb_raise(rb_eTypeError, "`to_a' did not return Array"); | |
@@ -3683,7 +3683,7 @@ eval_node(defs, void) | |
if (OBJ_FROZEN(recv)) rb_error_frozen("object"); | |
klass = rb_singleton_class(recv); | |
- if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) { | |
+ if (st_lookup(RCLASS_M_TBL(klass), node->nd_mid, &data)) { | |
body = (NODE *)data; | |
if (ruby_safe_level >= 4) { | |
rb_raise(rb_eSecurityError, "redefining method prohibited"); | |
@@ -9847,8 +9847,8 @@ umethod_bind(method, recv) | |
rb_raise(rb_eTypeError, "singleton method bound for a different object"); | |
} | |
if (TYPE(data->rklass) == T_MODULE) { | |
- st_table *m_tbl = RCLASS(data->rklass)->m_tbl; | |
- while (RCLASS(rklass)->m_tbl != m_tbl) { | |
+ st_table *m_tbl = RCLASS_M_TBL(data->rklass); | |
+ while (RCLASS_M_TBL(rklass) != m_tbl) { | |
rklass = RCLASS(rklass)->super; | |
if (!rklass) goto not_instace; | |
} | |
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c | |
index 09e3b39..0e88743 100644 | |
--- a/ext/iconv/iconv.c | |
+++ b/ext/iconv/iconv.c | |
@@ -136,10 +136,10 @@ map_charset | |
{ | |
VALUE val = *code; | |
- if (RHASH(charset_map)->tbl && RHASH(charset_map)->tbl->num_entries) { | |
+ if (RHASH_TBL(charset_map) && RHASH_TBL(charset_map)->num_entries) { | |
VALUE key = rb_funcall2(val, rb_intern("downcase"), 0, 0); | |
StringValuePtr(key); | |
- if (st_lookup(RHASH(charset_map)->tbl, key, &val)) { | |
+ if (st_lookup(RHASH_TBL(charset_map), key, &val)) { | |
*code = val; | |
} | |
} | |
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c | |
index 76e8279..580a79a 100644 | |
--- a/ext/syck/rubyext.c | |
+++ b/ext/syck/rubyext.c | |
@@ -636,7 +636,7 @@ rb_syck_load_handler(p, n) | |
if ( bonus->taint) OBJ_TAINT( obj ); | |
if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj); | |
- rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj); | |
+ rb_hash_aset(bonus->data, INT2FIX(RHASH_TBL(bonus->data)->num_entries), obj); | |
return obj; | |
} | |
diff --git a/gc.c b/gc.c | |
index 8c1c6d6..a2deffb 100644 | |
--- a/gc.c | |
+++ b/gc.c | |
@@ -1323,6 +1323,15 @@ mark_entry(key, value) | |
} | |
void | |
+rb_free_tbl(tbl) | |
+ st_table *tbl; | |
+{ | |
+ if (!tbl) return; | |
+ st_free_table(tbl); | |
+} | |
+#define free_tbl(tbl) rb_free_tbl(tbl) | |
+ | |
+void | |
rb_mark_tbl(tbl) | |
st_table *tbl; | |
{ | |
@@ -1941,10 +1950,8 @@ obj_free(obj) | |
case T_MODULE: | |
case T_CLASS: | |
rb_clear_cache_by_class((VALUE)obj); | |
- st_free_table(RANY(obj)->as.klass.m_tbl); | |
- if (RANY(obj)->as.object.iv_tbl) { | |
- st_free_table(RANY(obj)->as.object.iv_tbl); | |
- } | |
+ free_tbl(RANY(obj)->as.klass.m_tbl); | |
+ free_tbl(RANY(obj)->as.object.iv_tbl); | |
break; | |
case T_STRING: | |
if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { | |
diff --git a/hash.c b/hash.c | |
index 8086e22..01741d5 100644 | |
--- a/hash.c | |
+++ b/hash.c | |
@@ -28,7 +28,6 @@ static void | |
rb_hash_modify(hash) | |
VALUE hash; | |
{ | |
- if (!RHASH(hash)->tbl) rb_raise(rb_eTypeError, "uninitialized Hash"); | |
if (OBJ_FROZEN(hash)) rb_error_frozen("hash"); | |
if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4) | |
rb_raise(rb_eSecurityError, "Insecure: can't modify hash"); | |
@@ -121,7 +120,7 @@ rb_any_hash(a) | |
return RSHIFT(hnum, 1); | |
} | |
-static struct st_hash_type objhash = { | |
+struct st_hash_type objhash = { | |
rb_any_cmp, | |
rb_any_hash, | |
}; | |
@@ -181,10 +180,10 @@ hash_foreach_iter(key, value, arg) | |
int status; | |
st_table *tbl; | |
- tbl = RHASH(arg->hash)->tbl; | |
+ tbl = RHASH_TBL(arg->hash); | |
if (key == Qundef) return ST_CONTINUE; | |
status = (*arg->func)(key, value, arg->arg); | |
- if (RHASH(arg->hash)->tbl != tbl) { | |
+ if (RHASH_TBL(arg->hash) != tbl) { | |
rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); | |
} | |
switch (status) { | |
@@ -207,7 +206,7 @@ hash_foreach_ensure(hash) | |
if (RHASH(hash)->iter_lev == 0) { | |
if (FL_TEST(hash, HASH_DELETED)) { | |
- st_cleanup_safe(RHASH(hash)->tbl, Qundef); | |
+ st_cleanup_safe(RHASH_TBL(hash), Qundef); | |
FL_UNSET(hash, HASH_DELETED); | |
} | |
} | |
@@ -218,7 +217,7 @@ static VALUE | |
hash_foreach_call(arg) | |
struct hash_foreach_arg *arg; | |
{ | |
- if (st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, (st_data_t)arg)) { | |
+ if (st_foreach(RHASH_TBL(arg->hash), hash_foreach_iter, (st_data_t)arg)) { | |
rb_raise(rb_eRuntimeError, "hash modified during iteration"); | |
} | |
return Qnil; | |
@@ -249,6 +248,7 @@ hash_alloc0(klass) | |
OBJSETUP(hash, klass, T_HASH); | |
hash->ifnone = Qnil; | |
+ hash->tbl = 0; | |
return (VALUE)hash; | |
} | |
@@ -259,8 +259,6 @@ hash_alloc(klass) | |
{ | |
VALUE hash = hash_alloc0(klass); | |
- RHASH(hash)->tbl = st_init_table(&objhash); | |
- | |
return hash; | |
} | |
@@ -355,7 +353,7 @@ rb_hash_s_create(argc, argv, klass) | |
tmp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash"); | |
if (!NIL_P(tmp)) { | |
hash = hash_alloc0(klass); | |
- RHASH(hash)->tbl = st_copy(RHASH(tmp)->tbl); | |
+ RHASH(hash)->tbl = st_copy(RHASH_TBL(tmp)); | |
return hash; | |
} | |
@@ -435,9 +433,9 @@ rb_hash_rehash(hash) | |
st_table *tbl; | |
rb_hash_modify(hash); | |
- tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries); | |
+ tbl = st_init_table_with_size(&objhash, RHASH_TBL(hash)->num_entries); | |
rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl); | |
- st_free_table(RHASH(hash)->tbl); | |
+ st_free_table(RHASH_TBL(hash)); | |
RHASH(hash)->tbl = tbl; | |
return hash; | |
@@ -463,7 +461,7 @@ rb_hash_aref(hash, key) | |
{ | |
VALUE val; | |
- if (!st_lookup(RHASH(hash)->tbl, key, &val)) { | |
+ if (!st_lookup(RHASH_TBL(hash), key, &val)) { | |
return rb_funcall(hash, id_default, 1, key); | |
} | |
return val; | |
@@ -475,7 +473,7 @@ rb_hash_lookup(hash, key) | |
{ | |
VALUE val; | |
- if (!st_lookup(RHASH(hash)->tbl, key, &val)) { | |
+ if (!st_lookup(RHASH_TBL(hash), key, &val)) { | |
return Qnil; /* without Hash#default */ | |
} | |
return val; | |
@@ -526,7 +524,7 @@ rb_hash_fetch(argc, argv, hash) | |
if (block_given && argc == 2) { | |
rb_warn("block supersedes default value argument"); | |
} | |
- if (!st_lookup(RHASH(hash)->tbl, key, &val)) { | |
+ if (!st_lookup(RHASH_TBL(hash), key, &val)) { | |
if (block_given) return rb_yield(key); | |
if (argc == 1) { | |
rb_raise(rb_eIndexError, "key not found"); | |
@@ -647,12 +645,12 @@ rb_hash_delete_key(hash, key) | |
st_data_t ktmp = (st_data_t)key, val; | |
if (RHASH(hash)->iter_lev > 0) { | |
- if (st_delete_safe(RHASH(hash)->tbl, &ktmp, &val, Qundef)) { | |
+ if (st_delete_safe(RHASH_TBL(hash), &ktmp, &val, Qundef)) { | |
FL_SET(hash, HASH_DELETED); | |
return (VALUE)val; | |
} | |
} | |
- else if (st_delete(RHASH(hash)->tbl, &ktmp, &val)) | |
+ else if (st_delete(RHASH_TBL(hash), &ktmp, &val)) | |
return (VALUE)val; | |
return Qundef; | |
} | |
@@ -796,7 +794,7 @@ rb_hash_shift(hash) | |
rb_hash_foreach(hash, shift_i_safe, (st_data_t)&var); | |
if (var.key != Qundef) { | |
st_data_t key = var.key; | |
- if (st_delete_safe(RHASH(hash)->tbl, &key, 0, Qundef)) { | |
+ if (st_delete_safe(RHASH_TBL(hash), &key, 0, Qundef)) { | |
FL_SET(hash, HASH_DELETED); | |
} | |
} | |
@@ -864,9 +862,9 @@ rb_hash_reject_bang(hash) | |
int n; | |
RETURN_ENUMERATOR(hash, 0, 0); | |
- n = RHASH(hash)->tbl->num_entries; | |
+ n = RHASH_TBL(hash)->num_entries; | |
rb_hash_delete_if(hash); | |
- if (n == RHASH(hash)->tbl->num_entries) return Qnil; | |
+ if (n == RHASH_TBL(hash)->num_entries) return Qnil; | |
return hash; | |
} | |
@@ -971,7 +969,7 @@ rb_hash_clear(hash) | |
VALUE hash; | |
{ | |
rb_hash_modify(hash); | |
- if (RHASH(hash)->tbl->num_entries > 0) { | |
+ if (RHASH_TBL(hash)->num_entries > 0) { | |
rb_hash_foreach(hash, clear_i, 0); | |
} | |
@@ -1001,11 +999,11 @@ rb_hash_aset(hash, key, val) | |
VALUE hash, key, val; | |
{ | |
rb_hash_modify(hash); | |
- if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) { | |
- st_insert(RHASH(hash)->tbl, key, val); | |
+ if (TYPE(key) != T_STRING || st_lookup(RHASH_TBL(hash), key, 0)) { | |
+ st_insert(RHASH_TBL(hash), key, val); | |
} | |
else { | |
- st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val); | |
+ st_add_direct(RHASH_TBL(hash), rb_str_new4(key), val); | |
} | |
return val; | |
} | |
@@ -1069,7 +1067,7 @@ static VALUE | |
rb_hash_size(hash) | |
VALUE hash; | |
{ | |
- return INT2FIX(RHASH(hash)->tbl->num_entries); | |
+ return INT2FIX(RHASH_TBL(hash)->num_entries); | |
} | |
@@ -1087,7 +1085,7 @@ static VALUE | |
rb_hash_empty_p(hash) | |
VALUE hash; | |
{ | |
- if (RHASH(hash)->tbl->num_entries == 0) | |
+ if (RHASH_TBL(hash)->num_entries == 0) | |
return Qtrue; | |
return Qfalse; | |
} | |
@@ -1335,7 +1333,7 @@ static VALUE | |
rb_hash_inspect(hash) | |
VALUE hash; | |
{ | |
- if (RHASH(hash)->tbl == 0 || RHASH(hash)->tbl->num_entries == 0) | |
+ if (RHASH_TBL(hash) == 0 || RHASH_TBL(hash)->num_entries == 0) | |
return rb_str_new2("{}"); | |
if (rb_inspecting_p(hash)) return rb_str_new2("{...}"); | |
return rb_protect_inspect(inspect_hash, hash, 0); | |
@@ -1469,7 +1467,7 @@ rb_hash_has_key(hash, key) | |
VALUE hash; | |
VALUE key; | |
{ | |
- if (st_lookup(RHASH(hash)->tbl, key, 0)) { | |
+ if (st_lookup(RHASH_TBL(hash), key, 0)) { | |
return Qtrue; | |
} | |
return Qfalse; | |
@@ -1570,7 +1568,7 @@ hash_equal(hash1, hash2, eql) | |
} | |
return rb_equal(hash2, hash1); | |
} | |
- if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) | |
+ if (RHASH_TBL(hash1)->num_entries != RHASH_TBL(hash2)->num_entries) | |
return Qfalse; | |
if (eql) { | |
if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) && | |
@@ -1578,7 +1576,7 @@ hash_equal(hash1, hash2, eql) | |
return Qfalse; | |
} | |
- data.tbl = RHASH(hash2)->tbl; | |
+ data.tbl = RHASH_TBL(hash2); | |
data.eql = eql; | |
return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data); | |
} | |
@@ -1633,7 +1631,7 @@ recursive_hash(hash, dummy, recur) | |
if (recur) { | |
return LONG2FIX(0); | |
} | |
- hval = RHASH(hash)->tbl->num_entries; | |
+ hval = RHASH_TBL(hash)->num_entries; | |
rb_hash_foreach(hash, hash_i, (st_data_t)&hval); | |
return INT2FIX(hval); | |
} | |
diff --git a/marshal.c b/marshal.c | |
index 0112257..e6ce071 100644 | |
--- a/marshal.c | |
+++ b/marshal.c | |
@@ -404,7 +404,7 @@ w_extended(klass, arg, check) | |
const char *path; | |
if (check && FL_TEST(klass, FL_SINGLETON)) { | |
- if (RCLASS(klass)->m_tbl->num_entries || | |
+ if (RCLASS_M_TBL(klass)->num_entries || | |
(RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) { | |
rb_raise(rb_eTypeError, "singleton can't be dumped"); | |
} | |
@@ -652,7 +652,7 @@ w_object(obj, arg, limit) | |
else { | |
w_byte(TYPE_HASH_DEF, arg); | |
} | |
- w_long(RHASH(obj)->tbl->num_entries, arg); | |
+ w_long(RHASH_TBL(obj)->num_entries, arg); | |
rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg); | |
if (!NIL_P(RHASH(obj)->ifnone)) { | |
w_object(RHASH(obj)->ifnone, arg, limit); | |
diff --git a/object.c b/object.c | |
index ab62cbf..8d66116 100644 | |
--- a/object.c | |
+++ b/object.c | |
@@ -485,7 +485,7 @@ rb_obj_is_kind_of(obj, c) | |
} | |
while (cl) { | |
- if (cl == c || RCLASS(cl)->m_tbl == RCLASS(c)->m_tbl) | |
+ if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) | |
return Qtrue; | |
cl = RCLASS(cl)->super; | |
} | |
@@ -1364,18 +1364,18 @@ rb_class_inherited_p(mod, arg) | |
} | |
if (FL_TEST(mod, FL_SINGLETON)) { | |
- if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl) | |
+ if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) | |
return Qtrue; | |
mod = RBASIC(mod)->klass; | |
} | |
while (mod) { | |
- if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl) | |
+ if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) | |
return Qtrue; | |
mod = RCLASS(mod)->super; | |
} | |
/* not mod < arg; check if mod > arg */ | |
while (arg) { | |
- if (RCLASS(arg)->m_tbl == RCLASS(start)->m_tbl) | |
+ if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) | |
return Qfalse; | |
arg = RCLASS(arg)->super; | |
} | |
diff --git a/ruby.h b/ruby.h | |
index 4d003a8..8cffbb6 100644 | |
--- a/ruby.h | |
+++ b/ruby.h | |
@@ -332,7 +332,8 @@ struct RClass { | |
VALUE super; | |
}; | |
#define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl) | |
-#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) | |
+#define RCLASS_M_TBL(c) \ | |
+ ((!RCLASS(c)->m_tbl) ? RCLASS(c)->m_tbl = st_init_numtable() : RCLASS(c)->m_tbl) | |
#define RCLASS_SUPER(c) (RCLASS(c)->super) | |
#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) | |
#define RMODULE_M_TBL(m) RCLASS_M_TBL(m) | |
@@ -386,10 +387,13 @@ struct RHash { | |
int iter_lev; | |
VALUE ifnone; | |
}; | |
-#define RHASH_TBL(h) (RHASH(h)->tbl) | |
+ | |
+extern struct st_hash_type objhash; | |
+#define RHASH_TBL(h) \ | |
+ ((!RHASH(h)->tbl) ? RHASH(h)->tbl = st_init_table(&objhash) : RHASH(h)->tbl) | |
#define RHASH_ITER_LEV(h) (RHASH(h)->iter_lev) | |
#define RHASH_IFNONE(h) (RHASH(h)->ifnone) | |
-#define RHASH_SIZE(h) (RHASH(h)->tbl->num_entries) | |
+#define RHASH_SIZE(h) (RHASH_TBL(h)->num_entries) | |
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0) | |
struct RFile { | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark' | |
GC.enable_stats | |
module A | |
def a; end | |
def b; end | |
def c; end | |
end | |
class B | |
end | |
ITER = 100_000 | |
Benchmark.bm do |x| | |
x.report("Hash.new") do | |
ITER.times { Hash.new } | |
end | |
x.report("Hash#[]") do | |
ITER.times { Hash.new[:x] } | |
end | |
x.report("Hash#size") do | |
ITER.times { Hash.new.size } | |
end | |
x.report("Hash['a','b'].keys") do | |
ITER.times { Hash['a','b'].keys } | |
end | |
x.report("Class.new") do | |
ITER.times { Class.new } | |
end | |
x.report("Module.new") do | |
ITER.times { Module.new } | |
end | |
x.report("B.new.extend(A)") do | |
ITER.times { B.new.extend(A) } | |
end | |
end | |
puts "Allocated #{GC.allocated_size} bytes" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment