[macruby-changes] [382] MacRuby/branches/lrz_unstable
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jul 29 19:27:07 PDT 2008
Revision: 382
http://trac.macosforge.org/projects/ruby/changeset/382
Author: lsansonetti at apple.com
Date: 2008-07-29 19:27:07 -0700 (Tue, 29 Jul 2008)
Log Message:
-----------
new dispatcher, work still in progress
Modified Paths:
--------------
MacRuby/branches/lrz_unstable/Rakefile
MacRuby/branches/lrz_unstable/array.c
MacRuby/branches/lrz_unstable/class.c
MacRuby/branches/lrz_unstable/compile.c
MacRuby/branches/lrz_unstable/debug.h
MacRuby/branches/lrz_unstable/eval.c
MacRuby/branches/lrz_unstable/gc.c
MacRuby/branches/lrz_unstable/hash.c
MacRuby/branches/lrz_unstable/id.c
MacRuby/branches/lrz_unstable/id.h
MacRuby/branches/lrz_unstable/include/ruby/intern.h
MacRuby/branches/lrz_unstable/include/ruby/node.h
MacRuby/branches/lrz_unstable/include/ruby/ruby.h
MacRuby/branches/lrz_unstable/insnhelper.h
MacRuby/branches/lrz_unstable/insns.def
MacRuby/branches/lrz_unstable/io.c
MacRuby/branches/lrz_unstable/marshal.c
MacRuby/branches/lrz_unstable/numeric.c
MacRuby/branches/lrz_unstable/objc.m
MacRuby/branches/lrz_unstable/object.c
MacRuby/branches/lrz_unstable/parse.y
MacRuby/branches/lrz_unstable/proc.c
MacRuby/branches/lrz_unstable/string.c
MacRuby/branches/lrz_unstable/thread.c
MacRuby/branches/lrz_unstable/variable.c
MacRuby/branches/lrz_unstable/vm.c
MacRuby/branches/lrz_unstable/vm_eval.c
MacRuby/branches/lrz_unstable/vm_insnhelper.c
MacRuby/branches/lrz_unstable/vm_method.c
Modified: MacRuby/branches/lrz_unstable/Rakefile
===================================================================
--- MacRuby/branches/lrz_unstable/Rakefile 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/Rakefile 2008-07-30 02:27:07 UTC (rev 382)
@@ -21,6 +21,7 @@
NO_WARN_BUILD = !do_option('allow_build_warnings', false)
BUILD_AS_EMBEDDABLE = do_option('build_as_embeddable', false)
ENABLE_STATIC_LIBRARY = do_option('enable_static_library', 'no') { 'yes' }
+ENABLE_DEBUG_LOGGING = do_option('enable_debug_logging', false)
# TODO: we should find a way to document these options in rake's --help
@@ -208,31 +209,28 @@
desc "Create config.h"
task :config_h do
config_h = 'include/ruby/config.h'
- if !File.exist?(config_h) \
- or File.mtime(config_h) < File.mtime(config_h + '.in') \
- or File.mtime(config_h) < File.mtime(__FILE__)
- new_config_h = File.read(config_h + '.in') << "\n"
- flag = ['/System/Library/Frameworks', '/Library/Frameworks'].any? do |p|
- File.exist?(File.join(p, 'BridgeSupport.framework'))
- end
- new_config_h << "#define HAVE_BRIDGESUPPORT_FRAMEWORK #{flag ? 1 : 0}\n"
- flag = File.exist?('/usr/include/auto_zone.h')
- new_config_h << "#define HAVE_AUTO_ZONE_H #{flag ? 1 : 0}\n"
- new_config_h << "#define RUBY_PLATFORM \"#{NEW_RUBY_PLATFORM}\"\n"
- new_config_h << "#define RUBY_LIB \"#{RUBY_LIB}\"\n"
- new_config_h << "#define RUBY_ARCHLIB \"#{RUBY_ARCHLIB}\"\n"
- new_config_h << "#define RUBY_SITE_LIB \"#{RUBY_SITE_LIB}\"\n"
- new_config_h << "#define RUBY_SITE_LIB2 \"#{RUBY_SITE_LIB2}\"\n"
- new_config_h << "#define RUBY_SITE_ARCHLIB \"#{RUBY_SITE_ARCHLIB}\"\n"
- new_config_h << "#define RUBY_VENDOR_LIB \"#{RUBY_VENDOR_LIB}\"\n"
- new_config_h << "#define RUBY_VENDOR_LIB2 \"#{RUBY_VENDOR_LIB2}\"\n"
- new_config_h << "#define RUBY_VENDOR_ARCHLIB \"#{RUBY_VENDOR_ARCHLIB}\"\n"
- if !File.exist?(config_h) or File.read(config_h) != new_config_h
- File.open(config_h, 'w') { |io| io.print new_config_h }
- ext_dir = ".ext/include/#{NEW_RUBY_PLATFORM}/ruby"
- mkdir_p(ext_dir)
- cp(config_h, ext_dir)
- end
+ new_config_h = File.read(config_h + '.in') << "\n"
+ flag = ['/System/Library/Frameworks', '/Library/Frameworks'].any? do |p|
+ File.exist?(File.join(p, 'BridgeSupport.framework'))
+ end
+ new_config_h << "#define HAVE_BRIDGESUPPORT_FRAMEWORK #{flag ? 1 : 0}\n"
+ flag = File.exist?('/usr/include/auto_zone.h')
+ new_config_h << "#define HAVE_AUTO_ZONE_H #{flag ? 1 : 0}\n"
+ new_config_h << "#define ENABLE_DEBUG_LOGGING 1\n" if ENABLE_DEBUG_LOGGING
+ new_config_h << "#define RUBY_PLATFORM \"#{NEW_RUBY_PLATFORM}\"\n"
+ new_config_h << "#define RUBY_LIB \"#{RUBY_LIB}\"\n"
+ new_config_h << "#define RUBY_ARCHLIB \"#{RUBY_ARCHLIB}\"\n"
+ new_config_h << "#define RUBY_SITE_LIB \"#{RUBY_SITE_LIB}\"\n"
+ new_config_h << "#define RUBY_SITE_LIB2 \"#{RUBY_SITE_LIB2}\"\n"
+ new_config_h << "#define RUBY_SITE_ARCHLIB \"#{RUBY_SITE_ARCHLIB}\"\n"
+ new_config_h << "#define RUBY_VENDOR_LIB \"#{RUBY_VENDOR_LIB}\"\n"
+ new_config_h << "#define RUBY_VENDOR_LIB2 \"#{RUBY_VENDOR_LIB2}\"\n"
+ new_config_h << "#define RUBY_VENDOR_ARCHLIB \"#{RUBY_VENDOR_ARCHLIB}\"\n"
+ if !File.exist?(config_h) or File.read(config_h) != new_config_h
+ File.open(config_h, 'w') { |io| io.print new_config_h }
+ ext_dir = ".ext/include/#{NEW_RUBY_PLATFORM}/ruby"
+ mkdir_p(ext_dir)
+ cp(config_h, ext_dir)
end
end
@@ -261,7 +259,7 @@
cp('lex.c.blt', 'lex.c')
end
inc_to_gen = %w{opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc vmtc.inc vm.inc}.select { |inc| !File.exist?(inc) or File.mtime("template/#{inc}.tmpl") > File.mtime(inc) }
- unless inc_to_gen.empty?
+ if !inc_to_gen.empty? or File.mtime('insns.def') > File.mtime('vm.inc')
sh("/usr/bin/ruby -Ks tool/insns2vm.rb #{inc_to_gen.join(' ')}")
end
if !File.exist?('node_name.inc') or File.mtime('include/ruby/node.h') > File.mtime('node_name.inc')
Modified: MacRuby/branches/lrz_unstable/array.c
===================================================================
--- MacRuby/branches/lrz_unstable/array.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/array.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -191,7 +191,7 @@
ary = (VALUE)CFArrayCreateMutable(NULL, 0, &cb);
if (klass != 0 && klass != rb_cArray && klass != rb_cArrayRuby)
- *(Class *)ary = RCLASS_OCID(klass);
+ *(Class *)ary = (Class)klass;
CFMakeCollectable((CFTypeRef)ary);
rb_gc_malloc_increase(sizeof(void *));
@@ -3992,11 +3992,9 @@
#if WITH_OBJC
-#define NSCFARRAY() RCLASS_OCID(rb_cCFArray)
-
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFARRAY();
+ *(Class *)x = (Class)rb_cCFArray;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -4004,7 +4002,7 @@
bool
rb_objc_ary_is_pure(VALUE ary)
{
- return *(Class *)ary == NSCFARRAY();
+ return *(Class *)ary == (Class)rb_cCFArray;
}
static CFIndex
@@ -4135,7 +4133,6 @@
rb_cArray = rb_objc_import_class((Class)objc_getClass("NSArray"));
rb_cArrayRuby =
rb_objc_import_class((Class)objc_getClass("NSMutableArray"));
- FL_UNSET(rb_cArrayRuby, RCLASS_OBJC_IMPORTED);
rb_const_set(rb_cObject, rb_intern("Array"), rb_cArrayRuby);
#else
rb_cArray = rb_define_class("Array", rb_cObject);
Modified: MacRuby/branches/lrz_unstable/class.c
===================================================================
--- MacRuby/branches/lrz_unstable/class.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/class.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -13,6 +13,8 @@
#include "ruby/signal.h"
#include "ruby/node.h"
#include "ruby/st.h"
+#include "debug.h"
+#include "id.h"
#include <ctype.h>
extern st_table *rb_class_tbl;
@@ -20,37 +22,19 @@
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
-static VALUE
-class_init(VALUE obj)
-{
- GC_WB(&RCLASS(obj)->ptr, ALLOC(rb_classext_t));
- RCLASS_IV_TBL(obj) = 0;
- RCLASS_M_TBL(obj) = 0;
- RCLASS_SUPER(obj) = 0;
- RCLASS_IV_INDEX_TBL(obj) = 0;
- return obj;
-}
-
#if WITH_OBJC
-extern st_table *rb_objc_class_tbl;
-
VALUE
rb_objc_import_class(Class ocklass)
{
+#if 0
VALUE rbklass;
ID nameid;
VALUE super;
assert(ocklass != NULL);
assert(class_isMetaClass(ocklass) == 0);
- assert(rb_objc_class_tbl != NULL);
- if (st_lookup(rb_objc_class_tbl, (st_data_t)ocklass, (st_data_t *)&rbklass))
- return rbklass;
-
-//printf("import %s (%p)\n", class_getName(ocklass), ocklass);
-
{
NEWOBJ(obj, struct RClass);
OBJSETUP(obj, rb_cClass, T_CLASS);
@@ -60,8 +44,6 @@
RBASIC(rbklass)->isa = ocklass->isa;
RCLASS(rbklass)->ocklass = ocklass;
- class_init(rbklass);
-
RCLASS_M_TBL(rbklass) = st_init_numtable();
nameid = rb_intern(class_getName(ocklass));
@@ -72,7 +54,6 @@
/* FIXME do we need to maintain rb_class_tbl anymore? */
st_insert(rb_class_tbl, (st_data_t)nameid, (st_data_t)rbklass);
- st_insert(rb_objc_class_tbl, (st_data_t)ocklass, (st_data_t)rbklass);
ocklass = class_getSuperclass(ocklass);
@@ -99,6 +80,8 @@
rb_make_metaclass(rbklass, RBASIC(super)->klass);
return rbklass;
+#endif
+ return (VALUE)ocklass;
}
void rb_objc_install_array_primitives(Class);
@@ -110,15 +93,15 @@
{
if (rb_cArray != 0 && rb_cHash != 0 && rb_cString != 0) {
do {
- if (ocsuper == RCLASS_OCID(rb_cArray)) {
+ if (ocsuper == (Class)rb_cArray) {
rb_objc_install_array_primitives(ocklass);
return true;
}
- if (ocsuper == RCLASS_OCID(rb_cHash)) {
+ if (ocsuper == (Class)rb_cHash) {
rb_objc_install_hash_primitives(ocklass);
return true;
}
- if (ocsuper == RCLASS_OCID(rb_cString)) {
+ if (ocsuper == (Class)rb_cString) {
rb_objc_install_string_primitives(ocklass);
return true;
}
@@ -130,14 +113,11 @@
}
static VALUE
-rb_objc_alloc_class(const char *name, VALUE *psuper, VALUE flags, VALUE klass)
+rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
{
- VALUE super, obj;
- Class ocklass, ocsuper;
+ Class ocsuper, ocklass;
char ocname[128];
- super = psuper == NULL ? 0 : *psuper;
-
if (name == NULL) {
static long anon_count = 1;
snprintf(ocname, sizeof ocname, "RBAnonymous%ld", ++anon_count);
@@ -146,7 +126,7 @@
if (super == rb_cBasicObject && strcmp(name, "Object") != 0) {
rb_warn("Do not subclass NSObject directly, please subclass " \
"Object instead.");
- super = *psuper = rb_cObject;
+ super = rb_cObject;
}
if (objc_getClass(name) != NULL) {
long count = 1;
@@ -161,28 +141,26 @@
}
}
- ocsuper = super == 0 ? NULL : RCLASS_OCID(super);
- ocklass = objc_allocateClassPair(ocsuper, ocname, 0);
+ ocsuper = super == 0 ? (Class)rb_cBasicObject : (Class)super;
+ ocklass = objc_allocateClassPair(ocsuper, ocname, sizeof(id));
assert(ocklass != NULL);
- {
- NEWOBJ(obj2, struct RClass);
- OBJSETUP(obj2, klass, flags);
- obj = (VALUE)obj2;
- }
+ int version_flag;
- RBASIC(obj)->isa = ocklass->isa;
- RCLASS(obj)->ocklass = ocklass;
+ version_flag = RCLASS_IS_RUBY_CLASS;
+ if (flags == T_MODULE)
+ version_flag |= RCLASS_IS_MODULE;
+ if ((RCLASS_VERSION(ocsuper) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS)
+ version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
- rb_objc_retain((const void *)obj); /* classes should never be released */
+ class_setVersion(ocklass, version_flag);
- if (name == NULL)
- FL_SET(obj, RCLASS_ANONYMOUS);
+ DLOG("DEFC", "%s < %s (version=%d)", ocname, class_getName(class_getSuperclass((Class)ocklass)), version_flag);
if (klass != 0)
rb_objc_install_primitives(ocklass, ocsuper);
- return obj;
+ return (VALUE)ocklass;
}
VALUE
@@ -190,76 +168,48 @@
{
VALUE klass;
- klass = rb_objc_alloc_class(name, &super, T_CLASS, rb_cClass);
+ klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
- class_init(klass);
-
- objc_registerClassPair(RCLASS_OCID(klass));
+ objc_registerClassPair((Class)klass);
if (name != NULL)
st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
- st_insert(rb_objc_class_tbl, (st_data_t)RCLASS_OCID(klass),
- (st_data_t)klass);
- RCLASS_M_TBL(klass) = st_init_numtable();
- RCLASS_SUPER(klass) = super;
-
- OBJ_INFECT(klass, super);
-
return klass;
}
VALUE
rb_objc_rename_class(VALUE klass, const char *name)
{
-#if 0
- Class ocorig;
- Class ocnew;
- char *ocname;
- unsigned i, count;
+ /* TODO */
+ return klass;
+}
- count = strlen(name);
- ocname = (char *)alloca(count + 3);
- ocname[0] = 'R';
- ocname[1] = 'B';
- for (i = 0; i < count; i++) {
- char c = name[i];
- if (c == ':')
- c = '_';
- ocname[i + 2] = c;
- }
- ocname[count + 2] = '\0';
+#else /* WITH_OBJC */
- ocorig = RCLASS_OCID(klass);
+static VALUE
+class_init(VALUE obj)
+{
+ GC_WB(&RCLASS(obj)->ptr, ALLOC(rb_classext_t));
+ RCLASS_IV_TBL(obj) = 0;
+ RCLASS_M_TBL(obj) = 0;
+ RCLASS_SUPER(obj) = 0;
+ RCLASS_IV_INDEX_TBL(obj) = 0;
+ return obj;
+}
- //printf("renamed class %p %s to %s\n", klass, class_getName(ocorig), ocname);
-
- ocnew = objc_duplicateClass(ocorig, ocname, 0);
-
- RBASIC(klass)->isa = ocnew->isa;
- RCLASS(klass)->ocklass = ocnew;
-
- //printf("old %p new %p\n", ocorig, ocnew);
-
- //objc_disposeClassPair(ocorig);
-
- return klass;
#endif
- return klass;
-}
-#endif /* WITH_OBJC */
-
static VALUE
class_alloc(VALUE flags, VALUE klass)
{
#if WITH_OBJC
- VALUE obj = rb_objc_alloc_class(NULL, NULL, flags, klass);
+ return rb_objc_alloc_class(NULL, 0, flags, klass);
#else
NEWOBJ(obj, struct RClass);
OBJSETUP(obj, klass, flags);
+ return class_init((VALUE)obj);
#endif
- return class_init((VALUE)obj);
}
VALUE
@@ -272,8 +222,8 @@
RCLASS_SUPER(klass) = super;
RCLASS_M_TBL(klass) = st_init_numtable();
+ OBJ_INFECT(klass, super);
#endif
- OBJ_INFECT(klass, super);
return (VALUE)klass;
}
@@ -284,7 +234,7 @@
rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
rb_obj_classname(super));
}
- if (RBASIC(super)->flags & FL_SINGLETON) {
+ if (RCLASS_SINGLETON(super)) {
rb_raise(rb_eTypeError, "can't make subclass of singleton class");
}
}
@@ -300,6 +250,7 @@
return rb_class_boot(super);
}
+#if !WITH_OBJC
struct clone_method_data {
st_table *tbl;
VALUE klass;
@@ -322,6 +273,7 @@
}
return ST_CONTINUE;
}
+#endif
/* :nodoc: */
VALUE
@@ -331,26 +283,26 @@
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
RBASIC(clone)->klass = rb_singleton_class_clone(orig);
}
+#if !WITH_OBJC
RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
+#endif
#if WITH_OBJC
{
Class ocsuper;
- extern VALUE rb_cStringRuby;
- extern VALUE rb_cArrayRuby;
- extern VALUE rb_cHashRuby;
if (orig == rb_cStringRuby
|| orig == rb_cArrayRuby
|| orig == rb_cHashRuby) {
- ocsuper = RCLASS_OCID(orig);
+ ocsuper = (Class)orig;
rb_warn("cloning class `%s' is not supported, creating a " \
"subclass instead", rb_class2name(orig));
}
else {
- ocsuper = class_getSuperclass(RCLASS_OCID(orig));
+ ocsuper = class_getSuperclass((Class)orig);
}
- class_setSuperclass(RCLASS(clone)->ocklass, ocsuper);
+ class_setSuperclass((Class)clone, ocsuper);
}
#endif
+#if 0 // TODO
if (RCLASS_IV_TBL(orig)) {
ID id;
@@ -368,6 +320,7 @@
st_foreach(RCLASS_M_TBL(orig), clone_method,
(st_data_t)&data);
}
+#endif
return clone;
}
@@ -384,7 +337,7 @@
}
clone = rb_mod_init_copy(clone, orig);
#if WITH_OBJC
- rb_objc_install_primitives(RCLASS_OCID(clone), RCLASS_OCID(orig));
+ rb_objc_install_primitives((Class)clone, (Class)orig);
#endif
return clone;
}
@@ -393,7 +346,9 @@
rb_singleton_class_clone(VALUE obj)
{
VALUE klass = RBASIC(obj)->klass;
-
+#if WITH_OBJC
+ return klass;
+#else
if (!FL_TEST(klass, FL_SINGLETON))
return klass;
else {
@@ -419,22 +374,29 @@
(st_data_t)&data);
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
FL_SET(clone, FL_SINGLETON);
-#if WITH_OBJC
- objc_registerClassPair(RCLASS_OCID(clone));
-#endif
return (VALUE)clone;
}
+#endif
}
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
+#if WITH_OBJC
+ if (RCLASS_SINGLETON(klass)) {
+ static ID attachedId = 0;
+ if (attachedId == 0)
+ attachedId = rb_intern("__attached__");
+ rb_ivar_set(klass, attachedId, obj);
+ }
+#else
if (FL_TEST(klass, FL_SINGLETON)) {
if (!RCLASS_IV_TBL(klass)) {
GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
}
st_insert(RCLASS_IV_TBL(klass), rb_intern("__attached__"), obj);
}
+#endif
}
VALUE
@@ -443,50 +405,40 @@
bool pure;
#if WITH_OBJC
- pure = rb_objc_is_non_native(obj);
+ pure = NATIVE(obj);
#else
pure = false;
#endif
+#if WITH_OBJC
+ if (!pure && TYPE(obj) == T_CLASS && RCLASS_SINGLETON(obj)) {
+#else
if (!pure && BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
- return RBASIC(obj)->klass = rb_cClass;
+#endif
+ RBASIC(obj)->klass = rb_cClass;
+ return rb_cClass;
}
else {
- VALUE metasuper;
+// VALUE metasuper;
VALUE klass;
+ klass = rb_class_boot(super);
+ RBASIC(obj)->klass = klass;
#if WITH_OBJC
- if (!pure && BUILTIN_TYPE(obj) == T_CLASS) {
- NEWOBJ(obj2, struct RClass);
- OBJSETUP(obj2, rb_cClass, T_CLASS);
- klass = (VALUE)obj2;
- rb_objc_retain((const void *)klass);
- class_init(klass);
- OBJ_INFECT(klass, super);
- RCLASS_SUPER(klass) = super;
- RCLASS_M_TBL(klass) = st_init_numtable();
- RCLASS(klass)->ocklass = RBASIC(super)->isa;
- RBASIC(obj)->klass = klass;
- }
- else {
- klass = rb_class_boot(super);
- *(Class *)obj = RCLASS_OCID(klass);
- if (!pure)
- RBASIC(obj)->klass = klass;
- }
+ //RCLASS_SET_SINGLETON(klass);
#else
- klass = rb_class_boot(super);
- RBASIC(obj)->klass = klass;
+ FL_SET(klass, FL_SINGLETON);
#endif
- FL_SET(klass, FL_SINGLETON);
rb_singleton_class_attached(klass, obj);
+#if 0
metasuper = RBASIC(rb_class_real(super))->klass;
/* metaclass of a superclass may be NULL at boot time */
if (metasuper) {
RBASIC(klass)->klass = metasuper;
}
+#endif
return klass;
}
}
@@ -501,8 +453,8 @@
klass = rb_objc_create_class(rb_id2name(id), super);
#else
klass = rb_class_new(super);
+ rb_make_metaclass(klass, RBASIC(super)->klass);
#endif
- rb_make_metaclass(klass, RBASIC(super)->klass);
return klass;
}
@@ -577,7 +529,9 @@
{
VALUE mdl = class_alloc(T_MODULE, rb_cModule);
+#if !WITH_OBJC
RCLASS_M_TBL(mdl) = st_init_numtable();
+#endif
return (VALUE)mdl;
}
@@ -588,9 +542,8 @@
VALUE mdl;
#if WITH_OBJC
- mdl = rb_objc_create_class(rb_id2name(id), 0);
- RBASIC(mdl)->flags = T_MODULE;
- RBASIC(mdl)->klass = rb_cModule; /* necessary? */
+ mdl = rb_objc_alloc_class(rb_id2name(id), 0, T_MODULE, rb_cModule);
+ objc_registerClassPair((Class)mdl);
#else
mdl = rb_module_new();
rb_name_class(mdl, id);
@@ -640,6 +593,7 @@
return module;
}
+#if !WITH_OBJC
static VALUE
include_class_new(VALUE module, VALUE super)
{
@@ -648,31 +602,71 @@
if (BUILTIN_TYPE(module) == T_ICLASS) {
module = RBASIC(module)->klass;
}
+#if !WITH_OBJC
if (!RCLASS_IV_TBL(module)) {
GC_WB(&RCLASS_IV_TBL(module), st_init_numtable());
}
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
RCLASS_SUPER(klass) = super;
+#else
+ class_setSuperclass((Class)klass, (Class)super);
+#endif
if (TYPE(module) == T_ICLASS) {
RBASIC(klass)->klass = RBASIC(module)->klass;
}
else {
RBASIC(klass)->klass = module;
}
-#if WITH_OBJC
- class_setSuperclass(RCLASS(klass)->ocklass,
- RCLASS(RBASIC(klass)->klass)->ocklass);
-#endif
OBJ_INFECT(klass, module);
OBJ_INFECT(klass, super);
return (VALUE)klass;
}
+#endif
void
rb_include_module(VALUE klass, VALUE module)
{
+#if WITH_OBJC
+ VALUE ary;
+
+ rb_frozen_class_p(klass);
+
+ if (!OBJ_TAINTED(klass))
+ rb_secure(4);
+
+ Check_Type(module, T_MODULE);
+
+ ary = rb_ivar_get(klass, idIncludedModules);
+ if (ary == Qnil) {
+ ary = rb_ary_new();
+ rb_ivar_set(klass, idIncludedModules, ary);
+ }
+ rb_ary_push(ary, module);
+
+ ary = rb_ivar_get(module, idIncludedInClasses);
+ if (ary == Qnil) {
+ ary = rb_ary_new();
+ rb_ivar_set(module, idIncludedInClasses, ary);
+ }
+ rb_ary_push(ary, klass);
+
+ DLOG("INCM", "%s <- %s", class_getName((Class)klass), class_getName((Class)module));
+
+ Method *methods;
+ unsigned int i, methods_count;
+
+ methods = class_copyMethodList((Class)module, &methods_count);
+ for (i = 0; i < methods_count; i++) {
+ Method method = methods[i];
+ DLOG("DEFI", "-[%s %s]", class_getName((Class)klass), (char *)method_getName(method));
+ assert(class_addMethod((Class)klass,
+ method_getName(method),
+ method_getImplementation(method),
+ method_getTypeEncoding(method)));
+ }
+#else
VALUE p, c;
int changed = 0;
@@ -708,15 +702,13 @@
break;
}
}
-#if WITH_OBJC
- rb_objc_sync_ruby_methods(module, klass);
-#endif
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
changed = 1;
skip:
module = RCLASS_SUPER(module);
}
if (changed) rb_clear_cache();
+#endif
}
/*
@@ -805,7 +797,10 @@
VALUE p, ary = rb_ary_new();
for (p = mod; p; p = RCLASS_SUPER(p)) {
- if (FL_TEST(p, FL_SINGLETON))
+#if WITH_OBJC
+ rb_ary_push(ary, p);
+#else
+ if (RCLASS_SINGLETON(p))
continue;
if (BUILTIN_TYPE(p) == T_ICLASS) {
rb_ary_push(ary, RBASIC(p)->klass);
@@ -813,6 +808,7 @@
else {
rb_ary_push(ary, p);
}
+#endif
}
return ary;
}
@@ -862,6 +858,7 @@
return ins_methods_push(name, type, ary, NOEX_PUBLIC);
}
+#if !WITH_OBJC
static int
method_entry(ID key, NODE *body, st_table *list)
{
@@ -882,11 +879,60 @@
}
return ST_CONTINUE;
}
+#endif
+#if WITH_OBJC
+static inline bool
+is_ignored_selector(SEL sel)
+{
+#if defined(__ppc__)
+ return sel == (SEL)0xfffef000;
+#elif defined(__i386__)
+ return sel == (SEL)0xfffeb010;
+#else
+# error Unsupported arch
+#endif
+}
+#endif
+
static VALUE
class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, long, VALUE))
{
+#if WITH_OBJC
VALUE ary;
+ bool recur;
+
+ ary = rb_ary_new();
+
+ if (argc == 0) {
+ recur = true;
+ }
+ else {
+ VALUE r;
+ rb_scan_args(argc, argv, "01", &r);
+ recur = RTEST(r);
+ }
+
+ while (mod != 0) {
+ unsigned i, count;
+ Method *methods;
+
+ methods = class_copyMethodList((Class)mod, &count);
+ if (methods != NULL) {
+ for (i = 0; i < count; i++) {
+ SEL sel = method_getName(methods[i]);
+ if (is_ignored_selector(sel))
+ continue;
+ rb_ary_push(ary, ID2SYM(rb_intern(sel_getName(sel))));
+ }
+ free(methods);
+ }
+ if (!recur)
+ break;
+ mod = (VALUE)class_getSuperclass((Class)mod);
+ }
+#else
+ VALUE ary;
int recur;
st_table *list;
VALUE mod_orig = mod;
@@ -910,9 +956,6 @@
ary = rb_ary_new();
st_foreach(list, func, ary);
st_free_table(list);
-
-#if WITH_OBJC
- rb_objc_methods(ary, RCLASS(mod_orig)->ocklass);
#endif
return ary;
@@ -1039,6 +1082,9 @@
VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{
+#if WITH_OBJC // TODO
+ return Qnil;
+#else
VALUE recur, ary, klass;
st_table *list;
@@ -1065,6 +1111,7 @@
st_free_table(list);
return ary;
+#endif
}
void
@@ -1120,35 +1167,38 @@
DEFER_INTS;
#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
Class ocklass;
ocklass = *(Class *)obj;
- klass = rb_objc_import_class(ocklass);
+ klass = (VALUE)ocklass;
if (class_isMetaClass(ocklass))
return klass;
- if (!FL_TEST(klass, FL_SINGLETON))
- klass = rb_make_metaclass(obj, klass);
+ if (!RCLASS_SINGLETON(ocklass))
+ klass = rb_make_metaclass(obj, (VALUE)ocklass);
+
return klass;
}
+ if (TYPE(obj) == T_CLASS)
+ return obj;
#endif
- if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
+ if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
klass = RBASIC(obj)->klass;
}
else {
klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
}
-#if !WITH_OBJC
+#if 0
if (OBJ_TAINTED(obj)) {
OBJ_TAINT(klass);
}
else {
- FL_UNSET(klass, FL_TAINT);
+ OBJ_UNTAINT(klass);
}
+#endif
if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
-#endif
ALLOW_INTS;
return klass;
Modified: MacRuby/branches/lrz_unstable/compile.c
===================================================================
--- MacRuby/branches/lrz_unstable/compile.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/compile.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -338,9 +338,9 @@
alloc_size *= 2;
goto retry;
}
- storage->next = (void *)ALLOC_N(char, alloc_size +
+ GC_WB(&storage->next, (void *)ALLOC_N(char, alloc_size +
sizeof(struct
- iseq_compile_data_storage));
+ iseq_compile_data_storage)));
storage = iseq->compile_data->storage_current = storage->next;
storage->next = 0;
storage->pos = 0;
@@ -687,13 +687,15 @@
{
INSN *iobj = 0;
VALUE *operands =
- (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5);
+ (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 7);
operands[0] = id;
operands[1] = argc;
operands[2] = block;
operands[3] = flag;
operands[4] = 0;
- iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
+ operands[5] = (VALUE)sel_registerName(rb_id2name(SYM2ID(id)));
+ operands[6] = 0;
+ iobj = new_insn_core(iseq, line_no, BIN(send), 6, operands);
return iobj;
}
Modified: MacRuby/branches/lrz_unstable/debug.h
===================================================================
--- MacRuby/branches/lrz_unstable/debug.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/debug.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -29,4 +29,25 @@
void ruby_debug_breakpoint(void);
void ruby_debug_gc_check_func(void);
+#if ENABLE_DEBUG_LOGGING
+static inline bool dlog_enabled(void) {
+ static int flag = -1;
+ if (flag == -1) {
+ flag = getenv("MACRUBY_DEBUG") != NULL;
+ }
+ return (bool)flag;
+}
+# define DLOG(mod, fmt, args...) \
+ do { \
+ if (dlog_enabled()) { \
+ printf("%10s ", mod); \
+ printf(fmt, ##args); \
+ printf("\n"); \
+ } \
+ } \
+ while (0)
+#else
+# define DLOG(mod, fmt, args...)
+#endif
+
#endif /* RUBY_DEBUG_H */
Modified: MacRuby/branches/lrz_unstable/eval.c
===================================================================
--- MacRuby/branches/lrz_unstable/eval.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/eval.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -336,7 +336,7 @@
const char *desc = "something(?!)";
if (OBJ_FROZEN(klass)) {
- if (FL_TEST(klass, FL_SINGLETON))
+ if (RCLASS_SINGLETON(klass))
desc = "object";
else {
switch (TYPE(klass)) {
Modified: MacRuby/branches/lrz_unstable/gc.c
===================================================================
--- MacRuby/branches/lrz_unstable/gc.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/gc.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -1029,7 +1029,7 @@
#endif
if (__nsobject == NULL)
__nsobject = (void *)objc_getClass("NSObject");
- RBASIC(obj)->isa = __nsobject;
+ RBASIC(obj)->klass = (VALUE)__nsobject;
return obj;
}
@@ -2267,9 +2267,10 @@
if (type != AUTO_OBJECT_SCANNED && type != AUTO_OBJECT_UNSCANNED)
continue;
if (ctx->class_of != 0) {
+#if 0
if (ctx->class_of == rb_cClass || ctx->class_of == rb_cModule) {
/* Class/Module are a special case. */
- if (rb_objc_is_non_native(r->address)
+ if (NATIVE(r->address)
|| FL_TEST(r->address, FL_SINGLETON))
continue;
if (ctx->class_of == rb_cClass) {
@@ -2284,11 +2285,13 @@
continue;
}
}
- else {
+ else
+#endif
+ {
unsigned ok = 0;
for (c = *(Class *)r->address; c != NULL;
c = class_getSuperclass(c)) {
- if (c == RCLASS(ctx->class_of)->ocklass) {
+ if (c ==(Class)ctx->class_of) {
ok = 1;
break;
}
@@ -2297,14 +2300,14 @@
continue;
}
}
- if (!rb_objc_is_non_native((VALUE)r->address)) {
+ if (!NATIVE((VALUE)r->address)) {
switch (BUILTIN_TYPE(r->address)) {
case T_NONE:
case T_ICLASS:
case T_NODE:
continue;
case T_CLASS:
- if (FL_TEST(r->address, FL_SINGLETON))
+ if (RCLASS_SINGLETON(r->address))
continue;
}
}
@@ -2437,7 +2440,7 @@
if (__os_finalizers != NULL)
CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
rb_objc_flag_set((void *)obj, FL_FINALIZE, false);
}
else {
@@ -2491,7 +2494,7 @@
rb_ary_push(table, block);
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
rb_objc_flag_set((void *)obj, FL_FINALIZE, true);
}
else {
@@ -2536,7 +2539,7 @@
if (__os_finalizers == NULL)
return;
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
if (!rb_objc_flag_check((void *)obj, FL_FINALIZE))
return;
}
@@ -2802,7 +2805,7 @@
auto_zone_get_layout_type_no_lock(__auto_zone, p0);
if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
&& !rb_objc_is_placeholder(p0)
- && (rb_objc_is_non_native((VALUE)p0)
+ && (NATIVE((VALUE)p0)
|| (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
return (VALUE)p0;
}
@@ -3076,7 +3079,7 @@
__rb_objc_finalize(void *obj, void *data)
{
//printf("finalize %p <%s>\n",obj, class_getName(*(Class *)obj));
- if (rb_objc_is_non_native((VALUE)obj)) {
+ if (NATIVE((VALUE)obj)) {
static SEL sel = NULL;
long flag;
flag = rb_objc_remove_flags(obj);
Modified: MacRuby/branches/lrz_unstable/hash.c
===================================================================
--- MacRuby/branches/lrz_unstable/hash.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/hash.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -339,7 +339,7 @@
hash = (VALUE)CFDictionaryCreateMutable(NULL, 0, &keys_cb, &values_cb);
if (klass != 0 && klass != rb_cHash && klass != rb_cHashRuby)
- *(Class *)hash = RCLASS_OCID(klass);
+ *(Class *)hash = (Class)klass;
CFMakeCollectable((CFTypeRef)hash);
rb_gc_malloc_increase(sizeof(void *));
@@ -2918,11 +2918,9 @@
#if WITH_OBJC
-#define NSCFDICTIONARY() RCLASS_OCID(rb_cCFHash)
-
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFDICTIONARY();
+ *(Class *)x = (Class)rb_cCFHash;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -2930,7 +2928,7 @@
bool
rb_objc_hash_is_pure(VALUE ary)
{
- return *(Class *)ary == NSCFDICTIONARY();
+ return *(Class *)ary == (Class)rb_cCFHash;
}
static CFIndex
@@ -3061,7 +3059,6 @@
rb_cCFHash = rb_objc_import_class((Class)objc_getClass("NSCFDictionary"));
rb_cHash = rb_objc_import_class((Class)objc_getClass("NSDictionary"));
rb_cHashRuby = rb_objc_import_class((Class)objc_getClass("NSMutableDictionary"));
- FL_UNSET(rb_cHashRuby, RCLASS_OBJC_IMPORTED);
rb_const_set(rb_cObject, rb_intern("Hash"), rb_cHashRuby);
#else
rb_cHash = rb_define_class("Hash", rb_cObject);
Modified: MacRuby/branches/lrz_unstable/id.c
===================================================================
--- MacRuby/branches/lrz_unstable/id.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/id.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -66,4 +66,7 @@
idRespond_to = rb_intern("respond_to?");
idInitialize = rb_intern("initialize");
+
+ idIncludedModules = rb_intern("__included_modules__");
+ idIncludedInClasses = rb_intern("__included_in_classes__");
}
Modified: MacRuby/branches/lrz_unstable/id.h
===================================================================
--- MacRuby/branches/lrz_unstable/id.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/id.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -52,4 +52,8 @@
extern ID id__send__;
extern ID idRespond_to;
extern ID idInitialize;
+#if WITH_OBJC
+extern ID idIncludedModules;
+extern ID idIncludedInClasses;
+#endif
#endif /* RUBY_ID_H */
Modified: MacRuby/branches/lrz_unstable/include/ruby/intern.h
===================================================================
--- MacRuby/branches/lrz_unstable/include/ruby/intern.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/include/ruby/intern.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -691,6 +691,7 @@
VALUE rb_mod_remove_cvar(VALUE, VALUE);
/* objc.m */
#if WITH_OBJC
+void rb_objc_alias(VALUE, ID, ID);
VALUE rb_mod_objc_ancestors(VALUE);
VALUE rb_mod_objc_ib_outlet(int, VALUE *, VALUE);
VALUE rb_require_framework(int, VALUE *, VALUE);
@@ -700,7 +701,6 @@
void rb_objc_flag_set(const void *, int, bool);
bool rb_objc_flag_check(const void *, int);
long rb_objc_remove_flags(const void *obj);
-void rb_objc_sync_ruby_methods(VALUE, VALUE);
void rb_objc_methods(VALUE, Class);
bool rb_objc_is_immutable(VALUE);
#endif
Modified: MacRuby/branches/lrz_unstable/include/ruby/node.h
===================================================================
--- MacRuby/branches/lrz_unstable/include/ruby/node.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/include/ruby/node.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -507,7 +507,8 @@
void rb_add_method(VALUE, ID, NODE *, int);
void rb_add_method_direct(VALUE, ID, NODE *);
#if WITH_OBJC
-NODE *rb_objc_define_objc_mid_closure(VALUE, ID, ID);
+void rb_objc_register_ruby_method(VALUE, ID, NODE *);
+NODE *rb_objc_method_node(VALUE, ID, IMP *, SEL *);
#endif
NODE *rb_node_newnode(enum node_type,VALUE,VALUE,VALUE);
Modified: MacRuby/branches/lrz_unstable/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/lrz_unstable/include/ruby/ruby.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/include/ruby/ruby.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -416,20 +416,11 @@
#else
# define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
#endif
-#define __OBJSETUP(obj,c,t) do {\
+#define OBJSETUP(obj,c,t) do {\
RBASIC(obj)->flags = (t);\
RBASIC(obj)->klass = (c);\
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
} while (0)
-#if WITH_OBJC
-# define OBJSETUP(obj,c,t) do {\
- __OBJSETUP(obj,c,t);\
- if (c != 0) \
- RBASIC(obj)->isa = (void *)RCLASS_OCID(c); \
-} while (0)
-#else
-# define OBJSETUP(obj,c,t) __OBJSETUP(obj,c,t)
-#endif
#define CLONESETUP(clone,obj) do {\
OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
@@ -441,37 +432,34 @@
} while (0)
struct RBasic {
- void *isa;
+ VALUE klass; /* isa */
VALUE flags;
- VALUE klass;
};
-#define ROBJECT_EMBED_LEN_MAX 3
-struct RObject {
- struct RBasic basic;
+struct rb_ivars {
+#define RB_IVAR_ARY 0
+#define RB_IVAR_TBL 1
+#define RB_IVAR_TYPE(ivars) (ivars.type & 0x1)
+#define RB_IVAR_SET_TYPE(ivars, t) (ivars.type |= t)
+#define RB_IVAR_ARY_LEN(ivars) (ivars.type >> 1)
+#define RB_IVAR_ARY_SET_LEN(ivars, len) (ivars.type = (len << 1) | (ivars.type & 0x1))
+#define RB_IVAR_ARY_MAX 10
+ short type;
union {
- struct {
- long numiv;
- VALUE *ivptr;
- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
- } heap;
- VALUE ary[ROBJECT_EMBED_LEN_MAX];
+ struct rb_ivar_ary_entry {
+ ID name;
+ VALUE value;
+ } *ary;
+ CFMutableDictionaryRef tbl;
} as;
};
-#define ROBJECT_EMBED FL_USER1
-#define ROBJECT_NUMIV(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT_EMBED_LEN_MAX : \
- ROBJECT(o)->as.heap.numiv)
-#define ROBJECT_IVPTR(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT(o)->as.ary : \
- ROBJECT(o)->as.heap.ivptr)
-#define ROBJECT_IV_INDEX_TBL(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
- ROBJECT(o)->as.heap.iv_index_tbl)
+struct RObject {
+ struct RBasic basic;
+ struct rb_ivars ivars;
+};
+
+#if !WITH_OBJC
typedef struct {
VALUE super;
struct st_table *iv_tbl;
@@ -484,17 +472,38 @@
struct st_table *m_tbl;
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)
-#if WITH_OBJC
-# define RCLASS_ANONYMOUS FL_USER1
-# define RCLASS_OBJC_IMPORTED FL_USER2
-# define RCLASS_OCID(obj) ((Class)RCLASS(obj)->ocklass)
+# 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)
+#else
+# define RCLASS_IS_OBJECT_SUBCLASS 0x100 /* class is a true RBObject subclass */
+# define RCLASS_IS_RUBY_CLASS 0x200 /* class was created from Ruby */
+# define RCLASS_IS_MODULE 0x400 /* class represents a Ruby Module */
+# define RCLASS_IS_SINGLETON 0x800 /* class represents a singleton/metaclass */
+# define RCLASS_IS_FROZEN 0x1000 /* class is frozen */
+# define RCLASS_IS_TAINTED 0x2000 /* class is tainted */
+# if __OBJC2__
+# define RCLASS_VERSION(m) (class_getVersion((Class)m))
+# define RCLASS_SET_VERSION_FLAG(m,f) (class_setVersion((Class)m, (RCLASS_VERSION(m) | f)))
+# define RCLASS_SUPER(m) (class_getSuperclass((Class)m))
+# define RCLASS_SINGLETON(m) (class_isMetaclass((Class)m))
+# else
+# define RCLASS_VERSION(m) (*(long *)((void *)m + (sizeof(void *) * 3)))
+# define RCLASS_SET_VERSION_FLAG(m,f) (RCLASS_VERSION(m) |= f)
+# define RCLASS_SUPER(m) (*(VALUE *)((void *)m + (sizeof(void *) * 1)))
+# define _RCLASS_INFO(m) (*(long *)((void *)m + (sizeof(void *) * 4)))
+# define RCLASS_SINGLETON(m) (_RCLASS_INFO(m) & CLS_META)
+# endif
+# define NATIVE(obj) (*(Class *)obj != NULL && (RCLASS_VERSION(*(Class *)obj) & RCLASS_IS_OBJECT_SUBCLASS) != RCLASS_IS_OBJECT_SUBCLASS)
+# define RCLASS_RUBY(m) ((RCLASS_VERSION(m) & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS)
+# define RCLASS_MODULE(m) ((RCLASS_VERSION(m) & RCLASS_IS_MODULE) == RCLASS_IS_MODULE)
+CFMutableDictionaryRef rb_class_ivar_dict(VALUE);
+CFMutableDictionaryRef rb_class_ivar_dict_or_create(VALUE);
+void rb_class_ivar_set_dict(VALUE, CFMutableDictionaryRef);
#endif
struct RFloat {
@@ -710,12 +719,12 @@
#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
-#define RCLASS(obj) (R_CAST(RClass)(obj))
-#define RMODULE(obj) RCLASS(obj)
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
#if !WITH_OBJC
+# define RCLASS(obj) (R_CAST(RClass)(obj))
+# define RMODULE(obj) RCLASS(obj)
# define RSTRING(obj) (R_CAST(RString)(obj))
# define RARRAY(obj) (R_CAST(RArray)(obj))
# define RHASH(obj) (R_CAST(RHash)(obj))
@@ -984,6 +993,15 @@
RUBY_EXTERN VALUE rb_cVM;
RUBY_EXTERN VALUE rb_cEnv;
+#if WITH_OBJC
+RUBY_EXTERN VALUE rb_cCFString;
+RUBY_EXTERN VALUE rb_cStringRuby;
+RUBY_EXTERN VALUE rb_cCFArray;
+RUBY_EXTERN VALUE rb_cArrayRuby;
+RUBY_EXTERN VALUE rb_cCFHash;
+RUBY_EXTERN VALUE rb_cHashRuby;
+#endif
+
RUBY_EXTERN VALUE rb_eException;
RUBY_EXTERN VALUE rb_eStandardError;
RUBY_EXTERN VALUE rb_eSystemExit;
@@ -1018,22 +1036,6 @@
RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
-#if WITH_OBJC
-static inline unsigned
-rb_objc_is_non_native(VALUE obj)
-{
- void *isa = RBASIC(obj)->isa;
- if (isa == NULL || class_isMetaClass(isa))
- return 0;
- while (isa != NULL) {
- if (rb_cObject != 0 && isa == RCLASS_OCID(rb_cObject))
- return 0;
- isa = (void *)class_getSuperclass(isa);
- }
- return 1;
-}
-#endif
-
static inline VALUE
rb_class_of(VALUE obj)
{
@@ -1046,20 +1048,6 @@
if (obj == Qnil) return rb_cNilClass;
if (obj == Qfalse) return rb_cFalseClass;
}
-#if WITH_OBJC
- extern VALUE rb_cCFString;
- extern VALUE rb_cCFArray;
- extern VALUE rb_cCFHash;
- if (rb_cCFString != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFString))
- return rb_cCFString;
- if (rb_cCFArray != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFArray))
- return rb_cCFArray;
- if (rb_cCFHash != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFHash))
- return rb_cCFHash;
- VALUE rb_objc_import_class(Class);
- if (rb_objc_is_non_native(obj))
- return rb_objc_import_class(RBASIC(obj)->isa);
-#endif
return RBASIC(obj)->klass;
}
@@ -1077,20 +1065,14 @@
if (obj == Qfalse) return T_FALSE;
}
#if WITH_OBJC
- /* FIXME this is super slow */
- else if (rb_cHash != 0
- && rb_cArray != 0
- && rb_cString != 0) {
- Class k = *(Class *)obj;
- while (k != NULL) {
- if (k == RCLASS_OCID(rb_cHash))
- return T_HASH;
- if (k == RCLASS_OCID(rb_cArray))
- return T_ARRAY;
- if (k == RCLASS_OCID(rb_cString))
- return T_STRING;
- k = class_getSuperclass(k);
+ else if (*(Class *)obj != NULL) {
+ if (RCLASS_SINGLETON(*(Class *)obj)) {
+ if (RCLASS_MODULE(obj)) return T_MODULE;
+ else return T_CLASS;
}
+ if (*(Class *)obj == (Class)rb_cCFString) return T_STRING;
+ if (*(Class *)obj == (Class)rb_cCFArray) return T_ARRAY;
+ if (*(Class *)obj == (Class)rb_cCFHash) return T_HASH;
}
#endif
return BUILTIN_TYPE(obj);
Modified: MacRuby/branches/lrz_unstable/insnhelper.h
===================================================================
--- MacRuby/branches/lrz_unstable/insnhelper.h 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/insnhelper.h 2008-07-30 02:27:07 UTC (rev 382)
@@ -112,8 +112,8 @@
c1->nd_next = __tmp_c2->nd_next; \
} while (0)
-#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass) do { \
- VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass); \
+#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, sel) do { \
+ VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass, sel); \
if (v == Qundef) { \
RESTORE_REGS(); \
NEXT_INSN(); \
@@ -142,7 +142,7 @@
#define CALL_SIMPLE_METHOD(num, id, recv) do { \
VALUE klass = CLASS_OF(recv); \
- CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv)); \
+ CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv), (SEL)0); \
} while (0)
#endif /* RUBY_INSNHELPER_H */
Modified: MacRuby/branches/lrz_unstable/insns.def
===================================================================
--- MacRuby/branches/lrz_unstable/insns.def 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/insns.def 2008-07-30 02:27:07 UTC (rev 382)
@@ -1023,7 +1023,7 @@
*/
DEFINE_INSN
send
-(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)
+(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic, VALUE sel)
(...)
(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
{
@@ -1038,17 +1038,19 @@
/* get receiver */
recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
klass = CLASS_OF(recv);
+#if WITH_OBJC
+ ic = 0;
+ mn = NULL;
+#else
mn = vm_method_search(id, klass, ic);
-#if WITH_OBJC
- vm_method_process_named_args(&id, &mn, recv, &num, GET_CFP());
-#endif
/* send/funcall optimization */
if (flag & VM_CALL_SEND_BIT) {
vm_send_optimize(GET_CFP(), &mn, &flag, &num, &id, klass);
}
+#endif
- CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
+ CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, (SEL)sel);
}
/**
@@ -1073,12 +1075,13 @@
recv = GET_SELF();
vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass);
+#if WITH_OBJC
+ mn = NULL;
+#else
mn = rb_method_node(klass, id);
-#if WITH_OBJC
- vm_method_process_named_args(&id, &mn, recv, (rb_num_t *)&num, GET_CFP());
#endif
- CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
+ CALL_METHOD(num, blockptr, flag, id, mn, recv, klass, (SEL)0);
}
/**
@@ -1405,7 +1408,11 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idPLUS, recv);
+
+ static SEL selPLUS=0;
+ if (selPLUS==0) { selPLUS = sel_registerName("+:"); }
+ CALL_METHOD(1, 0, 0, idPLUS, NULL, recv, CLASS_OF(recv), (SEL)selPLUS);
+ //CALL_SIMPLE_METHOD(1, idPLUS, recv);
}
}
@@ -1716,6 +1723,8 @@
else {
PUSH(recv);
PUSH(obj);
+ //static SEL selPLUS=0;
+ //if (selPLUS==0) { selPLUS = sel_registerName("+:"); }
CALL_SIMPLE_METHOD(1, idLT, recv);
}
}
Modified: MacRuby/branches/lrz_unstable/io.c
===================================================================
--- MacRuby/branches/lrz_unstable/io.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/io.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -5209,7 +5209,7 @@
p->filename = Qnil;
p->current_file = Qnil;
p->lineno = Qnil;
- p->argv = v;
+ GC_WB(&p->argv, v);
}
static VALUE
@@ -5248,11 +5248,11 @@
argf_initialize_copy(VALUE argf, VALUE orig)
{
ARGF = argf_of(orig);
- rb_argv = rb_obj_dup(rb_argv);
+ GC_WB(&rb_argv, rb_obj_dup(rb_argv));
if (ARGF.inplace) {
const char *inplace = ARGF.inplace;
ARGF.inplace = 0;
- ARGF.inplace = ruby_strdup(inplace);
+ GC_WB(&ARGF.inplace, ruby_strdup(inplace));
}
return argf;
}
@@ -7812,7 +7812,7 @@
rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, 0);
- filename = rb_str_new2("-");
+ GC_WB(&filename, rb_str_new2("-"));
rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
rb_define_hooked_variable("$*", &argf, argf_argv_getter, 0);
Modified: MacRuby/branches/lrz_unstable/marshal.c
===================================================================
--- MacRuby/branches/lrz_unstable/marshal.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/marshal.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -420,14 +420,16 @@
{
const char *path;
- if (check && FL_TEST(klass, FL_SINGLETON)) {
+ if (check && RCLASS_SINGLETON(klass)) {
+#if !WITH_OBJC // TODO
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");
}
+#endif
klass = RCLASS_SUPER(klass);
}
- while (BUILTIN_TYPE(klass) == T_ICLASS) {
+ while (TYPE(klass) == T_ICLASS) {
path = rb_class2name(RBASIC(klass)->klass);
w_byte(TYPE_EXTENDED_R, arg);
w_unique(path, arg);
@@ -534,6 +536,7 @@
static void
w_objivar(VALUE obj, struct dump_call_arg *arg)
{
+#if !WITH_OBJC /* TODO */
VALUE *ptr;
long i, len, num;
@@ -548,6 +551,7 @@
if (num != 0) {
rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
}
+#endif
}
static void
@@ -650,7 +654,7 @@
st_add_direct(arg->data, obj, arg->data->num_entries);
#if WITH_OBJC
- if (!rb_objc_is_non_native(obj))
+ if (!NATIVE(obj))
#endif
{
st_data_t compat_data;
@@ -667,7 +671,7 @@
switch (/*BUILTIN_*/TYPE(obj)) {
case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(obj)) {
rb_raise(rb_eTypeError, "singleton class can't be dumped");
}
w_byte(TYPE_CLASS, arg);
@@ -1279,28 +1283,20 @@
{
VALUE c = path2class(r_unique(arg));
- if (FL_TEST(c, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(c)) {
rb_raise(rb_eTypeError, "singleton can't be loaded");
}
v = r_object0(arg, 0, extmod);
-#if WITH_OBJC
- if (rb_objc_is_non_native(v)) {
- *(Class *)v = RCLASS_OCID(c);
- }
- else
-#endif
- {
- if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
+ if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
format_error:
- rb_raise(rb_eArgError, "dump format error (user class)");
- }
- if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
- VALUE tmp = rb_obj_alloc(c);
+ rb_raise(rb_eArgError, "dump format error (user class)");
+ }
+ if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
+ VALUE tmp = rb_obj_alloc(c);
- if (TYPE(v) != TYPE(tmp)) goto format_error;
- }
- RBASIC(v)->klass = c;
+ if (TYPE(v) != TYPE(tmp)) goto format_error;
}
+ RBASIC(v)->klass = c;
}
break;
Modified: MacRuby/branches/lrz_unstable/numeric.c
===================================================================
--- MacRuby/branches/lrz_unstable/numeric.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/numeric.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -3148,7 +3148,7 @@
static void
rb_install_nsnumber_float_primitives(void)
{
- Class klass = RCLASS_OCID(rb_cFloat);
+ Class klass = (Class)rb_cFloat;
rb_objc_install_method(klass, sel_registerName("objCType"),
(IMP)imp_rb_float_objCType);
rb_objc_install_method(klass, sel_registerName("getValue:"),
@@ -3160,7 +3160,7 @@
static void
rb_install_nsnumber_integer_primitives(void)
{
- Class klass = RCLASS_OCID(rb_cNumeric);
+ Class klass = (Class)rb_cNumeric;
rb_objc_install_method(klass, sel_registerName("objCType"),
(IMP)imp_rb_integer_objCType);
rb_objc_install_method(klass, sel_registerName("getValue:"),
Modified: MacRuby/branches/lrz_unstable/objc.m
===================================================================
--- MacRuby/branches/lrz_unstable/objc.m 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/objc.m 2008-07-30 02:27:07 UTC (rev 382)
@@ -40,6 +40,7 @@
#endif
#include "vm_core.h"
#include "vm.h"
+#include "eval_intern.h"
typedef struct {
bs_element_type_t type;
@@ -442,9 +443,6 @@
*(id *)ocval = (id)number;
}
}
- else if (class_isMetaClass(*(Class *)rval)) {
- *(id *)ocval = (id)RCLASS_OCID(rval);
- }
else {
*(id *)ocval = (id)rval;
}
@@ -697,7 +695,8 @@
if (*octype == _C_VOID)
return;
- if (st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
+ if (bs_boxeds != NULL
+ && st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
void *data;
data = rb_objc_rval_to_boxed_data(rval, bs_boxed, &ok);
@@ -712,7 +711,7 @@
goto bails;
}
- if (st_lookup(bs_cftypes, (st_data_t)octype, NULL))
+ if (bs_cftypes != NULL && st_lookup(bs_cftypes, (st_data_t)octype, NULL))
octype = "@";
if (*octype != _C_BOOL && *octype != _C_ID) {
@@ -854,7 +853,7 @@
VALUE
rb_objc_boot_ocid(id ocid)
{
- if (rb_objc_is_non_native((VALUE)ocid)) {
+ if (NATIVE((VALUE)ocid)) {
/* Make sure the ObjC class is imported in Ruby. */
rb_objc_import_class(object_getClass(ocid));
}
@@ -909,13 +908,15 @@
{
bs_element_boxed_t *bs_boxed;
- if (st_lookup(bs_boxeds, (st_data_t)octype,
+ if (bs_boxeds != NULL
+ && st_lookup(bs_boxeds, (st_data_t)octype,
(st_data_t *)&bs_boxed)) {
*rbval = rb_bs_boxed_new_from_ocdata(bs_boxed, ocval);
goto bails;
}
- if (st_lookup(bs_cftypes, (st_data_t)octype, NULL))
+ if (bs_cftypes != NULL
+ && st_lookup(bs_cftypes, (st_data_t)octype, NULL))
octype = "@";
}
@@ -1024,6 +1025,7 @@
rb_raise(rb_eRuntimeError, "%s: %s", name, desc);
}
+#if 0
static bs_element_method_t *
rb_bs_find_method(Class klass, SEL sel)
{
@@ -1046,6 +1048,7 @@
return NULL;
}
+#endif
static const char *
rb_objc_method_get_type(Method method, unsigned count,
@@ -1077,8 +1080,6 @@
return type;
}
-extern NODE *rb_current_cfunc_node;
-
struct objc_ruby_closure_context {
SEL selector;
bs_element_method_t *bs_method;
@@ -1100,6 +1101,8 @@
char buf[128];
void *imp;
+ DLOG("OCALL", "[%p %s] argc=%d", ocrcv, (char *)ctx->selector, argc);
+
count = method_getNumberOfArguments(ctx->method);
assert(count >= 2);
@@ -1231,6 +1234,7 @@
}
}
+#if 0
static VALUE
rb_objc_to_ruby_closure(int argc, VALUE *argv, VALUE rcv)
{
@@ -1296,7 +1300,93 @@
return rb_objc_call_objc(argc, argv, ocrcv, klass, super_call, ctx);
}
+#endif
+VALUE
+rb_objc_call(VALUE recv, ID mid, int argc, VALUE *argv)
+{
+ VALUE klass;
+ SEL sel;
+ IMP imp;
+ NODE *node;
+
+ klass = CLASS_OF(recv);
+ node = rb_objc_method_node(klass, mid, &imp, &sel);
+
+ if (imp == NULL) {
+ // TODO
+ printf("METHOD_MISSING!");
+ assert(1 == 0);
+ return Qnil;
+ }
+ else if (node != NULL) {
+ assert(node->nd_body != NULL);
+
+ DLOG("RCALL", "[<%s %p> %s] node=%p argc=%d", class_getName((Class)klass), (void *)recv, (char *)sel, node->nd_body, argc);
+
+ VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id,
+ ID oid, int argc, const VALUE *argv, const NODE *body,
+ int nosuper);
+
+ return rb_vm_call(GET_THREAD(), klass, recv, mid, Qnil,
+ argc, argv, node->nd_body, 0);
+ }
+ else {
+ id ocrcv;
+ struct objc_ruby_closure_context fake_ctx;
+
+ rb_objc_rval_to_ocid(recv, (void **)&ocrcv, true);
+
+ fake_ctx.selector = sel;
+ fake_ctx.method = class_getInstanceMethod((Class)klass, fake_ctx.selector);
+ assert(fake_ctx.method != NULL);
+ fake_ctx.bs_method = NULL;
+ fake_ctx.cif = NULL;
+ fake_ctx.imp = imp;
+ fake_ctx.klass = NULL;
+
+ return rb_objc_call_objc(argc, argv, ocrcv, (Class)klass, true, &fake_ctx);
+ }
+}
+
+void
+rb_objc_alias(VALUE klass, ID name, ID def)
+{
+ const char *name_str, *def_str;
+ SEL name_sel, def_sel;
+ Method method;
+
+ name_str = rb_id2name(name);
+ def_str = rb_id2name(def);
+
+ name_sel = sel_registerName(name_str);
+ def_sel = sel_registerName(def_str);
+
+ method = class_getInstanceMethod((Class)klass, def_sel);
+ if (method == NULL) {
+ if (def_str[strlen(def_str) - 1] != ':') {
+ char buf[512];
+ strlcpy(buf, def_str, sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+ def_sel = sel_registerName(buf);
+ method = class_getInstanceMethod((Class)klass, def_sel);
+ if (method == NULL)
+ rb_print_undef(klass, def, 0);
+ if (name_str[strlen(name_str) - 1] != ':') {
+ strlcpy(buf, name_str, sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+ name_sel = sel_registerName(buf);
+ }
+ }
+ }
+
+ DLOG("ALIAS", "[%s %s -> %s]", class_getName((Class)klass), (char *)name_sel, (char *)def_sel);
+
+ assert(class_addMethod((Class)klass, name_sel,
+ method_getImplementation(method),
+ method_getTypeEncoding(method)));
+}
+
static VALUE
rb_super_objc_send(int argc, VALUE *argv, VALUE rcv)
{
@@ -1340,11 +1430,12 @@
char type[128];
long i, argc;
VALUE *argv;
- NODE *body;
+ NODE *body, *node;
rcv = (*(id **)args)[0];
sel = (*(SEL **)args)[1];
body = (NODE *)userdata;
+ node = body->nd_body;
method = class_getInstanceMethod(*(Class *)rcv, sel);
assert(method != NULL);
@@ -1363,14 +1454,14 @@
mid = rb_intern((const char *)sel);
-//NSLog(@"ObjC -> Ruby [%@ mid=%s]\n", rrcv, rb_id2name(mid));
+ DLOG("RCALL", "[%p %s] node=%p argc=%ld", (void *)rrcv, (char *)sel, body, argc);
VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id,
ID oid, int argc, const VALUE *argv, const NODE *body,
int nosuper);
ret = rb_vm_call(GET_THREAD(), CLASS_OF(rrcv), rrcv, mid, Qnil,
- argc, argv, body, 0);
+ argc, argv, node, 0);
method_getReturnType(method, type, sizeof type);
rb_objc_rval_to_ocval(ret, type, resp);
@@ -1407,289 +1498,257 @@
!= FFI_OK)
rb_fatal("can't prepare ruby to objc closure");
+ rb_objc_retain(node);
+
return closure;
}
+NODE *
+rb_objc_method_node2(VALUE mod, SEL sel, IMP *pimp)
+{
+ IMP imp;
+
+ if (pimp != NULL)
+ *pimp = NULL;
+
+ imp = class_getMethodImplementation((Class)mod, sel);
+ extern void *_objc_msgForward;
+ if (imp == (IMP)&_objc_msgForward)
+ imp = NULL;
+
+ if (pimp != NULL)
+ *pimp = imp;
+
+ if (imp == NULL || ((ffi_closure *)imp)->fun != rb_ruby_to_objc_closure_handler)
+ return NULL;
+
+ return ((ffi_closure *)imp)->user_data;
+}
+
+NODE *
+rb_objc_method_node(VALUE mod, ID mid, IMP *pimp, SEL *psel)
+{
+ SEL sel;
+ IMP imp;
+ NODE *node;
+
+ if (mid == ID_ALLOCATOR)
+ sel = @selector(alloc);
+ else
+ sel = sel_registerName(rb_id2name(mid));
+
+ if (psel != NULL)
+ *psel = sel;
+
+ node = rb_objc_method_node2(mod, sel, &imp);
+
+ if (pimp != NULL)
+ *pimp = imp;
+
+ if (imp == NULL) {
+ char buf[512];
+ strlcpy(buf, (char *)sel, sizeof buf);
+ if (buf[strlen(buf) - 1] == ':')
+ return NULL;
+ strlcat(buf, ":", sizeof buf);
+ return rb_objc_method_node2(mod, sel_registerName(buf), pimp);
+ }
+
+ return node;
+}
+
void
-rb_objc_sync_ruby_method(VALUE mod, ID mid, NODE *node, unsigned override)
+rb_objc_register_ruby_method(VALUE mod, ID mid, NODE *body)
{
SEL sel;
- Class ocklass;
Method method;
char *types;
- int arity;
+ int arity, oc_arity;
char *mid_str;
IMP imp;
bool direct_override;
+ NODE *node;
+ VALUE included_in_classes;
+ int included_in_classes_count = - 1;
- /* Do not expose C functions. */
- if (bs_functions != NULL
- && mod == CLASS_OF(rb_mKernel)
- && st_lookup(bs_functions, (st_data_t)mid, NULL))
- return;
+#define forward_method_definition(ary,sel,imp,types) \
+ do { \
+ if (included_in_classes != Qnil) { \
+ int i; \
+ if (included_in_classes_count == -1) \
+ included_in_classes_count = RARRAY_LEN(included_in_classes); \
+ for (i = 0; i < included_in_classes_count; i++) { \
+ VALUE k = RARRAY_AT(included_in_classes, i); \
+ Method m = class_getInstanceMethod((Class)k, sel); \
+ DLOG("DEFI", "-[%s %s]", class_getName((Class)k), (char *)sel); \
+ if (m != NULL) { \
+ Method m2 = class_getInstanceMethod((Class)RCLASS_SUPER(k), sel); \
+ if (m != m2) { \
+ method_setImplementation(m, imp); \
+ break; \
+ } \
+ } \
+ assert(class_addMethod((Class)k, sel, imp, types)); \
+ } \
+ } \
+ } \
+ while (0)
- arity = rb_node_arity(node);
- mid_str = (char *)rb_id2name(mid);
+ if (body != NULL) {
+ if (nd_type(body) != NODE_METHOD)
+ rb_bug("non-method node (%d)", nd_type(body));
- if (arity < 0) {
- //printf("mid %s has negative arity %d\n", mid_str, arity);
- return;
+ node = body->nd_body;
+ arity = oc_arity = rb_node_arity(node);
}
+ else {
+ node = NULL;
+ arity = oc_arity = 0;
+ }
- if (arity == 1 && mid_str[strlen(mid_str) - 1] != ':') {
+ if (mid == ID_ALLOCATOR) {
+ mid_str = "alloc";
+ }
+ else {
+ mid_str = (char *)rb_id2name(mid);
+ }
+
+ included_in_classes = RCLASS_MODULE(mod) ? rb_ivar_get(mod, idIncludedInClasses) : Qnil;
+
+ if ((arity < 0 || arity > 0) && mid_str[strlen(mid_str) - 1] != ':') {
char buf[100];
snprintf(buf, sizeof buf, "%s:", mid_str);
sel = sel_registerName(buf);
+ oc_arity = 1;
}
else {
sel = sel_registerName(mid_str);
}
- ocklass = RCLASS_OCID(mod);
direct_override = false;
- method = class_getInstanceMethod(ocklass, sel);
+ method = class_getInstanceMethod((Class)mod, sel);
if (method != NULL) {
- void *klass;
- if (!override)
- return;
+ Class klass;
/* Do not override certain NSObject selectors. */
if (sel == @selector(superclass)
|| sel == @selector(hash)
|| sel == @selector(zone)) {
- klass = RCLASS_OCID(rb_cBasicObject);
- if (class_getInstanceMethod(klass, sel) == method)
+ if (class_getInstanceMethod((Class)rb_cBasicObject, sel) == method)
return;
}
- if (arity >= 0 && arity + 2 != method_getNumberOfArguments(method)) {
- rb_warning("cannot override Objective-C method `%s' in " \
+ if (oc_arity + 2 != method_getNumberOfArguments(method)) {
+printf("method %p\n",method);
+ rb_warn("cannot override Objective-C method `%s' in " \
"class `%s' because of an arity mismatch (%d for %d)",
- (char *)sel,
- class_getName(ocklass),
- arity + 2,
+ (char *)method_getName(method),
+ class_getName((Class)mod),
+ oc_arity + 2,
method_getNumberOfArguments(method));
return;
}
types = (char *)method_getTypeEncoding(method);
- klass = class_getSuperclass(ocklass);
+ klass = (Class)RCLASS_SUPER(mod);
direct_override =
klass == NULL || class_getInstanceMethod(klass, sel) != method;
}
else {
- struct st_table *t = class_isMetaClass(ocklass)
+ struct st_table *t = class_isMetaClass((Class)mod)
? bs_inf_prot_cmethods
: bs_inf_prot_imethods;
if (t == NULL || !st_lookup(t, (st_data_t)sel, (st_data_t *)&types)) {
- types = (char *)alloca((arity + 4) * sizeof(char));
- types[0] = '@';
- types[1] = '@';
- types[2] = ':';
- memset(&types[3], '@', arity);
- types[arity + 3] = '\0';
+ if (oc_arity == 0) {
+ types = "@@:";
+ }
+ else if (oc_arity == 1) {
+ types = "@@:@";
+ }
+ else {
+ int i;
+ types = alloca(3 + oc_arity + 1);
+ types[0] = '@';
+ types[1] = '@';
+ types[2] = ':';
+ for (i = 0; i < oc_arity; i++)
+ types[3 + i] = '@';
+ types[3 + oc_arity] = '\0';
+ }
}
}
-// printf("registering sel %s of types %s arity %d to class %s\n",
-// (char *)sel, types, arity, class_getName(ocklass));
+ DLOG("DEFM", "%c[%s %s] types=%s arity=%d body=%p override=%d direct_override=%d",
+ class_isMetaClass((Class)mod) ? '+' : '-', class_getName((Class)mod), (char *)sel, types, arity, body, method != NULL, direct_override);
- imp = rb_ruby_to_objc_closure(types, arity, node);
-
- if (method != NULL && direct_override) {
- method_setImplementation(method, imp);
+ if (node == NULL) {
+ assert(class_addMethod((Class)mod, sel, NULL, types));
+ forward_method_definition(included_in_classes, sel, NULL, types);
}
else {
- assert(class_addMethod(ocklass, sel, imp, types));
- }
-}
+ const char *sel_str = (const char *)sel;
+ const size_t sel_len = strlen(sel_str);
+ SEL new_sel;
+ char *new_types;
+ bool override;
-static int
-__rb_objc_add_ruby_method(ID mid, NODE *body, VALUE mod)
-{
- if (mid == ID_ALLOCATOR)
- return ST_CONTINUE;
-
- if (body == NULL || body->nd_body->nd_body == NULL)
- return ST_CONTINUE;
+ imp = rb_ruby_to_objc_closure(types, oc_arity, body);
- if ((body->nd_body->nd_noex & NOEX_MASK) != NOEX_PUBLIC)
- return ST_CONTINUE;
+ if (method != NULL && direct_override) {
+ method_setImplementation(method, imp);
+ }
+ else {
+ assert(class_addMethod((Class)mod, sel, imp, types));
+ }
+ forward_method_definition(included_in_classes, sel, imp, types);
- rb_objc_sync_ruby_method(mod, mid, body->nd_body->nd_body, 0);
+ if (sel_str[sel_len - 1] == ':') {
+ char buf[512];
+ strlcpy(buf, sel_str, sizeof buf);
+ assert(sizeof buf > sel_len);
+ buf[sel_len - 1] = '\0';
+ new_sel = sel_registerName(buf);
+ new_types = "@@:";
+ override = arity == -1;
+ arity = 0;
+ }
+ else {
+ char buf[512];
+ strlcpy(buf, sel_str, sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+ new_sel = sel_registerName(buf);
+ new_types = "@@:@";
+ override = false;
+ arity = -1;
+ }
- return ST_CONTINUE;
-}
-
-void
-rb_objc_sync_ruby_methods(VALUE mod, VALUE klass)
-{
- for (;;) {
- st_foreach(RCLASS_M_TBL(mod), __rb_objc_add_ruby_method,
- (st_data_t)klass);
- mod = RCLASS_SUPER(mod);
- if (mod == 0 || BUILTIN_TYPE(mod) != T_ICLASS)
- break;
+ method = class_getInstanceMethod((Class)mod, new_sel);
+ direct_override = false;
+ if (method != NULL || override) {
+ direct_override = method != NULL && class_getInstanceMethod((Class)RCLASS_SUPER(mod), new_sel) != method;
+ DLOG("DEFM", "%c[%s %s] types=%s arity=%d body=%p override=%d direct_override=%d",
+ class_isMetaClass((Class)mod) ? '+' : '-', class_getName((Class)mod), (char *)new_sel, new_types, arity, body, method != NULL, direct_override);
+ if (method != NULL && direct_override) {
+ method_setImplementation(method, imp);
+ }
+ else {
+ assert(class_addMethod((Class)mod, new_sel, imp, new_types));
+ }
+ forward_method_definition(included_in_classes, new_sel, imp, new_types);
+ }
}
}
-static inline unsigned
-is_ignored_selector(SEL sel)
-{
-#if defined(__ppc__)
- return sel == (SEL)0xfffef000;
-#elif defined(__i386__)
- return sel == (SEL)0xfffeb010;
-#else
-# error Unsupported arch
-#endif
-}
-
-#if 0
-static void
-__rb_objc_sync_methods(VALUE mod, Class ocklass)
-{
- Method *methods;
- unsigned int i, count;
- char buffer[128];
- VALUE imod;
-
- methods = class_copyMethodList(ocklass, &count);
-
- imod = mod;
-#if 0
- for (;;) {
- st_foreach(RCLASS_M_TBL(imod), __rb_objc_add_ruby_method,
- (st_data_t)mod);
- imod = RCLASS_SUPER(imod);
- if (imod == 0 || BUILTIN_TYPE(imod) != T_ICLASS)
- break;
- }
-#endif
-
- for (i = 0; i < count; i++) {
- SEL sel;
- ID mid;
- st_data_t data;
- NODE *node;
-
- sel = method_getName(methods[i]);
- if (is_ignored_selector(sel))
- continue;
-#if IGNORE_PRIVATE_OBJC_METHODS
- if (*(char *)sel == '_')
- continue;
-#endif
-
- rb_objc_sel_to_mid(sel, buffer, sizeof buffer);
- mid = rb_intern(buffer);
-
- if (rb_method_boundp(mod, mid, 1) == Qtrue)
- continue;
-
- node = NEW_CFUNC(rb_objc_to_ruby_closure(methods[i]), -2);
- data = (st_data_t)NEW_FBODY(NEW_METHOD(node, mod,
- NOEX_WITH_SAFE(NOEX_PUBLIC)), 0);
-
- st_insert(RCLASS_M_TBL(mod), mid, data);
- }
-
- free(methods);
-}
-#endif
-
-NODE *
-rb_objc_define_objc_mid_closure(VALUE recv, ID mid, ID alias_mid)
-{
- SEL sel;
- Class ocklass;
- Method method;
- VALUE mod;
- NODE *node, *data;
- Method (*getMethod)(Class, SEL);
-
- assert(mid > 1);
-
- sel = sel_registerName(rb_id2name(mid));
-
- if (!rb_special_const_p(recv) && !rb_objc_is_non_native(recv)
- && TYPE(recv) == T_CLASS) {
- mod = recv;
- getMethod = class_getClassMethod;
- }
- else {
- mod = CLASS_OF(recv);
- getMethod = class_getInstanceMethod;
- }
-
- ocklass = RCLASS_OCID(mod);
-
- if (class_isMetaClass(ocklass))
- return NULL;
-
- method = (*getMethod)(ocklass, sel);
- if (method == NULL || method_getImplementation(method) == NULL)
- return NULL; /* recv doesn't respond to this selector */
-
- do {
- Class ocsuper = class_getSuperclass(ocklass);
- if ((*getMethod)(ocsuper, sel) == NULL) /* != method */
- break;
- ocklass = ocsuper;
- }
- while (1);
-
- if (RCLASS(mod)->ocklass != ocklass) {
- mod = rb_objc_import_class(ocklass);
- if (TYPE(recv) == T_CLASS)
- mod = CLASS_OF(mod);
- }
-
- /* Already defined. */
- node = rb_method_node(mod, mid);
- if (node != NULL)
- return node;
-
- node = NEW_CFUNC(rb_objc_to_ruby_closure, -1);
- data = NEW_FBODY(NEW_METHOD(node, mod,
- NOEX_WITH_SAFE(NOEX_PUBLIC)), 0);
-
- rb_add_method_direct(mod, mid, data);
-
- if (alias_mid != 0)
- rb_add_method_direct(mod, alias_mid, data);
-
- return data->nd_body;
-}
-
-#if 0
-rb_objc_sync_objc_methods_into(VALUE mod, Class ocklass)
-{
- /* Load instance methods */
- __rb_objc_sync_methods(mod, ocklass);
-
- /* Load class methods */
- __rb_objc_sync_methods(rb_singleton_class(mod),
- object_getClass((id)ocklass));
-}
-
-void
-rb_objc_sync_objc_methods(VALUE mod)
-{
- rb_objc_sync_objc_methods_into(mod, RCLASS_OCID(mod));
-}
-#endif
-
VALUE
rb_mod_objc_ancestors(VALUE recv)
{
- void *klass;
+ Class klass;
VALUE ary;
ary = rb_ary_new();
- for (klass = RCLASS(recv)->ocklass; klass != NULL;
+ for (klass = (Class)recv; klass != NULL;
klass = class_getSuperclass(klass)) {
rb_ary_push(ary, rb_str_new2(class_getName(klass)));
}
@@ -1697,29 +1756,6 @@
return ary;
}
-void
-rb_objc_methods(VALUE ary, Class ocklass)
-{
- while (ocklass != NULL) {
- unsigned i, count;
- Method *methods;
-
- methods = class_copyMethodList(ocklass, &count);
- if (methods != NULL) {
- for (i = 0; i < count; i++) {
- SEL sel = method_getName(methods[i]);
- if (is_ignored_selector(sel))
- continue;
- rb_ary_push(ary, ID2SYM(rb_intern(sel_getName(sel))));
- }
- free(methods);
- }
- ocklass = class_getSuperclass(ocklass);
- }
-
- rb_funcall(ary, rb_intern("uniq!"), 0);
-}
-
static bool
rb_objc_resourceful(VALUE obj)
{
@@ -1833,15 +1869,10 @@
"constant `%s'", bs_const->name);
rb_objc_ocval_to_rbval(sym, bs_const->type, &v);
-
- /* To avoid a runtime warning when re-defining the constant, we remove
- * its entry from the table before.
- */
- klass = rb_cObject;
- assert(RCLASS_IV_TBL(klass) != NULL);
- assert(st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&id, NULL));
- rb_const_set(klass, id, v);
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
+ assert(iv_dict != NULL);
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)v);
}
return v;
@@ -2592,18 +2623,19 @@
}
static void
-rb_install_objc_primitives(void)
+rb_install_boxed_primitives(void)
{
Class klass;
/* Boxed */
- klass = RCLASS_OCID(rb_cBoxed);
+ klass = (Class)rb_cBoxed;
rb_objc_install_method(klass, @selector(objCType),
(IMP)imp_rb_boxed_objCType);
rb_objc_install_method(klass, @selector(getValue:),
(IMP)imp_rb_boxed_getValue);
}
+#if 0
static void *
rb_objc_allocate(void *klass)
{
@@ -2640,6 +2672,7 @@
rb_objc_install_method(RCLASS_OCID(rb_cObject), @selector(init),
(IMP)imp_rb_obj_init);
}
+#endif
ID
rb_objc_missing_sel(ID mid, int arity)
@@ -2686,8 +2719,6 @@
return mid;
}
- //printf("new sel %s for %s\n", buf, name);
-
return rb_intern(buf);
}
@@ -2787,7 +2818,7 @@
strlcat(buf, &symname[1], sizeof buf);
strlcat(buf, ":", sizeof buf);
- if (!class_addMethod(RCLASS_OCID(recv), sel_registerName(buf),
+ if (!class_addMethod((Class)recv, sel_registerName(buf),
(IMP)rb_objc_ib_outlet_imp, "v@:@"))
rb_raise(rb_eArgError,
"can't register `%s' (method %s) as an IB outlet",
@@ -3084,6 +3115,7 @@
rb_define_singleton_method(rb_cBoxed, "objc_type", rb_boxed_objc_type, 0);
rb_define_singleton_method(rb_cBoxed, "opaque?", rb_boxed_is_opaque, 0);
rb_define_singleton_method(rb_cBoxed, "fields", rb_boxed_fields, 0);
+ rb_install_boxed_primitives();
rb_cPointer = rb_define_class("Pointer", rb_cObject);
rb_undef_alloc_func(rb_cPointer);
@@ -3091,8 +3123,7 @@
rb_ivar_type = rb_intern("@__objc_type__");
- rb_install_objc_primitives();
- rb_install_alloc_methods();
+ //rb_install_alloc_methods();
rb_define_global_function("load_bridge_support_file", rb_objc_load_bs, 1);
@@ -3106,6 +3137,9 @@
rb_define_method(rb_cBasicObject, "__super_objc_send__", rb_super_objc_send, -1);
}
+// for debug in gdb
+int __rb_type(VALUE v) { return TYPE(v); }
+
@interface Protocol
@end
Modified: MacRuby/branches/lrz_unstable/object.c
===================================================================
--- MacRuby/branches/lrz_unstable/object.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/object.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -126,12 +126,16 @@
VALUE
rb_class_real(VALUE cl)
{
+#if WITH_OBJC
+ return cl;
+#else
if (cl == 0)
return 0;
while ((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS) {
cl = RCLASS_SUPER(cl);
}
return cl;
+#endif
}
/*
@@ -158,7 +162,7 @@
init_copy(VALUE dest, VALUE obj)
{
#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
if (rb_objc_flag_check((const void *)obj, FL_TAINT))
rb_objc_flag_set((const void *)dest, FL_TAINT, true);
goto call_init_copy;
@@ -173,6 +177,35 @@
rb_gc_copy_finalizer(dest, obj);
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ ROBJECT(dest)->ivars.type = ROBJECT(obj)->ivars.type;
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ GC_WB(&ROBJECT(dest)->ivars.as.ary,
+ (struct rb_ivar_ary_entry *)xmalloc(
+ sizeof(struct rb_ivar_ary_entry)
+ * RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars)));
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ ROBJECT(dest)->ivars.as.ary[i].name = ROBJECT(obj)->ivars.as.ary[i].name;
+ GC_WB(&ROBJECT(dest)->ivars.as.ary[i].value, ROBJECT(obj)->ivars.as.ary[i].value);
+ }
+ }
+ break;
+
+ case RB_IVAR_TBL:
+ {
+ CFMutableDictionaryRef new_tbl;
+ new_tbl = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl);
+ assert(new_tbl != NULL);
+ GC_WB(&ROBJECT(dest)->ivars.as.tbl, new_tbl);
+ CFMakeCollectable(new_tbl);
+ }
+ break;
+ }
+ break;
+#else
if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
xfree(ROBJECT_IVPTR(dest));
ROBJECT(dest)->as.heap.ivptr = 0;
@@ -192,9 +225,29 @@
ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
RBASIC(dest)->flags &= ~ROBJECT_EMBED;
}
+#endif
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef dest_dict, obj_dict;
+
+ obj_dict = rb_class_ivar_dict(obj);
+ dest_dict = rb_class_ivar_dict(dest);
+ if (dest_dict != NULL)
+ CFDictionaryRemoveAllValues(dest_dict);
+ if (obj_dict != NULL) {
+ dest_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)obj_dict);
+ CFMakeCollectable(dest_dict);
+ rb_class_ivar_set_dict(dest, dest_dict);
+ }
+ else {
+ if (dest_dict)
+ rb_class_ivar_set_dict(dest, NULL);
+ }
+ }
+#else
if (RCLASS_IV_TBL(dest)) {
st_free_table(RCLASS_IV_TBL(dest));
RCLASS_IV_TBL(dest) = 0;
@@ -202,6 +255,7 @@
if (RCLASS_IV_TBL(obj)) {
RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
}
+#endif
break;
}
call_init_copy:
@@ -241,7 +295,7 @@
rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
}
#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
clone = rb_obj_alloc(rb_obj_class(obj));
init_copy(clone, obj);
if (OBJ_FROZEN(obj))
@@ -250,9 +304,6 @@
}
#endif
clone = rb_obj_alloc(rb_obj_class(obj));
-#if WITH_OBJC
- RBASIC(clone)->isa = RBASIC(obj)->isa;
-#endif
RBASIC(clone)->klass = rb_singleton_class_clone(obj);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
init_copy(clone, obj);
@@ -406,6 +457,30 @@
if (TYPE(obj) == T_OBJECT) {
int has_ivar = 0;
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i, len = RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars);
+ if (len == 0)
+ break;
+ for (i = 0; i < len; i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].value != Qundef) {
+ has_ivar = 1;
+ break;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ has_ivar =
+ CFDictionaryGetCount(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl)
+ > 0;
+ break;
+ }
+#else
VALUE *ptr = ROBJECT_IVPTR(obj);
long len = ROBJECT_NUMIV(obj);
long i;
@@ -416,6 +491,7 @@
break;
}
}
+#endif
if (has_ivar) {
VALUE str;
@@ -496,7 +572,11 @@
}
while (cl) {
+#if WITH_OBJC
+ if (cl == c) // TODO check included modules
+#else
if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
+#endif
return Qtrue;
cl = RCLASS_SUPER(cl);
}
@@ -677,7 +757,7 @@
rb_obj_tainted(VALUE obj)
{
#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
return rb_objc_flag_check((const void *)obj, FL_TAINT) ? Qtrue : Qfalse;
}
#endif
@@ -700,7 +780,7 @@
{
rb_secure(4);
#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_TAINT, true);
return obj;
}
@@ -727,7 +807,7 @@
{
rb_secure(3);
#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_TAINT, false);
return obj;
}
@@ -772,6 +852,7 @@
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
+ int type;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
}
@@ -783,9 +864,12 @@
st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
}
#if WITH_OBJC
- else if (rb_objc_is_non_native(obj)) {
+ else if (NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
}
+ else if ((type = TYPE(obj)) == T_CLASS || type == T_MODULE) {
+ RCLASS_SET_VERSION_FLAG(obj, RCLASS_IS_FROZEN);
+ }
#endif
else {
FL_SET(obj, FL_FREEZE);
@@ -814,11 +898,15 @@
return Qfalse;
}
#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
return rb_objc_is_immutable(obj)
|| rb_objc_flag_check((const void *)obj, FL_FREEZE)
? Qtrue : Qfalse;
}
+ int type = TYPE(obj);
+ if (type == T_CLASS || type == T_MODULE) {
+ return (RCLASS_VERSION(obj) & RCLASS_IS_FROZEN) == RCLASS_IS_FROZEN ? Qtrue : Qfalse;
+ }
#endif
if (FL_TEST(obj, FL_FREEZE)) return Qtrue;
return Qfalse;
@@ -1155,7 +1243,7 @@
static VALUE
rb_mod_to_s(VALUE klass)
{
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
VALUE s = rb_usascii_str_new2("#<");
VALUE v = rb_iv_get(klass, "__attached__");
@@ -1220,7 +1308,9 @@
VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
+#if !WITH_OBJC
VALUE start = mod;
+#endif
if (mod == arg) return Qtrue;
switch (TYPE(arg)) {
@@ -1230,6 +1320,8 @@
default:
rb_raise(rb_eTypeError, "compared with non class/module");
}
+#if WITH_OBJC // TODO
+#else
while (mod) {
if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg))
return Qtrue;
@@ -1241,6 +1333,7 @@
return Qfalse;
arg = RCLASS_SUPER(arg);
}
+#endif
return Qnil;
}
@@ -1416,8 +1509,7 @@
}
RCLASS_SUPER(klass) = super;
#if WITH_OBJC
- class_setSuperclass(RCLASS(klass)->ocklass, RCLASS(super)->ocklass);
- rb_objc_install_primitives(RCLASS(klass)->ocklass, RCLASS(super)->ocklass);
+ rb_objc_install_primitives((Class)klass, (Class)super);
#endif
rb_make_metaclass(klass, RBASIC(super)->klass);
rb_class_inherited(super, klass);
@@ -1443,7 +1535,7 @@
if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_raise(rb_eTypeError, "can't create instance of singleton class");
}
obj = rb_funcall(klass, ID_ALLOCATOR, 0, 0);
@@ -1480,7 +1572,7 @@
{
VALUE obj;
-#if WITH_OBJC
+#if 0//WITH_OBJC
if (FL_TEST(klass, RCLASS_OBJC_IMPORTED)) {
static SEL sel_new = 0;
if (sel_new == 0)
@@ -1720,9 +1812,6 @@
args[0] = Qtrue;
ary = rb_class_instance_methods(1, args, CLASS_OF(obj));
-#if WITH_OBJC
- rb_objc_methods(ary, RCLASS(CLASS_OF(obj))->ocklass);
-#endif
return ary;
}
else {
@@ -2361,13 +2450,12 @@
#if WITH_OBJC
static VALUE
-rb_obj_is_pure(VALUE recv)
+rb_obj_is_native(VALUE recv)
{
- return rb_objc_is_non_native(recv) ? Qtrue : Qfalse;
+ return NATIVE(recv) ? Qtrue : Qfalse;
}
#endif
-
/*
* Document-class: Class
*
@@ -2453,7 +2541,8 @@
VALUE metaclass;
#if WITH_OBJC
- rb_cBasicObject = rb_objc_import_class((Class)objc_getClass("NSObject"));
+ rb_cBasicObject = boot_defclass("BasicObject", rb_objc_import_class((Class)objc_getClass("NSObject")));
+ RCLASS_SET_VERSION_FLAG(rb_cBasicObject, RCLASS_IS_OBJECT_SUBCLASS);
#else
rb_cBasicObject = boot_defclass("BasicObject", 0);
#endif
@@ -2461,13 +2550,24 @@
rb_cModule = boot_defclass("Module", rb_cObject);
rb_cClass = boot_defclass("Class", rb_cModule);
+#if WITH_OBJC
+ metaclass = 0; // eliminate warning
+ RCLASS_SUPER(*(Class *)RCLASS_SUPER(rb_cBasicObject)) = rb_cClass;
+ //metaclass = boot_defclass("MetaClass", rb_cClass);
+ //RCLASS_SUPER(*(Class *)rb_cBasicObject) = rb_cClass;//metaclass;
+#else
metaclass = rb_make_metaclass(rb_cBasicObject, rb_cClass);
metaclass = rb_make_metaclass(rb_cObject, metaclass);
metaclass = rb_make_metaclass(rb_cModule, metaclass);
metaclass = rb_make_metaclass(rb_cClass, metaclass);
+#endif
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
+#if WITH_OBJC
+ // required because otherwise NSObject.new will be first in the method chain.
+ rb_define_singleton_method(rb_cBasicObject, "new", rb_class_new_instance, -1);
+#endif
rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);
rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0);
@@ -2478,11 +2578,7 @@
rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy, 1);
rb_mKernel = rb_define_module("Kernel");
-#if WITH_OBJC
- rb_include_module(rb_cBasicObject, rb_mKernel);
-#else
rb_include_module(rb_cObject, rb_mKernel);
-#endif
rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
@@ -2496,7 +2592,9 @@
rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
+#if !WITH_OBJC // defined in NSObject
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
+#endif
rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
@@ -2527,7 +2625,7 @@
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
#if WITH_OBJC
- rb_define_method(rb_mKernel, "__pure__?", rb_obj_is_pure, 0);
+ rb_define_method(rb_mKernel, "__native__?", rb_obj_is_native, 0);
#endif
rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
Modified: MacRuby/branches/lrz_unstable/parse.y
===================================================================
--- MacRuby/branches/lrz_unstable/parse.y 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/parse.y 2008-07-30 02:27:07 UTC (rev 382)
@@ -8711,6 +8711,14 @@
n->nd_mid = rb_intern(buf);
n->nd_args = new_argv;
}
+ else if (args != NULL && args->nd_argc >= 1) {
+ char buf[512];
+
+ strlcpy(buf, rb_id2name(n->u2.id), sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+
+ n->nd_mid = rb_intern(buf);
+ }
return n;
}
Modified: MacRuby/branches/lrz_unstable/proc.c
===================================================================
--- MacRuby/branches/lrz_unstable/proc.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/proc.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -757,7 +757,7 @@
}
while (rclass != klass &&
- (FL_TEST(rclass, FL_SINGLETON) || TYPE(rclass) == T_ICLASS)) {
+ (RCLASS_SINGLETON(rclass) || TYPE(rclass) == T_ICLASS)) {
rclass = RCLASS_SUPER(rclass);
}
if (TYPE(klass) == T_ICLASS)
@@ -1080,7 +1080,7 @@
struct METHOD *method = (struct METHOD *)DATA_PTR(body);
VALUE rclass = method->rclass;
if (rclass != mod) {
- if (FL_TEST(rclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(rclass)) {
rb_raise(rb_eTypeError,
"can't bind singleton method to a different class");
}
@@ -1299,7 +1299,7 @@
Data_Get_Struct(method, struct METHOD, data);
if (data->rclass != CLASS_OF(recv)) {
- if (FL_TEST(data->rclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(data->rclass)) {
rb_raise(rb_eTypeError,
"singleton method called for a different object");
}
@@ -1435,7 +1435,7 @@
rb_str_buf_cat2(str, s);
rb_str_buf_cat2(str, ": ");
- if (FL_TEST(data->oclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(data->oclass)) {
VALUE v = rb_iv_get(data->oclass, "__attached__");
if (data->recv == Qundef) {
Modified: MacRuby/branches/lrz_unstable/string.c
===================================================================
--- MacRuby/branches/lrz_unstable/string.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/string.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -478,7 +478,7 @@
&& klass != rb_cString
&& klass != rb_cStringRuby
&& klass != rb_cSymbol)
- *(Class *)str = RCLASS_OCID(klass);
+ *(Class *)str = (Class)klass;
CFMakeCollectable((CFTypeRef)str);
#else
NEWOBJ(str, struct RString);
@@ -8378,11 +8378,10 @@
}
#if WITH_OBJC
-#define NSCFSTRING() (RCLASS_OCID(rb_cCFString))
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFSTRING();
+ *(Class *)x = (Class)rb_cCFString;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -8390,7 +8389,7 @@
bool
rb_objc_str_is_pure(VALUE str)
{
- return *(Class *)str == NSCFSTRING();
+ return *(Class *)str == (Class)rb_cCFString;
}
static CFIndex
@@ -8521,7 +8520,6 @@
rb_cString = rb_objc_import_class((Class)objc_getClass("NSString"));
rb_cStringRuby =
rb_objc_import_class((Class)objc_getClass("NSMutableString"));
- FL_UNSET(rb_cStringRuby, RCLASS_OBJC_IMPORTED);
rb_const_set(rb_cObject, rb_intern("String"), rb_cStringRuby);
rb_define_method(rb_cString, "__bytestring__?", rb_str_bytestring_m, 0);
#else
Modified: MacRuby/branches/lrz_unstable/thread.c
===================================================================
--- MacRuby/branches/lrz_unstable/thread.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/thread.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -3102,7 +3102,7 @@
if (TYPE(klass) == T_ICLASS) {
klass = RBASIC(klass)->klass;
}
- else if (FL_TEST(klass, FL_SINGLETON)) {
+ else if (RCLASS_SINGLETON(klass)) {
klass = rb_iv_get(klass, "__attached__");
}
}
Modified: MacRuby/branches/lrz_unstable/variable.c
===================================================================
--- MacRuby/branches/lrz_unstable/variable.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/variable.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -19,9 +19,6 @@
void rb_vm_change_state(void);
st_table *rb_global_tbl;
st_table *rb_class_tbl;
-#if WITH_OBJC
-st_table *rb_objc_class_tbl;
-#endif
static ID autoload, classpath, tmp_classpath;
void
@@ -31,10 +28,6 @@
GC_ROOT(&rb_global_tbl);
rb_class_tbl = st_init_numtable();
GC_ROOT(&rb_class_tbl);
-#if WITH_OBJC
- rb_objc_class_tbl = st_init_numtable();
- GC_ROOT(&rb_objc_class_tbl);
-#endif
autoload = rb_intern("__autoload__");
classpath = rb_intern("__classpath__");
tmp_classpath = rb_intern("__tmp_classpath__");
@@ -56,8 +49,12 @@
path = rb_str_dup(rb_id2str(name));
while (fc) {
if (fc->track == rb_cObject) break;
+#if WITH_OBJC
+ if ((tmp = rb_attr_get(fc->track, classpath)) != Qnil) {
+#else
if (RCLASS_IV_TBL(fc->track) &&
st_lookup(RCLASS_IV_TBL(fc->track), classpath, &tmp)) {
+#endif
tmp = rb_str_dup(tmp);
rb_str_cat2(tmp, "::");
rb_str_append(tmp, path);
@@ -86,7 +83,13 @@
switch (TYPE(value)) {
case T_MODULE:
case T_CLASS:
+ {
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(value);
+ if (iv_dict == NULL) return ST_CONTINUE;
+#else
if (!RCLASS_IV_TBL(value)) return ST_CONTINUE;
+#endif
else {
struct fc_result arg;
struct fc_result *list;
@@ -102,13 +105,18 @@
arg.klass = res->klass;
arg.track = value;
arg.prev = res;
+#if WITH_OBJC
+ rb_hash_foreach((VALUE)iv_dict, fc_i, (VALUE)&arg);
+#else
st_foreach(RCLASS_IV_TBL(value), fc_i, (st_data_t)&arg);
+#endif
if (arg.path) {
res->path = arg.path;
return ST_STOP;
}
}
break;
+ }
default:
break;
@@ -126,18 +134,32 @@
arg.klass = klass;
arg.track = rb_cObject;
arg.prev = 0;
+
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
+ if (iv_dict != NULL) {
+ rb_hash_foreach((VALUE)iv_dict, fc_i, (VALUE)&arg);
+ }
+#else
if (RCLASS_IV_TBL(rb_cObject)) {
st_foreach_safe(RCLASS_IV_TBL(rb_cObject), fc_i, (st_data_t)&arg);
}
+#endif
if (arg.path == 0) {
st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
}
if (arg.path) {
+#if WITH_OBJC
+ iv_dict = rb_class_ivar_dict_or_create(klass);
+ CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)arg.path);
+ CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
+#else
if (!RCLASS_IV_TBL(klass)) {
GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
}
st_insert(RCLASS_IV_TBL(klass), classpath, arg.path);
st_delete(RCLASS_IV_TBL(klass), &tmp_classpath, 0);
+#endif
return arg.path;
}
return Qnil;
@@ -149,6 +171,25 @@
VALUE path = Qnil;
if (!klass) klass = rb_cObject;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
+ if (iv_dict != NULL) {
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)classpath, (const void **)&path)) {
+
+ static ID classid = 0;
+ if (classid == 0)
+ classid = rb_intern("__classid__");
+
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)classid, (const void **)&path))
+ return find_class_path(klass);
+
+ path = rb_str_dup(rb_id2str(SYM2ID(path)));
+ OBJ_FREEZE(path);
+ CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)path);
+ CFDictionaryRemoveValue(iv_dict, (const void *)classid);
+#else
if (RCLASS_IV_TBL(klass)) {
if (!st_lookup(RCLASS_IV_TBL(klass), classpath, &path)) {
ID classid = rb_intern("__classid__");
@@ -160,12 +201,11 @@
OBJ_FREEZE(path);
st_insert(RCLASS_IV_TBL(klass), classpath, path);
st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&classid, 0);
+#endif
}
-#if !WITH_OBJC
if (TYPE(path) != T_STRING) {
rb_bug("class path is not set properly");
}
-#endif
return path;
}
return find_class_path(klass);
@@ -193,8 +233,12 @@
VALUE path = classname(klass);
if (!NIL_P(path)) return path;
+#if WITH_OBJC
+ if ((path = rb_attr_get(klass, tmp_classpath)) != Qnil) {
+#else
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
tmp_classpath, &path)) {
+#endif
return path;
}
else {
@@ -1078,21 +1122,115 @@
#endif
}
+#if WITH_OBJC
+# define RCLASS_RUBY_IVAR_DICT(mod) (*(CFMutableDictionaryRef *)((void *)mod + class_getInstanceSize(*(Class *)RCLASS_SUPER(mod))))
+CFMutableDictionaryRef
+rb_class_ivar_dict(VALUE mod)
+{
+ CFMutableDictionaryRef dict;
+
+ if (RCLASS_RUBY(mod)) {
+ dict = RCLASS_RUBY_IVAR_DICT(mod);
+ }
+ else {
+ dict = NULL;
+ if (generic_iv_dict != NULL) {
+ CFDictionaryGetValueIfPresent(generic_iv_dict,
+ (const void *)mod, (const void **)&dict);
+ }
+ }
+ return dict;
+}
+
+void
+rb_class_ivar_set_dict(VALUE mod, CFMutableDictionaryRef dict)
+{
+ if (RCLASS_RUBY(mod)) {
+ CFMutableDictionaryRef old_dict = RCLASS_RUBY_IVAR_DICT(mod);
+ if (old_dict != dict) {
+ if (old_dict != NULL)
+ CFRelease(old_dict);
+ CFRetain(dict);
+ RCLASS_RUBY_IVAR_DICT(mod) = dict;
+ }
+ }
+ else {
+ if (generic_iv_dict == NULL) {
+ CFDictionaryValueCallBacks values_cb;
+
+ memset(&values_cb, 0, sizeof(values_cb));
+ values_cb.retain = rb_cfdictionary_retain_cb;
+ values_cb.release = rb_cfdictionary_release_cb;
+
+ generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ }
+ CFDictionarySetValue(generic_iv_dict, (const void *)mod, (const void *)dict);
+ }
+}
+
+CFMutableDictionaryRef
+rb_class_ivar_dict_or_create(VALUE mod)
+{
+ CFMutableDictionaryRef dict;
+
+ dict = rb_class_ivar_dict(mod);
+ if (dict == NULL) {
+ CFDictionaryValueCallBacks values_cb;
+
+ memset(&values_cb, 0, sizeof(values_cb));
+ values_cb.retain = rb_cfdictionary_retain_cb;
+ values_cb.release = rb_cfdictionary_release_cb;
+
+ dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ rb_class_ivar_set_dict(mod, dict);
+ CFMakeCollectable(dict);
+ }
+ return dict;
+}
+#endif
+
static VALUE
ivar_get(VALUE obj, ID id, int warn)
{
- VALUE val, *ptr;
+ VALUE val;
+#if !WITH_OBJC
+ VALUE *ptr;
struct st_table *iv_index_tbl;
long len;
st_data_t index;
+#endif
#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj))
+ if (!rb_special_const_p(obj) && NATIVE(obj))
return generic_ivar_get(obj, id, warn);
#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ val = Qundef;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ break;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (!CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id,
+ (const void **)val))
+ val = Qundef;
+ break;
+ }
+#else
len = ROBJECT_NUMIV(obj);
ptr = ROBJECT_IVPTR(obj);
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
@@ -1100,13 +1238,24 @@
if (!st_lookup(iv_index_tbl, id, &index)) break;
if (len <= index) break;
val = ptr[index];
+#endif
if (val != Qundef)
return val;
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL
+ && CFDictionaryGetValueIfPresent(
+ iv_dict, (const void *)id, (const void **)&val))
+ return val;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, &val))
return val;
+#endif
break;
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
@@ -1134,16 +1283,18 @@
VALUE
rb_ivar_set(VALUE obj, ID id, VALUE val)
{
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
long i, len;
int ivar_extended;
+#endif
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");
#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj)) {
+ if (!rb_special_const_p(obj) && NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
generic_ivar_set(obj, id, val);
return val;
@@ -1151,6 +1302,78 @@
#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i, len;
+ bool new_ivar;
+
+ len = RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars);
+ new_ivar = true;
+
+ if (len == 0) {
+ assert(ROBJECT(obj)->ivars.as.ary == NULL);
+ GC_WB(&ROBJECT(obj)->ivars.as.ary,
+ (struct rb_ivar_ary_entry *)xmalloc(
+ sizeof(struct rb_ivar_ary_entry)));
+ }
+ else {
+ assert(ROBJECT(obj)->ivars.as.ary != NULL);
+ for (i = 0; i < len; i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].value == Qundef) {
+ ROBJECT(obj)->ivars.as.ary[i].name = id;
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[i].value, val);
+ new_ivar = false;
+ break;
+ }
+ else if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[i].value, val);
+ new_ivar = false;
+ break;
+ }
+ }
+ }
+ if (new_ivar) {
+ if (len + 1 == RB_IVAR_ARY_MAX) {
+ CFMutableDictionaryRef tbl;
+ CFDictionaryValueCallBacks values_cb;
+
+ memset(&values_cb, 0, sizeof(values_cb));
+ values_cb.retain = rb_cfdictionary_retain_cb;
+ values_cb.release = rb_cfdictionary_release_cb;
+
+ tbl = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+
+ for (i = 0; i < len; i++)
+ CFDictionarySetValue(tbl,
+ (const void *)ROBJECT(obj)->ivars.as.ary[i].name,
+ (const void *)ROBJECT(obj)->ivars.as.ary[i].value);
+
+ xfree(ROBJECT(obj)->ivars.as.ary);
+ GC_WB(&ROBJECT(obj)->ivars.as.tbl, tbl);
+ RB_IVAR_SET_TYPE(ROBJECT(obj)->ivars, RB_IVAR_TBL);
+ }
+ else {
+ if (len > 0) {
+ struct rb_ivar_ary_entry *ary;
+ ary = ROBJECT(obj)->ivars.as.ary;
+ REALLOC_N(ary, struct rb_ivar_ary_entry, len + 1);
+ GC_WB(&ROBJECT(obj)->ivars.as.ary, ary);
+ }
+ ROBJECT(obj)->ivars.as.ary[len].name = id;
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[len].value, val);
+ RB_IVAR_ARY_SET_LEN(ROBJECT(obj)->ivars, len + 1);
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ CFDictionarySetValue(ROBJECT(obj)->ivars.as.tbl, (const void *)id, (const void *)val);
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) {
VALUE klass = rb_obj_class(obj);
@@ -1200,14 +1423,23 @@
}
}
GC_WB(&ROBJECT_IVPTR(obj)[index], val);
+#endif
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(obj);
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
+ break;
+ }
+#else
if (!RCLASS_IV_TBL(obj)) {
GC_WB(&RCLASS_IV_TBL(obj), st_init_numtable());
}
st_insert(RCLASS_IV_TBL(obj), id, val);
break;
+#endif
default:
generic_ivar_set(obj, id, val);
FL_SET(obj, FL_EXIVAR);
@@ -1220,28 +1452,64 @@
rb_ivar_defined(VALUE obj, ID id)
{
VALUE val;
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
+#endif
+
#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj)) {
+ if (!rb_special_const_p(obj) && NATIVE(obj)) {
return generic_ivar_defined(obj, id);
}
#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ val = Qundef;
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ break;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id, NULL))
+ val = Qtrue;
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, id, &index)) break;
if (ROBJECT_NUMIV(obj) <= index) break;
val = ROBJECT_IVPTR(obj)[index];
+#endif
if (val != Qundef)
return Qtrue;
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, NULL))
+ return Qtrue;
+ break;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, 0))
return Qtrue;
break;
+#endif
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
return generic_ivar_defined(obj, id);
@@ -1256,6 +1524,7 @@
st_data_t arg;
};
+#if !WITH_OBJC
static int
obj_ivar_i(ID key, VALUE index, struct obj_ivar_tag *data)
{
@@ -1284,22 +1553,52 @@
st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
}
+#endif
void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
{
#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj))
+ if (!rb_special_const_p(obj) && NATIVE(obj))
goto generic;
#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if ((*func)(ROBJECT(obj)->ivars.as.ary[i].name,
+ ROBJECT(obj)->ivars.as.ary[i].value, arg)
+ != ST_CONTINUE)
+ break;
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ CFDictionaryApplyFunction(ROBJECT(obj)->ivars.as.tbl,
+ (CFDictionaryApplierFunction)func, (void *)arg);
+ break;
+ }
+#else
obj_ivar_each(obj, func, arg);
+#endif
return;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL)
+ rb_hash_foreach((VALUE)iv_dict, func, arg);
+ }
+#else
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
}
+#endif
return;
}
if (!FL_TEST(obj, FL_EXIVAR) && !rb_special_const_p(obj))
@@ -1390,8 +1689,10 @@
{
VALUE val = Qnil;
ID id = rb_to_id(name);
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
+#endif
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
@@ -1402,6 +1703,33 @@
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ ROBJECT(obj)->ivars.as.ary[i].value = Qundef;
+ return val;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id,
+ (const void **)val)) {
+ CFDictionaryRemoveValue(ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id);
+ return val;
+ }
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, id, &index)) break;
@@ -1411,13 +1739,25 @@
ROBJECT_IVPTR(obj)[index] = Qundef;
return val;
}
+#endif
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ return val;
+ }
+ break;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t*)&id, &val)) {
return val;
}
break;
+#endif
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
if (generic_ivar_remove(obj, id, &val)) {
@@ -1486,14 +1826,15 @@
return Qnil; /* not reached */
}
+#if WITH_OBJC
+static void *rb_mark_tbl = (void *)0x42;
+#endif
+
static struct st_table *
check_autoload_table(VALUE av)
{
Check_Type(av, T_DATA);
- if (
-#if !WITH_OBJC
- RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
-#endif
+ if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
VALUE desc = rb_inspect(av);
rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING_PTR(desc));
@@ -1514,21 +1855,29 @@
rb_raise(rb_eArgError, "empty file name");
}
+#if WITH_OBJC
+ if ((av = rb_attr_get(mod, id)) != Qnil && av != Qundef)
+#else
if ((tbl = RCLASS_IV_TBL(mod)) && st_lookup(tbl, id, &av) && av != Qundef)
+#endif
return;
rb_const_set(mod, id, Qundef);
+#if WITH_OBJC
+ if ((av = rb_attr_get(mod, autoload)) != Qnil) {
+#else
tbl = RCLASS_IV_TBL(mod);
if (st_lookup(tbl, autoload, &av)) {
+#endif
tbl = check_autoload_table(av);
}
else {
+ av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
#if WITH_OBJC
- av = Data_Wrap_Struct(0, NULL, st_free_table, 0);
+ rb_ivar_set(mod, autoload, av);
#else
- av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
+ st_add_direct(tbl, autoload, av);
#endif
- st_add_direct(tbl, autoload, av);
DATA_PTR(av) = tbl = st_init_numtable();
}
fn = rb_str_new2(file);
@@ -1543,8 +1892,16 @@
VALUE val;
st_data_t load = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ assert(iv_dict != NULL);
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)autoload, (const void **)&val)) {
+#else
st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, 0);
if (st_lookup(RCLASS_IV_TBL(mod), autoload, &val)) {
+#endif
struct st_table *tbl = check_autoload_table(val);
st_delete(tbl, (st_data_t*)&id, &load);
@@ -1553,9 +1910,13 @@
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
+#if WITH_OBJC
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
rb_gc_force_recycle(val);
}
+#endif
}
}
@@ -1581,10 +1942,20 @@
struct st_table *tbl;
st_data_t load;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ assert(iv_dict != NULL);
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)autoload, (const void **)&val)
+ || (tbl = check_autoload_table(val)) == NULL
+ || !st_lookup(tbl, id, &load))
+ return Qnil;
+#else
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
!(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
return Qnil;
}
+#endif
file = ((NODE *)load)->nd_lit;
Check_Type(file, T_STRING);
if (RSTRING_LEN(file) == 0) {
@@ -1600,9 +1971,13 @@
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
+#if WITH_OBJC
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
rb_gc_force_recycle(val);
}
+#endif
}
return Qnil;
}
@@ -1610,12 +1985,22 @@
VALUE
rb_autoload_p(VALUE mod, ID id)
{
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = (CFDictionaryRef)rb_class_ivar_dict(mod);
+ VALUE val;
+
+ if (iv_dict == NULL
+ || !CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)
+ || val != Qundef)
+ return Qnil;
+#else
struct st_table *tbl = RCLASS_IV_TBL(mod);
VALUE val;
if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
return Qnil;
}
+#endif
return autoload_file(mod, id);
}
@@ -1628,7 +2013,11 @@
tmp = klass;
retry:
while (RTEST(tmp)) {
+#if WITH_OBJC
+ while ((value = rb_attr_get(tmp, id)) != Qnil) {
+#else
while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) {
+#endif
if (value == Qundef) {
if (!RTEST(rb_autoload_load(tmp, id))) break;
continue;
@@ -1712,7 +2101,13 @@
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
+#endif
if (val == Qundef) {
autoload_delete(mod, id);
val = Qnil;
@@ -1746,9 +2141,15 @@
if (!tbl) {
tbl = st_init_numtable();
}
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL)
+ rb_hash_foreach((VALUE)iv_dict, sv_i, (VALUE)tbl);
+#else
if (RCLASS_IV_TBL(mod)) {
st_foreach_safe(RCLASS_IV_TBL(mod), sv_i, (st_data_t)tbl);
}
+#endif
return tbl;
}
@@ -1831,7 +2232,13 @@
tmp = klass;
retry:
while (tmp) {
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(tmp);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict,
+ (const void *)id, (const void **)&value)) {
+#else
if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) {
+#endif
if (value == Qundef && NIL_P(autoload_file(klass, id)))
return Qfalse;
return Qtrue;
@@ -1880,13 +2287,22 @@
rb_error_frozen("class");
}
}
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(klass);
+#else
if (!RCLASS_IV_TBL(klass)) {
GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
}
- else if (isconst) {
+ else
+#endif
+ if (isconst) {
VALUE value = Qfalse;
+#if WITH_OBJC
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&value)) {
+#else
if (st_lookup(RCLASS_IV_TBL(klass), id, &value)) {
+#endif
if (value == Qundef)
autoload_delete(klass, id);
else
@@ -1894,10 +2310,14 @@
}
}
- if(isconst){
+ if (isconst) {
rb_vm_change_state();
}
+#if WITH_OBJC
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
+#else
st_insert(RCLASS_IV_TBL(klass), id, val);
+#endif
}
void
@@ -1938,11 +2358,17 @@
return c;
}
+#if WITH_OBJC
+# define IV_LOOKUP(k,i,v) ((iv_dict = rb_class_ivar_dict(k)) != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)i, (const void **)(v)))
+#else
+# define IV_LOOKUP(k,i,v) (RCLASS_IV_TBL(k) && st_lookup(RCLASS_IV_TBL(k),(i),(v)))
+#endif
+
#define CVAR_LOOKUP(v,r) do {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
+ if (IV_LOOKUP(klass, id, v)) {\
r;\
}\
- if (FL_TEST(klass, FL_SINGLETON) ) {\
+ if (RCLASS_SINGLETON(klass)) {\
VALUE obj = rb_iv_get(klass, "__attached__");\
switch (TYPE(obj)) {\
case T_MODULE:\
@@ -1958,7 +2384,7 @@
klass = RCLASS_SUPER(klass);\
}\
while (klass) {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
+ if (IV_LOOKUP(klass, id, v)) {\
r;\
}\
klass = RCLASS_SUPER(klass);\
@@ -1969,6 +2395,9 @@
rb_cvar_set(VALUE klass, ID id, VALUE val)
{
VALUE tmp, front = 0, target = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
tmp = klass;
CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
@@ -1981,8 +2410,12 @@
rb_id2name(id), rb_class2name(original_module(front)),
rb_class2name(original_module(target)));
}
- if (BUILTIN_TYPE(front) == T_CLASS) {
+ if (TYPE(front) == T_CLASS) {
+#if WITH_OBJC
+ CFDictionaryRemoveValue(rb_class_ivar_dict(front), (const void *)did);
+#else
st_delete(RCLASS_IV_TBL(front),&did,0);
+#endif
}
}
}
@@ -1996,6 +2429,9 @@
rb_cvar_get(VALUE klass, ID id)
{
VALUE value, tmp, front = 0, target = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
tmp = klass;
CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
@@ -2012,7 +2448,11 @@
rb_class2name(original_module(target)));
}
if (BUILTIN_TYPE(front) == T_CLASS) {
+#if WITH_OBJC
+ CFDictionaryRemoveValue(rb_class_ivar_dict(front), (const void *)did);
+#else
st_delete(RCLASS_IV_TBL(front),&did,0);
+#endif
}
}
return value;
@@ -2021,6 +2461,9 @@
VALUE
rb_cvar_defined(VALUE klass, ID id)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
if (!klass) return Qfalse;
CVAR_LOOKUP(0,return Qtrue);
return Qfalse;
@@ -2090,9 +2533,15 @@
{
VALUE ary = rb_ary_new();
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL)
+ rb_hash_foreach((VALUE)iv_dict, cv_i, (VALUE)ary);
+#else
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary);
}
+#endif
return ary;
}
@@ -2129,9 +2578,17 @@
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ return val;
+ }
+#else
if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
return val;
}
+#endif
if (rb_cvar_defined(mod, id)) {
rb_name_error(id, "cannot remove %s for %s",
rb_id2name(id), rb_class2name(mod));
Modified: MacRuby/branches/lrz_unstable/vm.c
===================================================================
--- MacRuby/branches/lrz_unstable/vm.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/vm.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -14,10 +14,6 @@
#include "ruby/encoding.h"
#include "gc.h"
-#if WITH_OBJC
-NODE *rb_current_cfunc_node = NULL;
-#endif
-
#include "insnhelper.h"
#include "vm_insnhelper.c"
#include "vm_eval.c"
@@ -852,6 +848,12 @@
/* optimization: redefine management */
VALUE ruby_vm_redefined_flag = 0;
+#if WITH_OBJC
+static void
+rb_vm_check_redefinition_opt_method(const NODE *node)
+{
+}
+#else
static st_table *vm_opt_method_table = 0;
static void
@@ -876,10 +878,12 @@
rb_bug("undefined optimized method: %s", rb_id2name(mid));
}
}
+#endif
static void
vm_init_redefined_flag(void)
{
+#if !WITH_OBJC
ID mid;
VALUE bop;
@@ -899,16 +903,13 @@
OP(LTLT, LTLT), (C(String), C(Array));
OP(AREF, AREF), (C(Array), C(Hash));
OP(ASET, ASET), (C(Array), C(Hash));
-#if WITH_OBJC
- OP(Length, LENGTH), (C(Array), C(Hash));
-#else
OP(Length, LENGTH), (C(Array), C(String), C(Hash));
-#endif
OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
OP(GT, GT), (C(Fixnum));
OP(GE, GE), (C(Fixnum));
#undef C
#undef OP
+#endif
}
/* evaluator body */
Modified: MacRuby/branches/lrz_unstable/vm_eval.c
===================================================================
--- MacRuby/branches/lrz_unstable/vm_eval.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/vm_eval.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -72,13 +72,7 @@
cfp->method_id = id;
cfp->method_class = klass;
-#if WITH_OBJC
- rb_current_cfunc_node = (NODE *)body;
-#endif
val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
-#if WITH_OBJC
- rb_current_cfunc_node = NULL;
-#endif
if (reg_cfp != th->cfp + 1) {
SDR2(reg_cfp);
@@ -188,42 +182,38 @@
NODE *body, *method;
int noex;
ID id = mid;
+#if !WITH_OBJC
struct cache_entry *ent;
- rb_thread_t *th = GET_THREAD();
-#if WITH_OBJC
- unsigned redo = 0;
#endif
+ rb_thread_t *th = GET_THREAD();
-rb_call0_redo:
-
-#if WITH_OBJC
-# define REDO_PERHAPS() \
- do { \
- if (!redo && mid != missing) { \
- ID newid = rb_objc_missing_sel(mid, argc); \
- if (newid != mid) { \
- id = mid = newid; \
- redo = 1; \
- goto rb_call0_redo; \
- } \
- } \
- } \
- while (0)
-#else
-# define REDO_PERHAPS()
-#endif
-
if (!klass) {
rb_raise(rb_eNotImpError,
"method `%s' called on terminated object (%p)",
rb_id2name(mid), (void *)recv);
}
+
+#if WITH_OBJC
+ IMP imp;
+ SEL sel;
+
+ method = rb_objc_method_node(klass, mid, &imp, &sel);
+
+ if (imp != NULL && method == NULL) {
+ printf("OBJC_CALL!\n");
+ assert(1==0);
+ }
+ else if (method != NULL) {
+ noex = method->nd_noex;
+ klass = method->nd_clss;
+ body = method->nd_body;
+ }
+#else
/* is it in the method cache? */
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
if (!ent->method) {
- REDO_PERHAPS();
return method_missing(recv, mid, argc, argv,
scope == 2 ? NOEX_VCALL : 0);
}
@@ -237,8 +227,8 @@
klass = method->nd_clss;
body = method->nd_body;
}
+#endif
else {
- REDO_PERHAPS();
if (scope == 3) {
return method_missing(recv, mid, argc, argv, NOEX_SUPER);
}
@@ -246,7 +236,6 @@
scope == 2 ? NOEX_VCALL : 0);
}
-
if (mid != missing) {
/* receiver specified form for private method */
if (UNLIKELY(noex)) {
Modified: MacRuby/branches/lrz_unstable/vm_insnhelper.c
===================================================================
--- MacRuby/branches/lrz_unstable/vm_insnhelper.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/vm_insnhelper.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -371,13 +371,7 @@
reg_cfp->sp -= num + 1;
-#if WITH_OBJC
- rb_current_cfunc_node = (NODE *)mn;
-#endif
val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1);
-#if WITH_OBJC
- rb_current_cfunc_node = NULL;
-#endif
if (reg_cfp != th->cfp + 1) {
rb_bug("cfp consistency error - send");
@@ -488,10 +482,50 @@
static inline VALUE
vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
const int num, rb_block_t * const blockptr, const VALUE flag,
- const ID id, const NODE * mn, const VALUE recv, VALUE klass)
+ const ID id, const NODE * mn, const VALUE recv, VALUE klass,
+ SEL sel)
{
VALUE val;
+#if WITH_OBJC
+ IMP imp;
+#define STUPID_CACHE 0
+
+#if STUPID_CACHE
+static VALUE c_klass = 0;
+static IMP c_imp = 0;
+static NODE *c_mn = NULL;
+
+if (c_klass == klass) {
+imp = c_imp;
+mn = c_mn;
+}
+else {
+#endif
+
+ NODE *rb_objc_method_node2(VALUE mod, SEL sel, IMP *pimp);
+
+ if (sel == 0)
+ mn = rb_objc_method_node(klass, id, &imp, &sel);
+ else
+ mn = rb_objc_method_node2(klass, sel, &imp);
+
+#if STUPID_CACHE
+c_klass = klass;
+c_imp = imp;
+c_mn = (NODE*)mn;
+}
+#endif
+
+ if (mn == NULL && imp != NULL) {
+ printf("OBJC_CALL %p %s %p %p\n",(void*)klass,(char*)sel,mn,imp);
+ assert(1==0);
+ return Qnil;
+ }
+
+ DLOG("RCALL", "[<%s %p> %s] node=%p", class_getName((Class)klass), (void *)recv, (char *)sel, mn);
+#endif
+
start_method_dispatch:
if (mn != 0) {
@@ -594,7 +628,7 @@
}
else {
int stat = 0;
-#if WITH_OBJC
+#if 0//WITH_OBJC
mn = rb_objc_define_objc_mid_closure(recv, id, 0);
if (mn != NULL) {
return vm_call_method(th, cfp, num, blockptr, flag, id,
@@ -997,6 +1031,9 @@
VALUE orig_klass, ID id, int is_defined)
{
VALUE val;
+#if WITH_OBJC
+ CFDictionaryRef iv_dict;
+#endif
if (orig_klass == Qnil) {
/* in current lexical scope */
@@ -1010,8 +1047,13 @@
if (!NIL_P(klass)) {
search_continue:
+#if WITH_OBJC
+ iv_dict = (CFDictionaryRef)rb_class_ivar_dict(klass);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)) {
+#else
if (RCLASS_IV_TBL(klass) &&
st_lookup(RCLASS_IV_TBL(klass), id, &val)) {
+#endif
if (val == Qundef) {
rb_autoload_load(klass, id);
goto search_continue;
@@ -1057,7 +1099,7 @@
{
VALUE klass;
- while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
+ while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || RCLASS_SINGLETON(cref->nd_clss))) {
cref = cref->nd_next;
if (!cref->nd_next) {
@@ -1114,7 +1156,7 @@
INC_VM_STATE_VERSION();
}
-#if WITH_OBJC
+#if 0//TODO WITH_OBJC
static inline void
vm_method_process_named_args(ID *pid, NODE **pmn, VALUE recv, rb_num_t *pnum,
rb_control_frame_t *cfp)
Modified: MacRuby/branches/lrz_unstable/vm_method.c
===================================================================
--- MacRuby/branches/lrz_unstable/vm_method.c 2008-07-30 02:24:49 UTC (rev 381)
+++ MacRuby/branches/lrz_unstable/vm_method.c 2008-07-30 02:27:07 UTC (rev 382)
@@ -62,6 +62,7 @@
}
}
+#if !WITH_OBJC
static void
rb_clear_cache_by_id(ID id)
{
@@ -80,6 +81,7 @@
ent++;
}
}
+#endif
void
rb_clear_cache_by_class(VALUE klass)
@@ -100,18 +102,7 @@
}
}
-#if WITH_OBJC
-void rb_objc_sync_ruby_method(VALUE, ID, NODE*, unsigned);
-#endif
-
void
-rb_add_method_direct(VALUE klass, ID mid, NODE *node)
-{
- rb_clear_cache_by_id(mid);
- st_insert(RCLASS_M_TBL(klass), (st_data_t)mid, (st_data_t)node);
-}
-
-void
rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
{
NODE *body;
@@ -122,12 +113,12 @@
if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
rb_raise(rb_eSecurityError, "Insecure: can't define method");
}
- if (!FL_TEST(klass, FL_SINGLETON) &&
+ if (!RCLASS_SINGLETON(klass) &&
node && nd_type(node) != NODE_ZSUPER &&
(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
noex = NOEX_PRIVATE | noex;
}
- else if (FL_TEST(klass, FL_SINGLETON) && node
+ else if (RCLASS_SINGLETON(klass) && node
&& nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
rb_warn
("defining %s.allocate is deprecated; use rb_define_alloc_func()",
@@ -137,7 +128,9 @@
if (OBJ_FROZEN(klass)) {
rb_error_frozen("class/module");
}
+#if !WITH_OBJC
rb_clear_cache_by_id(mid);
+#endif
/*
* NODE_METHOD (NEW_METHOD(body, klass, vis)):
@@ -157,6 +150,7 @@
body = 0;
}
+#if !WITH_OBJC // TODO
{
/* check re-definition */
st_data_t data;
@@ -184,18 +178,16 @@
}
}
}
+#endif
+#if WITH_OBJC
+ rb_objc_register_ruby_method(klass, mid, body != NULL ? body->nd_body : NULL);
+#else
st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
-
-#if WITH_OBJC
- if (node != NULL && noex == NOEX_PUBLIC) {
- unsigned override = !FL_TEST(klass, FL_SINGLETON);
- rb_objc_sync_ruby_method(klass, mid, node, override);
- }
#endif
if (node && mid != ID_ALLOCATOR && ruby_running) {
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
ID2SYM(mid));
}
@@ -236,6 +228,17 @@
static NODE *
search_method(VALUE klass, ID id, VALUE *klassp)
{
+#if WITH_OBJC
+ NODE *node;
+ if (klass == 0)
+ return NULL;
+ node = rb_objc_method_node(klass, id, NULL, NULL);
+ if (node != NULL) {
+ if (klassp != NULL) /* TODO honour klassp */
+ *klassp = klass;
+ }
+ return node;
+#else
st_data_t body;
if (!klass) {
@@ -253,6 +256,7 @@
}
return (NODE *)body;
+#endif
}
/*
@@ -266,6 +270,9 @@
NODE *
rb_get_method_body(VALUE klass, ID id, ID *idp)
{
+#if WITH_OBJC
+ return search_method(klass, id, NULL);
+#else
NODE *volatile fbody, *body;
NODE *method;
@@ -301,11 +308,15 @@
}
return body;
+#endif
}
NODE *
rb_method_node(VALUE klass, ID id)
{
+#if WITH_OBJC
+ return rb_objc_method_node(klass, id, NULL, NULL);
+#else
struct cache_entry *ent;
ent = cache + EXPR1(klass, id);
@@ -314,12 +325,15 @@
}
return rb_get_method_body(klass, id, 0);
+#endif
}
static void
remove_method(VALUE klass, ID mid)
{
+#if !WITH_OBJC
st_data_t data;
+#endif
NODE *body = 0;
if (klass == rb_cObject) {
@@ -333,6 +347,9 @@
if (mid == object_id || mid == __send__ || mid == idInitialize) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
+#if WITH_OBJC
+ // TODO
+#else
if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
body = (NODE *)data;
if (!body || !body->nd_body) body = 0;
@@ -340,6 +357,7 @@
st_delete(RCLASS_M_TBL(klass), &mid, &data);
}
}
+#endif
if (!body) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
@@ -350,7 +368,7 @@
}
rb_clear_cache_for_undef(klass, mid);
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
ID2SYM(mid));
}
@@ -408,10 +426,23 @@
if (klass == rb_cObject) {
rb_secure(4);
}
+#if WITH_OBJC
+ fbody = rb_method_node(klass, name);
+ if (fbody == NULL && TYPE(klass) == T_MODULE) {
+ fbody = rb_method_node(rb_cObject, name);
+ origin = rb_method_node(rb_cObject, name) == fbody
+ ? rb_cObject : klass;
+ }
+ else {
+ origin = rb_method_node(RCLASS_SUPER(klass), name) == fbody
+ ? RCLASS_SUPER(klass) : klass;
+ }
+#else
fbody = search_method(klass, name, &origin);
if (!fbody && TYPE(klass) == T_MODULE) {
fbody = search_method(rb_cObject, name, &origin);
}
+#endif
if (!fbody || !fbody->nd_body) {
rb_print_undef(klass, name, 0);
}
@@ -503,7 +534,7 @@
#if WITH_OBJC
/* TODO: we should only warn regarding important NSObject methods that
are necessary by the GC to call finalizers. */
- if (class_respondsToSelector(RCLASS_OCID(rb_cBasicObject),
+ if (class_respondsToSelector((Class)rb_cBasicObject,
sel_registerName(rb_id2name(id)))) {
rb_warn("undefining `NSObject#%s' may cause serious problem",
rb_id2name(id));
@@ -514,7 +545,7 @@
const char *s0 = " class";
VALUE c = klass;
- if (FL_TEST(c, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(c)) {
VALUE obj = rb_iv_get(klass, "__attached__");
switch (TYPE(obj)) {
@@ -527,27 +558,13 @@
else if (TYPE(c) == T_MODULE) {
s0 = " module";
}
-#if WITH_OBJC
- if (!class_respondsToSelector(RCLASS(klass)->ocklass,
- sel_registerName(rb_id2name(id))))
-#endif
rb_name_error(id, "undefined method `%s' for%s `%s'",
rb_id2name(id), s0, rb_class2name(c));
}
rb_add_method(klass, id, 0, NOEX_PUBLIC);
-#if WITH_OBJC
- {
- Method method;
- method = class_getInstanceMethod(RCLASS(klass)->ocklass,
- sel_registerName(rb_id2name(id)));
- if (method != NULL)
- method_setImplementation(method, NULL);
- }
-#endif
-
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"),
singleton_undefined, 1, ID2SYM(id));
}
@@ -766,14 +783,22 @@
void
rb_alias(VALUE klass, ID name, ID def)
{
+#if !WITH_OBJC
NODE *orig_fbody, *node;
+ st_data_t data;
+#endif
VALUE singleton = 0;
- st_data_t data;
rb_frozen_class_p(klass);
if (klass == rb_cObject) {
rb_secure(4);
}
+#if WITH_OBJC
+ if (RCLASS_SINGLETON(klass)) {
+ singleton = rb_iv_get(klass, "__attached__");
+ }
+ rb_objc_alias(klass, name, def);
+#else
orig_fbody = search_method(klass, def, 0);
if (!orig_fbody || !orig_fbody->nd_body) {
if (TYPE(klass) == T_MODULE) {
@@ -807,13 +832,9 @@
orig_fbody->nd_body->nd_clss,
NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
-#if WITH_OBJC
- if (orig_fbody->nd_body->nd_noex == NOEX_PUBLIC)
- rb_objc_sync_ruby_method(klass, name, orig_fbody->nd_body->nd_body, 0);
+ rb_clear_cache_by_id(name);
#endif
- rb_clear_cache_by_id(name);
-
if (!ruby_running) return;
if (singleton) {
@@ -1104,6 +1125,10 @@
int
rb_obj_respond_to(VALUE obj, ID id, int priv)
{
+#if WITH_OBJC
+ SEL sel = sel_registerName(rb_id2name(id));
+ return class_respondsToSelector(*(Class *)obj, sel);
+#else
VALUE klass = CLASS_OF(obj);
if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
@@ -1117,6 +1142,7 @@
args[n++] = Qtrue;
return RTEST(rb_funcall2(obj, idRespond_to, n, args));
}
+#endif
}
int
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080729/f1101d1c/attachment-0001.html
More information about the macruby-changes
mailing list