Skip to content

Instantly share code, notes, and snippets.

@methodmissing
Created March 14, 2010 00:16
Show Gist options
  • Save methodmissing/331658 to your computer and use it in GitHub Desktop.
Save methodmissing/331658 to your computer and use it in GitHub Desktop.
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
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 {
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