From 5c0e68c39c3fc7717311826549a30d1615eb2007 Mon Sep 17 00:00:00 2001 From: akr Date: Fri, 28 Sep 2007 06:21:46 +0000 Subject: * include/ruby/intern.h: export rb_ivar_foreach. * include/ruby/ruby.h: modify struct RObject and RClass for optimizing T_OBJECT space. [ruby-dev:31853] (ROBJECT_LEN, ROBJECT_PTR) (RCLASS_IV_TBL, RCLASS_M_TBL, RCLASS_SUPER, RCLASS_IV_INDEX_TBL) (RMODULE_IV_TBL, RMODULE_M_TBL, RMODULE_SUPER): abstract accessor defined. * variable.c: support the modified RObject and RClass. * object.c: ditto. * class.c: ditto. * gc.c: ditto. * marshal.c: ditto. * eval_method.ci: use the abstract accessor. * insns.def: ditto. * proc.c: ditto. * struct.c: ditto. * eval.c: ditto. * error.c: ditto. * vm.c: ditto. * insnhelper.ci: ditto. * ext/digest/digest.c: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13543 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 39 ++++++++ class.c | 117 +++++++++++----------- error.c | 2 +- eval.c | 2 +- eval_method.ci | 16 +-- ext/digest/digest.c | 2 +- gc.c | 29 ++++-- include/ruby/intern.h | 1 + include/ruby/ruby.h | 34 ++++++- insnhelper.ci | 12 +-- insns.def | 2 +- marshal.c | 29 +++++- object.c | 84 +++++++++++----- proc.c | 4 +- struct.c | 2 +- variable.c | 262 ++++++++++++++++++++++++++++++++++++-------------- vm.c | 4 +- 17 files changed, 448 insertions(+), 193 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5c32125ea4..d629a4c281 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +Fri Sep 28 15:05:24 2007 Tanaka Akira + + * include/ruby/intern.h: export rb_ivar_foreach. + + * include/ruby/ruby.h: modify struct RObject and RClass for optimizing + T_OBJECT space. [ruby-dev:31853] + (ROBJECT_LEN, ROBJECT_PTR) + (RCLASS_IV_TBL, RCLASS_M_TBL, RCLASS_SUPER, RCLASS_IV_INDEX_TBL) + (RMODULE_IV_TBL, RMODULE_M_TBL, RMODULE_SUPER): abstract accessor + defined. + + * variable.c: support the modified RObject and RClass. + + * object.c: ditto. + + * class.c: ditto. + + * gc.c: ditto. + + * marshal.c: ditto. + + * eval_method.ci: use the abstract accessor. + + * insns.def: ditto. + + * proc.c: ditto. + + * struct.c: ditto. + + * eval.c: ditto. + + * error.c: ditto. + + * vm.c: ditto. + + * insnhelper.ci: ditto. + + * ext/digest/digest.c: ditto. + Fri Sep 28 13:20:10 2007 Nobuyoshi Nakada * io.c (rb_io_getline_fast, rb_io_getline_1): set encoding to the diff --git a/class.c b/class.c index dff402c759..ead4d767ae 100644 --- a/class.c +++ b/class.c @@ -18,16 +18,27 @@ extern st_table *rb_class_tbl; +static VALUE +class_alloc(VALUE flags, VALUE klass) +{ + rb_classext_t *ext = ALLOC(rb_classext_t); + NEWOBJ(obj, struct RClass); + OBJSETUP(obj, klass, flags); + obj->ptr = ext; + RCLASS_IV_TBL(obj) = 0; + RCLASS_M_TBL(obj) = 0; + RCLASS_SUPER(obj) = 0; + RCLASS_IV_INDEX_TBL(obj) = 0; + return (VALUE)obj; +} + VALUE rb_class_boot(VALUE super) { - NEWOBJ(klass, struct RClass); - OBJSETUP(klass, rb_cClass, T_CLASS); + VALUE klass = class_alloc(T_CLASS, rb_cClass); - klass->super = super; - klass->iv_tbl = 0; - klass->m_tbl = 0; /* safe GC */ - klass->m_tbl = st_init_numtable(); + RCLASS_SUPER(klass) = super; + RCLASS_M_TBL(klass) = st_init_numtable(); OBJ_INFECT(klass, super); return (VALUE)klass; @@ -87,21 +98,21 @@ rb_mod_init_copy(VALUE clone, VALUE orig) if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { RBASIC(clone)->klass = rb_singleton_class_clone(orig); } - RCLASS(clone)->super = RCLASS(orig)->super; - if (RCLASS(orig)->iv_tbl) { + RCLASS_SUPER(clone) = RCLASS_SUPER(orig); + if (RCLASS_IV_TBL(orig)) { ID id; - RCLASS(clone)->iv_tbl = st_copy(RCLASS(orig)->iv_tbl); + RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); id = rb_intern("__classpath__"); - st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0); + st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0); id = rb_intern("__classid__"); - st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0); + st_delete(RCLASS_IV_TBL(clone), (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.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); data.klass = clone; - st_foreach(RCLASS(orig)->m_tbl, clone_method, + st_foreach(RCLASS_M_TBL(orig), clone_method, (st_data_t)&data); } @@ -112,7 +123,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig) VALUE rb_class_init_copy(VALUE clone, VALUE orig) { - if (RCLASS(clone)->super != 0) { + if (RCLASS_SUPER(clone) != 0) { rb_raise(rb_eTypeError, "already initialized class"); } if (FL_TEST(orig, FL_SINGLETON)) { @@ -131,8 +142,7 @@ rb_singleton_class_clone(VALUE obj) else { struct clone_method_data data; /* copy singleton(unnamed) class */ - NEWOBJ(clone, struct RClass); - OBJSETUP(clone, 0, RBASIC(klass)->flags); + VALUE clone = class_alloc(RBASIC(klass)->flags, 0); if (BUILTIN_TYPE(obj) == T_CLASS) { RBASIC(clone)->klass = (VALUE)clone; @@ -141,16 +151,14 @@ rb_singleton_class_clone(VALUE obj) RBASIC(clone)->klass = rb_singleton_class_clone(klass); } - clone->super = RCLASS(klass)->super; - clone->iv_tbl = 0; - clone->m_tbl = 0; - if (RCLASS(klass)->iv_tbl) { - clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl); + RCLASS_SUPER(clone) = RCLASS_SUPER(klass); + if (RCLASS_IV_TBL(klass)) { + RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); } - clone->m_tbl = st_init_numtable(); - data.tbl = clone->m_tbl; + RCLASS_M_TBL(clone) = st_init_numtable(); + data.tbl = RCLASS_M_TBL(clone); data.klass = (VALUE)clone; - st_foreach(RCLASS(klass)->m_tbl, clone_method, + 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); @@ -162,10 +170,10 @@ void rb_singleton_class_attached(VALUE klass, VALUE obj) { if (FL_TEST(klass, FL_SINGLETON)) { - if (!RCLASS(klass)->iv_tbl) { - RCLASS(klass)->iv_tbl = st_init_numtable(); + if (!RCLASS_IV_TBL(klass)) { + RCLASS_IV_TBL(klass) = st_init_numtable(); } - st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj); + st_insert(RCLASS_IV_TBL(klass), rb_intern("__attached__"), obj); } } @@ -223,7 +231,7 @@ rb_define_class(const char *name, VALUE super) if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } - if (rb_class_real(RCLASS(klass)->super) != super) { + if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; @@ -252,7 +260,7 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super) if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } - if (rb_class_real(RCLASS(klass)->super) != super) { + if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; @@ -272,13 +280,9 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super) VALUE rb_module_new(void) { - NEWOBJ(mdl, struct RClass); - OBJSETUP(mdl, rb_cModule, T_MODULE); + VALUE mdl = class_alloc(T_MODULE, rb_cModule); - mdl->super = 0; - mdl->iv_tbl = 0; - mdl->m_tbl = 0; - mdl->m_tbl = st_init_numtable(); + RCLASS_M_TBL(mdl) = st_init_numtable(); return (VALUE)mdl; } @@ -338,18 +342,17 @@ rb_define_module_under(VALUE outer, const char *name) static VALUE include_class_new(VALUE module, VALUE super) { - NEWOBJ(klass, struct RClass); - OBJSETUP(klass, rb_cClass, T_ICLASS); + VALUE klass = class_alloc(T_ICLASS, rb_cClass); if (BUILTIN_TYPE(module) == T_ICLASS) { module = RBASIC(module)->klass; } - if (!RCLASS(module)->iv_tbl) { - RCLASS(module)->iv_tbl = st_init_numtable(); + if (!RCLASS_IV_TBL(module)) { + RCLASS_IV_TBL(module) = st_init_numtable(); } - klass->iv_tbl = RCLASS(module)->iv_tbl; - klass->m_tbl = RCLASS(module)->m_tbl; - klass->super = super; + RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); + RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); + RCLASS_SUPER(klass) = super; if (TYPE(module) == T_ICLASS) { RBASIC(klass)->klass = RBASIC(module)->klass; } @@ -382,13 +385,13 @@ rb_include_module(VALUE klass, VALUE 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) { + for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { 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 */ } @@ -400,10 +403,10 @@ rb_include_module(VALUE klass, VALUE module) break; } } - c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super); + c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); changed = 1; skip: - module = RCLASS(module)->super; + module = RCLASS_SUPER(module); } if (changed) rb_clear_cache(); } @@ -431,7 +434,7 @@ rb_mod_included_modules(VALUE mod) VALUE ary = rb_ary_new(); VALUE p; - for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) { + for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass); } @@ -464,7 +467,7 @@ rb_mod_include_p(VALUE mod, VALUE mod2) VALUE p; Check_Type(mod2, T_MODULE); - for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) { + for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS) { if (RBASIC(p)->klass == mod2) return Qtrue; } @@ -493,7 +496,7 @@ rb_mod_ancestors(VALUE mod) { VALUE p, ary = rb_ary_new(); - for (p = mod; p; p = RCLASS(p)->super) { + for (p = mod; p; p = RCLASS_SUPER(p)) { if (FL_TEST(p, FL_SINGLETON)) continue; if (BUILTIN_TYPE(p) == T_ICLASS) { @@ -599,8 +602,8 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, lo } list = st_init_numtable(); - for (; mod; mod = RCLASS(mod)->super) { - st_foreach(RCLASS(mod)->m_tbl, method_entry, (st_data_t)list); + for (; mod; mod = RCLASS_SUPER(mod)) { + 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; @@ -756,13 +759,13 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE 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); - klass = RCLASS(klass)->super; + st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); + klass = RCLASS_SUPER(klass); } 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); - klass = RCLASS(klass)->super; + st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list); + klass = RCLASS_SUPER(klass); } } ary = rb_ary_new(); diff --git a/error.c b/error.c index e972bdd1b0..c72873d9b3 100644 --- a/error.c +++ b/error.c @@ -971,7 +971,7 @@ syserr_eqq(VALUE self, VALUE exc) VALUE klass = CLASS_OF(exc); while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { - klass = (VALUE)RCLASS(klass)->super; + klass = (VALUE)RCLASS_SUPER(klass); } num = rb_const_get(klass, rb_intern("Errno")); } diff --git a/eval.c b/eval.c index 639010efd8..49c6f5213d 100644 --- a/eval.c +++ b/eval.c @@ -2303,7 +2303,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) { break; /* normal case: need not to follow 'super' link */ } - m = RCLASS(m)->super; + m = RCLASS_SUPER(m); if (!m) break; } diff --git a/eval_method.ci b/eval_method.ci index 61ff38f532..6d86e52c50 100644 --- a/eval_method.ci +++ b/eval_method.ci @@ -143,7 +143,7 @@ rb_add_method(VALUE klass, ID mid, NODE * node, int noex) st_data_t data; NODE *old_node; - if (st_lookup(RCLASS(klass)->m_tbl, mid, &data)) { + if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) { old_node = (NODE *)data; if (old_node) { if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) { @@ -166,7 +166,7 @@ rb_add_method(VALUE klass, ID mid, NODE * node, int 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)) { @@ -216,8 +216,8 @@ search_method(VALUE klass, ID id, VALUE *klassp) return 0; } - while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) { - klass = RCLASS(klass)->super; + while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { + klass = RCLASS_SUPER(klass); if (!klass) return 0; } @@ -305,11 +305,11 @@ remove_method(VALUE klass, ID mid) if (mid == object_id || mid == __send || mid == __send_bang || 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) { @@ -583,7 +583,7 @@ rb_alias(VALUE klass, ID name, ID def) orig_fbody->nd_cnt++; - if (st_lookup(RCLASS(klass)->m_tbl, name, &data)) { + if (st_lookup(RCLASS_M_TBL(klass), name, &data)) { node = (NODE *)data; if (node) { if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) { @@ -595,7 +595,7 @@ rb_alias(VALUE klass, ID name, ID def) } } - st_insert(RCLASS(klass)->m_tbl, name, + st_insert(RCLASS_M_TBL(klass), name, (st_data_t) NEW_FBODY( NEW_METHOD(orig_fbody->nd_body->nd_body, orig_fbody->nd_body->nd_clss, diff --git a/ext/digest/digest.c b/ext/digest/digest.c index 0b910e8c47..41565759bb 100644 --- a/ext/digest/digest.c +++ b/ext/digest/digest.c @@ -426,7 +426,7 @@ get_digest_base_metadata(VALUE klass) VALUE obj; rb_digest_metadata_t *algo; - for (p = klass; p; p = RCLASS(p)->super) { + for (p = klass; p; p = RCLASS_SUPER(p)) { if (rb_ivar_defined(p, id_metadata)) { obj = rb_ivar_get(p, id_metadata); break; diff --git a/gc.c b/gc.c index 3a073d39d8..7dd5c4e681 100644 --- a/gc.c +++ b/gc.c @@ -1033,9 +1033,9 @@ gc_mark_children(VALUE ptr, int lev) case T_ICLASS: case T_CLASS: case T_MODULE: - mark_tbl(obj->as.klass.m_tbl, lev); - mark_tbl(obj->as.klass.iv_tbl, lev); - ptr = obj->as.klass.super; + mark_tbl(RCLASS_M_TBL(obj), lev); + mark_tbl(RCLASS_IV_TBL(obj), lev); + ptr = RCLASS_SUPER(obj); goto again; case T_ARRAY: @@ -1070,7 +1070,13 @@ gc_mark_children(VALUE ptr, int lev) break; case T_OBJECT: - mark_tbl(obj->as.object.iv_tbl, lev); + { + long i, len = ROBJECT_LEN(obj); + VALUE *ptr = ROBJECT_PTR(obj); + for (i = 0; i < len; i++) { + gc_mark(*ptr++, lev); + } + } break; case T_FILE: @@ -1269,17 +1275,22 @@ obj_free(VALUE obj) switch (RANY(obj)->as.basic.flags & T_MASK) { case T_OBJECT: - if (RANY(obj)->as.object.iv_tbl) { - st_free_table(RANY(obj)->as.object.iv_tbl); + if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) && + RANY(obj)->as.object.as.heap.ptr) { + RUBY_CRITICAL(free(RANY(obj)->as.object.as.heap.ptr)); } break; 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); + st_free_table(RCLASS_M_TBL(obj)); + if (RCLASS_IV_TBL(obj)) { + st_free_table(RCLASS_IV_TBL(obj)); + } + if (RCLASS_IV_INDEX_TBL(obj)) { + st_free_table(RCLASS_IV_INDEX_TBL(obj)); } + RUBY_CRITICAL(free(RANY(obj)->as.klass.ptr)); break; case T_STRING: rb_str_free(obj); diff --git a/include/ruby/intern.h b/include/ruby/intern.h index d9443f5788..1b453d1f30 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -583,6 +583,7 @@ void rb_free_generic_ivar(VALUE); VALUE rb_ivar_get(VALUE, ID); VALUE rb_ivar_set(VALUE, ID, VALUE); VALUE rb_ivar_defined(VALUE, ID); +void rb_ivar_foreach(VALUE, int (*)(ANYARGS), st_data_t); VALUE rb_iv_set(VALUE, const char*, VALUE); VALUE rb_iv_get(VALUE, const char*); VALUE rb_attr_get(VALUE, ID); diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 5ccf246734..4939609e31 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -402,10 +402,26 @@ struct RBasic { VALUE klass; }; +#define ROBJECT_EMBED_LEN_MAX 3 struct RObject { struct RBasic basic; - struct st_table *iv_tbl; + union { + struct { + long len; + VALUE *ptr; + } heap; + VALUE ary[ROBJECT_EMBED_LEN_MAX]; + } as; }; +#define ROBJECT_EMBED FL_USER1 +#define ROBJECT_LEN(o) \ + ((RBASIC(o)->flags & ROBJECT_EMBED) ? \ + ROBJECT_EMBED_LEN_MAX : \ + ROBJECT(o)->as.heap.len) +#define ROBJECT_PTR(o) \ + ((RBASIC(o)->flags & ROBJECT_EMBED) ? \ + ROBJECT(o)->as.ary : \ + ROBJECT(o)->as.heap.ptr) struct RValues { struct RBasic basic; @@ -414,12 +430,24 @@ struct RValues { VALUE v3; }; +typedef struct { + struct st_table *iv_tbl; + VALUE super; +} rb_classext_t; + struct RClass { struct RBasic basic; - struct st_table *iv_tbl; + rb_classext_t *ptr; struct st_table *m_tbl; - VALUE super; + struct st_table *iv_index_tbl; }; +#define RCLASS_IV_TBL(c) (RCLASS(c)->ptr->iv_tbl) +#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#define RCLASS_SUPER(c) (RCLASS(c)->ptr->super) +#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) +#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) +#define RMODULE_M_TBL(m) RCLASS_M_TBL(m) +#define RMODULE_SUPER(m) RCLASS_SUPER(m) struct RFloat { struct RBasic basic; diff --git a/insnhelper.ci b/insnhelper.ci index 4be9c7259e..afb0bd0e76 100644 --- a/insnhelper.ci +++ b/insnhelper.ci @@ -507,7 +507,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, break; } case NODE_ZSUPER:{ - klass = RCLASS(mn->nd_clss)->super; + klass = RCLASS_SUPER(mn->nd_clss); mn = rb_method_node(klass, id); if (mn != 0) { @@ -998,8 +998,8 @@ vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq, } } search_continue: - if (RCLASS(klass)->iv_tbl && - st_lookup(RCLASS(klass)->iv_tbl, id, &val)) { + if (RCLASS_IV_TBL(klass) && + st_lookup(RCLASS_IV_TBL(klass), id, &val)) { if (val == Qundef) { rb_autoload_load(klass, id); goto search_continue; @@ -1122,16 +1122,16 @@ static inline VALUE vm_search_normal_super_klass(VALUE klass, VALUE recv) { if (BUILTIN_TYPE(klass) == T_CLASS) { - klass = RCLASS(klass)->super; + klass = RCLASS_SUPER(klass); } else if (BUILTIN_TYPE(klass) == T_MODULE) { VALUE k = CLASS_OF(recv); while (k) { if (BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) { - klass = RCLASS(k)->super; + klass = RCLASS_SUPER(k); break; } - k = RCLASS(k)->super; + k = RCLASS_SUPER(k); } } return klass; diff --git a/insns.def b/insns.def index d31a9656bc..3cf8e4d67f 100644 --- a/insns.def +++ b/insns.def @@ -973,7 +973,7 @@ defineclass if (super != rb_cObject) { VALUE tmp; - tmp = rb_class_real(RCLASS(klass)->super); + tmp = rb_class_real(RCLASS_SUPER(klass)); if (tmp != super) { rb_raise(rb_eTypeError, "superclass mismatch for class %s", diff --git a/marshal.c b/marshal.c index 6b7108e4df..f4cc37942e 100644 --- a/marshal.c +++ b/marshal.c @@ -404,17 +404,17 @@ w_extended(VALUE klass, struct dump_arg *arg, int check) char *path; if (check && FL_TEST(klass, FL_SINGLETON)) { - if (RCLASS(klass)->m_tbl->num_entries || - (RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) { + if (RCLASS_M_TBL(klass)->num_entries || + (RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) { rb_raise(rb_eTypeError, "singleton can't be dumped"); } - klass = RCLASS(klass)->super; + klass = RCLASS_SUPER(klass); } while (BUILTIN_TYPE(klass) == T_ICLASS) { path = rb_class2name(RBASIC(klass)->klass); w_byte(TYPE_EXTENDED, arg); w_unique(path, arg); - klass = RCLASS(klass)->super; + klass = RCLASS_SUPER(klass); } } @@ -470,6 +470,25 @@ w_ivar(st_table *tbl, struct dump_call_arg *arg) } } +static void +w_objivar(VALUE obj, struct dump_call_arg *arg) +{ + VALUE *ptr; + long i, len, num; + + len = ROBJECT_LEN(obj); + ptr = ROBJECT_PTR(obj); + num = 0; + for (i = 0; i < len; i++) + if (ptr[i] != Qundef) + num += 1; + + w_long(num, arg->arg); + if (num != 0) { + rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg); + } +} + static void w_object(VALUE obj, struct dump_arg *arg, int limit) { @@ -682,7 +701,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) case T_OBJECT: w_class(TYPE_OBJECT, obj, arg, Qtrue); - w_ivar(ROBJECT(obj)->iv_tbl, &c_arg); + w_objivar(obj, &c_arg); break; case T_DATA: diff --git a/object.c b/object.c index c6fa1176f3..e2b3e43bd0 100644 --- a/object.c +++ b/object.c @@ -100,7 +100,7 @@ VALUE rb_class_real(VALUE cl) { while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) { - cl = RCLASS(cl)->super; + cl = RCLASS_SUPER(cl); } return cl; } @@ -137,15 +137,34 @@ init_copy(VALUE dest, VALUE obj) rb_gc_copy_finalizer(dest, obj); switch (TYPE(obj)) { case T_OBJECT: + if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_PTR(dest)) { + xfree(ROBJECT_PTR(dest)); + ROBJECT(dest)->as.heap.ptr = 0; + ROBJECT(dest)->as.heap.len = 0; + } + if (RBASIC(obj)->flags & ROBJECT_EMBED) { + MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX); + RBASIC(dest)->flags |= ROBJECT_EMBED; + } + else { + long len = ROBJECT(obj)->as.heap.len; + VALUE *ptr = ALLOC_N(VALUE, len); + MEMCPY(ptr, ROBJECT(obj)->as.heap.ptr, VALUE, len); + ROBJECT(dest)->as.heap.ptr = ptr; + ROBJECT(dest)->as.heap.len = len; + RBASIC(dest)->flags &= ~ROBJECT_EMBED; + } + break; case T_CLASS: case T_MODULE: - if (ROBJECT(dest)->iv_tbl) { - st_free_table(ROBJECT(dest)->iv_tbl); - ROBJECT(dest)->iv_tbl = 0; + if (RCLASS_IV_TBL(dest)) { + st_free_table(RCLASS_IV_TBL(dest)); + RCLASS_IV_TBL(dest) = 0; } - if (ROBJECT(obj)->iv_tbl) { - ROBJECT(dest)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); + if (RCLASS_IV_TBL(obj)) { + RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); } + break; } rb_funcall(dest, id_init_copy, 1, obj); } @@ -296,7 +315,7 @@ inspect_obj(VALUE obj, VALUE str, int recur) rb_str_cat2(str, " ..."); } else { - st_foreach_safe(ROBJECT(obj)->iv_tbl, inspect_i, str); + rb_ivar_foreach(obj, inspect_i, str); } rb_str_cat2(str, ">"); RSTRING_PTR(str)[0] = '#'; @@ -321,15 +340,28 @@ inspect_obj(VALUE obj, VALUE str, int recur) static VALUE rb_obj_inspect(VALUE obj) { - if (TYPE(obj) == T_OBJECT - && ROBJECT(obj)->iv_tbl - && ROBJECT(obj)->iv_tbl->num_entries > 0) { - VALUE str; - char *c; - c = rb_obj_classname(obj); - str = rb_sprintf("-<%s:%p", c, (void*)obj); - return rb_exec_recursive(inspect_obj, obj, str); + if (TYPE(obj) == T_OBJECT) { + int has_ivar = 0; + VALUE *ptr = ROBJECT_PTR(obj); + long len = ROBJECT_LEN(obj); + long i; + + for (i = 0; i < len; i++) { + if (ptr[i] != Qundef) { + has_ivar = 1; + break; + } + } + + if (has_ivar) { + VALUE str; + char *c; + + c = rb_obj_classname(obj); + str = rb_sprintf("-<%s:%p", c, (void*)obj); + return rb_exec_recursive(inspect_obj, obj, str); + } } return rb_funcall(obj, rb_intern("to_s"), 0, 0); } @@ -402,9 +434,9 @@ rb_obj_is_kind_of(VALUE obj, VALUE 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; + cl = RCLASS_SUPER(cl); } return Qfalse; } @@ -1104,15 +1136,15 @@ rb_class_inherited_p(VALUE mod, VALUE arg) rb_raise(rb_eTypeError, "compared with non class/module"); } 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; + mod = RCLASS_SUPER(mod); } /* 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; + arg = RCLASS_SUPER(arg); } return Qnil; } @@ -1277,7 +1309,7 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass) { VALUE super; - if (RCLASS(klass)->super != 0) { + if (RCLASS_SUPER(klass) != 0) { rb_raise(rb_eTypeError, "already initialized class"); } if (rb_scan_args(argc, argv, "01", &super) == 0) { @@ -1286,7 +1318,7 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass) else { rb_check_inheritable(super); } - RCLASS(klass)->super = super; + RCLASS_SUPER(klass) = super; rb_make_metaclass(klass, RBASIC(super)->klass); rb_class_inherited(super, klass); rb_mod_initialize(klass); @@ -1308,7 +1340,7 @@ rb_obj_alloc(VALUE klass) { VALUE obj; - if (RCLASS(klass)->super == 0 && klass != rb_cBasicObject) { + if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) { rb_raise(rb_eTypeError, "can't instantiate uninitialized class"); } if (FL_TEST(klass, FL_SINGLETON)) { @@ -1367,13 +1399,13 @@ rb_class_new_instance(int argc, VALUE *argv, VALUE klass) static VALUE rb_class_superclass(VALUE klass) { - VALUE super = RCLASS(klass)->super; + VALUE super = RCLASS_SUPER(klass); if (!super) { rb_raise(rb_eTypeError, "uninitialized class"); } while (TYPE(super) == T_ICLASS) { - super = RCLASS(super)->super; + super = RCLASS_SUPER(super); } if (!super) { return Qnil; diff --git a/proc.c b/proc.c index 3b6d9a94f4..127a1bd073 100644 --- a/proc.c +++ b/proc.c @@ -620,13 +620,13 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mklass) body = body->nd_body; if (nd_type(body) == NODE_ZSUPER) { - klass = RCLASS(klass)->super; + klass = RCLASS_SUPER(klass); goto again; } while (rklass != klass && (FL_TEST(rklass, FL_SINGLETON) || TYPE(rklass) == T_ICLASS)) { - rklass = RCLASS(rklass)->super; + rklass = RCLASS_SUPER(rklass); } if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass; diff --git a/struct.c b/struct.c index 57050b7422..e87a082c23 100644 --- a/struct.c +++ b/struct.c @@ -25,7 +25,7 @@ rb_struct_iv_get(VALUE c, const char *name) for (;;) { if (rb_ivar_defined(c, id)) return rb_ivar_get(c, id); - c = RCLASS(c)->super; + c = RCLASS_SUPER(c); if (c == 0 || c == rb_cStruct) return Qnil; } diff --git a/variable.c b/variable.c index 2ddfb1ac5b..d5c3bfe100 100644 --- a/variable.c +++ b/variable.c @@ -48,8 +48,8 @@ fc_path(struct fc_result *fc, ID name) path = rb_str_new2(rb_id2name(name)); while (fc) { if (fc->track == rb_cObject) break; - if (ROBJECT(fc->track)->iv_tbl && - st_lookup(ROBJECT(fc->track)->iv_tbl, classpath, &tmp)) { + if (RCLASS_IV_TBL(fc->track) && + st_lookup(RCLASS_IV_TBL(fc->track), classpath, &tmp)) { tmp = rb_str_dup(tmp); rb_str_cat2(tmp, "::"); rb_str_append(tmp, path); @@ -78,7 +78,7 @@ fc_i(ID key, VALUE value, struct fc_result *res) switch (TYPE(value)) { case T_MODULE: case T_CLASS: - if (!RCLASS(value)->iv_tbl) return ST_CONTINUE; + if (!RCLASS_IV_TBL(value)) return ST_CONTINUE; else { struct fc_result arg; struct fc_result *list; @@ -94,7 +94,7 @@ fc_i(ID key, VALUE value, struct fc_result *res) arg.klass = res->klass; arg.track = value; arg.prev = res; - st_foreach(RCLASS(value)->iv_tbl, fc_i, (st_data_t)&arg); + st_foreach(RCLASS_IV_TBL(value), fc_i, (st_data_t)&arg); if (arg.path) { res->path = arg.path; return ST_STOP; @@ -118,18 +118,18 @@ find_class_path(VALUE klass) arg.klass = klass; arg.track = rb_cObject; arg.prev = 0; - if (RCLASS(rb_cObject)->iv_tbl) { - st_foreach_safe(RCLASS(rb_cObject)->iv_tbl, fc_i, (st_data_t)&arg); + if (RCLASS_IV_TBL(rb_cObject)) { + st_foreach_safe(RCLASS_IV_TBL(rb_cObject), fc_i, (st_data_t)&arg); } if (arg.path == 0) { st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); } if (arg.path) { - if (!ROBJECT(klass)->iv_tbl) { - ROBJECT(klass)->iv_tbl = st_init_numtable(); + if (!RCLASS_IV_TBL(klass)) { + RCLASS_IV_TBL(klass) = st_init_numtable(); } - st_insert(ROBJECT(klass)->iv_tbl, classpath, arg.path); - st_delete(RCLASS(klass)->iv_tbl, &tmp_classpath, 0); + st_insert(RCLASS_IV_TBL(klass), classpath, arg.path); + st_delete(RCLASS_IV_TBL(klass), &tmp_classpath, 0); return arg.path; } return Qnil; @@ -141,17 +141,17 @@ classname(VALUE klass) VALUE path = Qnil; if (!klass) klass = rb_cObject; - if (ROBJECT(klass)->iv_tbl) { - if (!st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) { + if (RCLASS_IV_TBL(klass)) { + if (!st_lookup(RCLASS_IV_TBL(klass), classpath, &path)) { ID classid = rb_intern("__classid__"); - if (!st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) { + if (!st_lookup(RCLASS_IV_TBL(klass), classid, &path)) { return find_class_path(klass); } path = rb_str_new2(rb_id2name(SYM2ID(path))); OBJ_FREEZE(path); - st_insert(ROBJECT(klass)->iv_tbl, classpath, path); - st_delete(RCLASS(klass)->iv_tbl, (st_data_t*)&classid, 0); + st_insert(RCLASS_IV_TBL(klass), classpath, path); + st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&classid, 0); } if (TYPE(path) != T_STRING) { rb_bug("class path is not set properly"); @@ -183,7 +183,7 @@ rb_class_path(VALUE klass) VALUE path = classname(klass); if (!NIL_P(path)) return path; - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, + if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), tmp_classpath, &path)) { return path; } @@ -926,12 +926,22 @@ static VALUE ivar_get(VALUE obj, ID id, int warn) { VALUE val; + VALUE klass; + st_data_t index; switch (TYPE(obj)) { case T_OBJECT: + klass = rb_obj_class(obj); + if (!RCLASS_IV_INDEX_TBL(klass)) break; + if (!st_lookup(RCLASS_IV_INDEX_TBL(klass), id, &index)) break; + if (ROBJECT_LEN(obj) <= index) break; + val = ROBJECT_PTR(obj)[index]; + if (val != Qundef) + return val; + break; case T_CLASS: case T_MODULE: - if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val)) + if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, &val)) return val; break; default: @@ -960,16 +970,63 @@ rb_attr_get(VALUE obj, ID id) VALUE rb_ivar_set(VALUE obj, ID id, VALUE val) { + VALUE klass; + st_data_t index; + long i, len; + int ivar_extended; + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); if (OBJ_FROZEN(obj)) rb_error_frozen("object"); switch (TYPE(obj)) { case T_OBJECT: + klass = rb_obj_class(obj); + if (!RCLASS_IV_INDEX_TBL(klass)) + RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); + ivar_extended = 0; + if (!st_lookup(RCLASS_IV_INDEX_TBL(klass), id, &index)) { + index = RCLASS_IV_INDEX_TBL(klass)->num_entries; + st_add_direct(RCLASS_IV_INDEX_TBL(klass), id, index); + ivar_extended = 1; + } + len = ROBJECT_LEN(obj); + if (len <= index) { + VALUE *ptr = ROBJECT_PTR(obj); + if (index < ROBJECT_EMBED_LEN_MAX) { + RBASIC(obj)->flags |= ROBJECT_EMBED; + ptr = ROBJECT(obj)->as.ary; + for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { + ptr[i] = Qundef; + } + } + else { + VALUE *newptr; + long newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */ + if (!ivar_extended && + RCLASS_IV_INDEX_TBL(klass)->num_entries < newsize) { + newsize = RCLASS_IV_INDEX_TBL(klass)->num_entries; + } + if (RBASIC(obj)->flags & ROBJECT_EMBED) { + newptr = ALLOC_N(VALUE, newsize); + MEMCPY(newptr, ptr, VALUE, len); + RBASIC(obj)->flags &= ~ROBJECT_EMBED; + ROBJECT(obj)->as.heap.ptr = newptr; + } + else { + REALLOC_N(ROBJECT(obj)->as.heap.ptr, VALUE, newsize); + newptr = ROBJECT(obj)->as.heap.ptr; + } + for (; len < newsize; len++) + newptr[len] = Qundef; + ROBJECT(obj)->as.heap.len = newsize; + } + } + ROBJECT_PTR(obj)[index] = val; + break; case T_CLASS: case T_MODULE: - if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable(); - st_insert(ROBJECT(obj)->iv_tbl, id, val); - break; + if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); + st_insert(RCLASS_IV_TBL(obj), id, val); default: generic_ivar_set(obj, id, val); break; @@ -980,11 +1037,21 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) VALUE rb_ivar_defined(VALUE obj, ID id) { + VALUE klass, val; + st_data_t index; switch (TYPE(obj)) { case T_OBJECT: + klass = rb_obj_class(obj); + if (!RCLASS_IV_INDEX_TBL(klass)) break; + if (!st_lookup(RCLASS_IV_INDEX_TBL(klass), id, &index)) break; + if (ROBJECT_LEN(obj) <= index) break; + val = ROBJECT_PTR(obj)[index]; + if (val != Qundef) + return Qtrue; + break; case T_CLASS: case T_MODULE: - if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0)) + if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, 0)) return Qtrue; break; default: @@ -995,8 +1062,69 @@ rb_ivar_defined(VALUE obj, ID id) return Qfalse; } +struct obj_ivar_tag { + VALUE obj; + int (*func)(ID key, VALUE val, st_data_t arg); + st_data_t arg; +}; + static int -ivar_i(ID key, struct global_entry *entry, VALUE ary) +obj_ivar_i(ID key, VALUE index, struct obj_ivar_tag *data) +{ + if (index < ROBJECT_LEN(data->obj)) { + VALUE val = ROBJECT_PTR(data->obj)[index]; + if (val != Qundef) { + return (data->func)(key, val, data->arg); + } + } + return ST_CONTINUE; +} + +static void +obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) +{ + VALUE klass = rb_obj_class(obj); + st_table *tbl; + struct obj_ivar_tag data; + + tbl = RCLASS_IV_INDEX_TBL(klass); + if (!tbl) + return; + + data.obj = obj; + data.func = func; + data.arg = arg; + + st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); +} + +void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) +{ + switch (TYPE(obj)) { + case T_OBJECT: + obj_ivar_each(obj, func, arg); + break; + case T_CLASS: + case T_MODULE: + if (RCLASS_IV_TBL(obj)) { + st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); + } + break; + default: + if (!generic_iv_tbl) break; + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { + st_data_t tbl; + + if (st_lookup(generic_iv_tbl, obj, &tbl)) { + st_foreach_safe((st_table *)tbl, func, arg); + } + } + break; + } +} + +static int +ivar_i(ID key, VALUE val, VALUE ary) { if (rb_is_instance_id(key)) { rb_ary_push(ary, ID2SYM(key)); @@ -1027,25 +1155,7 @@ rb_obj_instance_variables(VALUE obj) VALUE ary; ary = rb_ary_new(); - switch (TYPE(obj)) { - case T_OBJECT: - case T_CLASS: - case T_MODULE: - if (ROBJECT(obj)->iv_tbl) { - st_foreach_safe(ROBJECT(obj)->iv_tbl, ivar_i, ary); - } - break; - default: - if (!generic_iv_tbl) break; - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, obj, &tbl)) { - st_foreach_safe((st_table *)tbl, ivar_i, ary); - } - } - break; - } + rb_ivar_foreach(obj, ivar_i, ary); return ary; } @@ -1076,6 +1186,8 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) { VALUE val = Qnil; ID id = rb_to_id(name); + VALUE klass; + st_data_t index; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); @@ -1086,9 +1198,19 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) switch (TYPE(obj)) { case T_OBJECT: + klass = rb_obj_class(obj); + if (!RCLASS_IV_INDEX_TBL(klass)) break; + if (!st_lookup(RCLASS_IV_INDEX_TBL(klass), id, &index)) break; + if (ROBJECT_LEN(obj) <= index) break; + val = ROBJECT_PTR(obj)[index]; + if (val != Qundef) { + ROBJECT_PTR(obj)[index] = Qundef; + return val; + } + break; case T_CLASS: case T_MODULE: - if (ROBJECT(obj)->iv_tbl && st_delete(ROBJECT(obj)->iv_tbl, (st_data_t*)&id, &val)) { + if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t*)&id, &val)) { return val; } break; @@ -1185,11 +1307,11 @@ rb_autoload(VALUE mod, ID id, const char *file) rb_raise(rb_eArgError, "empty file name"); } - if ((tbl = RCLASS(mod)->iv_tbl) && st_lookup(tbl, id, &av) && av != Qundef) + if ((tbl = RCLASS_IV_TBL(mod)) && st_lookup(tbl, id, &av) && av != Qundef) return; rb_const_set(mod, id, Qundef); - tbl = RCLASS(mod)->iv_tbl; + tbl = RCLASS_IV_TBL(mod); if (st_lookup(tbl, autoload, &av)) { tbl = check_autoload_table(av); } @@ -1210,8 +1332,8 @@ autoload_delete(VALUE mod, ID id) VALUE val; st_data_t load = 0; - st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0); - if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) { + st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, 0); + if (st_lookup(RCLASS_IV_TBL(mod), autoload, &val)) { struct st_table *tbl = check_autoload_table(val); st_delete(tbl, (st_data_t*)&id, &load); @@ -1220,7 +1342,7 @@ autoload_delete(VALUE mod, ID id) DATA_PTR(val) = 0; st_free_table(tbl); id = autoload; - if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) { + if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) { rb_gc_force_recycle(val); } } @@ -1248,7 +1370,7 @@ autoload_file(VALUE mod, ID id) struct st_table *tbl; st_data_t load; - if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) || + if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) { return Qnil; } @@ -1267,7 +1389,7 @@ autoload_file(VALUE mod, ID id) DATA_PTR(val) = 0; st_free_table(tbl); id = autoload; - if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) { + if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) { rb_gc_force_recycle(val); } } @@ -1277,7 +1399,7 @@ autoload_file(VALUE mod, ID id) VALUE rb_autoload_p(VALUE mod, ID id) { - struct st_table *tbl = RCLASS(mod)->iv_tbl; + struct st_table *tbl = RCLASS_IV_TBL(mod); VALUE val; if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) { @@ -1295,7 +1417,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse) tmp = klass; retry: while (tmp && !NIL_P(tmp)) { - while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { + while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) { if (value == Qundef) { if (!RTEST(rb_autoload_load(tmp, id))) break; continue; @@ -1307,7 +1429,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse) return value; } if (!recurse && klass != rb_cObject) break; - tmp = RCLASS(tmp)->super; + tmp = RCLASS_SUPER(tmp); } if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) { mod_retry = 1; @@ -1360,7 +1482,7 @@ rb_mod_remove_const(VALUE mod, VALUE name) rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); if (OBJ_FROZEN(mod)) rb_error_frozen("class/module"); - if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) { + if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) { if (val == Qundef) { autoload_delete(mod, id); val = Qnil; @@ -1394,8 +1516,8 @@ rb_mod_const_at(VALUE mod, void *data) if (!tbl) { tbl = st_init_numtable(); } - if (RCLASS(mod)->iv_tbl) { - st_foreach_safe(RCLASS(mod)->iv_tbl, sv_i, (st_data_t)tbl); + if (RCLASS_IV_TBL(mod)) { + st_foreach_safe(RCLASS_IV_TBL(mod), sv_i, (st_data_t)tbl); } return tbl; } @@ -1406,7 +1528,7 @@ rb_mod_const_of(VALUE mod, void *data) VALUE tmp = mod; for (;;) { data = rb_mod_const_at(tmp, data); - tmp = RCLASS(tmp)->super; + tmp = RCLASS_SUPER(tmp); if (!tmp) break; if (tmp == rb_cObject && mod != rb_cObject) break; } @@ -1479,13 +1601,13 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse) tmp = klass; retry: while (tmp) { - if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) { + if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) { if (value == Qundef && NIL_P(autoload_file(klass, id))) return Qfalse; return Qtrue; } if (!recurse && klass != rb_cObject) break; - tmp = RCLASS(tmp)->super; + tmp = RCLASS_SUPER(tmp); } if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) { mod_retry = 1; @@ -1528,13 +1650,13 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst) rb_error_frozen("class"); } } - if (!RCLASS(klass)->iv_tbl) { - RCLASS(klass)->iv_tbl = st_init_numtable(); + if (!RCLASS_IV_TBL(klass)) { + RCLASS_IV_TBL(klass) = st_init_numtable(); } else if (isconst) { VALUE value = Qfalse; - if (st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { + if (st_lookup(RCLASS_IV_TBL(klass), id, &value)) { if (value == Qundef) autoload_delete(klass, id); else @@ -1545,7 +1667,7 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst) if(isconst){ rb_vm_change_state(); } - st_insert(RCLASS(klass)->iv_tbl, id, val); + st_insert(RCLASS_IV_TBL(klass), id, val); } void @@ -1585,7 +1707,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) } #define CVAR_LOOKUP(v,r) do {\ - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,(v))) {\ + if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\ return (r);\ }\ if (FL_TEST(klass, FL_SINGLETON) ) {\ @@ -1596,18 +1718,18 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) klass = obj;\ break;\ default:\ - klass = RCLASS(klass)->super;\ + klass = RCLASS_SUPER(klass);\ break;\ }\ }\ else {\ - klass = RCLASS(klass)->super;\ + klass = RCLASS_SUPER(klass);\ }\ while (klass) {\ - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,id,(v))) {\ + if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\ return (r);\ }\ - klass = RCLASS(klass)->super;\ + klass = RCLASS_SUPER(klass);\ }\ } while(0) @@ -1695,8 +1817,8 @@ rb_mod_class_variables(VALUE obj) { VALUE ary = rb_ary_new(); - if (RCLASS(obj)->iv_tbl) { - st_foreach_safe(RCLASS(obj)->iv_tbl, cv_i, ary); + if (RCLASS_IV_TBL(obj)) { + st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); } return ary; } @@ -1734,7 +1856,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); if (OBJ_FROZEN(mod)) rb_error_frozen("class/module"); - if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) { + if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) { return val; } if (rb_cvar_defined(mod, id)) { diff --git a/vm.c b/vm.c index f2c96eaeb0..0267ee93a4 100644 --- a/vm.c +++ b/vm.c @@ -503,7 +503,7 @@ vm_call_super(rb_thread_t *th, int argc, const VALUE *argv) if (!cfp->iseq) { klass = cfp->method_klass; - klass = RCLASS(klass)->super; + klass = RCLASS_SUPER(klass); if (klass == 0) { klass = vm_search_normal_super_klass(cfp->method_klass, recv); @@ -1001,7 +1001,7 @@ static void add_opt_method(VALUE klass, ID mid, VALUE bop) { NODE *node; - if (st_lookup(RCLASS(klass)->m_tbl, mid, (void *)&node) && + if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&node) && nd_type(node->nd_body->nd_body) == NODE_CFUNC) { st_insert(vm_opt_method_table, (st_data_t)node, (st_data_t)bop); } -- cgit v1.2.3