mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* 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
This commit is contained in:
		
							parent
							
								
									041fbcbf50
								
							
						
					
					
						commit
						5c0e68c39c
					
				
					 17 changed files with 448 additions and 193 deletions
				
			
		
							
								
								
									
										39
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,42 @@
 | 
			
		|||
Fri Sep 28 15:05:24 2007  Tanaka Akira  <akr@fsij.org>
 | 
			
		||||
 | 
			
		||||
	* 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  <nobu@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* io.c (rb_io_getline_fast, rb_io_getline_1): set encoding to the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										117
									
								
								class.c
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								error.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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"));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								gc.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								marshal.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										84
									
								
								object.c
									
										
									
									
									
								
							
							
						
						
									
										84
									
								
								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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								struct.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										262
									
								
								variable.c
									
										
									
									
									
								
							
							
						
						
									
										262
									
								
								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)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								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);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue