[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