[macruby-changes] [4119] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue May 18 01:22:00 PDT 2010


Revision: 4119
          http://trac.macosforge.org/projects/ruby/changeset/4119
Author:   lsansonetti at apple.com
Date:     2010-05-18 01:21:55 -0700 (Tue, 18 May 2010)
Log Message:
-----------
better ivar slot system for RubyObject + misc fixes/cleanup

Modified Paths:
--------------
    MacRuby/trunk/class.c
    MacRuby/trunk/class.h
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/objc.h
    MacRuby/trunk/objc.m
    MacRuby/trunk/object.c
    MacRuby/trunk/parse.y
    MacRuby/trunk/variable.c
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h
    MacRuby/trunk/vm_eval.c

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/class.c	2010-05-18 08:21:55 UTC (rev 4119)
@@ -21,6 +21,7 @@
 #include "class.h"
 
 extern st_table *rb_class_tbl;
+extern VALUE rb_cRubyObject;
 
 void
 rb_objc_class_sync_version(Class ocklass, Class ocsuper)
@@ -28,11 +29,7 @@
     const long super_version = RCLASS_VERSION(ocsuper);
     long klass_version = RCLASS_VERSION(ocklass);
 
-    if ((super_version & RCLASS_NO_IV_SLOTS) == RCLASS_NO_IV_SLOTS) {
-	klass_version |= RCLASS_NO_IV_SLOTS;
-    }
-
-    if (ocsuper == (Class)rb_cObject
+    if (ocsuper == (Class)rb_cRubyObject
 	|| (super_version & RCLASS_IS_OBJECT_SUBCLASS)
 	    == RCLASS_IS_OBJECT_SUBCLASS) {
 	klass_version |= RCLASS_IS_OBJECT_SUBCLASS;
@@ -139,8 +136,6 @@
 	    (IMP)rb_obj_imp_copyWithZone, method_getTypeEncoding(m));
 }
 
-extern VALUE rb_cRubyObject;
-
 static VALUE
 rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
 {
@@ -349,7 +344,7 @@
 	}
 
 	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-	if (RCLASS_SUPER(clone) == rb_cNSObject) {
+	if (RCLASS_SUPER(clone) == rb_cRubyObject) {
 	    long v = RCLASS_VERSION(clone) ^ RCLASS_IS_OBJECT_SUBCLASS;
 	    RCLASS_SET_VERSION(clone, v);
 	}
@@ -376,7 +371,7 @@
 {
     VALUE klass = rb_objc_create_class(NULL, super);
     long v = RCLASS_VERSION(klass);
-    if (super == rb_cNSObject) {
+    if (super == rb_cRubyObject) {
 	v ^= RCLASS_IS_OBJECT_SUBCLASS;
     }
     v |= RCLASS_IS_RUBY_CLASS;
@@ -1320,10 +1315,6 @@
 		type = T_SYMBOL;
 		goto done;
 	    }
-	    if (k == (Class)rb_cFixnum) {
-		type = T_FIXNUM;
-		goto done;
-	    }
 	    if ((type = foundation_type(k)) != 0) {
 		goto done;
 	    }

Modified: MacRuby/trunk/class.h
===================================================================
--- MacRuby/trunk/class.h	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/class.h	2010-05-18 08:21:55 UTC (rev 4119)
@@ -11,7 +11,7 @@
 extern "C" {
 #endif
 
-#define RCLASS_IS_OBJECT_SUBCLASS    (1<<1)  /* class is a true RBObject subclass */
+#define RCLASS_IS_OBJECT_SUBCLASS    (1<<1)  /* class is a true RubyObject subclass */
 #define RCLASS_IS_RUBY_CLASS         (1<<2)  /* class was created from Ruby */
 #define RCLASS_IS_MODULE             (1<<3)  /* class represents a Ruby Module */
 #define RCLASS_IS_SINGLETON	     (1<<4)  /* class represents a singleton */
@@ -23,7 +23,6 @@
 #define RCLASS_SCOPE_PROTECTED	     (1<<13)  /* class opened for protected methods */
 #define RCLASS_SCOPE_MOD_FUNC	     (1<<14)  /* class opened for module_function methods */
 #define RCLASS_KVO_CHECK_DONE	     (1<<15)  /* class created by KVO and flags merged */
-#define RCLASS_NO_IV_SLOTS	     (1<<16)  /* class cannot hold ivar slots (T_DATA & friends) */
 
 unsigned long rb_class_get_flags(Class k);
 void rb_class_set_flags(Class k, unsigned long flags);

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/compiler.cpp	2010-05-18 08:21:55 UTC (rev 4119)
@@ -1112,64 +1112,57 @@
 	    "", bb);
 }
 
-Value *
-RoxorCompiler::gen_slot_cache(ID id)
+extern "C"
+struct icache *
+rb_vm_ivar_slot_allocate(void)
 {
-    int *slot = (int *)malloc(sizeof(int));
-    *slot = -1;
-    return compile_const_pointer(slot, Int32PtrTy);
+    struct icache *icache = (struct icache *)malloc(sizeof(struct icache));
+    icache->klass = 0;
+    icache->slot = SLOT_CACHE_VIRGIN;
+    return icache;
 }
 
 Value *
-RoxorAOTCompiler::gen_slot_cache(ID id)
-{
-    GlobalVariable *gvar = new GlobalVariable(*RoxorCompiler::module,
-	    Int32PtrTy, false, GlobalValue::InternalLinkage,
-	    Constant::getNullValue(Int32PtrTy), "");
-    ivar_slots.push_back(gvar);
-    return new LoadInst(gvar, "");
-}
-
-Value *
 RoxorCompiler::compile_slot_cache(ID id)
 {
-    if (inside_eval || current_block || !current_instance_method
-	|| current_module) {
-	return compile_const_pointer(NULL, Int32PtrTy);
+    std::map<ID, void *>::iterator iter = ivars_slots_cache.find(id);
+    void *cache = NULL;
+    if (iter == ivars_slots_cache.end()) {
+	cache = rb_vm_ivar_slot_allocate();
+	ivars_slots_cache[id] = cache;
     }
-
-    std::map<ID, Value *>::iterator iter = ivar_slots_cache.find(id);
-    Value *slot;
-    if (iter == ivar_slots_cache.end()) {
-#if ROXOR_COMPILER_DEBUG
-	printf("allocating a new slot for ivar %s\n", rb_id2name(id));
-#endif
-	slot = gen_slot_cache(id);
-	ivar_slots_cache[id] = slot;
-    }
     else {
-	slot = iter->second;
+	cache = iter->second;
     }
+    return compile_const_pointer(cache);
+}
 
-    Instruction *slot_insn = dyn_cast<Instruction>(slot);
-    if (slot_insn != NULL) {
-	Instruction *insn = slot_insn->clone();
-	BasicBlock::InstListType &list = bb->getInstList();
-	list.insert(list.end(), insn);
-	return insn;
+Value *
+RoxorAOTCompiler::compile_slot_cache(ID id)
+{
+    std::map<ID, void *>::iterator iter = ivars_slots_cache.find(id);
+    GlobalVariable *gvar = NULL;
+    if (iter == ivars_slots_cache.end()) {
+	gvar = new GlobalVariable(*RoxorCompiler::module,
+		PtrTy, false, GlobalValue::InternalLinkage,
+		compile_const_pointer(NULL), "");
+	ivar_slots.push_back(gvar);
+	ivars_slots_cache[id] = gvar;
     }
     else {
-	return slot;
+	gvar = (GlobalVariable *)iter->second;
     }
+    return new LoadInst(gvar, "", bb);
 }
 
 Value *
 RoxorCompiler::compile_ivar_read(ID vid)
 {
     if (getIvarFunc == NULL) {
-	// VALUE rb_vm_ivar_get(VALUE obj, ID name, int *slot_cache);
-	getIvarFunc = cast<Function>(module->getOrInsertFunction("rb_vm_ivar_get",
-		    RubyObjTy, RubyObjTy, IntTy, Int32PtrTy, NULL)); 
+	// VALUE rb_vm_ivar_get(VALUE obj, ID name, struct icache *cache);
+	getIvarFunc = cast<Function>(module->getOrInsertFunction(
+		    "rb_vm_ivar_get",
+		    RubyObjTy, RubyObjTy, IntTy, PtrTy, NULL)); 
     }
 
     std::vector<Value *> params;
@@ -1185,11 +1178,11 @@
 RoxorCompiler::compile_ivar_assignment(ID vid, Value *val)
 {
     if (setIvarFunc == NULL) {
-	// void rb_vm_ivar_set(VALUE obj, ID name, VALUE val, int *slot_cache);
+	// void rb_vm_ivar_set(VALUE obj, ID name, VALUE val,
+	// 	struct icache *cache);
 	setIvarFunc = 
 	    cast<Function>(module->getOrInsertFunction("rb_vm_ivar_set",
-			VoidTy, RubyObjTy, IntTy, RubyObjTy, Int32PtrTy,
-			NULL)); 
+			VoidTy, RubyObjTy, IntTy, RubyObjTy, PtrTy, NULL)); 
     }
 
     std::vector<Value *> params;
@@ -3000,57 +2993,6 @@
 }
 
 void
-RoxorCompiler::compile_ivar_slots(Value *klass,
-	BasicBlock::InstListType &list, 
-	BasicBlock::InstListType::iterator list_iter)
-{
-    if (ivar_slots_cache.size() > 0) {
-	if (prepareIvarSlotFunc == NULL) {
-	    // void rb_vm_prepare_class_ivar_slot(VALUE klass, ID name,
-	    // 		int *slot_cache);
-	    prepareIvarSlotFunc = cast<Function>(
-		    module->getOrInsertFunction(
-			"rb_vm_prepare_class_ivar_slot", 
-			VoidTy, RubyObjTy, IntTy, Int32PtrTy, NULL));
-	}
-	for (std::map<ID, Value *>::iterator iter
-		= ivar_slots_cache.begin();
-	     iter != ivar_slots_cache.end();
-	     ++iter) {
-
-	    ID ivar_name = iter->first;
-	    Value *ivar_slot = iter->second;
-	    std::vector<Value *> params;
-
-	    params.push_back(klass);
-
-	    Value *id_val = compile_id(ivar_name);
-	    if (Instruction::classof(id_val)) {
-		Instruction *insn = cast<Instruction>(id_val);
-		insn->removeFromParent();
-		list.insert(list_iter, insn);
-	    }
-	    params.push_back(id_val);
-
-	    Instruction *slot_insn = dyn_cast<Instruction>(ivar_slot);
-	    if (slot_insn != NULL) {
-		Instruction *insn = slot_insn->clone();
-		list.insert(list_iter, insn);
-		params.push_back(insn);
-	    }
-	    else {
-		params.push_back(ivar_slot);
-	    }
-
-	    CallInst *call = CallInst::Create(prepareIvarSlotFunc, 
-		    params.begin(), params.end(), "");
-
-	    list.insert(list_iter, call);
-	}
-    }
-}
-
-void
 RoxorCompiler::compile_node_error(const char *msg, NODE *node)
 {
     int t = nd_type(node);
@@ -4115,10 +4057,6 @@
 			current_block_chain = false;
 			dynamic_class = false;
 
-			std::map<ID, Value *> old_ivar_slots_cache
-			    = ivar_slots_cache;
-			ivar_slots_cache.clear();
-
 			new StoreInst(classVal, current_opened_class, bb);
 
 			current_module = nd_type(node) == NODE_MODULE;
@@ -4128,6 +4066,10 @@
 			bool old_block_declaration = block_declaration;
 			block_declaration = false;
 
+			std::map<ID, void *> old_ivars_slots_cache
+			    = ivars_slots_cache;
+			old_ivars_slots_cache.clear();
+
 			DEBUG_LEVEL_INC();
 			Value *val = compile_node(body);
 			assert(Function::classof(val));
@@ -4135,6 +4077,8 @@
 			GET_CORE()->optimize(f);
 			DEBUG_LEVEL_DEC();
 
+			ivars_slots_cache = old_ivars_slots_cache;
+
 			block_declaration = old_block_declaration;
 
 			std::vector<Value *> params;
@@ -4147,16 +4091,11 @@
 			dynamic_class = old_dynamic_class;
 			compile_set_current_scope(classVal, defaultScope);
 
-			BasicBlock::InstListType &list = bb->getInstList();
-			compile_ivar_slots(classVal, list, list.end());
-
 			current_self = old_self;
 			current_opened_class = old_class;
 			current_module = old_current_module;
 			current_block_chain = old_current_block_chain;
 
-			ivar_slots_cache = old_ivar_slots_cache;
-
 			return val;
 		    }
 		}
@@ -5575,15 +5514,7 @@
 
     Value *val = compile_node(node);
     assert(Function::classof(val));
-    Function *function = cast<Function>(val);
-
-    Value *klass = ConstantInt::get(RubyObjTy, (long)rb_cTopLevel);
-    BasicBlock::InstListType &list = 
-	function->getEntryBlock().getInstList();
-    compile_ivar_slots(klass, list, list.begin());
-    ivar_slots_cache.clear();
-
-    return function;
+    return cast<Function>(val);
 }
 
 Function *
@@ -5979,33 +5910,11 @@
 	list.insert(list.begin(), load);
     }
 
-    // Compile ivar slots.
+    // Instance variable slots.
 
-    if (!ivar_slots_cache.empty()) {
-	GlobalVariable *toplevel = compile_const_global_string("TopLevel");
-
-	std::vector<Value *> idxs;
-	idxs.push_back(ConstantInt::get(Int32Ty, 0));
-	idxs.push_back(ConstantInt::get(Int32Ty, 0));
-	Instruction *load = GetElementPtrInst::Create(toplevel,
-		idxs.begin(), idxs.end(), "");
-
-	std::vector<Value *> params;
-	params.push_back(load);
-
-	Instruction *call = CallInst::Create(objcGetClassFunc, params.begin(),
-		params.end(), "");
-
-	compile_ivar_slots(call, list, list.begin());
-	ivar_slots_cache.clear();
-
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), load);
-    }
-
     Function *ivarSlotAlloc = cast<Function>(module->getOrInsertFunction(
 		"rb_vm_ivar_slot_allocate",
-		Int32PtrTy, NULL));
+		PtrTy, NULL));
 
     for (std::vector<GlobalVariable *>::iterator i = ivar_slots.begin();
 	 i != ivar_slots.end();
@@ -6014,12 +5923,9 @@
 	GlobalVariable *gvar = *i;
 
 	Instruction *call = CallInst::Create(ivarSlotAlloc, "");
-	Instruction *assign1 =
-	    new StoreInst(ConstantInt::getSigned(Int32Ty, -1), call, "");
-	Instruction *assign2 = new StoreInst(call, gvar, "");
+	Instruction *assign = new StoreInst(call, gvar, "");
 
-	list.insert(list.begin(), assign2);
-	list.insert(list.begin(), assign1);
+	list.insert(list.begin(), assign);
 	list.insert(list.begin(), call);
     }
 
@@ -6039,15 +5945,8 @@
 
     bb = BasicBlock::Create(context, "EntryBlock", f);
 
-    // This disables ivar slot generation.
-    // TODO: make it work
-    const bool old_current_instance_method = current_instance_method;
-    current_instance_method = false;
-
     Value *val = compile_ivar_read(name);
 
-    current_instance_method = old_current_instance_method;
-
     ReturnInst::Create(context, val, bb);
 
     return f;
@@ -6066,19 +5965,21 @@
 
     bb = BasicBlock::Create(context, "EntryBlock", f);
 
-    std::vector<Value *> params;
-    params.push_back(current_self);
-    params.push_back(compile_id(name));
-    params.push_back(new_val);
-
     if (setKVOIvarFunc == NULL) {
 	    setKVOIvarFunc =
 	    cast<Function>(module->getOrInsertFunction("rb_vm_set_kvo_ivar",
-	            RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, NULL));
+	            RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, Int32PtrTy,
+		    NULL));
     }
 
+    std::vector<Value *> params;
+    params.push_back(current_self);
+    params.push_back(compile_id(name));
+    params.push_back(new_val);
+    params.push_back(compile_slot_cache(name));
+
     Value *val = CallInst::Create(setKVOIvarFunc,
-	params.begin(), params.end(), "", bb);
+	    params.begin(), params.end(), "", bb);
 
     ReturnInst::Create(context, val, bb);
 

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/compiler.h	2010-05-18 08:21:55 UTC (rev 4119)
@@ -78,7 +78,7 @@
 
 	std::map<ID, Value *> lvars;
 	std::vector<ID> dvars;
-	std::map<ID, Value *> ivar_slots_cache;
+	std::map<ID, void *> ivars_slots_cache;
 	std::map<std::string, GlobalVariable *> static_strings;
 	std::map<CFHashCode, GlobalVariable *> static_ustrings;
 
@@ -358,8 +358,7 @@
 					  const Type *llvm_type, Value *val);
 	void compile_debug_trap(void);
 
-	Value *compile_slot_cache(ID id);
-	virtual Value *gen_slot_cache(ID id);
+	virtual Value *compile_slot_cache(ID id);
 	ICmpInst *is_value_a_fixnum(Value *val);
 	void compile_ivar_slots(Value *klass, BasicBlock::InstListType &list, 
 				BasicBlock::InstListType::iterator iter);
@@ -413,9 +412,8 @@
 	Value *compile_id(ID id);
 	Value *compile_immutable_literal(VALUE val);
 	Value *compile_global_entry(NODE *node);
+	Value *compile_slot_cache(ID id);
 
-	Value *gen_slot_cache(ID id);
-
 	Constant *
 	compile_const_pointer(void *ptr, const PointerType *type=NULL) {
 	    if (ptr == NULL) {

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/dispatcher.cpp	2010-05-18 08:21:55 UTC (rev 4119)
@@ -670,7 +670,7 @@
 
 	    // Enable helpers for classes which are not RubyObject based.
 	    if ((RCLASS_VERSION(klass) & RCLASS_IS_OBJECT_SUBCLASS)
-		!= RCLASS_IS_OBJECT_SUBCLASS) {
+		    != RCLASS_IS_OBJECT_SUBCLASS) {
 		// Let's try to see if we are not given a helper selector.
 		SEL new_sel = helper_sel(selname, selname_len);
 		if (new_sel != NULL) {

Modified: MacRuby/trunk/objc.h
===================================================================
--- MacRuby/trunk/objc.h	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/objc.h	2010-05-18 08:21:55 UTC (rev 4119)
@@ -21,7 +21,6 @@
 bool rb_objc_supports_forwarding(VALUE recv, SEL sel);
 
 void rb_objc_define_kvo_setter(VALUE klass, ID mid);
-VALUE rb_vm_set_kvo_ivar(VALUE obj, ID name, VALUE val);
 
 static inline IMP
 rb_objc_install_method(Class klass, SEL sel, IMP imp)

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/objc.m	2010-05-18 08:21:55 UTC (rev 4119)
@@ -538,17 +538,19 @@
 }
 
 VALUE
-rb_vm_set_kvo_ivar(VALUE obj, ID name, VALUE val)
+rb_vm_set_kvo_ivar(VALUE obj, ID name, VALUE val, void *cache)
 {
-    NSString *key = NULL;
     if (enable_kvo_notifications) {
-	key = [(NSString *)rb_id2str(name) substringFromIndex:1]; // skip '@' prefix
+	NSString *key = [(NSString *)rb_id2str(name) substringFromIndex:1]; // skip '@' prefix
 	[(id)obj willChangeValueForKey:key];
-    }
-    rb_ivar_set(obj, name, val);
-    if (enable_kvo_notifications) {
+
+	rb_vm_ivar_set(obj, name, val, cache);
+
 	[(id)obj didChangeValueForKey:key];
     }
+    else {
+	rb_vm_ivar_set(obj, name, val, cache);
+    }
     return val;
 }
 

Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/object.c	2010-05-18 08:21:55 UTC (rev 4119)
@@ -196,23 +196,16 @@
     rb_gc_copy_finalizer(dest, obj);
     switch (TYPE(obj)) {
 	case T_OBJECT:
-	    if (ROBJECT(obj)->tbl != NULL) {
-		CFMutableDictionaryRef new_tbl;
-		new_tbl = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ROBJECT(obj)->tbl);
-		assert(new_tbl != NULL);
-		GC_WB(&ROBJECT(dest)->tbl, new_tbl);
-		CFMakeCollectable(new_tbl);
-	    }
-	    else {
-		ROBJECT(dest)->tbl = NULL;
-	    }
 	    if (ROBJECT(obj)->num_slots > 0) {
 		if (ROBJECT(dest)->num_slots < ROBJECT(obj)->num_slots) {
 		    rb_vm_regrow_robject_slots(ROBJECT(dest),
 			    ROBJECT(obj)->num_slots);
 		}
 		for (int i = 0; i < ROBJECT(obj)->num_slots; i++) {
-		    GC_WB(&ROBJECT(dest)->slots[i], ROBJECT(obj)->slots[i]);
+		    rb_object_ivar_slot_t *dest_sl = &ROBJECT(dest)->slots[i];
+		    rb_object_ivar_slot_t *orig_sl = &ROBJECT(obj)->slots[i];
+		    dest_sl->name = orig_sl->name;
+		    GC_WB(&dest_sl->value, orig_sl->value);
 		}
 	    }
 	    ROBJECT(dest)->num_slots = ROBJECT(obj)->num_slots;
@@ -293,8 +286,9 @@
     }
 
     init_copy(clone, obj);
-    if (OBJ_FROZEN(obj))
+    if (OBJ_FROZEN(obj)) {
 	OBJ_FREEZE(clone);
+    }
 
     return clone;
 }
@@ -464,26 +458,14 @@
 rb_obj_inspect(VALUE obj, SEL sel)
 {
     if (TYPE(obj) == T_OBJECT) {
-        bool has_ivar = false;
-
-	if (ROBJECT(obj)->tbl != NULL
-		&& CFDictionaryGetCount(ROBJECT(obj)->tbl) > 0) {
-	    has_ivar = true;
-	}
-	else {
-	    for (int i = 0; i < ROBJECT(obj)->num_slots; i++) {
-		if (ROBJECT(obj)->slots[i] != Qundef) {
-		    has_ivar = true;
-		    break;
-		}
+	for (int i = 0; i < ROBJECT(obj)->num_slots; i++) {
+	    if (ROBJECT(obj)->slots[i].value != Qundef) {
+		// There is at least an ivar.
+		const char *c = rb_obj_classname(obj);
+		VALUE str = rb_sprintf("#<%s:%p", c, (void*)obj);
+		return rb_exec_recursive(inspect_obj, obj, str);
 	    }
 	}
-
-        if (has_ivar) {
-            const char *c = rb_obj_classname(obj);
-            VALUE 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);
 }
@@ -2960,10 +2942,8 @@
 	    "BasicObject", 0);
     rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
     rb_cModule = boot_defclass("Module", rb_cNSObject);
-    RCLASS_SET_VERSION_FLAG(rb_cModule, RCLASS_NO_IV_SLOTS);
     rb_define_object_special_methods(rb_cModule);
     rb_cClass =  boot_defclass("Class",  rb_cModule);
-    RCLASS_SET_VERSION_FLAG(rb_cClass, RCLASS_NO_IV_SLOTS);
     rb_cRubyObject = boot_defclass("RubyObject", rb_cObject);
     RCLASS_SET_VERSION_FLAG(rb_cRubyObject, RCLASS_IS_SINGLETON);
     RCLASS_SET_VERSION_FLAG(rb_cRubyObject, RCLASS_IS_OBJECT_SUBCLASS);

Modified: MacRuby/trunk/parse.y
===================================================================
--- MacRuby/trunk/parse.y	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/parse.y	2010-05-18 08:21:55 UTC (rev 4119)
@@ -10085,7 +10085,6 @@
 Init_ripper(void)
 {
     VALUE Ripper = rb_define_class("Ripper", rb_cObject);
-    RCLASS_SET_VERSION_FLAG(Ripper, RCLASS_NO_IV_SLOTS);
     rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
     rb_objc_define_method(*(VALUE *)Ripper, "alloc", ripper_s_allocate, 0);
     rb_objc_define_method(Ripper, "initialize", ripper_initialize, -1);

Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/variable.c	2010-05-18 08:21:55 UTC (rev 4119)
@@ -980,7 +980,7 @@
     }
     return generic_ivar_dict(mod, false);
 }
-
+ 
 void
 rb_class_ivar_set_dict(VALUE mod, CFMutableDictionaryRef dict)
 {
@@ -1018,31 +1018,16 @@
 {
     VALUE val;
 
-    const int slot = rb_vm_find_class_ivar_slot(CLASS_OF(obj), id);
-    if (slot != -1) {
-	val = rb_vm_get_ivar_from_slot(obj, slot);
-	if (val != Qundef) {
-	    return val;
-	}
-    }
-
     switch (TYPE(obj)) {
 	case T_OBJECT:
 	    {
-		val = Qundef;
-
-		if (ROBJECT(obj)->tbl != NULL) {
-		    if (!CFDictionaryGetValueIfPresent(
-				(CFDictionaryRef)ROBJECT(obj)->tbl,
-				(const void *)id,
-				(const void **)&val)) {
-			val = Qundef;
+		const int slot = rb_vm_get_ivar_slot(obj, id, false);
+		if (slot != -1) {
+		    val = rb_vm_get_ivar_from_slot(obj, slot);
+		    if (val != Qundef) {
+			return val;
 		    }
 		}
-
-		if (val != Qundef) {
-		    return val;
-		}
 	    }
 	    break;
 
@@ -1090,27 +1075,13 @@
 	rb_error_frozen("object");
     }
 
-    const int slot = rb_vm_find_class_ivar_slot(CLASS_OF(obj), id);
-    if (slot != -1) {
-	rb_vm_set_ivar_from_slot(obj, val, slot);
-	return val;
-    }
-
     switch (TYPE(obj)) {
 	case T_OBJECT:
 	    {
-		if (ROBJECT(obj)->tbl == NULL) {
-		    CFMutableDictionaryRef tbl;
-
-		    tbl = CFDictionaryCreateMutable(NULL, 0, NULL, 
-			    &rb_cfdictionary_value_cb);
-
-		    GC_WB(&ROBJECT(obj)->tbl, tbl);
-		    CFMakeCollectable(tbl);
-		}
-
-		CFDictionarySetValue(ROBJECT(obj)->tbl, 
-			(const void *)id, (const void *)val);
+		const int slot = rb_vm_get_ivar_slot(obj, id, true);
+		assert(slot >= 0);
+		rb_vm_set_ivar_from_slot(obj, val, slot);
+		return val;
 	    }
 	    break;
 
@@ -1133,31 +1104,15 @@
 VALUE
 rb_ivar_defined(VALUE obj, ID id)
 {
-    VALUE val;
-
-    const int slot = rb_vm_find_class_ivar_slot(CLASS_OF(obj), id);
-    if (slot != -1) {
-	if (rb_vm_get_ivar_from_slot(obj, slot) != Qundef) {
-	    return Qtrue;
-	}
-    }
-
     switch (TYPE(obj)) {
 	case T_OBJECT:
 	    {
-		val = Qundef;
-
-		if (ROBJECT(obj)->tbl != NULL) {
-		    if (CFDictionaryGetValueIfPresent(
-				(CFDictionaryRef)ROBJECT(obj)->tbl,
-				(const void *)id, NULL)) {
-			val = Qtrue;
+		const int slot = rb_vm_get_ivar_slot(obj, id, false);
+		if (slot != -1) {
+		    if (rb_vm_get_ivar_from_slot(obj, slot) != Qundef) {
+			return Qtrue;
 		    }
 		}
-
-		if (val != Qundef) {
-		    return Qtrue;
-		}
 	    }
 	    break;
 
@@ -1182,33 +1137,36 @@
 rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
 {
     switch (TYPE(obj)) {
-      case T_OBJECT:
-	  rb_vm_each_ivar_slot(obj, func, (void *)arg);
-	  if (ROBJECT(obj)->tbl != NULL) {
-	      CFDictionaryApplyFunction(ROBJECT(obj)->tbl, 
-		      (CFDictionaryApplierFunction)func, (void *)arg);
-	  }
-	  return;
+	case T_OBJECT:
+	    for (unsigned int i = 0; i < ROBJECT(obj)->num_slots; i++) {
+		ID name = ROBJECT(obj)->slots[i].name;
+		VALUE value = ROBJECT(obj)->slots[i].value;
+		if (name != 0 && value != Qundef) {
+		    func(name, value, arg);
+		}
+	    }
+	    break;
 
       case T_CLASS:
       case T_MODULE:
-	  {
-	      CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
-	      if (iv_dict != NULL) {
-		  ivar_dict_foreach(iv_dict, func, arg);
-	      }
-	  }
-	  return;
+	    {
+		CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+		if (iv_dict != NULL) {
+		    ivar_dict_foreach(iv_dict, func, arg);
+		}
+	    }
+	    break;
 
       case T_NATIVE:
       default:
-	  {
-	      CFDictionaryRef obj_dict = generic_ivar_dict(obj, false);
-	      if (obj_dict != NULL) {
-		  CFDictionaryApplyFunction(obj_dict, (CFDictionaryApplierFunction)func,
-			  (void *)arg);
-	      }
-	  }
+	    {
+		CFDictionaryRef obj_dict = generic_ivar_dict(obj, false);
+		if (obj_dict != NULL) {
+		    CFDictionaryApplyFunction(obj_dict,
+			    (CFDictionaryApplierFunction)func, (void *)arg);
+		}
+	    }
+	    break;
     }
 }
 
@@ -1288,14 +1246,7 @@
 
     switch (TYPE(obj)) {
 	case T_OBJECT:
-	    // TODO support slots
-	    if (ROBJECT(obj)->tbl != NULL) {
-		if (CFDictionaryGetValueIfPresent(ROBJECT(obj)->tbl, (const void *)id, (const void **)val)) {
-		    CFDictionaryRemoveValue(ROBJECT(obj)->tbl, 
-			    (const void *)id);
-		    return val;
-		}
-	    }
+	    // TODO
 	    break;
 
 	case T_CLASS:

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/vm.cpp	2010-05-18 08:21:55 UTC (rev 4119)
@@ -1044,76 +1044,6 @@
     }
 }
 
-inline int
-RoxorCore::find_ivar_slot(VALUE klass, ID name, bool create)
-{
-    VALUE k = klass;
-    int slot = 0;
-
-    while (k != 0) {
-	std::map <ID, int> *slots = get_ivar_slots((Class)k);
-	std::map <ID, int>::iterator iter = slots->find(name);
-	if (iter != slots->end()) {
-#if ROXOR_VM_DEBUG
-	    printf("prepare ivar %s slot as %d (already prepared in class %s)\n",
-		    rb_id2name(name), iter->second, class_getName((Class)k));
-#endif
-	    return iter->second;
-	}
-	slot += slots->size();
-	k = RCLASS_SUPER(k);
-    }
-
-    if (create) {
-#if ROXOR_VM_DEBUG
-	printf("prepare ivar %s slot as %d (new in class %s)\n",
-		rb_id2name(name), slot, class_getName((Class)klass));
-#endif
-	get_ivar_slots((Class)klass)->insert(std::pair<ID, int>(name, slot));
-	return slot;
-    }
-    else {
-	return -1;
-    }
-}
-
-void
-RoxorCore::each_ivar_slot(VALUE obj, int (*func)(ANYARGS),
-	void *ctx)
-{
-    VALUE k = *(VALUE *)obj;
-
-    while (k != 0) {
-	std::map <ID, int> *slots = get_ivar_slots((Class)k, false);
-	if (slots != NULL) {
-	    for (std::map <ID, int>::iterator iter = slots->begin();
-		 iter != slots->end();
-		 ++iter) {
-		ID name = iter->first;
-		int slot = iter->second;
-		VALUE value = rb_vm_get_ivar_from_slot(obj, slot);
-		if (value != Qundef) {
-		    func(name, value, ctx);
-		}
-	    }
-	}
-	k = RCLASS_SUPER(k);
-    }
-}
-
-inline bool
-RoxorCore::class_can_have_ivar_slots(VALUE klass)
-{
-    const long klass_version = RCLASS_VERSION(klass);
-    if ((klass_version & RCLASS_IS_RUBY_CLASS) != RCLASS_IS_RUBY_CLASS
-	|| (klass_version & RCLASS_IS_OBJECT_SUBCLASS)
-	    != RCLASS_IS_OBJECT_SUBCLASS
-	|| (klass_version & RCLASS_NO_IV_SLOTS) == RCLASS_NO_IV_SLOTS) {
-	return false;
-    }
-    return true;
-}
-
 extern "C"
 bool
 rb_vm_running(void)
@@ -1494,47 +1424,125 @@
     return klass;
 }
 
+#define LIKELY(x)   (__builtin_expect((x), 1))
+#define UNLIKELY(x) (__builtin_expect((x), 0))
+
 extern "C"
-int *
-rb_vm_ivar_slot_allocate(void)
+int
+rb_vm_get_ivar_slot(VALUE obj, ID name, bool create)
 {
-    return (int *)malloc(sizeof(int));
+    if (TYPE(obj) == T_OBJECT) {
+        unsigned int i;
+        for (i = 0; i < ROBJECT(obj)->num_slots; i++) {
+            if (ROBJECT(obj)->slots[i].name == name) {
+                return i;
+            }
+        }
+	if (create) {
+	    for (i = 0; i < ROBJECT(obj)->num_slots; i++) {
+		if (ROBJECT(obj)->slots[i].value == Qundef) {
+		    ROBJECT(obj)->slots[i].name = name;
+		    return i;
+		}
+	    }
+	    const int new_slot = ROBJECT(obj)->num_slots;
+	    rb_vm_regrow_robject_slots(ROBJECT(obj), new_slot + 1);
+	    ROBJECT(obj)->slots[new_slot].name = name;
+	    return new_slot;
+	}
+    }
+    return -1;
 }
 
 extern "C"
 VALUE
-rb_vm_ivar_get(VALUE obj, ID name, int *slot_cache)
+rb_vm_ivar_get(VALUE obj, ID name, struct icache *cache)
 {
 #if ROXOR_VM_DEBUG
-    printf("get ivar <%s %p>.%s slot %d\n",
+    printf("get ivar <%s %p>.%s cache klass %p slot %d\n",
 	    class_getName((Class)CLASS_OF(obj)), (void *)obj,
-	    rb_id2name(name), slot_cache == NULL ? -1 : *slot_cache);
+	    rb_id2name(name), (void *)cache->klass, cache->slot);
 #endif
-    if (slot_cache == NULL || *slot_cache == -1) {
-	return rb_ivar_get(obj, name);
+
+    VALUE klass = CLASS_OF(obj);
+    if (LIKELY(klass == cache->klass)) {
+use_slot:
+	VALUE val = Qundef;
+	if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
+	    rb_object_ivar_slot_t *slot = &ROBJECT(obj)->slots[cache->slot];
+	    if (slot->name == name) {
+		val = slot->value;
+	    }
+	    else {
+		goto recache;
+	    }
+	}
+	return val == Qundef ? Qnil : val;
     }
     else {
-	VALUE val = rb_vm_get_ivar_from_slot(obj, *slot_cache);
-	return val == Qundef ? Qnil : val;
+	goto recache;
     }
+
+    if (cache->slot == SLOT_CACHE_VIRGIN) {
+recache:
+	const int slot = rb_vm_get_ivar_slot(obj, name, true);
+	if (slot >= 0) {
+	    cache->klass = klass;
+	    cache->slot = slot;
+	    goto use_slot;
+	}
+	cache->klass = 0;
+	cache->slot = SLOT_CACHE_CANNOT;
+    }
+
+    assert(cache->slot == SLOT_CACHE_CANNOT);
+    return rb_ivar_get(obj, name);
 }
 
 extern "C"
 void
-rb_vm_ivar_set(VALUE obj, ID name, VALUE val, int *slot_cache)
+rb_vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache_ptr)
 {
+    struct icache *cache = (struct icache *)cache_ptr;
+
 #if ROXOR_VM_DEBUG
-    printf("set ivar %p.%s slot %d new_val %p\n", (void *)obj, 
-	    rb_id2name(name), 
-	    slot_cache == NULL ? -1 : *slot_cache,
-	    (void *)val);
+    printf("set ivar <%s %p>.%s cache klass %p slot %d val %p\n",
+	    class_getName((Class)CLASS_OF(obj)), (void *)obj,
+	    rb_id2name(name), (void *)cache->klass, cache->slot, (void *)val);
 #endif
-    if (slot_cache == NULL || *slot_cache == -1) {
-	rb_ivar_set(obj, name, val);
+
+    VALUE klass = CLASS_OF(obj);
+    if (LIKELY(klass == cache->klass)) {
+use_slot:
+	if ((unsigned int)cache->slot < ROBJECT(obj)->num_slots) {
+	    rb_object_ivar_slot_t *slot = &ROBJECT(obj)->slots[cache->slot];
+	    if (slot->name == name) {
+		if ((ROBJECT(obj)->basic.flags & FL_FREEZE) == FL_FREEZE) {
+		    rb_error_frozen("object");
+		}
+		GC_WB(&slot->value, val);
+		return;
+	    }
+	}
+	goto recache;
     }
     else {
-	rb_vm_set_ivar_from_slot(obj, val, *slot_cache);
+	goto recache;
     }
+
+    if (cache->slot == SLOT_CACHE_VIRGIN) {
+recache:
+	const int slot = rb_vm_get_ivar_slot(obj, name, true);
+	if (slot >= 0) {
+	    cache->klass = klass;
+	    cache->slot = slot;
+	    goto use_slot;
+	}
+	cache->slot = SLOT_CACHE_CANNOT;
+    }
+
+    assert(cache->slot == SLOT_CACHE_CANNOT);
+    rb_ivar_set(obj, name, val);
 }
 
 extern "C"
@@ -1777,37 +1785,6 @@
     return str == NULL ? Qnil : rb_str_new2(str);
 }
 
-extern "C"
-void
-rb_vm_prepare_class_ivar_slot(VALUE klass, ID name, int *slot_cache)
-{
-    assert(slot_cache != NULL);
-    assert(*slot_cache == -1);
-
-    if (GET_CORE()->class_can_have_ivar_slots(klass)) {
-	*slot_cache = GET_CORE()->find_ivar_slot(klass, name, true);
-    }
-}
-
-extern "C"
-int
-rb_vm_find_class_ivar_slot(VALUE klass, ID name)
-{
-    if (GET_CORE()->class_can_have_ivar_slots(klass)) {
-	return GET_CORE()->find_ivar_slot(klass, name, false);
-    }
-    return -1;
-}
-
-extern "C"
-void
-rb_vm_each_ivar_slot(VALUE obj, int (*func)(ANYARGS), void *ctx)
-{
-    if (GET_CORE()->class_can_have_ivar_slots(CLASS_OF(obj))) {
-	GET_CORE()->each_ivar_slot(obj, func, ctx);	
-    } 
-}
-
 static bool
 kvo_sel(Class klass, const char *selname, const size_t selsize,
 	const char *begin, const char *end)

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/vm.h	2010-05-18 08:21:55 UTC (rev 4119)
@@ -13,15 +13,6 @@
 extern "C" {
 #endif
 
-typedef struct rb_object {
-    struct RBasic basic;
-    CFMutableDictionaryRef tbl;   /* dynamic ivars (runtime) */
-    unsigned int num_slots;
-    VALUE *slots;                 /* static ivars (compilation) */
-} rb_object_t;
-
-#define ROBJECT(o) ((rb_object_t *)o)
-
 typedef struct {
     short min;		// min number of args that we accept
     short max;		// max number of args that we accept (-1 if rest)
@@ -338,48 +329,79 @@
 VALUE rb_vm_method_missing(VALUE obj, int argc, const VALUE *argv);
 void rb_vm_push_methods(VALUE ary, VALUE mod, bool include_objc_methods,
 	int (*filter) (VALUE, ID, VALUE));
-int rb_vm_find_class_ivar_slot(VALUE klass, ID name);
-void rb_vm_each_ivar_slot(VALUE obj, int (*func)(ANYARGS), void *ctx);
+void rb_vm_ivar_set(VALUE obj, ID name, VALUE val, void *cache);
 void rb_vm_set_outer(VALUE klass, VALUE under);
 VALUE rb_vm_get_outer(VALUE klass);
 VALUE rb_vm_catch(VALUE tag);
 VALUE rb_vm_throw(VALUE tag, VALUE value);
 
+typedef struct {
+    ID name;
+    VALUE value; 
+} rb_object_ivar_slot_t;
+
+#define SLOT_CACHE_VIRGIN	-2
+#define SLOT_CACHE_CANNOT	-1
+
+typedef struct {
+    struct RBasic basic;
+    rb_object_ivar_slot_t *slots;
+    unsigned int num_slots;
+} rb_object_t;
+
+#define ROBJECT(o) ((rb_object_t *)o)
+
 static inline void
 rb_vm_regrow_robject_slots(rb_object_t *obj, unsigned int new_num_slot)
 {
-    unsigned int i;
-    VALUE *new_slots = (VALUE *)xrealloc(obj->slots,
-	    sizeof(VALUE) * (new_num_slot + 1));
+    rb_object_ivar_slot_t *new_slots =
+	(rb_object_ivar_slot_t *)xrealloc(obj->slots,
+		sizeof(rb_object_ivar_slot_t) * (new_num_slot + 1));
     if (new_slots != obj->slots) {
 	GC_WB(&obj->slots, new_slots);
     }
+
+    unsigned int i;
     for (i = obj->num_slots; i <= new_num_slot; i++) {
-	obj->slots[i] = Qundef;
+	obj->slots[i].name = 0;
+	obj->slots[i].value = Qundef;
     }
     obj->num_slots = new_num_slot + 1;
 }
 
+int rb_vm_get_ivar_slot(VALUE obj, ID name, bool create);
+
 static inline VALUE
 rb_vm_get_ivar_from_slot(VALUE obj, int slot) 
 {
     rb_object_t *robj = ROBJECT(obj);
-    assert(slot >= 0);
-    if ((unsigned int)slot >= robj->num_slots)  {
-	return Qnil;
-    }
-    return robj->slots[slot];
+    return robj->slots[slot].value;
 }
 
 static inline void
 rb_vm_set_ivar_from_slot(VALUE obj, VALUE val, int slot) 
 {
     rb_object_t *robj = ROBJECT(obj);
-    assert(slot >= 0);
-    if ((unsigned int)slot >= robj->num_slots)  {
-	rb_vm_regrow_robject_slots(robj, (unsigned int)slot);
+    GC_WB(&robj->slots[slot].value, val);
+}
+
+static inline VALUE
+rb_robject_allocate_instance(VALUE klass)
+{
+    const int num_slots = 10;
+
+    rb_object_t *obj = (rb_object_t *)rb_objc_newobj(sizeof(rb_object_t));
+    GC_WB(&obj->slots, xmalloc(sizeof(rb_object_ivar_slot_t) * num_slots));
+
+    OBJSETUP(obj, klass, T_OBJECT);
+    obj->num_slots = num_slots;
+
+    int i;
+    for (i = 0; i < num_slots; i++) {
+	obj->slots[i].name = 0;
+	obj->slots[i].value = Qundef;
     }
-    GC_WB(&robj->slots[slot], val);
+    return (VALUE)obj;
 }
 
 // Defined in proc.c
@@ -446,26 +468,6 @@
 
 bool rb_vm_aot_feature_load(const char *name);
 
-static inline VALUE
-rb_robject_allocate_instance(VALUE klass)
-{
-    const int num_slots = 10;
-
-    rb_object_t *obj = (rb_object_t *)rb_objc_newobj(sizeof(rb_object_t));
-    GC_WB(&obj->slots, xmalloc_ptrs(num_slots * sizeof(VALUE)));
-
-    OBJSETUP(obj, klass, T_OBJECT);
-
-    ROBJECT(obj)->tbl = NULL;
-    ROBJECT(obj)->num_slots = num_slots;
-
-    int i;
-    for (i = 0; i < num_slots; i++) {
-	ROBJECT(obj)->slots[i] = Qundef;
-    }
-    return (VALUE)obj;
-}
-
 void rb_vm_raise(VALUE exception);
 void rb_vm_raise_current_exception(void);
 VALUE rb_vm_current_exception(void);
@@ -525,6 +527,11 @@
 
 #include "bridgesupport.h"
 
+struct icache {
+    VALUE klass;
+    int slot;
+};
+
 typedef struct {
     Function *func;
     rb_vm_arity_t arity;
@@ -532,12 +539,11 @@
 } rb_vm_method_source_t;
 
 typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
-				const VALUE *argv);
+	const VALUE *argv);
 typedef VALUE rb_vm_c_stub_t(IMP imp, int argc, const VALUE *argv);
 #define rb_vm_long_arity_stub_t rb_vm_objc_stub_t
 typedef VALUE rb_vm_long_arity_bstub_t(IMP imp, id self, SEL sel,
-				       VALUE dvars, rb_vm_block_t *b,
-				       int argc, const VALUE *argv);
+	VALUE dvars, rb_vm_block_t *b, int argc, const VALUE *argv);
 
 struct mcache {
 #define MCACHE_RCALL 0x1 // Ruby call
@@ -636,9 +642,6 @@
 	std::map<SEL, struct mcache *> mcache;
 	std::map<ID, struct ccache *> ccache;
 
-	// Instance variable slots cache.
-	std::map<Class, std::map<ID, int> *> ivar_slots;
-
 	// Optimized selectors redefinition cache.
 	std::map<SEL, GlobalVariable *> redefined_ops_gvars;
 
@@ -803,25 +806,6 @@
 	struct ccache *constant_cache_get(ID path);
 	void const_defined(ID path);
 	
-	std::map<ID, int> *get_ivar_slots(Class klass, bool create=true) {
-	    std::map<Class, std::map<ID, int> *>::iterator iter = 
-		ivar_slots.find(klass);
-	    if (iter == ivar_slots.end()) {
-		if (create) {
-		    std::map<ID, int> *map = new std::map<ID, int>;
-		    ivar_slots[klass] = map;
-		    return map;
-		}
-		else {
-		    return NULL;
-		}
-	    }
-	    return iter->second;
-	}
-	int find_ivar_slot(VALUE klass, ID name, bool create);
-	void each_ivar_slot(VALUE obj, int (*func)(ANYARGS), void *ctx);
-	bool class_can_have_ivar_slots(VALUE klass);
-
 	struct rb_vm_outer *get_outer(Class klass);
 	void set_outer(Class klass, Class mod);
 

Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c	2010-05-18 04:03:04 UTC (rev 4118)
+++ MacRuby/trunk/vm_eval.c	2010-05-18 08:21:55 UTC (rev 4119)
@@ -511,20 +511,6 @@
     }
     else {
 	switch (TYPE(self)) {
-#if 0
-	    case T_CLASS:
-	    case T_MODULE:
-		if (RCLASS_RUBY(self)) {
-		    VALUE sself = rb_make_singleton_class(RCLASS_SUPER(self));
-		    RCLASS_SET_SUPER(self, sself);
-		    self = sself;
-		}
-		else {
-		    klass = rb_singleton_class(self);
-		    break;
-		}
-		// fall through
-#endif
 	    default:
 		klass = rb_singleton_class(self);
 		switch (TYPE(top)) {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100518/6e5ffa8e/attachment-0001.html>


More information about the macruby-changes mailing list