[macruby-changes] [459] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Aug 20 23:13:14 PDT 2008


Revision: 459
          http://trac.macosforge.org/projects/ruby/changeset/459
Author:   lsansonetti at apple.com
Date:     2008-08-20 23:13:14 -0700 (Wed, 20 Aug 2008)
Log Message:
-----------
merging lrz_unstable branch

Modified Paths:
--------------
    MacRuby/trunk/Rakefile
    MacRuby/trunk/array.c
    MacRuby/trunk/bignum.c
    MacRuby/trunk/bs.c
    MacRuby/trunk/class.c
    MacRuby/trunk/compile.c
    MacRuby/trunk/debug.h
    MacRuby/trunk/encoding.c
    MacRuby/trunk/eval.c
    MacRuby/trunk/ext/extmk.rb
    MacRuby/trunk/ext/syck/rubyext.c
    MacRuby/trunk/gc.c
    MacRuby/trunk/hash.c
    MacRuby/trunk/id.c
    MacRuby/trunk/id.h
    MacRuby/trunk/include/ruby/defines.h
    MacRuby/trunk/include/ruby/intern.h
    MacRuby/trunk/include/ruby/node.h
    MacRuby/trunk/include/ruby/ruby.h
    MacRuby/trunk/insnhelper.h
    MacRuby/trunk/insns.def
    MacRuby/trunk/instruby.rb
    MacRuby/trunk/io.c
    MacRuby/trunk/lib/delegate.rb
    MacRuby/trunk/lib/fileutils.rb
    MacRuby/trunk/marshal.c
    MacRuby/trunk/numeric.c
    MacRuby/trunk/objc.m
    MacRuby/trunk/object.c
    MacRuby/trunk/parse.y
    MacRuby/trunk/proc.c
    MacRuby/trunk/process.c
    MacRuby/trunk/re.c
    MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb
    MacRuby/trunk/signal.c
    MacRuby/trunk/st.c
    MacRuby/trunk/string.c
    MacRuby/trunk/struct.c
    MacRuby/trunk/thread.c
    MacRuby/trunk/variable.c
    MacRuby/trunk/version.c
    MacRuby/trunk/version.h
    MacRuby/trunk/vm.c
    MacRuby/trunk/vm_core.h
    MacRuby/trunk/vm_eval.c
    MacRuby/trunk/vm_insnhelper.c
    MacRuby/trunk/vm_method.c

Modified: MacRuby/trunk/Rakefile
===================================================================
--- MacRuby/trunk/Rakefile	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/Rakefile	2008-08-21 06:13:14 UTC (rev 459)
@@ -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', true)
 
 # 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/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/array.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,25 +1,23 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's array.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  array.c -
-
-  $Author: matz $
-  created at: Fri Aug  6 09:46:12 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-  Copyright (C) 2000  Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/util.h"
 #include "ruby/st.h"
+#include "id.h"
 
 VALUE rb_cArray;
-#if WITH_OBJC
 VALUE rb_cCFArray;
-VALUE rb_cArrayRuby;
-#endif
+VALUE rb_cNSArray;
+VALUE rb_cNSMutableArray;
 
 static ID id_cmp;
 
@@ -33,15 +31,6 @@
     }
 }
 
-static inline void
-memfill(register VALUE *mem, register long size, register VALUE val)
-{
-    while (size--) {
-	*mem++ = val;
-    }
-}
-
-#if WITH_OBJC
 /* TODO optimize this */
 struct rb_objc_ary_struct {
     void *cptr;
@@ -69,24 +58,7 @@
     }
     return s;
 }
-#else
-#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
 
-#define ARY_SET_LEN(ary, n) do { \
-    RARRAY(ary)->len = (n);\
-} while (0) 
-
-#define ARY_CAPA(ary) RARRAY(ary)->aux.capa
-#define RESIZE_CAPA(ary,capacity) do {\
-    REALLOC_N(RARRAY(ary)->ptr, VALUE, (capacity));\
-    RARRAY(ary)->aux.capa = (capacity);\
-} while (0)
-#endif
-
-VALUE rb_ary_frozen_p(VALUE ary);
-
-#if WITH_OBJC
-
 static inline void
 rb_ary_modify_check(VALUE ary)
 {
@@ -104,32 +76,6 @@
 }
 #define rb_ary_modify rb_ary_modify_check
 
-#else
-
-static inline void
-rb_ary_modify_check(VALUE ary)
-{
-    if (OBJ_FROZEN(ary)) rb_error_frozen("array");
-    if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: can't modify array");
-}
-
-static void
-rb_ary_modify(VALUE ary)
-{
-    VALUE *ptr;
-
-    rb_ary_modify_check(ary);
-    if (ARY_SHARED_P(ary)) {
-	ptr = ALLOC_N(VALUE, RARRAY_LEN(ary));
-	FL_UNSET(ary, ELTS_SHARED);
-	RARRAY(ary)->aux.capa = RARRAY_LEN(ary);
-	MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
-	RARRAY(ary)->ptr = ptr;
-    }
-}
-#endif
-
 VALUE
 rb_ary_freeze(VALUE ary)
 {
@@ -151,62 +97,21 @@
     return Qfalse;
 }
 
-#if WITH_OBJC
-int rb_any_cmp(VALUE a, VALUE b);
+void rb_ary_insert(VALUE ary, long idx, VALUE val);
 
-static Boolean
-rb_cfarray_equal_cb(const void *v1, const void *v2)
-{
-    return !rb_any_cmp((VALUE)v1, (VALUE)v2);
-}
-
-static const void *
-rb_cfarray_retain_cb(CFAllocatorRef allocator, const void *v)
-{
-    rb_objc_retain(v);
-    return v;
-}
-
-static void
-rb_cfarray_release_cb(CFAllocatorRef allocator, const void *v)
-{
-    rb_objc_release(v);
-}
-
-static void
-rb_ary_insert(VALUE ary, long idx, VALUE val);
-#endif
-
 static VALUE
 ary_alloc(VALUE klass)
 {
-#if WITH_OBJC
-    VALUE ary;
-    CFArrayCallBacks cb;
+    CFMutableArrayRef ary;
 
-    memset(&cb, 0, sizeof(CFArrayCallBacks));
-    cb.retain = rb_cfarray_retain_cb;
-    cb.release = rb_cfarray_release_cb;
-    cb.equal = rb_cfarray_equal_cb;
+    ary = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    if (klass != 0 && klass != rb_cNSArray && klass != rb_cNSMutableArray)
+	*(Class *)ary = (Class)klass;
 
-    ary = (VALUE)CFArrayCreateMutable(NULL, 0, &cb);
-    if (klass != 0 && klass != rb_cArray && klass != rb_cArrayRuby)
-        *(Class *)ary = RCLASS_OCID(klass);
-
-    CFMakeCollectable((CFTypeRef)ary);
+    CFMakeCollectable(ary);
     rb_gc_malloc_increase(sizeof(void *));
-    
-    return ary;
-#else
-    NEWOBJ(ary, struct RArray);
-    OBJSETUP(ary, klass, T_ARRAY);
 
-    ary->len = 0;
-    ary->ptr = 0;
-    ary->aux.capa = 0;
-
     return (VALUE)ary;
-#endif
 }
 
 static VALUE
@@ -221,11 +126,6 @@
 	rb_raise(rb_eArgError, "array size too big");
     }
     ary = ary_alloc(klass);
-#if !WITH_OBJC
-    if (len == 0) len++;
-    GC_WB(&RARRAY(ary)->ptr, ALLOC_N(VALUE, len));
-    RARRAY(ary)->aux.capa = len;
-#endif
 
     return ary;
 }
@@ -233,11 +133,7 @@
 VALUE
 rb_ary_new2(long len)
 {
-#if WITH_OBJC
     return ary_new(0, len);
-#else
-    return ary_new(rb_cArray, len);
-#endif
 }
 
 
@@ -264,9 +160,6 @@
     }
     va_end(ar);
 
-#if !WITH_OBJC
-    RARRAY(ary)->len = n;
-#endif
     return ary;
 }
 
@@ -277,51 +170,16 @@
 
     ary = rb_ary_new2(n);
     if (n > 0 && elts) {
-#if WITH_OBJC
-	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)elts, n);
-#else
-	MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
-	RARRAY(ary)->len = n;
-#endif
+	long i;
+	void **vals = (void **)alloca(n * sizeof(void *));
+	for (i = 0; i < n; i++)
+	    vals[i] = RB2OC(elts[i]);
+	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)vals, n);
     }
 
     return ary;
 }
 
-void
-rb_ary_free(VALUE ary)
-{
-#if WITH_OBJC
-    rb_notimplement();
-#else
-    if (!ARY_SHARED_P(ary)) {
-	xfree(RARRAY(ary)->ptr);
-    }
-#endif
-}
-
-#if !WITH_OBJC
-static VALUE
-ary_make_shared(VALUE ary)
-{
-    if (ARY_SHARED_P(ary)) {
-	return RARRAY(ary)->aux.shared;
-    }
-    else {
-	NEWOBJ(shared, struct RArray);
-	OBJSETUP(shared, 0, T_ARRAY);
-
-	shared->len = RARRAY(ary)->len;
-	shared->ptr = RARRAY(ary)->ptr;
-	shared->aux.capa = RARRAY(ary)->aux.capa;
-	RARRAY(ary)->aux.shared = (VALUE)shared;
-	FL_SET(ary, ELTS_SHARED);
-	OBJ_FREEZE(shared);
-	return (VALUE)shared;
-    }
-}
-#endif
-
 VALUE
 rb_assoc_new(VALUE car, VALUE cdr)
 {
@@ -410,14 +268,9 @@
     long len;
     VALUE size, val;
 
-    rb_ary_modify(ary);
+    ary = (VALUE)objc_msgSend((id)ary, selInit);
+
     if (argc ==  0) {
-#if !WITH_OBJC
-	if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
-	    free(RARRAY(ary)->ptr);
-	}
-	RARRAY(ary)->len = 0;
-#endif
 	if (rb_block_given_p()) {
 	    rb_warning("given block not used");
 	}
@@ -440,9 +293,6 @@
 	rb_raise(rb_eArgError, "array size too big");
     }
     rb_ary_modify(ary);
-#if !WITH_OBJC
-    RESIZE_CAPA(ary, len);
-#endif
     if (rb_block_given_p()) {
 	long i;
 
@@ -451,20 +301,17 @@
 	}
 	for (i=0; i<len; i++) {
 	    rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
-#if !WITH_OBJC
-	    RARRAY(ary)->len = i + 1;
-#endif
 	}
     }
     else {
-#if WITH_OBJC
 	long i;
+	const void **values = alloca(sizeof(void *) * len);
+	void *ocval = RB2OC(val);
+
 	for (i=0; i<len; i++)
-	    rb_ary_insert(ary, i, val);
-#else
-	memfill(RARRAY_PTR(ary), len, val);
-	RARRAY(ary)->len = len;
-#endif
+	    values[i] = ocval;
+
+	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, len); 
     }
     return ary;
 }
@@ -481,26 +328,21 @@
 static VALUE
 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
 {
+    int i;
+
     VALUE ary = ary_alloc(klass);
 
     if (argc < 0) {
 	rb_raise(rb_eArgError, "negative array size");
     }
-#if WITH_OBJC
-    CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), 
-	(const void **)argv, argc);
-#else
-    RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
-    RARRAY(ary)->aux.capa = argc;
-    MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
-    RARRAY(ary)->len = argc;
-#endif
+    for (i = 0; i < argc; i++) {
+	CFArrayAppendValue((CFMutableArrayRef)ary, RB2OC(argv[i]));
+    }
     
     return ary;
 }
 
-#if WITH_OBJC
-static void
+void
 rb_ary_insert(VALUE ary, long idx, VALUE val)
 {
     if (idx < 0) {
@@ -514,9 +356,8 @@
     rb_ary_modify(ary);
 
     CFArrayInsertValueAtIndex((CFMutableArrayRef)ary, idx, 
-	(const void *)val);
+	(const void *)RB2OC(val));
 }
-#endif
 
 void
 rb_ary_store(VALUE ary, long idx, VALUE val)
@@ -532,71 +373,22 @@
 
     rb_ary_modify(ary);
 
-#if WITH_OBJC
     if (idx > len) {
-	const void **objs;
 	long i;
-	if (idx > sizeof(CFIndex))
-	if ((idx - len) * (long)sizeof(VALUE) <= idx - len)
+	if ((idx - len) * (long)sizeof(VALUE) <= idx - len) {
 	    rb_raise(rb_eArgError, "index too big");
-	objs = (const void **)alloca(sizeof(void *) * (idx - len));
-	if (objs == NULL)
-	    rb_raise(rb_eArgError, "index too big");
-	for (i = 0; i < (idx - len); i++)
-	    objs[i] = (const void *)Qnil;
-	CFArrayReplaceValues((CFMutableArrayRef)ary, 
-	    CFRangeMake(len, 0),
-	    objs,
-	    idx - len);
-	CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)val);	
-    }
-    else {
-        CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx, (const void *)val);
-    }
-#else
-    if (idx >= ARY_CAPA(ary)) {
-	long new_capa = ARY_CAPA(ary) / 2;
-
-	if (new_capa < ARY_DEFAULT_SIZE) {
-	    new_capa = ARY_DEFAULT_SIZE;
 	}
-	if (new_capa + idx < new_capa) {
-	    rb_raise(rb_eArgError, "index too big");
+	for (i = 0; i < (idx - len); i++) {
+	    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
 	}
-	new_capa += idx;
-	if (new_capa * (long)sizeof(VALUE) <= new_capa) {
-	    rb_raise(rb_eArgError, "index too big");
-	}
-	RESIZE_CAPA(ary, new_capa);
+	CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(val));	
     }
-    if (idx > RARRAY_LEN(ary)) {
-	rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
-		     idx-RARRAY_LEN(ary) + 1);
+    else {
+        CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx, (const void *)RB2OC(val));
     }
-
-    if (idx >= RARRAY_LEN(ary)) {
-	RARRAY(ary)->len = idx + 1;
-    }
-    GC_WB(&RARRAY_PTR(ary)[idx], val);
-#endif
 }
 
-#if !WITH_OBJC
 static VALUE
-ary_shared_array(VALUE klass, VALUE ary)
-{
-    VALUE val = ary_alloc(klass);
-
-    ary_make_shared(ary);
-    RARRAY(val)->ptr = RARRAY(ary)->ptr;
-    RARRAY(val)->len = RARRAY(ary)->len;
-    RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
-    FL_SET(val, ELTS_SHARED);
-    return val;
-}
-#endif
-
-static VALUE
 ary_shared_first(int argc, VALUE *argv, VALUE ary, int last, bool remove)
 {
     VALUE nv, result;
@@ -616,16 +408,11 @@
     if (last) {
 	offset = ary_len - n;
     }
-#if WITH_OBJC
     result = rb_ary_new();
     CFArrayAppendArray((CFMutableArrayRef)result, (CFArrayRef)ary, CFRangeMake(offset, n));
-    if (remove)
+    if (remove) {
 	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(offset, n), NULL, 0);
-#else
-    result = ary_shared_array(rb_cArray, ary);
-    RARRAY(result)->ptr += offset;
-    RARRAY(result)->len = n;
-#endif
+    }
 
     return result;
 }
@@ -646,12 +433,8 @@
 VALUE
 rb_ary_push(VALUE ary, VALUE item)
 {
-#if WITH_OBJC
     rb_ary_modify(ary);
-    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)item);
-#else
-    rb_ary_store(ary, RARRAY_LEN(ary), item);
-#endif
+    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(item));
     return ary;
 }
 
@@ -682,7 +465,6 @@
 {
     long n;
     rb_ary_modify_check(ary);
-#if WITH_OBJC
     n = RARRAY_LEN(ary);
     if (n == 0) {
 	return Qnil;
@@ -692,18 +474,6 @@
 	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, n - 1);
 	return val;
     }
-#else
-    if (RARRAY_LEN(ary) == 0) return Qnil;
-    if (!ARY_SHARED_P(ary) &&
-	RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
-	ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
-    {
-	RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2);
-    }
-    n = RARRAY_LEN(ary)-1;
-    RARRAY(ary)->len = n;
-    return RARRAY_PTR(ary)[n];
-#endif
 }
 
 /*
@@ -734,9 +504,6 @@
 
     rb_ary_modify_check(ary);
     result = ary_shared_first(argc, argv, ary, Qtrue, true);
-#if !WITH_OBJC
-    RARRAY(ary)->len -= RARRAY_LEN(result);
-#endif
     return result;
 }
 
@@ -747,24 +514,8 @@
 
     rb_ary_modify_check(ary);
     if (RARRAY_LEN(ary) == 0) return Qnil;
-#if WITH_OBJC
     top = RARRAY_AT(ary, 0);
     CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, 0);
-#else
-    top = RARRAY_PTR(ary)[0];
-    if (!ARY_SHARED_P(ary)) {
-	if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
-	    MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
-	    RARRAY(ary)->len--;
-	    return top;
-	}
-	RARRAY_PTR(ary)[0] = Qnil;
-	ary_make_shared(ary);
-    }
-    RARRAY(ary)->ptr++;		/* shift ptr */
-    RARRAY(ary)->len--;
-
-#endif
     return top;
 }
 
@@ -800,17 +551,6 @@
 
     rb_ary_modify_check(ary);
     result = ary_shared_first(argc, argv, ary, Qfalse, true);
-#if !WITH_OBJC
-    n = RARRAY_LEN(result);
-    if (ARY_SHARED_P(ary)) {
-	RARRAY(ary)->ptr += n;
-	RARRAY(ary)->len -= n;
-	}
-    else {
-	MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
-	RARRAY(ary)->len -= n;
-    }
-#endif
 
     return result;
 }
@@ -830,26 +570,15 @@
 static VALUE
 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
 {
-    if (argc == 0) return ary;
-    rb_ary_modify(ary);
-#if WITH_OBJC
-    {
-	long i;
-	for (i = argc - 1; i >= 0; i--)
-	    CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
-		0, (const void *)argv[i]);
+    int i;
+    if (argc == 0) {
+	return ary;
     }
-#else
-    if (RARRAY(ary)->aux.capa <= (len = RARRAY(ary)->len) + argc) {
-	RESIZE_CAPA(ary, len + argc + ARY_DEFAULT_SIZE);
-    }
+    rb_ary_modify(ary);
+    for (i = argc - 1; i >= 0; i--)
+	CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
+	    0, (const void *)RB2OC(argv[i]));
 
-    /* sliding items */
-    MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
-    MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
-    RARRAY(ary)->len += argc;
-#endif
-
     return ary;
 }
 
@@ -860,7 +589,6 @@
 }
 
 /* faster version - use this if you don't need to treat negative offset */
-#if WITH_OBJC
 VALUE
 rb_ary_elt(VALUE ary, long offset)
 {
@@ -869,42 +597,29 @@
 	return Qnil;
     if (offset < 0 || n <= offset)
 	return Qnil;
-    return (VALUE)CFArrayGetValueAtIndex((CFArrayRef)ary, offset);
+    return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
 }
-#else
-static inline VALUE
-rb_ary_elt(VALUE ary, long offset)
-{
-    if (RARRAY_LEN(ary) == 0) return Qnil;
-    if (offset < 0 || RARRAY_LEN(ary) <= offset) {
-	return Qnil;
-    }
-    return RARRAY_PTR(ary)[offset];
-}
-#endif
 
 const VALUE *
 rb_ary_ptr(VALUE ary)
 {
-#if WITH_OBJC
     /* FIXME we could inline __CFArrayGetBucketsPtr for non-store arrays,
      * for performance reasons.
      */
-    const VALUE *values;
-    long len;
+    VALUE *values;
+    long i, len;
 
     len = RARRAY_LEN(ary);
     if (len == 0)
 	return NULL;
-    values = (const VALUE *)xmalloc(sizeof(VALUE) * len);
+    values = (VALUE *)xmalloc(sizeof(VALUE) * len);
     CFArrayGetValues((CFArrayRef)ary, CFRangeMake(0, len), 
 	(const void **)values);
+    for (i = 0; i < len; i++)
+	values[i] = OC2RB(values[i]);
     GC_WB(&rb_objc_ary_get_struct2(ary)->cptr, values);
 
     return values;
-#else
-    return RARRAY_PTR(ary);
-#endif
 }
 
 VALUE
@@ -919,7 +634,6 @@
 VALUE
 rb_ary_subseq(VALUE ary, long beg, long len)
 {
-#if WITH_OBJC
     long n;
     VALUE newary;
     VALUE klass;
@@ -944,29 +658,6 @@
 	    values, len);
     }	
     return newary;
-#else
-    VALUE klass, ary2, shared;
-    VALUE *ptr;
-
-    if (beg > RARRAY_LEN(ary)) return Qnil;
-    if (beg < 0 || len < 0) return Qnil;
-
-    if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
-	len = RARRAY_LEN(ary) - beg;
-    }
-    klass = rb_obj_class(ary);
-    if (len == 0) return ary_new(klass, 0);
-
-    shared = ary_make_shared(ary);
-    ptr = RARRAY_PTR(ary);
-    ary2 = ary_alloc(klass);
-    RARRAY(ary2)->ptr = ptr + beg;
-    RARRAY(ary2)->len = len;
-    RARRAY(ary2)->aux.shared = shared;
-    FL_SET(ary2, ELTS_SHARED);
-
-    return ary2;
-#endif
 }
 
 /* 
@@ -1187,18 +878,11 @@
 	}
     }
     else {
-#if WITH_OBJC
 	CFIndex idx;
 	idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n), 
-	    (const void *)val);
+	    (const void *)RB2OC(val));
 	if (idx != -1)
 	    return LONG2NUM(idx);
-#else
-	for (i=0; i<n; i++) {
-	    if (rb_equal(RARRAY_AT(ary, i), val))
-		return LONG2NUM(i);
-	}
-#endif
     }
     return Qnil;
 }
@@ -1238,20 +922,10 @@
     }
     else {
  	rb_scan_args(argc, argv, "01", &val);
-#if WITH_OBJC
 	i = CFArrayGetLastIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
-	   (const void *)val);
+	   (const void *)RB2OC(val));
 	if (i != -1)
 	    return LONG2NUM(i);
-#else
-	while (i--) {
-	    if (rb_equal(RARRAY_AT(ary, i), val))
-		return LONG2NUM(i);
-	    if (i > n) {
-		i = n;
-	    }
-	}
-#endif
     }
     return Qnil;
 }
@@ -1294,11 +968,10 @@
 	rlen = RARRAY_LEN(rpl);
     }
     rb_ary_modify(ary);
-#if WITH_OBJC
     if (beg >= n) {
 	long i;
 	for (i = n; i < beg - n; i++) {
-	    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)Qnil);
+	    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
 	}
 	if (rlen > 0) 
 	    CFArrayAppendArray((CFMutableArrayRef)ary, (CFArrayRef)rpl,
@@ -1318,40 +991,6 @@
 		values,
 		rlen);
     }
-#else
-    if (beg >= RARRAY_LEN(ary)) {
-	len = beg + rlen;
-	if (len >= ARY_CAPA(ary)) {
-	    RESIZE_CAPA(ary, len);
-	}
-	rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
-	if (rlen > 0) {
-	    MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
-	}
-	RARRAY(ary)->len = len;
-    }
-    else {
-	long alen;
-
-	if (beg + len > RARRAY_LEN(ary)) {
-	    len = RARRAY_LEN(ary) - beg;
-	}
-
-	alen = RARRAY_LEN(ary) + rlen - len;
-	if (alen >= ARY_CAPA(ary)) {
-	    RESIZE_CAPA(ary, alen);
-	}
-
-	if (len != rlen) {
-	    MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
-		    VALUE, RARRAY_LEN(ary) - (beg + len));
-	    RARRAY(ary)->len = alen;
-	}
-	if (rlen > 0) {
-	    MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
-	}
-    }
-#endif
 }
 
 /* 
@@ -1560,38 +1199,28 @@
     return Qfalse;
 }
 
-#if WITH_OBJC
-static inline VALUE
-rb_ary_dup2(VALUE ary)
-{
-    VALUE klass, dup;
-    long n;
-
-    klass = rb_obj_class(ary);
-    dup = ary_new(klass, 0);
-    n = RARRAY_LEN(ary);
-    if (n > 0)
-	CFArrayAppendArray((CFMutableArrayRef)dup, (CFArrayRef)ary,
-		CFRangeMake(0, n));
-    return dup;
-}
-#endif
-
 VALUE
 rb_ary_dup(VALUE ary)
 {
-#if WITH_OBJC
-    VALUE dup = rb_ary_dup2(ary);
-#else
-    VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
+    VALUE dup;
 
-    MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
-    RARRAY(dup)->len = RARRAY_LEN(ary);
+    dup = (VALUE)CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)ary);
+    if (OBJ_TAINTED(ary))
+	OBJ_TAINT(dup);
 
-#endif
+    CFMakeCollectable((CFTypeRef)dup);
     return dup;
 }
 
+static VALUE
+rb_ary_clone(VALUE ary)
+{
+    VALUE clone = rb_ary_dup(ary);
+    if (OBJ_FROZEN(ary))
+	OBJ_FREEZE(clone);
+    return clone;
+}
+
 extern VALUE rb_output_fs;
 
 static VALUE
@@ -1613,19 +1242,7 @@
 
     if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0);
     if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue;
-#if WITH_OBJC
     result = rb_str_buf_new(0);
-#else
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	tmp = rb_check_string_type(RARRAY_AT(ary, i));
-	len += NIL_P(tmp) ? 10 : RSTRING_BYTELEN(tmp);
-    }
-    if (!NIL_P(sep)) {
-	StringValue(sep);
-	len += RSTRING_BYTELEN(sep) * (RARRAY_LEN(ary) - 1);
-    }
-    result = rb_str_buf_new(len);
-#endif
 
     for (i=0, count=RARRAY_LEN(ary); i<count; i++) {
 	tmp = RARRAY_AT(ary, i);
@@ -1728,11 +1345,7 @@
 static VALUE
 rb_ary_to_a(VALUE ary)
 {
-#if WITH_OBJC
     if (!rb_objc_ary_is_pure(ary)) {
-#else
-    if (rb_obj_class(ary) != rb_cArray) {
-#endif
 	VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
 	rb_ary_replace(dup, ary);
 	return dup;
@@ -1756,33 +1369,25 @@
 VALUE
 rb_ary_reverse(VALUE ary)
 {
-#if WITH_OBJC
     long n;
 
     rb_ary_modify(ary);
     n = RARRAY_LEN(ary);
     if (n > 0) {
+	void **values;
+	CFRange range;
 	long i;
-	for (i = 0; i < (n / 2); i++)
-	    CFArrayExchangeValuesAtIndices((CFMutableArrayRef)ary,
-		i, n - i - 1);
-    }
-#else
-    VALUE *p1, *p2;
-    VALUE tmp;
 
-    rb_ary_modify(ary);
-    if (RARRAY_LEN(ary) > 1) {
-	p1 = RARRAY_PTR(ary);
-	p2 = p1 + RARRAY_LEN(ary) - 1;	/* points last item */
-
-	while (p1 < p2) {
-	    tmp = *p1;
-	    *p1++ = *p2;
-	    *p2-- = tmp;
+	values = alloca(sizeof(void *) * n);
+	range = CFRangeMake(0, n);
+	CFArrayGetValues((CFArrayRef)ary, range, (const void **)values);
+	for (i = 0; i < (n / 2); i++) {
+	    void *v = values[i];
+	    values[i] = values[n - i - 1];
+	    values[n - i - 1] = v;
 	}
+	CFArrayReplaceValues((CFMutableArrayRef)ary, range, (const void **)values, n);
     }
-#endif
     return ary;
 }
 
@@ -1822,11 +1427,7 @@
 static int
 sort_1(const void *ap, const void *bp, void *dummy)
 {
-#if WITH_OBJC
     VALUE a = (VALUE)ap, b = (VALUE)bp;
-#else
-    VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
-#endif
     VALUE retval = rb_yield_values(2, a, b);
     int n;
 
@@ -1838,18 +1439,10 @@
 sort_2(const void *ap, const void *bp, void *dummy)
 {
     VALUE retval;
-#if WITH_OBJC
     VALUE a = (VALUE)ap, b = (VALUE)bp;
-#else
-    VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
-#endif
     int n;
 
-    if (FIXNUM_P(a) && FIXNUM_P(b)) {
-	if ((long)a > (long)b) return 1;
-	if ((long)a < (long)b) return -1;
-	return 0;
-    }
+    /* FIXME optimize!!! */
     if (TYPE(a) == T_STRING) {
 	if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
     }
@@ -1876,7 +1469,6 @@
  *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
  */
 
-#if WITH_OBJC
 static void
 rb_ary_sort_bang1(VALUE ary, bool is_dup)
 {
@@ -1899,34 +1491,12 @@
 	}
     }
 }
-#endif
 
 VALUE
 rb_ary_sort_bang(VALUE ary)
 {
     rb_ary_modify(ary);
-#if WITH_OBJC
     rb_ary_sort_bang1(ary, false);
-#else
-    if (RARRAY_LEN(ary) > 1) {
-	VALUE tmp = ary_make_shared(ary);
-
-	RBASIC(tmp)->klass = 0;
-	ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE),
-		   rb_block_given_p()?sort_1:sort_2, &RBASIC(tmp)->klass);
-	if (RARRAY(ary)->ptr != RARRAY(tmp)->ptr) {
-	    xfree(RARRAY(ary)->ptr);
-	    RARRAY(ary)->ptr = RARRAY(tmp)->ptr;
-	    RARRAY(ary)->len = RARRAY(tmp)->len;
-	    RARRAY(ary)->aux.capa = RARRAY(tmp)->aux.capa;
-	};
-	FL_UNSET(ary, ELTS_SHARED);
-	RARRAY(tmp)->ptr = 0;
-	RARRAY(tmp)->len = 0;
-	RARRAY(tmp)->aux.capa = 0;
-	RBASIC(tmp)->klass = RBASIC(ary)->klass;
-    }
-#endif
     return ary;
 }
 
@@ -2112,56 +1682,29 @@
 VALUE
 rb_ary_delete(VALUE ary, VALUE item)
 {
-#if WITH_OBJC
-    long n, i;
+    long k, n, i;
     CFRange r;
+    const void *ocitem;
 
     rb_ary_modify(ary);
 
-    r = CFRangeMake(0, RARRAY_LEN(ary));
-    n = 0;
-    while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r, 
-	(const void *)item)) != -1) {
+    ocitem = (const void *)RB2OC(item);
+    n = RARRAY_LEN(ary);
+    r = CFRangeMake(0, n);
+    k = 0;
+    while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r, ocitem)) != -1) {
 	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
-    	n++;
+	r.location = i;
+	r.length = --n - i;
+	k++;
     }
-    if (n == 0) {
+    if (k == 0) {
 	if (rb_block_given_p()) {
 	    return rb_yield(item);
 	}
 	return Qnil;
     }
     return item;
-#else
-    long i1, i2;
-
-    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
-	VALUE e = RARRAY_PTR(ary)[i1];
-
-	if (rb_equal(e, item)) continue;
-	if (i1 != i2) {
-	    rb_ary_store(ary, i2, e);
-	}
-	i2++;
-    }
-    if (RARRAY_LEN(ary) == i2) {
-	if (rb_block_given_p()) {
-	    return rb_yield(item);
-	}
-	return Qnil;
-    }
-
-    rb_ary_modify(ary);
-    if (RARRAY_LEN(ary) > i2) {
-	RARRAY(ary)->len = i2;
-	if (i2 * 2 < ARY_CAPA(ary) &&
-	    ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
-	    RESIZE_CAPA(ary, i2*2);
-	}
-    }
-
-    return item;
-#endif
 }
 
 VALUE
@@ -2178,13 +1721,7 @@
 
     rb_ary_modify(ary);
     del = RARRAY_AT(ary, pos);
-#if WITH_OBJC
     CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, pos);
-#else
-    MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
-	    RARRAY_LEN(ary)-pos-1);
-    RARRAY(ary)->len--;
-#endif
 
     return del;
 }
@@ -2248,12 +1785,7 @@
 	if (alen < len || alen < pos + len) {
 	    len = alen - pos;
 	}
-#if WITH_OBJC
 	arg2 = rb_ary_subseq(ary, pos, len);
-#else
-	arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
-	RBASIC(arg2)->klass = rb_obj_class(ary);
-#endif
 	rb_ary_splice(ary, pos, len, Qundef);	/* Qnil/rb_ary_new2(0) */
 	return arg2;
     }
@@ -2295,30 +1827,16 @@
     orign = n = RARRAY_LEN(ary);
     for (i1 = i2 = 0; i1 < n; i1++) {
 	VALUE v = RARRAY_AT(ary, i1);
-#if WITH_OBJC
 	if (!RTEST(rb_yield(v))) {
 	    continue;
 	}
 	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i1);
 	n--;
 	i1--;
-#else
-	if (RTEST(rb_yield(v))) continue;
-	if (i1 != i2) {
-	    rb_ary_store(ary, i2, v);
-	}
-	i2++;
-#endif
     }
 
-#if WITH_OBJC
     if (n == orign) 
 	return Qnil;
-#else
-    if (n == i2) return Qnil;
-    if (i2 < RARRAY_LEN(ary))
-	RARRAY(ary)->len = i2;
-#endif
     return ary;
 }
 
@@ -2492,22 +2010,10 @@
     orig = to_ary(orig);
     rb_ary_modify_check(copy);
     if (copy == orig) return copy;
-#if WITH_OBJC
     CFArrayRemoveAllValues((CFMutableArrayRef)copy);
     CFArrayAppendArray((CFMutableArrayRef)copy,
 	(CFArrayRef)orig,
 	CFRangeMake(0, RARRAY_LEN(orig)));
-#else
-    shared = ary_make_shared(orig);
-    if (!ARY_SHARED_P(copy)) {
-	ptr = RARRAY(copy)->ptr;
-	xfree(ptr);
-    }
-    RARRAY(copy)->ptr = RARRAY(orig)->ptr;
-    RARRAY(copy)->len = RARRAY(orig)->len;
-    RARRAY(copy)->aux.shared = shared;
-    FL_SET(copy, ELTS_SHARED);
-#endif
 
     return copy;
 }
@@ -2526,14 +2032,7 @@
 rb_ary_clear(VALUE ary)
 {
     rb_ary_modify(ary);
-#if WITH_OBJC
     CFArrayRemoveAllValues((CFMutableArrayRef)ary);
-#else
-    RARRAY(ary)->len = 0;
-    if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
-	RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
-    }
-#endif
     return ary;
 }
 
@@ -2603,15 +2102,6 @@
     if (end < 0) {
 	rb_raise(rb_eArgError, "argument too big");
     }
-#if !WITH_OBJC
-    if (n < end) {
-	if (end >= ARY_CAPA(ary)) {
-	    RESIZE_CAPA(ary, end);
-	}
-	rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
-	RARRAY(ary)->len = end;
-    }
-#endif
 
     if (block_p) {
 	VALUE v;
@@ -2619,25 +2109,14 @@
 
 	for (i=beg; i<end; i++) {
 	    v = rb_yield(LONG2NUM(i));
-#if !WITH_OBJC
-	    if (i>=RARRAY_LEN(ary)) break;
-#endif
 	    rb_ary_store(ary, i, v);
 	}
     }
     else {
-#if WITH_OBJC
 	long i;
 	for (i=beg; i<end; i++) {
 	    rb_ary_store(ary, i, item);
 	}
-#else
-	p = RARRAY_PTR(ary) + beg;
-	pend = p + len;
-	while (p < pend) {
-	    *p++ = item;
-	}
-#endif
     }
     return ary;
 }
@@ -2657,21 +2136,12 @@
 {
     VALUE z;
 
-#if WITH_OBJC
     y = to_ary(y);
     z = rb_ary_new2(0);
     CFArrayAppendArray((CFMutableArrayRef)z, 
 	(CFArrayRef)x, CFRangeMake(0, RARRAY_LEN(x)));    
     CFArrayAppendArray((CFMutableArrayRef)z, 
 	(CFArrayRef)y, CFRangeMake(0, RARRAY_LEN(y)));    
-#else
-    y = to_ary(y);
-    len = RARRAY_LEN(x) + RARRAY_LEN(y);
-    z = rb_ary_new2(len);
-    MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
-    MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
-    RARRAY(z)->len = len;
-#endif
     return z;
 }
 
@@ -2731,25 +2201,13 @@
     if (LONG_MAX/len < n) {
 	rb_raise(rb_eArgError, "argument too big");
     }
-#if WITH_OBJC
     ary2 = ary_new(rb_obj_class(ary), 0);
     for (i = 0; i < len; i++) {
 	CFArrayAppendArray((CFMutableArrayRef)ary2,
 		(CFArrayRef)ary,
 		CFRangeMake(0, n));
     }
-#else
-    len *= RARRAY_LEN(ary);
 
-    ary2 = ary_new(rb_obj_class(ary), len);
-    RARRAY(ary2)->len = len;
-
-    for (i=0; i<len; i+=RARRAY_LEN(ary)) {
-	MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
-    }
-    OBJ_INFECT(ary2, ary);
-#endif
-
     return ary2;
 }
 
@@ -2818,19 +2276,6 @@
     return Qnil;
 }
 
-static VALUE
-recursive_equal(VALUE ary1, VALUE ary2, int recur)
-{
-    long i;
-
-    if (recur) return Qfalse;
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
-	if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
-	    return Qfalse;
-    }
-    return Qtrue;
-}
-
 /* 
  *  call-seq:
  *     array == other_array   ->   bool
@@ -2855,8 +2300,7 @@
 	}
 	return rb_equal(ary2, ary1);
     }
-    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
-    return rb_exec_recursive(recursive_equal, ary1, ary2);
+    return CFEqual((CFTypeRef)ary1, (CFTypeRef)ary2) ? Qtrue : Qfalse;
 }
 
 static VALUE
@@ -2889,40 +2333,8 @@
     return rb_exec_recursive(recursive_eql, ary1, ary2);
 }
 
-static VALUE
-recursive_hash(VALUE ary, VALUE dummy, int recur)
-{
-    long i, h;
-    VALUE n;
-
-    if (recur) {
-	return LONG2FIX(0);
-    }
-    h = RARRAY_LEN(ary);
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	h = (h << 1) | (h<0 ? 1 : 0);
-	n = rb_hash(RARRAY_AT(ary, i));
-	h ^= NUM2LONG(n);
-    }
-    return LONG2FIX(h);
-}
-
 /*
  *  call-seq:
- *     array.hash   -> fixnum
- *
- *  Compute a hash-code for this array. Two arrays with the same content
- *  will have the same hash code (and will compare using <code>eql?</code>).
- */
-
-static VALUE
-rb_ary_hash(VALUE ary)
-{
-    return rb_exec_recursive(recursive_hash, ary, 0);
-}
-
-/*
- *  call-seq:
  *     array.include?(obj)   -> true or false
  *  
  *  Returns <code>true</code> if the given object is present in
@@ -2937,19 +2349,8 @@
 VALUE
 rb_ary_includes(VALUE ary, VALUE item)
 {
-#if WITH_OBJC
     return CFArrayContainsValue((CFArrayRef)ary, 
-	CFRangeMake(0, RARRAY_LEN(ary)), (const void *)item) ? Qtrue : Qfalse;
-#else
-    long i;
-    
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	if (rb_equal(RARRAY_PTR(ary)[i], item)) {
-	    return Qtrue;
-	}
-    }
-    return Qfalse;
-#endif
+	CFRangeMake(0, RARRAY_LEN(ary)), (const void *)RB2OC(item)) ? Qtrue : Qfalse;
 }
 
 
@@ -3048,12 +2449,9 @@
     ary3 = rb_ary_new();
 
     for (i=0; i<RARRAY_LEN(ary1); i++) {
-#if WITH_OBJC
-	if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
-	    (const void *)RARRAY_AT(ary1, i), NULL)) continue;
-#else
-	if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
-#endif
+	const void *v = CFArrayGetValueAtIndex((CFArrayRef)ary1, i);
+	if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)v, NULL)) 
+	    continue;
 	rb_ary_push(ary3, rb_ary_elt(ary1, i));
     }
     return ary3;
@@ -3086,13 +2484,10 @@
 
     for (i=0; i<RARRAY_LEN(ary1); i++) {
 	v = vv = rb_ary_elt(ary1, i);
-#if WITH_OBJC
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+	id ocvv = RB2OC(vv);
+	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
 	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)vv);
-#else
-	if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+		(const void *)ocvv);
 	    rb_ary_push(ary3, v);
 	}
     }
@@ -3124,25 +2519,19 @@
 
     for (i=0; i<RARRAY_LEN(ary1); i++) {
 	v = vv = rb_ary_elt(ary1, i);
-#if WITH_OBJC
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+	id ocvv = RB2OC(vv);
+	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
 	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)vv);
-#else
-	if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+		(const void *)ocvv);
 	    rb_ary_push(ary3, v);
 	}
     }
     for (i=0; i<RARRAY_LEN(ary2); i++) {
 	v = vv = rb_ary_elt(ary2, i);
-#if WITH_OBJC
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+	id ocvv = RB2OC(vv);
+	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
 	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)vv);
-#else
-	if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+		(const void *)ocvv);
 	    rb_ary_push(ary3, v);
 	}
     }
@@ -3166,7 +2555,6 @@
 static VALUE
 rb_ary_uniq_bang(VALUE ary)
 {
-#if WITH_OBJC
     long i, n;
     bool changed;
 
@@ -3174,13 +2562,15 @@
     n = RARRAY_LEN(ary);
     for (i = 0, changed = false; i < n; i++) {
 	VALUE e;
+	id oce;
 	long idx;
      	CFRange r;
 
         e = RARRAY_AT(ary, i);
+	oce = RB2OC(e);
 	r = CFRangeMake(i + 1, n - i - 1);	
 	while ((idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, 
-	    r, (const void *)e)) != -1) {
+	    r, (const void *)oce)) != -1) {
 	    CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, idx);
 	    r.location = idx;
 	    r.length = --n - idx;
@@ -3189,30 +2579,7 @@
     }
     if (!changed)
 	return Qnil;
-#else
-    VALUE hash, v, vv;
-    long i, j;
 
-    hash = ary_make_hash(ary, 0);
-
-    if (RARRAY_LEN(ary) == RHASH_SIZE(hash)) {
-	return Qnil;
-    }
-    for (i=j=0; i<RARRAY_LEN(ary); i++) {
-	v = vv = rb_ary_elt(ary, i);
-#if WITH_OBJC
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
-	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)vv);
-#else
-	if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
-	    rb_ary_store(ary, j++, v);
-	}
-    }
-    RARRAY(ary)->len = j;
-#endif
-
     return ary;
 }
 
@@ -3248,7 +2615,6 @@
 static VALUE
 rb_ary_compact_bang(VALUE ary)
 {
-#if WITH_OBJC
     long i, n, k;
     CFRange r;
 
@@ -3259,34 +2625,15 @@
     k = 0;
     r = CFRangeMake(0, n);
     while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
-	r, (const void *)Qnil)) != -1) {
+	r, (const void *)kCFNull)) != -1) {
 	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
 	r.location = i;
-	r.length = n - i;
+	r.length = --n - i;
 	k++;
     }
     if (k == 0)
 	return Qnil;
-#else
-    VALUE *p, *t, *end;
-    long n;
 
-    rb_ary_modify(ary);
-    p = t = RARRAY_PTR(ary);
-    end = p + RARRAY_LEN(ary);
-    
-    while (t < end) {
-	if (NIL_P(*t)) t++;
-	else *p++ = *t++;
-    }
-    if (RARRAY_LEN(ary) == (p - RARRAY_PTR(ary))) {
-	return Qnil;
-    }
-    n = p - RARRAY_PTR(ary);
-    RESIZE_CAPA(ary, n);
-    RARRAY(ary)->len = n;
-#endif
-
     return ary;
 }
 
@@ -3336,35 +2683,20 @@
 	if (!rb_block_given_p())
 	    return LONG2NUM(count);
 
-#if WITH_OBJC
 	for (i = 0; i < count; i++) {
 	    if (RTEST(rb_yield(RARRAY_AT(ary, i)))) 
 		n++;
 	}
-#else
-	for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
-	    if (RTEST(rb_yield(*p))) n++;
-	}
-#endif
     }
     else {
 	VALUE obj;
-	long i, count = RARRAY_LEN(ary);
+	long count = RARRAY_LEN(ary);
 
 	rb_scan_args(argc, argv, "1", &obj);
 	if (rb_block_given_p()) {
 	    rb_warn("given block not used");
 	}
-#if WITH_OBJC
-	for (i = 0; i < count; i++) {
-	    if (rb_equal(RARRAY_AT(ary, i), obj)) 
-		n++;
-	}
-#else
-	for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
-	    if (rb_equal(*p, obj)) n++;
-	}
-#endif
+	n = CFArrayGetCountOfValue((CFArrayRef)ary, CFRangeMake(0, count), RB2OC(obj));
     }
 
     return LONG2NUM(n);
@@ -3388,11 +2720,6 @@
 	while (i < RARRAY_LEN(ary)) {
 	    elt = RARRAY_AT(ary, i++);
 	    tmp = rb_check_array_type(elt);
-#if !WITH_OBJC
-	    if (RBASIC(result)->klass) {
-		rb_raise(rb_eRuntimeError, "flatten reentered");
-	    }
-#endif
 	    if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
 		rb_ary_push(result, elt);
 	    }
@@ -3422,9 +2749,6 @@
 
     st_free_table(memo);
 
-#if !WITH_OBJC
-    RBASIC(result)->klass = rb_class_of(ary);
-#endif
     return result;
 }
 
@@ -3513,13 +2837,7 @@
     rb_ary_modify(ary);
     while (i) {
 	long j = rb_genrand_real()*i;
-#if WITH_OBJC
 	CFArrayExchangeValuesAtIndices((CFMutableArrayRef)ary, --i, j);
-#else
-	VALUE tmp = RARRAY_AT(ary, --i);
-	RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
-	RARRAY_PTR(ary)[j] = tmp;
-#endif
     }
     return ary;
 }
@@ -3637,16 +2955,8 @@
 		/* Build a ruby array of the corresponding values */
 		/* And yield it to the associated block */
 		VALUE result = rb_ary_new2(r);
-#if WITH_OBJC
 		for (j = 0; j < r; j++) 
 		    rb_ary_store(result, j, RARRAY_AT(values, p[j]));
-#else
-		VALUE *result_array = RARRAY_PTR(result);
-		const VALUE *values_array = RARRAY_PTR(values);
-
-		for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
-		RARRAY(result)->len = r;
-#endif
 		rb_yield(result);
 	    }
 	}
@@ -3706,19 +3016,11 @@
 	long *p = (long*)RSTRING_BYTEPTR(t0);
 	volatile VALUE t1 = tmpbuf(n,sizeof(int));
 	int *used = (int*)RSTRING_BYTEPTR(t1);
-#if WITH_OBJC
 	VALUE ary0 = rb_ary_dup(ary);
-#else
-	VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
-#endif
 
 	for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
 
 	permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
-#if !WITH_OBJC
-	RB_GC_GUARD(t0);
-	RB_GC_GUARD(t1);
-#endif
     }
     return ary;
 }
@@ -3793,9 +3095,6 @@
 	volatile VALUE cc = rb_ary_new2(n);
 	long lev = 0;
 
-#if !WITH_OBJC
-	RBASIC(cc)->klass = 0;
-#endif
 	MEMZERO(stack, long, n);
 	stack[0] = -1;
 	for (i = 0; i < nlen; i++) {
@@ -3804,11 +3103,7 @@
 		stack[lev+1] = stack[lev]+1;
 		rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1]));
 	    }
-#if WITH_OBJC
 	    rb_yield(rb_ary_dup(cc));
-#else
-	    rb_yield(cc);
-#endif
 	    do {
 		stack[lev--]++;
 	    } while (lev && (stack[lev+1]+n == len+lev+1));
@@ -3990,13 +3285,9 @@
     return rb_ary_drop(ary, LONG2FIX(i));
 }
 
-#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 +3295,7 @@
 bool
 rb_objc_ary_is_pure(VALUE ary)
 {
-    return *(Class *)ary == NSCFARRAY();
+    return *(Class *)ary == (Class)rb_cCFArray;
 }
 
 static CFIndex
@@ -4114,12 +3405,12 @@
 	class_addMethod(klass, sel_registerName("_cfindexOfObject:inRange:"), 
 	    method_getImplementation(m), method_getTypeEncoding(m));
     }
+    
+    rb_define_alloc_func((VALUE)klass, ary_alloc);
 
 #undef INSTALL_METHOD
 }
 
-#endif
-
 /* Arrays are ordered, integer-indexed collections of any object. 
  * Array indexing starts at 0, as in C or Java.  A negative index is 
  * assumed to be relative to the end of the array---that is, an index of -1 
@@ -4130,19 +3421,14 @@
 void
 Init_Array(void)
 {
-#if WITH_OBJC
-    rb_cCFArray = rb_objc_import_class((Class)objc_getClass("NSCFArray"));;
-    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);
-#endif
+    rb_cCFArray = (VALUE)objc_getClass("NSCFArray");
+    rb_cArray = rb_cNSArray = (VALUE)objc_getClass("NSArray");
+    rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
+    rb_set_class_path(rb_cNSMutableArray, rb_cObject, "NSMutableArray");
+    rb_const_set(rb_cObject, rb_intern("Array"), rb_cNSMutableArray);
+
     rb_include_module(rb_cArray, rb_mEnumerable);
 
-    rb_define_alloc_func(rb_cArray, ary_alloc);
     rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
     rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
     rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
@@ -4156,7 +3442,6 @@
 
     rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
     rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
-    rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
 
     rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
     rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
@@ -4224,10 +3509,12 @@
     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
     rb_define_method(rb_cArray, "_count", rb_ary_count, -1);
-#if WITH_OBJC
-    /* to maintain backwards compatibility with our /etc/irbrc file */
+
+    /* to maintain backwards compatibility with our /etc/irbrc file
+     * TODO: fix /etc/irbrc to use #count, and remove this method.
+     */
     rb_define_method(rb_cArray, "nitems", rb_ary_count, -1);
-#endif
+
     rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
     rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
     rb_define_method(rb_cArray, "choice", rb_ary_choice, 0);
@@ -4241,5 +3528,9 @@
     rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
     rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
 
+    /* to return mutable copies */
+    rb_define_method(rb_cArray, "dup", rb_ary_dup, 0);
+    rb_define_method(rb_cArray, "clone", rb_ary_clone, 0);
+
     id_cmp = rb_intern("<=>");
 }

Modified: MacRuby/trunk/bignum.c
===================================================================
--- MacRuby/trunk/bignum.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/bignum.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -82,7 +82,7 @@
 	    ds = ALLOC_N(BDIGIT, len);
 	    MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
 	    RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
-	    RBIGNUM(big)->as.heap.digits = ds;
+	    GC_WB(&RBIGNUM(big)->as.heap.digits, ds);
 	    RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
 	}
     }
@@ -98,10 +98,11 @@
 	}
 	else {
 	    if (RBIGNUM_LEN(big) == 0) {
-		RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
+		GC_WB(&RBIGNUM(big)->as.heap.digits, ALLOC_N(BDIGIT, len));
 	    }
 	    else {
 		REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
+		GC_WB(&RBIGNUM(big)->as.heap.digits, RBIGNUM(big)->as.heap.digits);
 	    }
 	}
     }
@@ -2660,6 +2661,59 @@
     return Qtrue;
 }
 
+#if WITH_OBJC
+static const char *
+imp_rb_bignum_objCType(void *rcv, SEL sel)
+{
+    return "q";
+}
+    
+static void
+imp_rb_bignum_getValue(void *rcv, SEL sel, void *buffer)
+{
+    long long v = NUM2LL(rcv);
+    *(long long *)buffer = v;
+}
+
+static long long
+imp_rb_bignum_longLongValue(void *rcv, SEL sel)
+{
+    return NUM2LL(rcv);
+}
+
+static bool
+imp_rb_bignum_isEqual(void *rcv, SEL sel, void *other)
+{
+    if (other == NULL)
+	return false;
+    if (*(Class *)other != (Class)rb_cBignum)
+	return false;
+    return rb_big_eq((VALUE)rcv, (VALUE)other) == Qtrue;
+}
+
+static inline void
+rb_objc_install_method(Class klass, SEL sel, IMP imp)
+{
+    Method method = class_getInstanceMethod(klass, sel);
+    assert(method != NULL);
+    assert(class_addMethod(klass, sel, imp, method_getTypeEncoding(method)));
+}
+
+static void
+rb_install_nsnumber_primitives(void)
+{
+    Class klass = (Class)rb_cBignum;
+    rb_objc_install_method(klass, sel_registerName("objCType"),
+	    (IMP)imp_rb_bignum_objCType);
+    rb_objc_install_method(klass, sel_registerName("getValue:"),
+	    (IMP)imp_rb_bignum_getValue);
+    rb_objc_install_method(klass, sel_registerName("longLongValue"),
+	    (IMP)imp_rb_bignum_longLongValue);
+    rb_objc_install_method(klass, sel_registerName("isEqual:"),
+	    (IMP)imp_rb_bignum_isEqual);
+}
+#endif
+
 /*
  *  Bignum objects hold integers outside the range of
  *  Fixnum. Bignum objects are created
@@ -2716,4 +2770,8 @@
     rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
 
     power_cache_init();
+
+#if WITH_OBJC
+    rb_install_nsnumber_primitives();
+#endif
 }

Modified: MacRuby/trunk/bs.c
===================================================================
--- MacRuby/trunk/bs.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/bs.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -205,7 +205,7 @@
   return ret;
 }
 
-#define MAX_ENCODE_LEN 1024
+#define MAX_ENCODE_LEN 2048
 
 #ifndef MIN
 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -252,7 +252,7 @@
     p_src = pos + 1;
     pos = strchr(p_src, '"');
     if (pos == NULL) {
-      // XXX NSLog("Can't find the end of field delimiter starting at %d", p_src - src);
+      fprintf(stderr, "Can't find the end of field delimiter starting at %d\n", p_src - src);
       goto bails; 
     }
     if (field != NULL) {
@@ -307,19 +307,19 @@
       }
 
       if (ok == false) {
-        //XXX DLOG("MDLOSX", "Can't find the field encoding starting at %d", p_src - src);
+        fprintf(stderr, "Can't find the field encoding starting at %d\n", p_src - src);
         goto bails;
       }
 
       if (opposite == '}' || opposite == ')') {
         char buf[MAX_ENCODE_LEN];
         char buf2[MAX_ENCODE_LEN];
-   
+ 
         strncpy(buf, p_src, MIN(sizeof buf, i));
         buf[MIN(sizeof buf, i)] = '\0';        
      
         if (!undecorate_struct_type(buf, buf2, sizeof buf2, NULL, 0, NULL)) {
-          // XXX DLOG("MDLOSX", "Can't un-decode the field encoding '%s'", buf);
+          fprintf(stderr, "Can't un-decode the field encoding '%s'\n", buf);
           goto bails;
         }
 
@@ -597,10 +597,10 @@
           CHECK_ATTRIBUTE(struct_name, "name");
 
           if (!undecorate_struct_type(struct_decorated_type, type, 
-                                      MAX_ENCODE_LEN, fields, 128, 
+                                      sizeof type, fields, 128, 
                                       &field_count)) {
             BAIL("Can't handle structure '%s' with type '%s'", 
-                 name, struct_decorated_type);
+                 struct_name, struct_decorated_type);
           }
 
           free(struct_decorated_type);
@@ -1063,7 +1063,6 @@
     // FIXME this is inefficient
           memcpy(&methods[*methods_count], method, 
             sizeof(bs_element_method_t));
-          free(method);
 
           (*methods_count)++;
           
@@ -1071,7 +1070,8 @@
             klass->class_methods = methods;
           else
             klass->instance_methods = methods;
-          
+         
+          free(method);
           method = NULL;
           break;
         }

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/class.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,18 +1,20 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's class.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  class.c -
-
-  $Author: akr $
-  created at: Tue Aug 10 15:05:44 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #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,87 +22,6 @@
 #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)
-{
-    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);
-	rbklass = (VALUE)obj;
-    }
-
-    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));
-
-    if (rb_cObject != 0 && RCLASS_IV_TBL(rb_cObject) != NULL)
-	st_delete(RCLASS_IV_TBL(rb_cObject), (st_data_t*)&nameid, NULL);
-    rb_const_set((rb_cObject != 0 ? rb_cObject : rbklass), nameid, rbklass);   
-
-    /* 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);
-
-    /* Hack: make sure that all classes that inherit from NSObject have their
-     * Ruby class counterpart inherit from Object first.
-     * This is because constants declared in Object are meant to be visible
-     * in all scopes, and we need to be able to access them in Ruby-written
-     * subclasses of Objective-C classes. 
-     */
-    if (rb_cBasicObject != 0
-	&& rb_cObject != 0
-	&& ocklass == RCLASS_OCID(rb_cBasicObject)) {
-	super = rb_cObject;
-    }
-    else {
-	super = ocklass == NULL ? 0 : rb_objc_import_class(ocklass);
-    }
-
-    RCLASS_SUPER(rbklass) = super;
-    OBJ_INFECT(rbklass, super);
-    FL_SET(rbklass, RCLASS_OBJC_IMPORTED);
-
-    if (super != 0)
-	rb_make_metaclass(rbklass, RBASIC(super)->klass);
-
-    return rbklass;
-}
-
 void rb_objc_install_array_primitives(Class);
 void rb_objc_install_hash_primitives(Class);
 void rb_objc_install_string_primitives(Class);
@@ -110,16 +31,19 @@
 {
     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);
+		RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);
 		return true;
 	    }
-	    if (ocsuper == RCLASS_OCID(rb_cHash)) {
+	    if (ocsuper == (Class)rb_cHash) {
 		rb_objc_install_hash_primitives(ocklass);
+		RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS);
 		return true;
 	    }
-	    if (ocsuper == RCLASS_OCID(rb_cString)) {
+	    if (ocsuper == (Class)rb_cString) {
 		rb_objc_install_string_primitives(ocklass);
+		RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_STRING_SUBCLASS);
 		return true;
 	    }
 	    ocsuper = class_getSuperclass(ocsuper);
@@ -130,24 +54,42 @@
 }
 
 static VALUE
-rb_objc_alloc_class(const char *name, VALUE *psuper, VALUE flags, VALUE klass)
+rb_class_allocate_instance(VALUE klass)
 {
-    VALUE super, obj;
-    Class ocklass, ocsuper;
-    char ocname[128];
+    NEWOBJ(obj, struct RObject);
+    OBJSETUP(obj, klass, T_OBJECT);
+    return (VALUE)obj;
+}
 
-    super = psuper == NULL ? 0 : *psuper;
+static VALUE
+rb_objc_init(VALUE rcv)
+{
+    rb_funcall(rcv, idInitialize, 0);
+    return rcv;
+}
 
+void
+rb_define_object_special_methods(VALUE klass)
+{
+    rb_define_alloc_func(klass, rb_class_allocate_instance);
+    rb_define_singleton_method(klass, "new", rb_class_new_instance, -1);
+    rb_define_method(klass, "dup", rb_obj_dup, 0);
+    rb_define_method(klass, "init", rb_objc_init, 0);
+    rb_define_method(klass, "initialize_copy", rb_obj_init_copy, 1);
+}
+
+static VALUE
+rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
+{
+    Class ocklass;
+    char ocname[128];
+    int version_flag;
+
     if (name == NULL) {
 	static long anon_count = 1;
     	snprintf(ocname, sizeof ocname, "RBAnonymous%ld", ++anon_count);
     }
     else {
-	if (super == rb_cBasicObject && strcmp(name, "Object") != 0) {
-	    rb_warn("Do not subclass NSObject directly, please subclass " \
-		    "Object instead.");
-	    super = *psuper = rb_cObject; 
-	}
 	if (objc_getClass(name) != NULL) {
 	    long count = 1;
 	    snprintf(ocname, sizeof ocname, "RB%s", name);
@@ -161,28 +103,31 @@
 	}
     }
 
-    ocsuper = super == 0 ? NULL : RCLASS_OCID(super);
-    ocklass = objc_allocateClassPair(ocsuper, ocname, 0);
+    if (super == 0)
+	super = rb_cObject;
+
+    ocklass = objc_allocateClassPair((Class)super, ocname, sizeof(id));
     assert(ocklass != NULL);
 
-    {
-	NEWOBJ(obj2, struct RClass);
-	OBJSETUP(obj2, klass, flags);
-	obj = (VALUE)obj2;
+    version_flag = RCLASS_IS_RUBY_CLASS;
+    if (flags == T_MODULE) {
+	version_flag |= RCLASS_IS_MODULE;
     }
+    if (super == rb_cObject) {
+	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+    }
+    else if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
+	version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+    }
 
-    RBASIC(obj)->isa = ocklass->isa;
-    RCLASS(obj)->ocklass = ocklass;
+    class_setVersion(ocklass, version_flag);
 
-    rb_objc_retain((const void *)obj); /* classes should never be released */
+    DLOG("DEFC", "%s < %s (version=%d)", ocname, class_getName(class_getSuperclass((Class)ocklass)), version_flag);
 
-    if (name == NULL)
-	FL_SET(obj, RCLASS_ANONYMOUS);
-
     if (klass != 0)
-	rb_objc_install_primitives(ocklass, ocsuper);
+	rb_objc_install_primitives(ocklass, (Class)super);
 
-    return obj;
+    return (VALUE)ocklass;
 }
 
 VALUE
@@ -190,90 +135,23 @@
 {
     VALUE klass;
     
-    klass = rb_objc_alloc_class(name, &super, T_CLASS, rb_cClass);
- 
-    class_init(klass);
-
-    objc_registerClassPair(RCLASS_OCID(klass));
+    klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
+    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;
-
-    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;
+    if (super == rb_cNSObject) {
+	rb_define_object_special_methods(klass);
     }
-    ocname[count + 2] = '\0';
 
-    ocorig = RCLASS_OCID(klass);
+    if (name != NULL && rb_class_tbl != NULL) 
+	st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
 
-    //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);
-#else
-    NEWOBJ(obj, struct RClass);
-    OBJSETUP(obj, klass, flags);
-#endif
-    return class_init((VALUE)obj);
-}
-
 VALUE
 rb_class_boot(VALUE super)
 {
-#if WITH_OBJC
     VALUE klass = rb_objc_create_class(NULL, super);
-#else
-    VALUE klass = class_alloc(T_CLASS, rb_cClass);
-
-    RCLASS_SUPER(klass) = super;
-    RCLASS_M_TBL(klass) = st_init_numtable();
-#endif
-    OBJ_INFECT(klass, super);
     return (VALUE)klass;
 }
 
@@ -284,7 +162,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,57 +178,34 @@
     return rb_class_boot(super);
 }
 
-struct clone_method_data {
-    st_table *tbl;
-    VALUE klass;
-};
-
-static int
-clone_method(ID mid, NODE *body, struct clone_method_data *data)
-{
-    if (body == 0) {
-	st_insert(data->tbl, mid, 0);
-    }
-    else {
-	st_insert(data->tbl, mid,
-		  (st_data_t)
-		  NEW_FBODY(
-		      NEW_METHOD(body->nd_body->nd_body,
-				 data->klass, /* TODO */
-				 body->nd_body->nd_noex),
-		      0));
-    }
-    return ST_CONTINUE;
-}
-
 /* :nodoc: */
 VALUE
 rb_mod_init_copy(VALUE clone, VALUE orig)
 {
     rb_obj_init_copy(clone, orig);
-    if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
-	RBASIC(clone)->klass = rb_singleton_class_clone(orig);
-    }
-    RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
-#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);
+	VALUE super;
+	int version_flag;
+
+	if (orig == rb_cNSMutableString
+	    || orig == rb_cNSMutableArray
+	    || orig == rb_cNSMutableHash) {
+	    super = orig;
 	    rb_warn("cloning class `%s' is not supported, creating a " \
 		    "subclass instead", rb_class2name(orig));
 	}
 	else {
-	    ocsuper = class_getSuperclass(RCLASS_OCID(orig));
+	    super = RCLASS_SUPER(orig);
 	}
-	class_setSuperclass(RCLASS(clone)->ocklass, ocsuper);
+	RCLASS_SUPER(clone) = super;
+
+	version_flag = RCLASS_IS_RUBY_CLASS;
+	if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS)
+	    version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+
+	class_setVersion((Class)clone, version_flag);
     }
-#endif
+#if 0 // TODO
     if (RCLASS_IV_TBL(orig)) {
 	ID id;
 
@@ -368,6 +223,7 @@
 	st_foreach(RCLASS_M_TBL(orig), clone_method,
 	  (st_data_t)&data);
     }
+#endif
 
     return clone;
 }
@@ -376,16 +232,11 @@
 VALUE
 rb_class_init_copy(VALUE clone, VALUE orig)
 {
-    if (RCLASS_SUPER(clone) != 0) {
-	rb_raise(rb_eTypeError, "already initialized class");
-    }
-    if (FL_TEST(orig, FL_SINGLETON)) {
+    if (RCLASS_SINGLETON(orig)) {
 	rb_raise(rb_eTypeError, "can't copy singleton class");
     }
     clone =  rb_mod_init_copy(clone, orig);
-#if WITH_OBJC 
-    rb_objc_install_primitives(RCLASS_OCID(clone), RCLASS_OCID(orig)); 
-#endif
+    rb_objc_install_primitives((Class)clone, (Class)orig);
     return clone;
 }
 
@@ -393,100 +244,82 @@
 rb_singleton_class_clone(VALUE obj)
 {
     VALUE klass = RBASIC(obj)->klass;
-
-    if (!FL_TEST(klass, FL_SINGLETON))
+    if (!RCLASS_SINGLETON(klass)) {
 	return klass;
+    }
     else {
-	struct clone_method_data data;
 	/* copy singleton(unnamed) class */
-        VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+	VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass));
 
-	if (BUILTIN_TYPE(obj) == T_CLASS) {
-	    RBASIC(clone)->klass = (VALUE)clone;
+	CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass);
+	if (ivar_dict != NULL) {
+	    CFMutableDictionaryRef cloned_ivar_dict;
+
+	    cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict);
+	    rb_class_ivar_set_dict(clone, cloned_ivar_dict);
+	    CFMakeCollectable(cloned_ivar_dict);
 	}
-	else {
-	    RBASIC(clone)->klass = rb_singleton_class_clone(klass);
-	}
 
-	RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
-	if (RCLASS_IV_TBL(klass)) {
-	    GC_WB(&RCLASS_IV_TBL(clone), st_copy(RCLASS_IV_TBL(klass)));
+	Method *methods;
+	unsigned i, methods_count;
+	methods = class_copyMethodList((Class)klass, &methods_count);
+	if (methods != NULL) {
+	    for (i = 0; i < methods_count; i++) {
+		Method method = methods[i], method2;
+		method2 = class_getInstanceMethod((Class)clone, method_getName(method));
+		if (method2 != class_getInstanceMethod((Class)RCLASS_SUPER(clone), method_getName(method))) {
+		    method_setImplementation(method2, method_getImplementation(method));
+		}
+		else {
+		    assert(class_addMethod((Class)clone, 
+				method_getName(method), 
+				method_getImplementation(method), 
+				method_getTypeEncoding(method)));
+		}
+	    }
+	    free(methods);
 	}
-	GC_WB(&RCLASS_M_TBL(clone), st_init_numtable());
-	data.tbl = RCLASS_M_TBL(clone);
-	data.klass = (VALUE)clone;
-	st_foreach(RCLASS_M_TBL(klass), clone_method,
-	  (st_data_t)&data);
+
 	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-	FL_SET(clone, FL_SINGLETON);
-#if WITH_OBJC
-    	objc_registerClassPair(RCLASS_OCID(clone));
-#endif
-	return (VALUE)clone;
+	if (RCLASS_SUPER(clone) == rb_cNSObject) {
+	    RCLASS_VERSION(clone) ^= RCLASS_IS_OBJECT_SUBCLASS;
+	}
+	RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON);
+
+	return clone;
     }
 }
 
 void
 rb_singleton_class_attached(VALUE klass, VALUE obj)
 {
-    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);
+    if (RCLASS_SINGLETON(klass)) {
+	static ID attachedId = 0;
+	if (attachedId == 0)
+	    attachedId = rb_intern("__attached__");
+	rb_ivar_set(klass, attachedId, obj);
     }
 }
 
 VALUE
 rb_make_metaclass(VALUE obj, VALUE super)
 {
-    bool pure;
-
-#if WITH_OBJC
-    pure = rb_objc_is_non_native(obj);
-#else
-    pure = false;
-#endif
-
-    if (!pure && BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
-	return RBASIC(obj)->klass = rb_cClass;
+    if (TYPE(obj) == T_CLASS && RCLASS_SINGLETON(obj)) {
+	RBASIC(obj)->klass = rb_cClass;
+	return rb_cClass;
     }
     else {
-	VALUE metasuper;
 	VALUE 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;
-	}
-#else
 	klass = rb_class_boot(super);
 	RBASIC(obj)->klass = klass;
-#endif
-	FL_SET(klass, FL_SINGLETON);
+	if (super == rb_cNSObject) {
+	    RCLASS_VERSION(klass) ^= RCLASS_IS_OBJECT_SUBCLASS;
+	}
+	RCLASS_SET_VERSION_FLAG(klass, RCLASS_IS_SINGLETON);
 
 	rb_singleton_class_attached(klass, obj);
 
-	metasuper = RBASIC(rb_class_real(super))->klass;
-	/* metaclass of a superclass may be NULL at boot time */
-	if (metasuper) {
-	    RBASIC(klass)->klass = metasuper;
-	}
 	return klass;
     }
 }
@@ -497,12 +330,7 @@
     VALUE klass;
 
     if (!super) super = rb_cObject;
-#if WITH_OBJC
     klass = rb_objc_create_class(rb_id2name(id), super);
-#else
-    klass = rb_class_new(super);
-#endif
-    rb_make_metaclass(klass, RBASIC(super)->klass);
 
     return klass;
 }
@@ -575,11 +403,7 @@
 VALUE
 rb_module_new(void)
 {
-    VALUE mdl = class_alloc(T_MODULE, rb_cModule);
-
-    RCLASS_M_TBL(mdl) = st_init_numtable();
-
-    return (VALUE)mdl;
+    return rb_define_module_id(0);
 }
 
 VALUE
@@ -587,15 +411,15 @@
 {
     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? */
-#else
-    mdl = rb_module_new();
-    rb_name_class(mdl, id);
-#endif
+    mdl = rb_objc_alloc_class(id == 0 ? NULL : rb_id2name(id), rb_cObject, T_MODULE, rb_cModule);
+    objc_registerClassPair((Class)mdl);
 
+    if (rb_mKernel != 0) {
+	/* because Module#initialize can accept a block */
+	extern VALUE rb_mod_initialize(VALUE);
+	rb_define_method(*(VALUE *)mdl, "initialize", rb_mod_initialize, 0);
+    }
+
     return mdl;
 }
 
@@ -640,83 +464,57 @@
     return module;
 }
 
-static VALUE
-include_class_new(VALUE module, VALUE super)
-{
-    VALUE klass = class_alloc(T_ICLASS, rb_cClass);
-
-    if (BUILTIN_TYPE(module) == T_ICLASS) {
-	module = RBASIC(module)->klass;
-    }
-    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;
-    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;
-}
-
 void
 rb_include_module(VALUE klass, VALUE module)
 {
-    VALUE p, c;
-    int changed = 0;
+    Method *methods;
+    unsigned int i, methods_count;
+    VALUE ary;
 
     rb_frozen_class_p(klass);
-    if (!OBJ_TAINTED(klass)) {
+
+    if (!OBJ_TAINTED(klass))
 	rb_secure(4);
+
+    Check_Type(module, T_MODULE);
+
+    ary = rb_attr_get(klass, idIncludedModules);
+    if (ary == Qnil) {
+	ary = rb_ary_new();
+	rb_ivar_set(klass, idIncludedModules, ary);
     }
-    
-    if (TYPE(module) != T_MODULE) {
-	Check_Type(module, T_MODULE);
+    if (rb_ary_includes(ary, module))
+	return;
+    rb_ary_insert(ary, 0, module);
+
+    ary = rb_attr_get(module, idIncludedInClasses);
+    if (ary == Qnil) {
+	ary = rb_ary_new();
+	rb_ivar_set(module, idIncludedInClasses, ary);
     }
+    rb_ary_push(ary, klass);
 
-    OBJ_INFECT(klass, module);
-    c = klass;
-    while (module) {
-       int superclass_seen = Qfalse;
+    DLOG("INCM", "%s <- %s", class_getName((Class)klass), class_getName((Class)module));
 
-	if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
-	    rb_raise(rb_eArgError, "cyclic include detected");
-	/* ignore if the module included already in superclasses */
-	for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
-	    switch (BUILTIN_TYPE(p)) {
-		case T_ICLASS:
-		    if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
-			if (!superclass_seen) {
-			    c = p;  /* move insertion point */
-			}
-			goto skip;
-		    }
-		    break;
-		case T_CLASS:
-		    superclass_seen = Qtrue;
-		    break;
+    methods = class_copyMethodList((Class)module, &methods_count);
+    if (methods != NULL) {
+	for (i = 0; i < methods_count; i++) {
+	    Method method = methods[i], method2;
+	    DLOG("DEFI", "-[%s %s]", class_getName((Class)klass), (char *)method_getName(method));
+	
+	    method2 = class_getInstanceMethod((Class)klass, method_getName(method));
+	    if (method2 != NULL && method2 != class_getInstanceMethod((Class)RCLASS_SUPER(klass), method_getName(method))) {
+		method_setImplementation(method2, method_getImplementation(method));
 	    }
+	    else {
+		assert(class_addMethod((Class)klass, 
+			    method_getName(method), 
+			    method_getImplementation(method), 
+			    method_getTypeEncoding(method)));
+	    }
 	}
-#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);
+	free(methods);
     }
-    if (changed) rb_clear_cache();
 }
 
 /*
@@ -736,16 +534,29 @@
  *     Outer.included_modules   #=> [Mixin]
  */
 
+static void
+rb_mod_included_modules_nosuper(VALUE mod, VALUE ary)
+{
+    VALUE inc_mods = rb_ivar_get(mod, idIncludedModules);
+    if (inc_mods != Qnil) {
+	int i, count = RARRAY_LEN(inc_mods);
+	for (i = 0; i < count; i++) {
+	    VALUE imod = RARRAY_AT(inc_mods, i);
+	    rb_ary_push(ary, imod);
+	    rb_ary_concat(ary, rb_mod_included_modules(imod));
+	}
+    }
+}
+
 VALUE
 rb_mod_included_modules(VALUE mod)
 {
-    VALUE ary = rb_ary_new();
-    VALUE p;
+    VALUE p, ary = rb_ary_new();
 
-    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
-	if (BUILTIN_TYPE(p) == T_ICLASS) {
-	    rb_ary_push(ary, RBASIC(p)->klass);
-	}
+    for (p = mod; p; p = RCLASS_SUPER(p)) {
+	rb_mod_included_modules_nosuper(p, ary);
+	if (RCLASS_MODULE(p))
+	    break;
     }
     return ary;
 }
@@ -772,15 +583,7 @@
 VALUE
 rb_mod_include_p(VALUE mod, VALUE mod2)
 {
-    VALUE p;
-
-    Check_Type(mod2, T_MODULE);
-    for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
-	if (BUILTIN_TYPE(p) == T_ICLASS) {
-	    if (RBASIC(p)->klass == mod2) return Qtrue;
-	}
-    }
-    return Qfalse;
+    return rb_ary_includes(rb_mod_included_modules(mod), mod2);
 }
 
 /*
@@ -799,20 +602,18 @@
  *     Math.ancestors   #=> [Math]
  */
 
+static void rb_mod_included_modules_nosuper(VALUE, VALUE);
+
 VALUE
 rb_mod_ancestors(VALUE mod)
 {
     VALUE p, ary = rb_ary_new();
-
+   
     for (p = mod; p; p = RCLASS_SUPER(p)) {
-	if (FL_TEST(p, FL_SINGLETON))
-	    continue;
-	if (BUILTIN_TYPE(p) == T_ICLASS) {
-	    rb_ary_push(ary, RBASIC(p)->klass);
-	}
-	else {
-	    rb_ary_push(ary, p);
-	}
+	rb_ary_push(ary, p);
+	rb_mod_included_modules_nosuper(p, ary);
+	if (RCLASS_MODULE(p))
+	    break;
     }
     return ary;
 }
@@ -862,59 +663,117 @@
     return ins_methods_push(name, type, ary, NOEX_PUBLIC);
 }
 
-static int
-method_entry(ID key, NODE *body, st_table *list)
+static void
+rb_objc_push_methods(VALUE ary, VALUE mod, VALUE objc_methods)
 {
-    long type;
+    Method *methods;
+    unsigned int i, count;
 
-    if (key == ID_ALLOCATOR) {
-	return ST_CONTINUE;
+    methods = class_copyMethodList((Class)mod, &count); 
+    if (methods != NULL) {  
+	for (i = 0; i < count; i++) { 
+	    Method method;
+	    SEL sel;
+	    char *sel_name, *p;
+	    VALUE sym;
+	    ID mid;
+	    char buf[100];
+	    BOOL is_ruby_method;
+	    size_t len;
+	   
+	    method = methods[i];
+
+	    sel = method_getName(method);
+	    if (sel == sel_ignored)
+		continue; 
+
+	    sel_name = (char *)sel;
+	    is_ruby_method = rb_objc_method_node3(method_getImplementation(method)) != NULL;
+
+	    if (!is_ruby_method && objc_methods == Qfalse)
+		continue;
+
+	    len = strlen(sel_name);
+
+	    if (is_ruby_method && len > 8 && sel_name[0] == '_' && sel_name[1] == '_' && sel_name[2] == 'r' && sel_name[3] == 'b' && sel_name[4] == '_' && sel_name[len - 1] == '_' && sel_name[len - 2] == '_') {
+		/* retransform ignored selectors, __rb_%s__ -> %s */
+		assert(sizeof buf > len - 7);
+		strncpy(buf, &sel_name[5], len - 7);
+		buf[len - 7] = '\0';
+		sel_name = buf;
+	    }
+	    else {
+		if (is_ruby_method && len >= 3 && sel_name[len - 1] == ':' && isalpha(sel_name[len - 3])) {
+		    assert(len + 3 < sizeof(buf));
+		    if (sel_name[len - 2] == '=') {
+			/* skip foo=: (ruby) -> setFoo: (objc) shortcuts */
+			snprintf(buf, sizeof buf, "set%s", sel_name);
+			buf[4] = toupper(buf[4]);
+			buf[len + 1] = ':';
+			buf[len + 2] = '\0';
+
+			method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
+			if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+			    continue;
+		    }
+		    else if (sel_name[len - 2] == '?') {
+			/* skip foo?: (ruby) -> isFoo: (objc) shortcuts */
+			snprintf(buf, sizeof buf, "is%s", sel_name);
+			buf[3] = toupper(buf[3]);
+			buf[len] = ':';
+			buf[len + 1] = '\0';
+
+			method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
+			if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+			    continue;
+		    }
+		}
+		p = strchr(sel_name, ':');
+		if (p != NULL && strchr(p + 1, ':') == NULL) {
+		    /* remove trailing ':' for methods with arity 1 */
+		    assert(len < sizeof(buf));
+		    strncpy(buf, sel_name, len);
+		    buf[len - 1] = '\0';
+		    sel_name = buf;
+		}
+	    }
+	    mid = rb_intern(sel_name);
+	    sym = ID2SYM(mid);
+
+	    if (rb_ary_includes(ary, sym) == Qfalse)
+		rb_ary_push(ary, sym);
+	} 
+	free(methods); 
     }
-    
-    if (!st_lookup(list, key, 0)) {
-	if (body ==0 || !body->nd_body->nd_body) {
-	    type = -1; /* none */
-	}
-	else {
-	    type = VISI(body->nd_body->nd_noex);
-	}
-	st_add_direct(list, key, type);
-    }
-    return ST_CONTINUE;
 }
 
 static VALUE
 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, long, VALUE))
 {
     VALUE ary;
-    int recur;
-    st_table *list;
-    VALUE mod_orig = mod;
+    VALUE recur, objc_methods;
 
+    ary = rb_ary_new();
+
     if (argc == 0) {
 	recur = Qtrue;
+	objc_methods = Qfalse;
     }
     else {
-	VALUE r;
-	rb_scan_args(argc, argv, "01", &r);
-	recur = RTEST(r);
+	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
+	if (NIL_P(recur))
+	    recur = Qtrue;
+	if (NIL_P(objc_methods))
+	    objc_methods = Qfalse;
     }
 
-    list = st_init_numtable();
-    for (; mod; mod = RCLASS_SUPER(mod)) {
-	st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
-	if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
-	if (FL_TEST(mod, FL_SINGLETON)) continue;
-	if (!recur) break;
-    }
-    ary = rb_ary_new();
-    st_foreach(list, func, ary);
-    st_free_table(list);
+    while (mod != 0) {
+	rb_objc_push_methods(ary, mod, objc_methods);
+	if (recur == Qfalse)
+	   break;	   
+	mod = (VALUE)class_getSuperclass((Class)mod); 
+    } 
 
-#if WITH_OBJC
-    rb_objc_methods(ary, RCLASS(mod_orig)->ocklass);
-#endif
-
     return ary;
 }
 
@@ -1039,30 +898,25 @@
 VALUE
 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
 {
-    VALUE recur, ary, klass;
-    st_table *list;
+    VALUE recur, objc_methods, klass, ary;
 
     if (argc == 0) {
 	recur = Qtrue;
+	objc_methods = Qfalse;
     }
     else {
-	rb_scan_args(argc, argv, "01", &recur);
+	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
     }
+
     klass = CLASS_OF(obj);
-    list = st_init_numtable();
-    if (klass && FL_TEST(klass, FL_SINGLETON)) {
-	st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
+    ary = rb_ary_new();
+
+    do {
+	if (RCLASS_SINGLETON(klass))
+	    rb_objc_push_methods(ary, klass, objc_methods);
 	klass = RCLASS_SUPER(klass);
     }
-    if (RTEST(recur)) {
-	while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
-	    st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
-	    klass = RCLASS_SUPER(klass);
-	}
-    }
-    ary = rb_ary_new();
-    st_foreach(list, ins_methods_i, ary);
-    st_free_table(list);
+    while (recur == Qtrue && klass != 0);
 
     return ary;
 }
@@ -1119,36 +973,30 @@
     }
 
     DEFER_INTS;
-#if WITH_OBJC
-    if (rb_objc_is_non_native(obj)) {
-	Class ocklass;
-
-	ocklass = *(Class *)obj;
-	klass = rb_objc_import_class(ocklass);
-	if (class_isMetaClass(ocklass))
-	    return klass;
-
-	if (!FL_TEST(klass, FL_SINGLETON))
-	    klass = rb_make_metaclass(obj, klass);
-	return klass;
-    }
-#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);
+	switch (TYPE(obj)) {
+	    case T_CLASS:
+	    case T_MODULE:
+		klass = *(VALUE *)obj;
+		break;
+	    default:
+		klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+		break;
+	}
     }
-#if !WITH_OBJC
+#if 0
     if (OBJ_TAINTED(obj)) {
 	OBJ_TAINT(klass);
     }
     else {
-	FL_UNSET(klass, FL_TAINT);
+	OBJ_UNTAINT(klass);
     }
-    if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
 #endif
+    if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
     ALLOW_INTS;
 
     return klass;
@@ -1227,7 +1075,7 @@
 	p++;
     }
 
-    if(*p == '*') {
+    if (*p == '*') {
       rest_arg:
 	var = va_arg(vargs, VALUE*);
 	if (argc > i) {

Modified: MacRuby/trunk/compile.c
===================================================================
--- MacRuby/trunk/compile.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/compile.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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;
@@ -674,7 +674,7 @@
 	operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
 	for (i = 0; i < argc; i++) {
 	    VALUE v = va_arg(argv, VALUE);
-	    operands[i] = v;
+	    GC_WB(&operands[i], v);
 	}
 	va_end(argv);
     }
@@ -687,12 +687,43 @@
 {
     INSN *iobj = 0;
     VALUE *operands =
-      (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5);
+      (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 7);
+    struct rb_method_cache *mcache;
+
     operands[0] = id;
     operands[1] = argc;
     operands[2] = block;
     operands[3] = flag;
-    operands[4] = 0;
+
+    mcache = (struct rb_method_cache *)xmalloc(sizeof(struct rb_method_cache));
+    mcache->flags = RB_MCACHE_RCALL_FLAG;
+    mcache->as.rcall.klass = 0;
+    mcache->as.rcall.node = NULL;
+    if (FIX2INT(argc) > 0) {
+	char *id_str;
+	size_t id_str_len;
+	char buf[100];
+
+	id_str = (char *)rb_sym2name(id);
+	id_str_len = strlen(id_str);
+
+	if (id_str[id_str_len - 1] != ':') {
+	    snprintf(buf, sizeof buf, "%s:", id_str);
+	    id_str = buf;
+	}
+
+	mcache->as.rcall.sel = sel_registerName(id_str);
+    }
+    else {
+	mcache->as.rcall.sel = sel_registerName(rb_sym2name(id));
+	if (mcache->as.rcall.sel == sel_ignored
+	    || mcache->as.rcall.sel == sel_zone) {
+	    char buf[100];
+	    snprintf(buf, sizeof buf, "__rb_%s__", rb_sym2name(id));
+	    mcache->as.rcall.sel = sel_registerName(buf);
+	}
+    }
+    GC_WB(&operands[4], (VALUE)mcache);
     iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
     return iobj;
 }
@@ -898,7 +929,7 @@
 	    i += 1;
 
 	    iseq->arg_opts = i;
-	    iseq->arg_opt_table = ALLOC_N(VALUE, i);
+	    GC_WB(&iseq->arg_opt_table, ALLOC_N(VALUE, i));
 #if WITH_OBJC
 	    CFArrayGetValues((CFArrayRef)labels, CFRangeMake(0, i), 
 		(const void **)iseq->arg_opt_table);
@@ -906,6 +937,9 @@
 	    MEMCPY(iseq->arg_opt_table, RARRAY_PTR(labels), VALUE, i);
 #endif
 	    for (j = 0; j < i; j++) {
+#if WITH_OBJC
+		iseq->arg_opt_table[j] = OC2RB(iseq->arg_opt_table[j]);
+#endif
 		iseq->arg_opt_table[j] &= ~1;
 	    }
 	}
@@ -1609,6 +1643,11 @@
 		    insn_set_specialized_instruction(iobj, BIN(opt_aref));
 		}
 	    }
+	    else if (argc == 2) {
+		if (mid == idASET) {
+		    insn_set_specialized_instruction(iobj, BIN(opt_aset));
+		}
+	    }
 	}
 
 	if (argc > 0) {

Modified: MacRuby/trunk/debug.h
===================================================================
--- MacRuby/trunk/debug.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/debug.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -29,4 +29,17 @@
 void  ruby_debug_breakpoint(void);
 void  ruby_debug_gc_check_func(void);
 
+#if ENABLE_DEBUG_LOGGING 
+# include "vm_core.h"
+extern bool ruby_dlog_enabled;
+# define DLOG(mod, fmt, args...)         \
+    if (UNLIKELY(ruby_dlog_enabled)) {   \
+	printf("%10s   ", mod);          \
+	printf(fmt, ##args);             \
+	printf("\n");                    \
+    }
+#else
+# define DLOG(mod, fmt, args...)
+#endif
+
 #endif /* RUBY_DEBUG_H */

Modified: MacRuby/trunk/encoding.c
===================================================================
--- MacRuby/trunk/encoding.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/encoding.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,14 +1,14 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's encoding.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  encoding.c -
-
-  $Author: nobu $
-  created at: Thu May 24 17:23:27 JST 2007
-
-  Copyright (C) 2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/encoding.h"
 #include "regenc.h"
@@ -20,8 +20,6 @@
 static ID id_encoding, id_base_encoding;
 VALUE rb_cEncoding;
 
-#if WITH_OBJC
-
 static CFMutableDictionaryRef __encodings = NULL;
 
 static VALUE
@@ -115,307 +113,6 @@
     return rb_enc_to_enc_ptr(v);
 }
 
-#else
-
-struct rb_encoding_entry {
-    const char *name;
-    rb_encoding *enc;
-};
-
-static struct {
-    struct rb_encoding_entry *list;
-    int count;
-    int size;
-    st_table *names;
-} enc_table;
-
-void rb_enc_init(void);
-
-#define ENCODING_COUNT ENCINDEX_BUILTIN_MAX
-
-#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
-
-#define ENC_UNINITIALIZED (&rb_cEncoding)
-#define enc_initialized_p(enc) ((enc)->auxiliary_data != &rb_cEncoding)
-#define ENC_FROM_ENCODING(enc) ((VALUE)(enc)->auxiliary_data)
-
-#define ENC_DUMMY_FLAG FL_USER2
-#define ENC_DUMMY_P(enc) (RBASIC(enc)->flags & ENC_DUMMY_FLAG)
-#define ENC_SET_DUMMY(enc) (RBASIC(enc)->flags |= ENC_DUMMY_FLAG)
-
-static int load_encoding(const char *name);
-static VALUE enc_base_encoding(VALUE self);
-
-static void
-enc_mark(void *ptr)
-{
-}
-
-static VALUE
-enc_new(rb_encoding *encoding)
-{
-    VALUE enc = Data_Wrap_Struct(rb_cEncoding, enc_mark, 0, encoding);
-    encoding->auxiliary_data = (void *)enc;
-    return enc;
-}
-
-VALUE
-rb_enc_from_encoding(rb_encoding *encoding)
-{
-    if (!encoding) return Qnil;
-    if (enc_initialized_p(encoding))
-	return ENC_FROM_ENCODING(encoding);
-    return enc_new(encoding);
-}
-
-static int
-enc_check_encoding(VALUE obj)
-{
-    int index;
-    rb_encoding *enc;
-
-    if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA ||
-	RDATA(obj)->dmark != enc_mark) {
-	return -1;
-    }
-    enc = (rb_encoding*)RDATA(obj)->data;
-    index = rb_enc_to_index(enc);
-    if (rb_enc_from_index(index) != enc)
-	return -1;
-    if (enc_autoload_p(enc)) {
-	index = rb_enc_find_index(enc->name);
-    }
-    return index;
-}
-
-int
-rb_to_encoding_index(VALUE enc)
-{
-    int idx;
-
-    idx = enc_check_encoding(enc);
-    if (idx >= 0) {
-	return idx;
-    }
-    else if (NIL_P(enc = rb_check_string_type(enc))) {
-	return -1;
-    }
-    else {
-	return rb_enc_find_index(StringValueCStr(enc));
-    }
-}
-
-rb_encoding *
-rb_to_encoding(VALUE enc)
-{
-    int idx;
-
-    idx = enc_check_encoding(enc);
-    if (idx >= 0) return RDATA(enc)->data;
-    if ((idx = rb_enc_find_index(StringValueCStr(enc))) < 0) {
-	rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
-    }
-    return rb_enc_from_index(idx);
-}
-
-void
-rb_gc_mark_encodings(void)
-{
-    int i;
-    for (i = 0; i < enc_table.count; ++i) {
-	rb_encoding *enc = enc_table.list[i].enc;
-	if (enc && enc_initialized_p(enc)) {
-	    rb_gc_mark(ENC_FROM_ENCODING(enc));
-	}
-    }
-}
-
-static int
-enc_table_expand(int newsize)
-{
-    struct rb_encoding_entry *ent;
-    int count = newsize;
-
-    if (enc_table.size >= newsize) return newsize;
-    newsize = (newsize + 7) / 8 * 8;
-    ent = realloc(enc_table.list, sizeof(*enc_table.list) * newsize);
-    if (!ent) return -1;
-    memset(ent + enc_table.size, 0, sizeof(*ent)*(newsize - enc_table.size));
-    enc_table.list = ent;
-    enc_table.size = newsize;
-    return count;
-}
-
-static int
-enc_register_at(int index, const char *name, rb_encoding *encoding)
-{
-    struct rb_encoding_entry *ent = &enc_table.list[index];
-    void *obj = ENC_UNINITIALIZED;
-
-    if (!ent->name) {
-	ent->name = name = strdup(name);
-    }
-    else if (STRCASECMP(name, ent->name)) {
-	return -1;
-    }
-    if (!ent->enc) {
-	ent->enc = malloc(sizeof(rb_encoding));
-    }
-    else {
-	obj = ent->enc->auxiliary_data;
-    }
-    if (encoding) {
-	*ent->enc = *encoding;
-    }
-    else {
-	memset(ent->enc, 0, sizeof(*ent->enc));
-    }
-    encoding = ent->enc;
-    encoding->name = name;
-    encoding->ruby_encoding_index = index;
-    st_insert(enc_table.names, (st_data_t)name, (st_data_t)index);
-    if (obj != ENC_UNINITIALIZED) {
-	encoding->auxiliary_data = obj;
-    }
-    else if (rb_cEncoding) {
-	/* initialize encoding data */
-	enc_new(encoding);
-    }
-    else {
-	encoding->auxiliary_data = ENC_UNINITIALIZED;
-    }
-    return index;
-}
-
-static int
-enc_register(const char *name, rb_encoding *encoding)
-{
-    int index = enc_table.count;
-
-    if ((index = enc_table_expand(index + 1)) < 0) return -1;
-    enc_table.count = index;
-    return enc_register_at(index - 1, name, encoding);
-}
-
-static void set_encoding_const(const char *, rb_encoding *);
-int rb_enc_registered(const char *name);
-
-int
-rb_enc_register(const char *name, rb_encoding *encoding)
-{
-    int index = rb_enc_registered(name);
-
-    if (index >= 0) {
-	rb_encoding *oldenc = rb_enc_from_index(index);
-	if (STRCASECMP(name, rb_enc_name(oldenc))) {
-	    index = enc_register(name, encoding);
-	}
-	else if (!enc_autoload_p(oldenc) ||
-		 (enc_initialized_p(oldenc) &&
-		  !ENC_DUMMY_P(ENC_FROM_ENCODING(oldenc)))) {
-	    enc_register_at(index, name, encoding);
-	}
-	else {
-	    rb_raise(rb_eArgError, "encoding %s is already registered", name);
-	}
-    }
-    else {
-	index = enc_register(name, encoding);
-	set_encoding_const(name, rb_enc_from_index(index));
-    }
-    return index;
-}
-
-void
-rb_encdb_declare(const char *name)
-{
-    int idx = rb_enc_registered(name);
-    if (idx < 0) {
-	idx = enc_register(name, 0);
-    }
-    set_encoding_const(name, rb_enc_from_index(idx));
-}
-
-static void
-enc_check_duplication(const char *name)
-{
-    if (rb_enc_registered(name) >= 0) {
-	rb_raise(rb_eArgError, "encoding %s is already registered", name);
-    }
-}
-
-static VALUE
-set_base_encoding(int index, rb_encoding *base)
-{
-    VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
-    rb_ivar_set(enc, id_base_encoding, rb_enc_from_encoding(base));
-    if (rb_enc_dummy_p(base)) ENC_SET_DUMMY(enc);
-    return enc;
-}
-
-int
-rb_enc_replicate(const char *name, rb_encoding *encoding)
-{
-    int idx;
-
-    enc_check_duplication(name);
-    idx = enc_register(name, encoding);
-    set_base_encoding(idx, encoding);
-    set_encoding_const(name, rb_enc_from_index(idx));
-    return idx;
-}
-
-static int
-enc_replicate(int idx, const char *name, rb_encoding *origenc)
-{
-    if (idx < 0) {
-	idx = enc_register(name, origenc);
-    }
-    else {
-	idx = enc_register_at(idx, name, origenc);
-    }
-    if (idx >= 0) {
-	set_base_encoding(idx, origenc);
-	set_encoding_const(name, rb_enc_from_index(idx));
-    }
-    return idx;
-}
-
-int
-rb_encdb_replicate(const char *name, const char *orig)
-{
-    int origidx = rb_enc_registered(orig);
-    int idx = rb_enc_registered(name);
-
-    if (origidx < 0) {
-	origidx = enc_register(orig, 0);
-    }
-    return enc_replicate(idx, name, rb_enc_from_index(origidx));
-}
-
-int
-rb_define_dummy_encoding(const char *name)
-{
-    int index = rb_enc_replicate(name, rb_ascii8bit_encoding());
-    VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
-    ENC_SET_DUMMY(enc);
-    return index;
-}
-
-int
-rb_encdb_dummy(const char *name)
-{
-    int index = enc_replicate(rb_enc_registered(name), name,
-			      rb_ascii8bit_encoding());
-    VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
-    ENC_SET_DUMMY(enc);
-    return index;
-}
-#endif // WITH_OBJC
-
 /*
  * call-seq:
  *   enc.dummy? => true or false
@@ -435,208 +132,6 @@
     return rb_enc_dummy_p(rb_to_encoding(enc)) ? Qtrue : Qfalse;
 }
 
-#if !WITH_OBJC
-static int
-enc_alias(const char *alias, int idx)
-{
-    alias = strdup(alias);
-    st_insert(enc_table.names, (st_data_t)alias, (st_data_t)idx);
-    set_encoding_const(alias, rb_enc_from_index(idx));
-    return idx;
-}
-
-int
-rb_enc_alias(const char *alias, const char *orig)
-{
-    int idx;
-
-    enc_check_duplication(alias);
-    if (!enc_table.list) {
-	rb_enc_init();
-    }
-    if ((idx = rb_enc_find_index(orig)) < 0) {
-	return -1;
-    }
-    return enc_alias(alias, idx);
-}
-
-int
-rb_encdb_alias(const char *alias, const char *orig)
-{
-    int idx = rb_enc_registered(orig);
-
-    if (idx < 0) {
-	idx = enc_register(orig, 0);
-    }
-    return enc_alias(alias, idx);
-}
-
-enum {
-    ENCINDEX_ASCII,
-    ENCINDEX_UTF_8,
-    ENCINDEX_US_ASCII,
-    ENCINDEX_BUILTIN_MAX
-};
-
-extern rb_encoding OnigEncodingUTF_8;
-extern rb_encoding OnigEncodingUS_ASCII;
-
-void
-rb_enc_init(void)
-{
-    enc_table_expand(ENCODING_COUNT + 1);
-    if (!enc_table.names) {
-	enc_table.names = st_init_strcasetable();
-	GC_ROOT(&enc_table.names);
-    }
-#define ENC_REGISTER(enc) enc_register_at(ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc)
-    ENC_REGISTER(ASCII);
-    ENC_REGISTER(UTF_8);
-    ENC_REGISTER(US_ASCII);
-#undef ENC_REGISTER
-    enc_table.count = ENCINDEX_BUILTIN_MAX;
-}
-
-rb_encoding *
-rb_enc_from_index(int index)
-{
-    if (!enc_table.list) {
-	rb_enc_init();
-    }
-    if (index < 0 || enc_table.count <= index) {
-	return 0;
-    }
-    return enc_table.list[index].enc;
-}
-
-int
-rb_enc_registered(const char *name)
-{
-    st_data_t idx = 0;
-
-    if (!name) return -1;
-    if (!enc_table.list) return -1;
-    if (st_lookup(enc_table.names, (st_data_t)name, &idx)) {
-	return (int)idx;
-    }
-    return -1;
-}
-
-static VALUE
-require_enc(VALUE enclib)
-{
-    return rb_require_safe(enclib, rb_safe_level());
-}
-
-static int
-load_encoding(const char *name)
-{
-    VALUE enclib = rb_sprintf("enc/%s", name);
-    VALUE verbose = ruby_verbose;
-    VALUE debug = ruby_debug;
-    VALUE loaded;
-    char *s = RSTRING_BYTEPTR(enclib) + 4, *e = RSTRING_END(enclib);
-    int idx;
-
-    while (s < e) {
-	if (!ISALNUM(*s)) *s = '_';
-	else if (ISUPPER(*s)) *s = TOLOWER(*s);
-	++s;
-    }
-    OBJ_FREEZE(enclib);
-    ruby_verbose = Qfalse;
-    ruby_debug = Qfalse;
-    loaded = rb_protect(require_enc, enclib, 0);
-    ruby_verbose = verbose;
-    ruby_debug = debug;
-    rb_set_errinfo(Qnil);
-    if (NIL_P(loaded)) return -1;
-    if ((idx = rb_enc_registered(name)) < 0) return -1;
-    if (enc_autoload_p(enc_table.list[idx].enc)) return -1;
-    return idx;
-}
-
-int
-rb_enc_find_index(const char *name)
-{
-    int i = rb_enc_registered(name), b;
-    rb_encoding *enc;
-    VALUE base;
-
-    if (i < 0) {
-	i = load_encoding(name);
-    }
-    else if (enc_autoload_p(enc = rb_enc_from_index(i))) {
-	if (enc_initialized_p(enc) &&
-	    (base = enc_base_encoding(ENC_FROM_ENCODING(enc)), !NIL_P(base))) {
-	    if ((b = enc_check_encoding(base)) < 0) {
-		goto failed;
-	    }
-	    enc_register_at(i, rb_enc_name(enc), rb_enc_from_index(b));
-	}
-	else {
-	    i = load_encoding(rb_enc_name(enc));
-	    if (i < 0) {
-	      failed:
-		rb_warn("failed to load encoding (%s); use ASCII-8BIT instead",
-			name);
-		return 0;
-	    }
-	}
-    }
-    return i;
-}
-
-rb_encoding *
-rb_enc_find(const char *name)
-{
-    int idx = rb_enc_find_index(name);
-    if (idx < 0) idx = 0;
-    return rb_enc_from_index(idx);
-}
-
-static inline int
-enc_capable(VALUE obj)
-{
-    if (SPECIAL_CONST_P(obj)) return Qfalse;
-    switch (/*BUILTIN_*/TYPE(obj)) {
-      case T_STRING:
-      case T_REGEXP:
-      case T_FILE:
-	return Qtrue;
-      case T_DATA:
-	if (RDATA(obj)->dmark == enc_mark) return Qtrue;
-      default:
-	return Qfalse;
-    }
-}
-
-static void
-enc_check_capable(VALUE x)
-{
-    if (!enc_capable(x)) {
-	const char *etype;
-
-	if (NIL_P(x)) {
-	    etype = "nil";
-	}
-	else if (FIXNUM_P(x)) {
-	    etype = "Fixnum";
-	}
-	else if (SYMBOL_P(x)) {
-	    etype = "Symbol";
-	}
-	else if (rb_special_const_p(x)) {
-	    etype = RSTRING_BYTEPTR(rb_obj_as_string(x));
-	}
-	else {
-	    etype = rb_obj_classname(x);
-	}
-	rb_raise(rb_eTypeError, "wrong argument type %s (not encode capable)", etype);
-    }
-}
-#endif
-
 ID
 rb_id_encoding(void)
 {
@@ -646,150 +141,16 @@
     return id_encoding;
 }
 
-#if !WITH_OBJC
-int
-rb_enc_internal_get_index(VALUE obj)
-{
-    int i;
-
-    i = ENCODING_GET_INLINED(obj);
-    if (i == ENCODING_INLINE_MAX) {
-	VALUE iv;
-
-	iv = rb_ivar_get(obj, rb_id_encoding());
-	i = NUM2INT(iv);
-    }
-    return i;
-}
-
-void
-rb_enc_internal_set_index(VALUE obj, int idx)
-{
-    if (idx < ENCODING_INLINE_MAX) {
-	ENCODING_SET_INLINED(obj, idx);
-	return;
-    }
-    ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX);
-    rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx));
-    return;
-}
-
-void
-rb_enc_associate_index(VALUE obj, int idx)
-{
-    enc_check_capable(obj);
-    if (rb_enc_internal_get_index(obj) == idx)
-    	return;
-    if (!ENC_CODERANGE_ASCIIONLY(obj) ||
-	!rb_enc_asciicompat(rb_enc_from_index(idx))) {
-	ENC_CODERANGE_CLEAR(obj);
-    }
-    rb_enc_internal_set_index(obj, idx);
-}
-
-void
-rb_enc_associate(VALUE obj, rb_encoding *enc)
-{
-    rb_enc_associate_index(obj, rb_enc_to_index(enc));
-}
-
-int
-rb_enc_get_index(VALUE obj)
-{
-    if (!enc_capable(obj)) return -1;
-    return rb_enc_internal_get_index(obj);
-}
-
 rb_encoding*
-rb_enc_get(VALUE obj)
-{
-    return rb_enc_from_index(rb_enc_get_index(obj));
-}
-
-rb_encoding*
-rb_enc_check(VALUE str1, VALUE str2)
-{
-    rb_encoding *enc = rb_enc_compatible(str1, str2);
-    if (!enc)
-	rb_raise(rb_eArgError, "character encodings differ: %s and %s",
-		 rb_enc_name(rb_enc_get(str1)),
-		 rb_enc_name(rb_enc_get(str2)));
-    return enc;
-}
-#endif
-
-rb_encoding*
 rb_enc_compatible(VALUE str1, VALUE str2)
 {
-#if WITH_OBJC
     /* TODO */
     rb_encoding *enc = rb_enc_get(str1);
     if (enc == rb_enc_get(str2))
 	return enc;
     return NULL;
-#else
-    int idx1, idx2;
-    rb_encoding *enc1, *enc2;
-
-    idx1 = rb_enc_get_index(str1);
-    idx2 = rb_enc_get_index(str2);
-
-    if (idx1 < 0 || idx2 < 0)
-        return 0;
-
-    if (idx1 == idx2) {
-	return rb_enc_from_index(idx1);
-    }
-    enc1 = rb_enc_from_index(idx1);
-    enc2 = rb_enc_from_index(idx2);
-
-    if (TYPE(str2) == T_STRING && RSTRING_BYTELEN(str2) == 0)
-	return enc1;
-    if (TYPE(str1) == T_STRING && RSTRING_BYTELEN(str1) == 0)
-	return enc2;
-    if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
-	return 0;
-    }
-
-    if (BUILTIN_TYPE(str1) != T_STRING) {
-	VALUE tmp = str1;
-	int idx0 = idx1;
-	str1 = str2;
-	str2 = tmp;
-	idx1 = idx2;
-	idx2 = idx0;
-    }
-    if (BUILTIN_TYPE(str1) == T_STRING) {
-	int cr1, cr2;
-
-	cr1 = rb_enc_str_coderange(str1);
-	if (BUILTIN_TYPE(str2) == T_STRING) {
-	    cr2 = rb_enc_str_coderange(str2);
-	    if (cr1 != cr2) {
-		/* may need to handle ENC_CODERANGE_BROKEN */
-		if (cr1 == ENC_CODERANGE_7BIT) return enc2;
-		if (cr2 == ENC_CODERANGE_7BIT) return enc1;
-	    }
-	    if (cr2 == ENC_CODERANGE_7BIT) {
-		if (idx1 == 0) return enc2;
-		return enc1;
-	    }
-	}
-	if (cr1 == ENC_CODERANGE_7BIT)
-	    return enc2;
-    }
-    return 0;
-#endif
 }
 
-#if !WITH_OBJC
-void
-rb_enc_copy(VALUE obj1, VALUE obj2)
-{
-    rb_enc_associate_index(obj1, rb_enc_get_index(obj2));
-}
-#endif
-
 /*
  *  call-seq:
  *     obj.encoding   => encoding
@@ -807,90 +168,6 @@
     return rb_enc_from_encoding(enc);
 }
 
-#if !WITH_OBJC
-int
-rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
-{
-    int n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
-    if (MBCLEN_CHARFOUND_P(n) && MBCLEN_CHARFOUND_LEN(n) <= e-p)
-        return MBCLEN_CHARFOUND_LEN(n);
-    else {
-        int min = rb_enc_mbminlen(enc);
-        return min <= e-p ? min : e-p;
-    }
-}
-
-int
-rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
-{
-    int n;
-    if (e <= p)
-        return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(1);
-    n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
-    if (e-p < n)
-        return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n-(e-p));
-    return n;
-}
-
-int
-rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
-{
-    int c, l;
-    if (e <= p)
-        return -1;
-    if (rb_enc_asciicompat(enc)) {
-        c = (unsigned char)*p;
-        if (!ISASCII(c))
-            return -1;
-        if (len) *len = 1;
-        return c;
-    }
-    l = rb_enc_precise_mbclen(p, e, enc);
-    if (!MBCLEN_CHARFOUND_P(l))
-        return -1;
-    c = rb_enc_mbc_to_codepoint(p, e, enc);
-    if (!rb_enc_isascii(c, enc))
-        return -1;
-    if (len) *len = l;
-    return c;
-}
-
-int
-rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
-{
-    int r;
-    if (e <= p)
-        rb_raise(rb_eArgError, "empty string");
-    r = rb_enc_precise_mbclen(p, e, enc);
-    if (MBCLEN_CHARFOUND_P(r))
-        return rb_enc_mbc_to_codepoint(p, e, enc);
-    else
-	rb_raise(rb_eArgError, "invalid mbstring sequence");
-}
-
-int
-rb_enc_codelen(int c, rb_encoding *enc)
-{
-    int n = ONIGENC_CODE_TO_MBCLEN(enc,c);
-    if (n == 0) {
-	rb_raise(rb_eArgError, "invalid codepoint 0x%x", c);
-    }
-    return n;
-}
-
-int
-rb_enc_toupper(int c, rb_encoding *enc)
-{
-    return (ONIGENC_IS_ASCII_CODE(c)?ONIGENC_ASCII_CODE_TO_UPPER_CASE(c):(c));
-}
-
-int
-rb_enc_tolower(int c, rb_encoding *enc)
-{
-    return (ONIGENC_IS_ASCII_CODE(c)?ONIGENC_ASCII_CODE_TO_LOWER_CASE(c):(c));
-}
-#endif
-
 /*
  * call-seq:
  *   enc.inspect => string
@@ -903,7 +180,6 @@
 static VALUE
 enc_inspect(VALUE self)
 {
-#if WITH_OBJC
     char buffer[512];
     VALUE enc_name;
     long n;
@@ -914,13 +190,6 @@
 	RSTRING_PTR(enc_name));
 
     return rb_str_new(buffer, n);
-#else
-    VALUE str = rb_sprintf("#<%s:%s%s>", rb_obj_classname(self),
-		      rb_enc_name((rb_encoding*)DATA_PTR(self)),
-		      (ENC_DUMMY_P(self) ? " (dummy)" : ""));
-    ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
-    return str;
-#endif
 }
 
 /*
@@ -934,11 +203,7 @@
 static VALUE
 enc_name(VALUE self)
 {
-#if WITH_OBJC
     return (VALUE)CFStringConvertEncodingToIANACharSetName(rb_enc_to_enc(self));
-#else
-    return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
-#endif
 }
 
 static VALUE
@@ -968,7 +233,6 @@
 static VALUE
 enc_list(VALUE klass)
 {
-#if WITH_OBJC
     VALUE ary;
     const CFStringEncoding *e;
 
@@ -978,16 +242,6 @@
 	rb_ary_push(ary, enc_make(e));
 	e++;
     }
-#else
-    VALUE ary = rb_ary_new2(enc_table.count);
-    int i;
-    for (i = 0; i < enc_table.count; ++i) {
-	rb_encoding *enc = enc_table.list[i].enc;
-	if (enc) {
-	    rb_ary_push(ary, rb_enc_from_encoding(enc));
-	}
-    }
-#endif
     return ary;
 }
 
@@ -1028,24 +282,10 @@
 static VALUE
 enc_find(VALUE klass, VALUE enc)
 {
-#if WITH_OBJC
     VALUE e = enc_find2(enc);
     if (e == Qnil)
 	rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
     return e;
-#else
-    int idx;
-
-    StringValue(enc);
-    if (!rb_enc_asciicompat(rb_enc_get(enc))) {
-	rb_raise(rb_eArgError, "invalid name encoding (non ASCII)");
-    }
-    idx = rb_enc_find_index(StringValueCStr(enc));
-    if (idx < 0) {
-	rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
-    }
-    return rb_enc_from_encoding(rb_enc_from_index(idx));
-#endif
 }
 
 /*
@@ -1091,72 +331,6 @@
     return enc_find(klass, str);
 }
 
-#if !WITH_OBJC
-rb_encoding *
-rb_ascii8bit_encoding(void)
-{
-    if (!enc_table.list) {
-	rb_enc_init();
-    }
-    return enc_table.list[0].enc;
-}
-
-rb_encoding *
-rb_utf8_encoding(void)
-{
-    if (!enc_table.list) {
-	rb_enc_init();
-    }
-    return enc_table.list[ENCINDEX_UTF_8].enc;
-}
-
-rb_encoding *
-rb_usascii_encoding(void)
-{
-    if (!enc_table.list) {
-	rb_enc_init();
-    }
-    return enc_table.list[ENCINDEX_US_ASCII].enc;
-}
-
-int
-rb_usascii_encindex(void)
-{
-    return ENCINDEX_US_ASCII;
-}
-
-rb_encoding *
-rb_locale_encoding(void)
-{
-    VALUE charmap = rb_locale_charmap(rb_cEncoding);
-    int idx;
-
-    if (NIL_P(charmap))
-        idx = rb_enc_find_index("US-ASCII");
-    else
-        idx = rb_enc_find_index(StringValueCStr(charmap));
-    if (idx < 0)
-        return rb_ascii8bit_encoding();
-
-    return rb_enc_from_index(idx);
-}
-
-static int default_external_index;
-
-rb_encoding *
-rb_default_external_encoding(void)
-{
-    return rb_enc_from_index(default_external_index);
-}
-
-VALUE
-rb_enc_default_external(void)
-{
-    return rb_enc_from_encoding(rb_default_external_encoding());
-}
-#endif
-
-#if WITH_OBJC
 static rb_encoding *default_external;
     
 rb_encoding *
@@ -1170,7 +344,6 @@
 {
     return enc_make(default_external);
 }
-#endif
 
 /*
  * call-seq:
@@ -1189,11 +362,7 @@
 void
 rb_enc_set_default_external(VALUE encoding)
 {
-#if WITH_OBJC
     default_external = rb_enc_to_enc_ptr(encoding);
-#else
-    default_external_index = rb_enc_to_index(rb_to_encoding(encoding));
-#endif
 }
 
 /*
@@ -1218,80 +387,10 @@
 VALUE
 rb_locale_charmap(VALUE klass)
 {
-#if WITH_OBJC
     CFStringEncoding enc = CFStringGetSystemEncoding();
     return (VALUE)CFStringConvertEncodingToIANACharSetName(enc);
-#elif defined NO_LOCALE_CHARMAP
-    return rb_usascii_str_new2("ASCII-8BIT");
-#elif defined HAVE_LANGINFO_H
-    char *codeset;
-    codeset = nl_langinfo(CODESET);
-    return rb_usascii_str_new2(codeset);
-#elif defined _WIN32
-    return rb_sprintf("CP%d", GetACP());
-#else
-    return Qnil;
-#endif
 }
 
-#if !WITH_OBJC
-static void
-set_encoding_const(const char *name, rb_encoding *enc)
-{
-    VALUE encoding = rb_enc_from_encoding(enc);
-    char *s = (char *)name;
-    int haslower = 0, hasupper = 0, valid = 0;
-
-    if (ISDIGIT(*s)) return;
-    if (ISUPPER(*s)) {
-	hasupper = 1;
-	while (*++s && (ISALNUM(*s) || *s == '_')) {
-	    if (ISLOWER(*s)) haslower = 1;
-	}
-    }
-    if (!*s) {
-	valid = 1;
-	rb_define_const(rb_cEncoding, name, encoding);
-    }
-    if (!valid || haslower) {
-	int len = strlen(name) + 1;
-	if (!haslower || !hasupper) {
-	    do {
-		if (ISLOWER(*s)) haslower = 1;
-		if (ISUPPER(*s)) hasupper = 1;
-	    } while (*++s && (!haslower || !hasupper));
-	}
-	MEMCPY(s = ALLOCA_N(char, len), name, char, len);
-	name = s;
-	if (!valid) {
-	    if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
-	    for (; *s; ++s) {
-		if (!ISALNUM(*s)) *s = '_';
-	    }
-	    if (hasupper) {
-		rb_define_const(rb_cEncoding, name, encoding);
-	    }
-	}
-	if (haslower) {
-	    for (s = (char *)name; *s; ++s) {
-		if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
-	    }
-	    rb_define_const(rb_cEncoding, name, encoding);
-	}
-    }
-}
-
-static int
-rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg)
-{
-    VALUE ary = (VALUE)arg;
-    VALUE str = rb_usascii_str_new2((char *)name);
-    OBJ_FREEZE(str);
-    rb_ary_push(ary, str);
-    return ST_CONTINUE;
-}
-#endif
-
 /*
  * call-seq:
  *   Encoding.name_list => ["enc1", "enc2", ...]
@@ -1311,7 +410,6 @@
 static VALUE
 rb_enc_name_list(VALUE klass)
 {
-#if WITH_OBJC
     VALUE ary, list;
     long i, count;
 
@@ -1319,39 +417,9 @@
     list = enc_list(klass);
     for (i = 0, count = RARRAY_LEN(list); i < count; i++)
 	rb_ary_push(ary, enc_name(RARRAY_AT(list, i)));
-#else
-    VALUE ary = rb_ary_new2(enc_table.names->num_entries);
-    st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
-#endif
     return ary;
 }
 
-#if !WITH_OBJC
-static int
-rb_enc_aliases_enc_i(st_data_t name, st_data_t orig, st_data_t arg)
-{
-    VALUE *p = (VALUE *)arg;
-    VALUE aliases = p[0], ary = p[1];
-    int idx = (int)orig;
-    VALUE key, str = rb_ary_entry(ary, idx);
-
-    if (NIL_P(str)) {
-	rb_encoding *enc = rb_enc_from_index(idx);
-
-	if (STRCASECMP((char*)name, rb_enc_name(enc)) == 0) {
-	    return ST_CONTINUE;
-	}
-	str = rb_usascii_str_new2(rb_enc_name(enc));
-	OBJ_FREEZE(str);
-	rb_ary_store(ary, idx, str);
-    }
-    key = rb_usascii_str_new2((char *)name);
-    OBJ_FREEZE(key);
-    rb_hash_aset(aliases, key, str);
-    return ST_CONTINUE;
-}
-#endif
-
 /*
  * call-seq:
  *   Encoding.aliases => {"alias1" => "orig1", "alias2" => "orig2", ...}
@@ -1367,18 +435,10 @@
 static VALUE
 rb_enc_aliases(VALUE klass)
 {
-#if WITH_OBJC
     /* TODO: the CFString IANA <-> charset code does support aliases, we should
      * find a way to return them here. 
      */
     return rb_hash_new();
-#else
-    VALUE aliases[2];
-    aliases[0] = rb_hash_new();
-    aliases[1] = rb_ary_new();
-    st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
-    return aliases[0];
-#endif
 }
 
 VALUE

Modified: MacRuby/trunk/eval.c
===================================================================
--- MacRuby/trunk/eval.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/eval.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -54,6 +54,10 @@
 void Init_PreGC(void);
 void Init_BareVM(void);
 
+#if WITH_OBJC
+bool ruby_dlog_enabled = false;
+#endif
+
 void
 ruby_init(void)
 {
@@ -70,6 +74,11 @@
     rb_origenviron = environ;
 #endif
 
+#if WITH_OBJC
+    char *s = getenv("MACRUBY_DEBUG");
+    ruby_dlog_enabled = !(s == NULL || *s == '0');
+#endif
+
     Init_stack((void *)&state);
     Init_PreGC();
     Init_BareVM();
@@ -336,7 +345,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)) {
@@ -857,11 +866,11 @@
     return module;
 }
 
-void
+VALUE
 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
 {
     PASS_PASSED_BLOCK();
-    rb_funcall2(obj, idInitialize, argc, argv);
+    return rb_funcall2(obj, idInitialize, argc, argv);
 }
 
 void

Modified: MacRuby/trunk/ext/extmk.rb
===================================================================
--- MacRuby/trunk/ext/extmk.rb	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/ext/extmk.rb	2008-08-21 06:13:14 UTC (rev 459)
@@ -85,7 +85,6 @@
 end
 
 def extmake(target)
-GC.start
   print "#{$message} #{target}\n"
   $stdout.flush
   if $force_static or $static_ext[target]
@@ -431,8 +430,6 @@
 FileUtils::makedirs('ext')
 Dir::chdir('ext')
 
-GC.start
-
 hdrdir = $hdrdir
 $hdrdir = ($top_srcdir = relative_from(srcdir, $topdir = "..")) + "/include"
 exts.each do |d|

Modified: MacRuby/trunk/ext/syck/rubyext.c
===================================================================
--- MacRuby/trunk/ext/syck/rubyext.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/ext/syck/rubyext.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -22,11 +22,11 @@
 #endif
     struct RBasic  basic;
     struct RObject object;
-    struct RClass  klass;
     /*struct RFloat  flonum;*/
     /*struct RString string;*/
     /*struct RRegexp regexp;*/
 #if !WITH_OBJC
+    struct RClass  klass;
     struct RArray  array;
     struct RHash   hash;
 #endif

Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/gc.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,16 +1,14 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's gc.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  gc.c -
-
-  $Author: akr $
-  created at: Tue Oct  5 09:44:46 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-  Copyright (C) 2000  Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/signal.h"
 #include "ruby/st.h"
@@ -33,16 +31,11 @@
 #include <sys/resource.h>
 #endif
 
-#if defined _WIN32 || defined __CYGWIN__
-#include <windows.h>
-#endif
-
-#if WITH_OBJC
-# include <mach/mach.h>
-# if HAVE_AUTO_ZONE_H
-#  include <auto_zone.h>
-# else
-#  include <malloc/malloc.h>
+#include <mach/mach.h>
+#if HAVE_AUTO_ZONE_H
+# include <auto_zone.h>
+#else
+# include <malloc/malloc.h>
 typedef malloc_zone_t auto_zone_t;
 #define AUTO_MEMORY_SCANNED   0
 #define AUTO_MEMORY_UNSCANNED 1
@@ -110,57 +103,17 @@
     size_t              bytes_freed_during_last_collection[2];
     // durations not included
 } auto_statistics_t;
-# endif
+#endif
 static auto_zone_t *__auto_zone = NULL;
 static long xmalloc_count = 0;
-#endif
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-# include <valgrind/memcheck.h>
-# ifndef VALGRIND_MAKE_MEM_DEFINED
-#  define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE(p, n)
-# endif
-# ifndef VALGRIND_MAKE_MEM_UNDEFINED
-#  define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE(p, n)
-# endif
-#else
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) /* empty */
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) /* empty */
-#endif
-
 int rb_io_fptr_finalize(struct rb_io_t*);
 
-#define rb_setjmp(env) RUBY_SETJMP(env)
 #define rb_jmp_buf rb_jmpbuf_t
 
-/* Make alloca work the best possible way.  */
-#ifdef __GNUC__
-# ifndef atarist
-#  ifndef alloca
-#   define alloca __builtin_alloca
-#  endif
-# endif /* atarist */
-#else
-# ifdef HAVE_ALLOCA_H
-#  include <alloca.h>
-# else
-#  ifdef _AIX
- #pragma alloca
-#  else
-#   ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca ();
-#   endif
-#  endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
 #ifndef GC_MALLOC_LIMIT
-#if defined(MSDOS) || defined(__human68k__)
-#define GC_MALLOC_LIMIT 200000
-#else
-#define GC_MALLOC_LIMIT 8000000
+# define GC_MALLOC_LIMIT 8000000
 #endif
-#endif
 
 static VALUE nomem_error;
 
@@ -170,169 +123,6 @@
 
 #undef GC_DEBUG
 
-#if !WITH_OBJC
-
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
-#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
-#endif
-
-typedef struct RVALUE {
-    union {
-	struct {
-	    VALUE flags;		/* always 0 for freed obj */
-	    struct RVALUE *next;
-	} free;
-	struct RBasic  basic;
-	struct RObject object;
-	struct RClass  klass;
-	struct RFloat  flonum;
-	struct RString string;
-	struct RArray  array;
-	struct RRegexp regexp;
-	struct RHash   hash;
-	struct RData   data;
-	struct RStruct rstruct;
-	struct RBignum bignum;
-	struct RFile   file;
-	struct RNode   node;
-	struct RMatch  match;
-	struct RRational rational;
-	struct RComplex complex;
-    } as;
-#ifdef GC_DEBUG
-    char *file;
-    int   line;
-#endif
-} RVALUE;
-
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
-#pragma pack(pop)
-#endif
-
-struct heaps_slot {
-    void *membase;
-    RVALUE *slot;
-    int limit;
-};
-
-#define HEAP_MIN_SLOTS 10000
-#define FREE_MIN  4096
-
-struct gc_list {
-    VALUE *varptr;
-    struct gc_list *next;
-};
-
-typedef struct rb_objspace {
-    struct {
-	size_t limit;
-	size_t increase;
-    } params;
-    struct {
-	size_t increment;
-	struct heaps_slot *ptr;
-	size_t length;
-	size_t used;
-	RVALUE *freelist;
-	RVALUE *range[2];
-	RVALUE *freed;
-    } heap;
-    struct {
-	int dont_gc;
-	int during_gc;
-    } flags;
-    struct {
-	int need_call;
-	st_table *table;
-	RVALUE *deferred;
-    } final;
-    struct {
-	VALUE buffer[MARK_STACK_MAX];
-	VALUE *ptr;
-	int overflow;
-    } markstack;
-    struct gc_list *global_list;
-    unsigned int count;
-} rb_objspace_t;
-
-#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
-#define rb_objspace (*GET_VM()->objspace)
-#else
-static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}};
-#endif
-#define malloc_limit		objspace->params.limit
-#define malloc_increase 	objspace->params.increase
-#define heap_slots		objspace->heap.slots
-#define heaps			objspace->heap.ptr
-#define heaps_length		objspace->heap.length
-#define heaps_used		objspace->heap.used
-#define freelist		objspace->heap.freelist
-#define lomem			objspace->heap.range[0]
-#define himem			objspace->heap.range[1]
-#define heaps_inc		objspace->heap.increment
-#define heaps_freed		objspace->heap.freed
-#define dont_gc 		objspace->flags.dont_gc
-#define during_gc		objspace->flags.during_gc
-#define need_call_final 	objspace->final.need_call
-#define finalizer_table 	objspace->final.table
-#define deferred_final_list	objspace->final.deferred
-#define mark_stack		objspace->markstack.buffer
-#define mark_stack_ptr		objspace->markstack.ptr
-#define mark_stack_overflow	objspace->markstack.overflow
-#define global_List		objspace->global_list
-
-rb_objspace_t *
-rb_objspace_alloc(void)
-{
-    rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t));
-    memset(objspace, 0, sizeof(*objspace));
-    malloc_limit = GC_MALLOC_LIMIT;
-
-    return objspace;
-}
-
-/* tiny heap size */
-/* 32KB */
-/*#define HEAP_SIZE 0x8000 */
-/* 128KB */
-/*#define HEAP_SIZE 0x20000 */
-/* 64KB */
-/*#define HEAP_SIZE 0x10000 */
-/* 16KB */
-#define HEAP_SIZE 0x4000
-/* 8KB */
-/*#define HEAP_SIZE 0x2000 */
-/* 4KB */
-/*#define HEAP_SIZE 0x1000 */
-/* 2KB */
-/*#define HEAP_SIZE 0x800 */
-
-#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
-#define FREE_MIN  4096
-
-extern st_table *rb_class_tbl;
-VALUE *rb_gc_stack_start = 0;
-#ifdef __ia64
-VALUE *rb_gc_register_stack_start = 0;
-#endif
-
-
-#ifdef DJGPP
-/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
-unsigned int _stklen = 0x180000; /* 1.5 kB */
-#endif
-
-#if defined(DJGPP) || defined(_WIN32_WCE)
-size_t rb_gc_stack_maxsize = 65535*sizeof(VALUE);
-#else
-size_t rb_gc_stack_maxsize = 655300*sizeof(VALUE);
-#endif
-
-static void run_final(rb_objspace_t *objspace, VALUE obj);
-static int garbage_collect(rb_objspace_t *objspace);
-
-#else
-
 int ruby_gc_stress = 0;
 static long malloc_increase = 0;
 bool dont_gc = false;
@@ -343,8 +133,6 @@
 #endif
 size_t rb_gc_stack_maxsize = 655300*sizeof(VALUE);
 
-#endif
-
 void
 rb_global_variable(VALUE *var)
 {
@@ -407,8 +195,6 @@
 	garbage_collect();
 }
 
-#if WITH_OBJC
-
 static void
 rb_objc_no_gc_error(void)
 { 
@@ -498,131 +284,13 @@
     return ruby_xrealloc(ptr, len);
 }
 
-#else
-
-void *
-ruby_vm_xmalloc(rb_objspace_t *objspace, size_t size)
-{
-    void *mem;
-
-    if (size < 0) {
-	rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
-    }
-    if (size == 0) size = 1;
-    rb_gc_malloc_increase(size);
-    RUBY_CRITICAL(mem = malloc(size));
-    if (!mem) {
-	if (garbage_collect(objspace)) {
-	    RUBY_CRITICAL(mem = malloc(size));
-	}
-	if (!mem) {
-	    rb_memerror();
-	}
-    }
-
-    return mem;
-}
-
-void *
-ruby_xmalloc(size_t size)
-{
-    return ruby_vm_xmalloc(&rb_objspace, size);
-}
-
-void *
-ruby_vm_xmalloc2(rb_objspace_t *objspace, size_t n, size_t size)
-{
-    size_t len = size * n;
-    if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "malloc: possible integer overflow");
-    }
-    return ruby_vm_xmalloc(objspace, len);
-}
-
-void *
-ruby_xmalloc2(size_t n, size_t size)
-{
-    return ruby_vm_xmalloc2(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xcalloc(rb_objspace_t *objspace, size_t n, size_t size)
-{
-    void *mem;
-
-    mem = ruby_vm_xmalloc2(objspace, n, size);
-    memset(mem, 0, n * size);
-
-    return mem;
-}
-
-void *
-ruby_xcalloc(size_t n, size_t size)
-{
-    return ruby_vm_xcalloc(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
-{
-    void *mem;
-
-    if (size < 0) {
-	rb_raise(rb_eArgError, "negative re-allocation size");
-    }
-    if (!ptr) return ruby_xmalloc(size);
-    if (size == 0) size = 1;
-    malloc_increase += size;
-    if (ruby_gc_stress) garbage_collect();
-    RUBY_CRITICAL(mem = realloc(ptr, size));
-    if (!mem) {
-	if (garbage_collect(objspace)) {
-	    RUBY_CRITICAL(mem = realloc(ptr, size));
-	}
-	if (!mem) {
-	    rb_memerror();
-        }
-    }
-
-    return mem;
-}
-
-void *
-ruby_xrealloc(void *ptr, size_t size)
-{
-    return ruby_vm_xrealloc(&rb_objspace, ptr, size);
-}
-
-void *
-ruby_vm_xrealloc2(rb_objspace_t *objspace, void *ptr, size_t n, size_t size)
-{
-    size_t len = size * n;
-    if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "realloc: possible integer overflow");
-    }
-    return ruby_vm_xrealloc(objspace, ptr, len);
-}
-
-void *
-ruby_xrealloc2(void *ptr, size_t n, size_t size)
-{
-    return ruby_vm_xrealloc2(&rb_objspace, ptr, n, size);
-}
-
-#endif
-
 void
 ruby_xfree(void *x)
 {
-#if WITH_OBJC
     if (x != NULL) {
 	auto_zone_retain(__auto_zone, x);
 	malloc_zone_free(__auto_zone, x);
     }
-#else
-    if (x)
-	RUBY_CRITICAL(free(x));
-#endif
 }
 
 
@@ -644,9 +312,7 @@
 {
     int old = dont_gc;
 
-#if WITH_OBJC
     auto_collector_reenable(__auto_zone);
-#endif
     dont_gc = Qfalse;
     return old;
 }
@@ -668,257 +334,14 @@
 {
     int old = dont_gc;
 
-#if WITH_OBJC
     auto_collector_disable(__auto_zone);
-#endif
     dont_gc = Qtrue;
     return old;
 }
 
 VALUE rb_mGC;
 
-#if !WITH_OBJC
-
 void
-rb_gc_register_address(VALUE *addr)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-    struct gc_list *tmp;
-
-    tmp = ALLOC(struct gc_list);
-    tmp->next = global_List;
-    tmp->varptr = addr;
-    global_List = tmp;
-}
-
-void
-rb_register_mark_object(VALUE obj)
-{
-    VALUE ary = GET_THREAD()->vm->mark_object_ary;
-    rb_ary_push(ary, obj);
-}
-
-void
-rb_gc_unregister_address(VALUE *addr)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-    struct gc_list *tmp = global_List;
-
-    if (tmp->varptr == addr) {
-	global_List = tmp->next;
-	RUBY_CRITICAL(free(tmp));
-	return;
-    }
-    while (tmp->next) {
-	if (tmp->next->varptr == addr) {
-	    struct gc_list *t = tmp->next;
-
-	    tmp->next = tmp->next->next;
-	    RUBY_CRITICAL(free(t));
-	    break;
-	}
-	tmp = tmp->next;
-    }
-}
-
-
-static void
-allocate_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
-{
-    struct heaps_slot *p;
-    size_t size;
-
-    size = next_heaps_length*sizeof(struct heaps_slot);
-    RUBY_CRITICAL(
-		  if (heaps_used > 0) {
-		      p = (struct heaps_slot *)realloc(heaps, size);
-		      if (p) heaps = p;
-		  }
-		  else {
-		      p = heaps = (struct heaps_slot *)malloc(size);
-		  }
-		  );
-    if (p == 0) rb_memerror();
-    heaps_length = next_heaps_length;
-}
-
-static void
-assign_heap_slot(rb_objspace_t *objspace)
-{
-    RVALUE *p, *pend, *membase;
-    size_t hi, lo, mid;
-    int objs;
-	
-    objs = HEAP_OBJ_LIMIT;
-    RUBY_CRITICAL(p = (RVALUE*)malloc(HEAP_SIZE));
-    if (p == 0)
-	rb_memerror();
-
-    membase = p;
-    if ((VALUE)p % sizeof(RVALUE) != 0) {
-	p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
-	if ((HEAP_SIZE - HEAP_OBJ_LIMIT * sizeof(RVALUE)) < ((char*)p - (char*)membase)) {
-	    objs--;
-	}
-    }
-    	
-
-    lo = 0;
-    hi = heaps_used;
-    while (lo < hi) {
-	register RVALUE *mid_membase;
-	mid = (lo + hi) / 2;
-	mid_membase = heaps[mid].membase;
-	if (mid_membase < membase) {
-	    lo = mid + 1;
-	}
-	else if (mid_membase > membase) {
-	    hi = mid;
-	}
-	else {
-	    rb_bug("same heap slot is allocated: %p at %ld", membase, mid);
-	}
-    }
-    if (hi < heaps_used) {
-	MEMMOVE(&heaps[hi+1], &heaps[hi], struct heaps_slot, heaps_used - hi);
-    }
-    heaps[hi].membase = membase;
-    heaps[hi].slot = p;
-    heaps[hi].limit = objs;
-    pend = p + objs;
-    if (lomem == 0 || lomem > p) lomem = p;
-    if (himem < pend) himem = pend;
-    heaps_used++;
-
-    while (p < pend) {
-	p->as.free.flags = 0;
-	p->as.free.next = freelist;
-	freelist = p;
-	p++;
-    }
-}
-
-static void
-init_heap(rb_objspace_t *objspace)
-{
-    size_t add, i;
-
-    add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT;
-
-    if ((heaps_used + add) > heaps_length) {
-    	allocate_heaps(objspace, heaps_used + add);
-    }
-
-    for (i = 0; i < add; i++) {
-    	assign_heap_slot(objspace);
-    }
-    heaps_inc = 0;
-}
-
-
-static void
-set_heaps_increment(rb_objspace_t *objspace)
-{
-    size_t next_heaps_length = heaps_used * 1.8;
-    heaps_inc = next_heaps_length - heaps_used;
-
-    if (next_heaps_length > heaps_length) {
-	allocate_heaps(objspace, next_heaps_length);
-    }
-}
-
-static int
-heaps_increment(rb_objspace_t *objspace)
-{
-    if (heaps_inc > 0) {
-	assign_heap_slot(objspace);
-	heaps_inc--;
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-#define RANY(o) ((RVALUE*)(o))
-
-static VALUE
-rb_newobj_from_heap(rb_objspace_t *objspace)
-{
-    VALUE obj;
-	
-    if (ruby_gc_stress || !freelist) {
-    	if (!heaps_increment(objspace) && !garbage_collect(objspace)) {
-	    rb_memerror();
-	}
-    }
-
-    obj = (VALUE)freelist;
-    freelist = freelist->as.free.next;
-
-    MEMZERO((void*)obj, RVALUE, 1);
-#ifdef GC_DEBUG
-    RANY(obj)->file = rb_sourcefile();
-    RANY(obj)->line = rb_sourceline();
-#endif
-
-    return obj;
-}
-
-#if USE_VALUE_CACHE
-static VALUE
-rb_fill_value_cache(rb_thread_t *th)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-    int i;
-    VALUE rv;
-
-    /* LOCK */
-    for (i=0; i<RUBY_VM_VALUE_CACHE_SIZE; i++) {
-	VALUE v = rb_newobj_from_heap(objspace);
-
-	th->value_cache[i] = v;
-	RBASIC(v)->flags = FL_MARK;
-    }
-    th->value_cache_ptr = &th->value_cache[0];
-    rv = rb_newobj_from_heap(objspace);
-    /* UNLOCK */
-    return rv;
-}
-#endif
-
-VALUE
-rb_newobj(void)
-{
-#if USE_VALUE_CACHE
-    rb_thread_t *th = GET_THREAD();
-    VALUE v = *th->value_cache_ptr;
-#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
-    rb_objspace_t *objspace = th->vm->objspace;
-#else
-    rb_objspace_t *objspace = &rb_objspace;
-#endif
-
-    if (v) {
-	RBASIC(v)->flags = 0;
-	th->value_cache_ptr++;
-    }
-    else {
-	v = rb_fill_value_cache(th);
-    }
-
-#if defined(GC_DEBUG)
-    printf("cache index: %d, v: %p, th: %p\n",
-	   th->value_cache_ptr - th->value_cache, v, th);
-#endif
-    return v;
-#else
-    rb_objspace_t *objspace = &rb_objspace;
-    return rb_newobj_from_heap(objspace);
-#endif
-}
-
-#else /* !WITH_OBJC */
-
-void
 rb_objc_wb(void *dst, void *newval)
 {
     if (!SPECIAL_CONST_P(newval)) {
@@ -1029,7 +452,7 @@
 #endif
     if (__nsobject == NULL)
 	__nsobject = (void *)objc_getClass("NSObject");
-    RBASIC(obj)->isa = __nsobject;
+    RBASIC(obj)->klass = (VALUE)__nsobject;
     return obj;
 }
 
@@ -1053,8 +476,6 @@
     //(*scanner)(context, th->stack, th->stack + th->stack_size);
 } 
 
-#endif /* WITH_OBJC */
-
 NODE*
 rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
 {
@@ -1148,960 +569,13 @@
     return ret;
 }
 
-#if !WITH_OBJC
-static void
-init_mark_stack(rb_objspace_t *objspace)
-{
-    mark_stack_overflow = 0;
-    mark_stack_ptr = mark_stack;
-}
-
-#define MARK_STACK_EMPTY (mark_stack_ptr == mark_stack)
-
-
-static void gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev);
-static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev);
-
-static void
-gc_mark_all(rb_objspace_t *objspace)
-{
-    RVALUE *p, *pend;
-    size_t i;
-
-    init_mark_stack(objspace);
-    for (i = 0; i < heaps_used; i++) {
-	p = heaps[i].slot; pend = p + heaps[i].limit;
-	while (p < pend) {
-	    if ((p->as.basic.flags & FL_MARK) &&
-		(p->as.basic.flags != FL_MARK)) {
-		gc_mark_children(objspace, (VALUE)p, 0);
-	    }
-	    p++;
-	}
-    }
-}
-
-static void
-gc_mark_rest(rb_objspace_t *objspace)
-{
-    VALUE tmp_arry[MARK_STACK_MAX];
-    VALUE *p;
-
-    p = (mark_stack_ptr - mark_stack) + tmp_arry;
-    MEMCPY(tmp_arry, mark_stack, VALUE, p - tmp_arry);
-
-    init_mark_stack(objspace);
-    while (p != tmp_arry) {
-	p--;
-	gc_mark_children(objspace, *p, 0);
-    }
-}
-
-static inline int
-is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
-{
-    register RVALUE *p = RANY(ptr);
-    register struct heaps_slot *heap;
-    register size_t hi, lo, mid;
-
-    if (p < lomem || p > himem) return Qfalse;
-    if ((VALUE)p % sizeof(RVALUE) != 0) return Qfalse;
-
-    /* check if p looks like a pointer using bsearch*/
-    lo = 0;
-    hi = heaps_used;
-    while (lo < hi) {
-	mid = (lo + hi) / 2;
-	heap = &heaps[mid];
-	if (heap->slot <= p) {
-	    if (p < heap->slot + heap->limit)
-		return Qtrue;
-	    lo = mid + 1;
-	}
-	else {
-	    hi = mid;
-	}
-    }
-    return Qfalse;
-}
-
-static void
-mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
-{
-    VALUE v;
-    while (n--) {
-        v = *x;
-        VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
-	if (is_pointer_to_heap(objspace, (void *)v)) {
-	    gc_mark(objspace, v, 0);
-	}
-	x++;
-    }
-}
-
-static void
-gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
-{
-    long n;
-
-    if (end <= start) return;
-    n = end - start;
-    mark_locations_array(&rb_objspace, start,n);
-}
-
 void
-rb_gc_mark_locations(VALUE *start, VALUE *end)
-{
-    gc_mark_locations(&rb_objspace, start, end);
-}
-
-#define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, start, end)
-
-struct mark_tbl_arg {
-    rb_objspace_t *objspace;
-    int lev;
-};
-
-static int
-mark_entry(ID key, VALUE value, st_data_t data)
-{
-    struct mark_tbl_arg *arg = (void*)data;
-    gc_mark(arg->objspace, value, arg->lev);
-    return ST_CONTINUE;
-}
-
-static void
-mark_tbl(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
-    struct mark_tbl_arg arg;
-    if (!tbl) return;
-    arg.objspace = objspace;
-    arg.lev = lev;
-    st_foreach(tbl, mark_entry, (st_data_t)&arg);
-}
-
-void
-rb_mark_tbl(st_table *tbl)
-{
-    mark_tbl(&rb_objspace, tbl, 0);
-}
-
-static int
-mark_key(VALUE key, VALUE value, st_data_t data)
-{
-    struct mark_tbl_arg *arg = (void*)data;
-    gc_mark(arg->objspace, key, arg->lev);
-    return ST_CONTINUE;
-}
-
-static void
-mark_set(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
-    struct mark_tbl_arg arg;
-    if (!tbl) return;
-    arg.objspace = objspace;
-    arg.lev = lev;
-    st_foreach(tbl, mark_key, (st_data_t)&arg);
-}
-
-void
-rb_mark_set(st_table *tbl)
-{
-    mark_set(&rb_objspace, tbl, 0);
-}
-
-static int
-mark_keyvalue(VALUE key, VALUE value, st_data_t data)
-{
-    struct mark_tbl_arg *arg = (void*)data;
-    gc_mark(arg->objspace, key, arg->lev);
-    gc_mark(arg->objspace, value, arg->lev);
-    return ST_CONTINUE;
-}
-
-static void
-mark_hash(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
-    struct mark_tbl_arg arg;
-    if (!tbl) return;
-    arg.objspace = objspace;
-    arg.lev = lev;
-    st_foreach(tbl, mark_keyvalue, (st_data_t)&arg);
-}
-
-void
-rb_mark_hash(st_table *tbl)
-{
-    mark_hash(&rb_objspace, tbl, 0);
-}
-
-void
-rb_gc_mark_maybe(VALUE obj)
-{
-    if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
-	gc_mark(&rb_objspace, obj, 0);
-    }
-}
-
-#define GC_LEVEL_MAX 250
-
-static void
-gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev)
-{
-    register RVALUE *obj;
-
-    obj = RANY(ptr);
-    if (rb_special_const_p(ptr)) return; /* special const not marked */
-    if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
-
-    if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
-	if (!mark_stack_overflow) {
-	    if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
-		*mark_stack_ptr = ptr;
-		mark_stack_ptr++;
-	    }
-	    else {
-		mark_stack_overflow = 1;
-	    }
-	}
-	return;
-    }
-    gc_mark_children(objspace, ptr, lev+1);
-}
-
-void
-rb_gc_mark(VALUE ptr)
-{
-    gc_mark(&rb_objspace, ptr, 0);
-}
-
-static void
-gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
-{
-    register RVALUE *obj = RANY(ptr);
-
-    goto marking;		/* skip */
-
-  again:
-    obj = RANY(ptr);
-    if (rb_special_const_p(ptr)) return; /* special const not marked */
-    if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
-
-  marking:
-    if (FL_TEST(obj, FL_EXIVAR)) {
-	rb_mark_generic_ivar(ptr);
-    }
-
-    switch (obj->as.basic.flags & T_MASK) {
-      case T_NIL:
-      case T_FIXNUM:
-	rb_bug("rb_gc_mark() called for broken object");
-	break;
-
-      case T_NODE:
-	switch (nd_type(obj)) {
-	  case NODE_IF:		/* 1,2,3 */
-	  case NODE_FOR:
-	  case NODE_ITER:
-	  case NODE_WHEN:
-	  case NODE_MASGN:
-	  case NODE_RESCUE:
-	  case NODE_RESBODY:
-	  case NODE_CLASS:
-	  case NODE_BLOCK_PASS:
-	    gc_mark(objspace, (VALUE)obj->as.node.u2.node, lev);
-	    /* fall through */
-	  case NODE_BLOCK:	/* 1,3 */
-	  case NODE_OPTBLOCK:
-	  case NODE_ARRAY:
-	  case NODE_DSTR:
-	  case NODE_DXSTR:
-	  case NODE_DREGX:
-	  case NODE_DREGX_ONCE:
-	  case NODE_ENSURE:
-	  case NODE_CALL:
-	  case NODE_DEFS:
-	  case NODE_OP_ASGN1:
-	  case NODE_ARGS:
-	    gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
-	    /* fall through */
-	  case NODE_SUPER:	/* 3 */
-	  case NODE_FCALL:
-	  case NODE_DEFN:
-	  case NODE_ARGS_AUX:
-	    ptr = (VALUE)obj->as.node.u3.node;
-	    goto again;
-
-	  case NODE_METHOD:	/* 1,2 */
-	  case NODE_WHILE:
-	  case NODE_UNTIL:
-	  case NODE_AND:
-	  case NODE_OR:
-	  case NODE_CASE:
-	  case NODE_SCLASS:
-	  case NODE_DOT2:
-	  case NODE_DOT3:
-	  case NODE_FLIP2:
-	  case NODE_FLIP3:
-	  case NODE_MATCH2:
-	  case NODE_MATCH3:
-	  case NODE_OP_ASGN_OR:
-	  case NODE_OP_ASGN_AND:
-	  case NODE_MODULE:
-	  case NODE_ALIAS:
-	  case NODE_VALIAS:
-	  case NODE_ARGSCAT:
-	    gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
-	    /* fall through */
-	  case NODE_FBODY:	/* 2 */
-	  case NODE_GASGN:
-	  case NODE_LASGN:
-	  case NODE_DASGN:
-	  case NODE_DASGN_CURR:
-	  case NODE_IASGN:
-	  case NODE_IASGN2:
-	  case NODE_CVASGN:
-	  case NODE_COLON3:
-	  case NODE_OPT_N:
-	  case NODE_EVSTR:
-	  case NODE_UNDEF:
-	  case NODE_POSTEXE:
-	    ptr = (VALUE)obj->as.node.u2.node;
-	    goto again;
-
-	  case NODE_HASH:	/* 1 */
-	  case NODE_LIT:
-	  case NODE_STR:
-	  case NODE_XSTR:
-	  case NODE_DEFINED:
-	  case NODE_MATCH:
-	  case NODE_RETURN:
-	  case NODE_BREAK:
-	  case NODE_NEXT:
-	  case NODE_YIELD:
-	  case NODE_COLON2:
-	  case NODE_SPLAT:
-	  case NODE_TO_ARY:
-	    ptr = (VALUE)obj->as.node.u1.node;
-	    goto again;
-
-	  case NODE_SCOPE:	/* 2,3 */
-	  case NODE_CDECL:
-	  case NODE_OPT_ARG:
-	    gc_mark(objspace, (VALUE)obj->as.node.u3.node, lev);
-	    ptr = (VALUE)obj->as.node.u2.node;
-	    goto again;
-
-	  case NODE_ZARRAY:	/* - */
-	  case NODE_ZSUPER:
-	  case NODE_CFUNC:
-	  case NODE_VCALL:
-	  case NODE_GVAR:
-	  case NODE_LVAR:
-	  case NODE_DVAR:
-	  case NODE_IVAR:
-	  case NODE_CVAR:
-	  case NODE_NTH_REF:
-	  case NODE_BACK_REF:
-	  case NODE_REDO:
-	  case NODE_RETRY:
-	  case NODE_SELF:
-	  case NODE_NIL:
-	  case NODE_TRUE:
-	  case NODE_FALSE:
-	  case NODE_ERRINFO:
-	  case NODE_ATTRSET:
-	  case NODE_BLOCK_ARG:
-	    break;
-	  case NODE_ALLOCA:
-	    mark_locations_array(objspace,
-				 (VALUE*)obj->as.node.u1.value,
-				 obj->as.node.u3.cnt);
-	    ptr = (VALUE)obj->as.node.u2.node;
-	    goto again;
-
-	  default:		/* unlisted NODE */
-	    if (is_pointer_to_heap(objspace, obj->as.node.u1.node)) {
-		gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
-	    }
-	    if (is_pointer_to_heap(objspace, obj->as.node.u2.node)) {
-		gc_mark(objspace, (VALUE)obj->as.node.u2.node, lev);
-	    }
-	    if (is_pointer_to_heap(objspace, obj->as.node.u3.node)) {
-		gc_mark(objspace, (VALUE)obj->as.node.u3.node, lev);
-	    }
-	}
-	return;			/* no need to mark class. */
-    }
-
-    gc_mark(objspace, obj->as.basic.klass, lev);
-    switch (obj->as.basic.flags & T_MASK) {
-      case T_ICLASS:
-      case T_CLASS:
-      case T_MODULE:
-	mark_tbl(objspace, RCLASS_M_TBL(obj), lev);
-	mark_tbl(objspace, RCLASS_IV_TBL(obj), lev);
-	ptr = RCLASS_SUPER(obj);
-	goto again;
-
-      case T_ARRAY:
-	if (FL_TEST(obj, ELTS_SHARED)) {
-	    ptr = obj->as.array.aux.shared;
-	    goto again;
-	}
-	else {
-	    long i, len = RARRAY_LEN(obj);
-	    VALUE *ptr = RARRAY_PTR(obj);
-	    for (i=0; i < len; i++) {
-		gc_mark(objspace, *ptr++, lev);
-	    }
-	}
-	break;
-
-      case T_HASH:
-	mark_hash(objspace, obj->as.hash.ntbl, lev);
-	ptr = obj->as.hash.ifnone;
-	goto again;
-
-      case T_STRING:
-#define STR_ASSOC FL_USER3   /* copied from string.c */
-	if (FL_TEST(obj, RSTRING_NOEMBED) && FL_ANY(obj, ELTS_SHARED|STR_ASSOC)) {
-	    ptr = obj->as.string.as.heap.aux.shared;
-	    goto again;
-	}
-	break;
-
-      case T_DATA:
-	if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
-	break;
-
-      case T_OBJECT:
-        {
-            long i, len = ROBJECT_NUMIV(obj);
-	    VALUE *ptr = ROBJECT_IVPTR(obj);
-            for (i  = 0; i < len; i++) {
-		gc_mark(objspace, *ptr++, lev);
-            }
-        }
-	break;
-
-      case T_FILE:
-        if (obj->as.file.fptr)
-            gc_mark(objspace, obj->as.file.fptr->tied_io_for_writing, lev);
-        break;
-
-      case T_REGEXP:
-      case T_FLOAT:
-      case T_BIGNUM:
-	break;
-
-      case T_MATCH:
-	gc_mark(objspace, obj->as.match.regexp, lev);
-	if (obj->as.match.str) {
-	    ptr = obj->as.match.str;
-	    goto again;
-	}
-	break;
-
-      case T_RATIONAL:
-	gc_mark(objspace, obj->as.rational.num, lev);
-	gc_mark(objspace, obj->as.rational.den, lev);
-	break;
-
-      case T_COMPLEX:
-	gc_mark(objspace, obj->as.complex.real, lev);
-	gc_mark(objspace, obj->as.complex.image, lev);
-	break;
-
-      case T_STRUCT:
-	{
-	    long len = RSTRUCT_LEN(obj);
-	    VALUE *ptr = RSTRUCT_PTR(obj);
-
-	    while (len--) {
-		gc_mark(objspace, *ptr++, lev);
-	    }
-	}
-	break;
-
-      case T_VALUES:
-	{
-            rb_gc_mark(RVALUES(obj)->v1);
-            rb_gc_mark(RVALUES(obj)->v2);
-            ptr = RVALUES(obj)->v3;
-            goto again;
-	}
-	break;
-
-      default:
-	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
-	       obj->as.basic.flags & T_MASK, obj,
-	       is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
-    }
-}
-
-static void obj_free(rb_objspace_t *, VALUE);
-
-static void
-finalize_list(rb_objspace_t *objspace, RVALUE *p)
-{
-    while (p) {
-	RVALUE *tmp = p->as.free.next;
-	run_final(objspace, (VALUE)p);
-	if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
-            VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-	    p->as.free.flags = 0;
-	    p->as.free.next = freelist;
-	    freelist = p;
-	}
-	p = tmp;
-    }
-}
-
-static void
-free_unused_heaps(rb_objspace_t *objspace)
-{
-    size_t i, j;
-    RVALUE *last = 0;
-
-    for (i = j = 1; j < heaps_used; i++) {
-	if (heaps[i].limit == 0) {
-	    if (!last) {
-		last = heaps[i].membase;
-	    }
-	    else {
-		free(heaps[i].membase);
-	    }
-	    heaps_used--;
-	}
-	else {
-	    if (i != j) {
-		heaps[j] = heaps[i];
-	    }
-	    j++;
-	}
-    }
-    if (last) {
-	if (last < heaps_freed) {
-	    free(heaps_freed);
-	    heaps_freed = last;
-	}
-	else {
-	    free(last);
-	}
-    }
-}
-
-void rb_gc_abort_threads(void);
-
-static void
-gc_sweep(rb_objspace_t *objspace)
-{
-    RVALUE *p, *pend, *final_list;
-    size_t freed = 0;
-    size_t i;
-    size_t live = 0, free_min = 0, do_heap_free = 0;
-
-    do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
-    free_min = (heaps_used * HEAP_OBJ_LIMIT)  * 0.2;
-    if (free_min < FREE_MIN) {
-	do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
-        free_min = FREE_MIN;
-    }
-
-    freelist = 0;
-    final_list = deferred_final_list;
-    deferred_final_list = 0;
-    for (i = 0; i < heaps_used; i++) {
-	int n = 0;
-	RVALUE *free = freelist;
-	RVALUE *final = final_list;
-
-	p = heaps[i].slot; pend = p + heaps[i].limit;
-	while (p < pend) {
-	    if (!(p->as.basic.flags & FL_MARK)) {
-		if (p->as.basic.flags) {
-		    obj_free(objspace, (VALUE)p);
-		}
-		if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
-		    p->as.free.flags = FL_MARK; /* remain marked */
-		    p->as.free.next = final_list;
-		    final_list = p;
-		}
-		else {
-                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-		    p->as.free.flags = 0;
-		    p->as.free.next = freelist;
-		    freelist = p;
-		}
-		n++;
-	    }
-	    else if (RBASIC(p)->flags == FL_MARK) {
-		/* objects to be finalized */
-		/* do nothing remain marked */
-	    }
-	    else {
-		RBASIC(p)->flags &= ~FL_MARK;
-		live++;
-	    }
-	    p++;
-	}
-	if (n == heaps[i].limit && freed > do_heap_free) {
-	    RVALUE *pp;
-
-	    heaps[i].limit = 0;
-	    for (pp = final_list; pp != final; pp = pp->as.free.next) {
-		p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
-	    }
-	    freelist = free;	/* cancel this page from freelist */
-	}
-	else {
-	    freed += n;
-	}
-    }
-    if (malloc_increase > malloc_limit) {
-	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
-	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
-    }
-    malloc_increase = 0;
-    if (freed < free_min) {
-    	set_heaps_increment(objspace);
-	heaps_increment(objspace);
-    }
-    during_gc = 0;
-
-    /* clear finalization list */
-    if (final_list) {
-	deferred_final_list = final_list;
-	return;
-    }
-    free_unused_heaps(objspace);
-}
-
-#endif /* !WITH_OBJC */
-
-void
 rb_gc_force_recycle(VALUE p)
 {
-#if WITH_OBJC
     xfree((void *)p);
-#else
-    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-    RANY(p)->as.free.flags = 0;
-    RANY(p)->as.free.next = freelist;
-    freelist = RANY(p);
-#endif
 }
 
-#if !WITH_OBJC
-static void
-obj_free(rb_objspace_t *objspace, VALUE obj)
-{
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
-      case T_NIL:
-      case T_FIXNUM:
-      case T_TRUE:
-      case T_FALSE:
-	rb_bug("obj_free() called for broken object");
-	break;
-    }
-
-    if (FL_TEST(obj, FL_EXIVAR)) {
-	rb_free_generic_ivar((VALUE)obj);
-    }
-
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
-      case T_OBJECT:
-	if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
-            RANY(obj)->as.object.as.heap.ivptr) {
-	    RUBY_CRITICAL(free(RANY(obj)->as.object.as.heap.ivptr));
-	}
-	break;
-      case T_MODULE:
-      case T_CLASS:
-	rb_clear_cache_by_class((VALUE)obj);
-	st_free_table(RCLASS_M_TBL(obj));
-	if (RCLASS_IV_TBL(obj)) {
-	    st_free_table(RCLASS_IV_TBL(obj));
-	}
-	if (RCLASS_IV_INDEX_TBL(obj)) {
-	    st_free_table(RCLASS_IV_INDEX_TBL(obj));
-	}
-        RUBY_CRITICAL(free(RANY(obj)->as.klass.ptr));
-	break;
-      case T_STRING:
-	rb_str_free(obj);
-	break;
-      case T_ARRAY:
-	rb_ary_free(obj);
-	break;
-      case T_HASH:
-	if (RANY(obj)->as.hash.ntbl) {
-	    st_free_table(RANY(obj)->as.hash.ntbl);
-	}
-	break;
-      case T_REGEXP:
-	if (RANY(obj)->as.regexp.ptr) {
-	    onig_free(RANY(obj)->as.regexp.ptr);
-	}
-	if (RANY(obj)->as.regexp.str) {
-	    RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
-	}
-	break;
-      case T_DATA:
-	if (DATA_PTR(obj)) {
-	    if ((long)RANY(obj)->as.data.dfree == -1) {
-		RUBY_CRITICAL(free(DATA_PTR(obj)));
-	    }
-	    else if (RANY(obj)->as.data.dfree) {
-		(*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
-	    }
-	}
-	break;
-      case T_MATCH:
-	if (RANY(obj)->as.match.rmatch) {
-            struct rmatch *rm = RANY(obj)->as.match.rmatch;
-	    onig_region_free(&rm->regs, 0);
-            if (rm->char_offset)
-                RUBY_CRITICAL(free(rm->char_offset));
-	    RUBY_CRITICAL(free(rm));
-	}
-	break;
-      case T_FILE:
-	if (RANY(obj)->as.file.fptr) {
-	    rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
-	}
-	break;
-      case T_RATIONAL:
-      case T_COMPLEX:
-	break;
-      case T_ICLASS:
-	/* iClass shares table with the module */
-	break;
-
-      case T_FLOAT:
-	break;
-      case T_VALUES:
-	break;
-
-      case T_BIGNUM:
-	if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
-	    RUBY_CRITICAL(free(RBIGNUM_DIGITS(obj)));
-	}
-	break;
-      case T_NODE:
-	switch (nd_type(obj)) {
-	  case NODE_SCOPE:
-	    if (RANY(obj)->as.node.u1.tbl) {
-		RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
-	    }
-	    break;
-	  case NODE_ALLOCA:
-	    RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
-	    break;
-	}
-	return;			/* no need to free iv_tbl */
-
-      case T_STRUCT:
-	if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
-	    RANY(obj)->as.rstruct.as.heap.ptr) {
-	    RUBY_CRITICAL(free(RANY(obj)->as.rstruct.as.heap.ptr));
-	}
-	break;
-
-      default:
-	rb_bug("gc_sweep(): unknown data type 0x%lx(%p)",
-	       RANY(obj)->as.basic.flags & T_MASK, (void*)obj);
-    }
-}
-
-#ifdef __GNUC__
-#if defined(__human68k__) || defined(DJGPP)
-#undef rb_setjmp
-#undef rb_jmp_buf
-#if defined(__human68k__)
-typedef unsigned long rb_jmp_buf[8];
-__asm__ (".even\n\
-_rb_setjmp:\n\
-	move.l	4(sp),a0\n\
-	movem.l	d3-d7/a3-a5,(a0)\n\
-	moveq.l	#0,d0\n\
-	rts");
-#else
-#if defined(DJGPP)
-typedef unsigned long rb_jmp_buf[6];
-__asm__ (".align 4\n\
-_rb_setjmp:\n\
-	pushl	%ebp\n\
-	movl	%esp,%ebp\n\
-	movl	8(%ebp),%ebp\n\
-	movl	%eax,(%ebp)\n\
-	movl	%ebx,4(%ebp)\n\
-	movl	%ecx,8(%ebp)\n\
-	movl	%edx,12(%ebp)\n\
-	movl	%esi,16(%ebp)\n\
-	movl	%edi,20(%ebp)\n\
-	popl	%ebp\n\
-	xorl	%eax,%eax\n\
-	ret");
-#endif
-#endif
-int rb_setjmp (rb_jmp_buf);
-#endif /* __human68k__ or DJGPP */
-#endif /* __GNUC__ */
-
-#define GC_NOTIFY 0
-
-void rb_vm_mark(void *ptr);
-
-static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
-{
-    rb_jmp_buf save_regs_gc_mark;
-    VALUE *stack_start, *stack_end;
-
-    SET_STACK_END;
-#if STACK_GROW_DIRECTION < 0
-    stack_start = th->machine_stack_end;
-    stack_end = th->machine_stack_start;
-#elif STACK_GROW_DIRECTION > 0
-    stack_start = th->machine_stack_start;
-    stack_end = th->machine_stack_end + 1;
-#else
-    if (th->machine_stack_end < th->machine_stack_start) {
-        stack_start = th->machine_stack_end;
-        stack_end = th->machine_stack_start;
-    }
-    else {
-        stack_start = th->machine_stack_start;
-        stack_end = th->machine_stack_end + 1;
-    }
-#endif
-
-    FLUSH_REGISTER_WINDOWS;
-    /* This assumes that all registers are saved into the jmp_buf (and stack) */
-    rb_setjmp(save_regs_gc_mark);
-    mark_locations_array(objspace,
-			 (VALUE*)save_regs_gc_mark,
-			 sizeof(save_regs_gc_mark) / sizeof(VALUE));
-
-    rb_gc_mark_locations(stack_start, stack_end);
-#ifdef __ia64
-    rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
-#endif
-#if defined(__human68k__) || defined(__mc68000__)
-    mark_locations_array((VALUE*)((char*)STACK_END + 2),
-			 (STACK_START - STACK_END));
-#endif
-}
-
-void rb_gc_mark_encodings(void);
-
 static int
-garbage_collect(rb_objspace_t *objspace)
-{
-    struct gc_list *list;
-    rb_thread_t *th = GET_THREAD();
-
-    if (GC_NOTIFY) printf("start garbage_collect()\n");
-
-    if (!heaps) {
-	return Qfalse;
-    }
-
-    if (dont_gc || during_gc) {
-	if (!freelist) {
-            if (!heaps_increment(objspace)) {
-                set_heaps_increment(objspace);
-                heaps_increment(objspace);
-            }
-	}
-	return Qtrue;
-    }
-    during_gc++;
-    objspace->count++;
-
-    SET_STACK_END;
-
-    init_mark_stack(objspace);
-
-    th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
-
-    if (finalizer_table) {
-	mark_tbl(objspace, finalizer_table, 0);
-    }
-
-    mark_current_machine_context(objspace, th);
-
-    rb_gc_mark_threads();
-    rb_gc_mark_symbols();
-    rb_gc_mark_encodings();
-
-    /* mark protected global variables */
-    for (list = global_List; list; list = list->next) {
-	rb_gc_mark_maybe(*list->varptr);
-    }
-    rb_mark_end_proc();
-    rb_gc_mark_global_tbl();
-
-    mark_tbl(objspace, rb_class_tbl, 0);
-    rb_gc_mark_trap_list();
-
-    /* mark generic instance variables for special constants */
-    rb_mark_generic_ivar_tbl();
-
-    rb_gc_mark_parser();
-
-    /* gc_mark objects whose marking are not completed*/
-    while (!MARK_STACK_EMPTY) {
-	if (mark_stack_overflow) {
-	    gc_mark_all(objspace);
-	}
-	else {
-	    gc_mark_rest(objspace);
-	}
-    }
-
-    gc_sweep(objspace);
-
-    if (GC_NOTIFY) printf("end garbage_collect()\n");
-    return Qtrue;
-}
-
-int
-rb_garbage_collect(void)
-{
-    return garbage_collect(&rb_objspace);
-}
-
-void
-rb_gc_mark_machine_stack(rb_thread_t *th)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-#if STACK_GROW_DIRECTION < 0
-    rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
-#elif STACK_GROW_DIRECTION > 0
-    rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end);
-#else
-    if (th->machine_stack_start < th->machine_stack_end) {
-	rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end);
-    }
-    else {
-	rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
-    }
-#endif
-#ifdef __ia64
-    rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
-#endif
-}
-
-#else /* !WITH_OBJC */
-
-static int
 garbage_collect(void)
 {
     if (dont_gc)
@@ -2111,15 +585,10 @@
     return Qtrue;
 }
 
-#endif
-
 void
 rb_gc(void)
 {
     garbage_collect();
-#if !WITH_OBJC
-    rb_gc_finalize_deferred();
-#endif
 }
 
 /*
@@ -2139,20 +608,6 @@
     return Qnil;
 }
 
-#if !WITH_OBJC
-void
-ruby_set_stack_size(size_t size)
-{
-    rb_gc_stack_maxsize = size;
-}
-
-void
-Init_stack(VALUE *addr)
-{
-    ruby_init_stack(addr);
-}
-#endif
-
 #undef ruby_init_stack
 void
 ruby_init_stack(VALUE *addr
@@ -2231,7 +686,6 @@
  *
  */
 
-#if WITH_OBJC
 static bool
 rb_objc_is_placeholder(void *obj)
 {
@@ -2251,6 +705,48 @@
     int count;
 };
 
+static int
+rb_objc_yield_classes(VALUE of)
+{
+    int i, count, rcount;
+    Class *buf;
+
+    count = objc_getClassList(NULL, 0);
+    assert(count > 0);
+
+    buf = (Class *)alloca(sizeof(Class) * count);
+    objc_getClassList(buf, count);
+
+    for (i = rcount = 0; i < count; i++) {
+	Class sk, k = buf[i];
+	bool nsobject_based;
+
+	if (class_getName(k)[0] == '_')
+	    continue;
+
+	if (of == rb_cModule && !RCLASS_MODULE(k))
+	    continue;
+
+	nsobject_based = false;
+	sk = k;
+	do {
+	    sk = (Class)RCLASS_SUPER(sk);
+	    if (sk == (Class)rb_cNSObject) {
+		nsobject_based = true;
+		break;
+	    }
+	}
+	while (sk != NULL);	
+
+	if (nsobject_based) {
+	    rb_yield((VALUE)k);
+	    rcount++;
+	}
+    }
+
+    return rcount;
+}
+
 static void 
 rb_objc_recorder(task_t task, void *context, unsigned type_mask,
 		 vm_range_t *ranges, unsigned range_count)
@@ -2266,101 +762,38 @@
 	    auto_zone_get_layout_type_no_lock(__auto_zone, (void *)r->address);
 	if (type != AUTO_OBJECT_SCANNED && type != AUTO_OBJECT_UNSCANNED)
 	    continue;
+	if (*(Class *)r->address == NULL)
+	    continue;
 	if (ctx->class_of != 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)
-		    || FL_TEST(r->address, FL_SINGLETON))
-		    continue;
-		if (ctx->class_of == rb_cClass) {
-		    /* Only match classes. */
-		    if (BUILTIN_TYPE(r->address) != T_CLASS)
-			continue;
+	    bool ok = false;
+	    for (c = *(Class *)r->address; c != NULL; 
+		    c = class_getSuperclass(c)) {
+		if (c ==(Class)ctx->class_of) {
+		    ok = true;
+		    break;
 		}
-		else {
-		    /* Match classes & modules. */
-		    if (BUILTIN_TYPE(r->address) != T_CLASS 
-			&& BUILTIN_TYPE(r->address) != T_MODULE)
-			continue;
-		}
 	    }
-	    else {
-	    	unsigned ok = 0;
-	    	for (c = *(Class *)r->address; c != NULL; 
-		     c = class_getSuperclass(c)) {
-		    if (c == RCLASS(ctx->class_of)->ocklass) {
-		        ok = 1;
-		        break;
-		    }
-	        }
-	        if (!ok)
-		    continue;
-	    }
+	    if (!ok)
+		continue;
 	}
-	if (!rb_objc_is_non_native((VALUE)r->address)) {
-	    switch (BUILTIN_TYPE(r->address)) {
-		case T_NONE: 
-		case T_ICLASS: 
-		case T_NODE:
+	switch (TYPE(r->address)) {
+	    case T_NONE: 
+	    case T_NODE:
+		continue;
+	    case T_ICLASS: 
+	    case T_CLASS:
+	    case T_MODULE:
+		rb_bug("object %p of type %d should not be recorded", 
+		       (void *)r->address, TYPE(r->address));
+	    case T_NATIVE:
+		if (rb_objc_is_placeholder((void *)r->address))
 		    continue;
-		case T_CLASS:
-		    if (FL_TEST(r->address, FL_SINGLETON))
-			continue;
-	    }
 	}
-	else {
-	    if (rb_objc_is_placeholder((void *)r->address))
-		continue;
-	}
 	rb_yield((VALUE)r->address);
 	ctx->count++;
     }	
 }
-#else
-void
-Init_heap(void)
-{
-    if (!rb_gc_stack_start) {
-	Init_stack(0);
-    }
-    init_heap(&rb_objspace);
-}
 
-static VALUE
-os_obj_of(rb_objspace_t *objspace, VALUE of)
-{
-    size_t i;
-    size_t n = 0;
-
-    for (i = 0; i < heaps_used; i++) {
-	RVALUE *p, *pend;
-
-	p = heaps[i].slot; pend = p + heaps[i].limit;
-	for (;p < pend; p++) {
-	    if (p->as.basic.flags) {
-		switch (BUILTIN_TYPE(p)) {
-		  case T_NONE:
-		  case T_ICLASS:
-		  case T_NODE:
-		  case T_VALUES:
-		    continue;
-		  case T_CLASS:
-		    if (FL_TEST(p, FL_SINGLETON)) continue;
-		  default:
-		    if (!p->as.basic.klass) continue;
-		    if (!of || rb_obj_is_kind_of((VALUE)p, of)) {
-			rb_yield((VALUE)p);
-			n++;
-		    }
-		}
-	    }
-	}
-    }
-
-    return SIZET2NUM(n);
-}
-#endif
-
 /*
  *  call-seq:
  *     ObjectSpace.each_object([module]) {|obj| ... } => fixnum
@@ -2398,6 +831,7 @@
 os_each_obj(int argc, VALUE *argv, VALUE os)
 {
     VALUE of;
+    int count;
 
     rb_secure(4);
     if (argc == 0) {
@@ -2407,15 +841,21 @@
 	rb_scan_args(argc, argv, "01", &of);
     }
     RETURN_ENUMERATOR(os, 1, &of);
-#if WITH_OBJC
-    struct rb_objc_recorder_context ctx = {of, 0};
-    (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
+
+    /* Class/Module are a special case, because they are not auto objects */
+    count = rb_objc_yield_classes(of);
+
+    if (of != rb_cClass && of != rb_cModule) {
+	struct rb_objc_recorder_context ctx = {of, count};
+
+	(((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
 	    mach_task_self(), (void *)&ctx, MALLOC_PTR_IN_USE_RANGE_TYPE,
 	    (vm_address_t)__auto_zone, NULL, rb_objc_recorder);
-    return INT2FIX(ctx.count);
-#else
-    return os_obj_of(&rb_objspace, of);
-#endif
+
+	count = ctx.count;
+    }
+
+    return INT2FIX(count);
 }
 
 /*
@@ -2426,29 +866,20 @@
  *
  */
 
-#if WITH_OBJC
 static CFMutableDictionaryRef __os_finalizers = NULL;
-#endif
 
 static VALUE
 undefine_final(VALUE os, VALUE obj)
 {
-#if WITH_OBJC
     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 {
 	FL_UNSET(obj, FL_FINALIZE);
     }
-#else
-    rb_objspace_t *objspace = &rb_objspace;
-    if (finalizer_table) {
-	st_delete(finalizer_table, (st_data_t*)&obj, 0);
-    }
-#endif
     return obj;
 }
 
@@ -2464,7 +895,6 @@
 static VALUE
 define_final(int argc, VALUE *argv, VALUE os)
 {
-#if WITH_OBJC
     VALUE obj, block, table;
 
     if (__os_finalizers == NULL)
@@ -2491,52 +921,24 @@
 
     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 {
 	FL_SET(obj, FL_FINALIZE);
     }
-#else
-    rb_objspace_t *objspace = &rb_objspace;
-    VALUE obj, block, table;
-
-    rb_scan_args(argc, argv, "11", &obj, &block);
-    if (argc == 1) {
-	block = rb_block_proc();
-    }
-    else if (!rb_respond_to(block, rb_intern("call"))) {
-	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
-		 rb_obj_classname(block));
-    }
-    need_call_final = 1;
-    FL_SET(obj, FL_FINALIZE);
-
-    block = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
-
-    if (!finalizer_table) {
-	finalizer_table = st_init_numtable();
-    }
-    if (st_lookup(finalizer_table, obj, &table)) {
-	rb_ary_push(table, block);
-    }
-    else {
-	st_add_direct(finalizer_table, obj, rb_ary_new3(1, block));
-    }
-#endif
     return block;
 }
 
 void
 rb_gc_copy_finalizer(VALUE dest, VALUE obj)
 {
-#if WITH_OBJC
     VALUE table;
 
     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;
     }
@@ -2555,55 +957,8 @@
 	CFDictionarySetValue(__os_finalizers, (const void *)dest, 
 	    (const void *)table);	
     }
-#else
-    rb_objspace_t *objspace = &rb_objspace;
-    VALUE table;
-
-    if (!finalizer_table) return;
-    if (!FL_TEST(obj, FL_FINALIZE)) return;
-    if (st_lookup(finalizer_table, obj, &table)) {
-	st_insert(finalizer_table, dest, table);
-    }
-    FL_SET(dest, FL_FINALIZE);
-#endif
 }
 
-#if !WITH_OBJC
-static VALUE
-run_single_final(VALUE arg)
-{
-    VALUE *args = (VALUE *)arg;
-    rb_eval_cmd(args[0], args[1], (int)args[2]);
-    return Qnil;
-}
-
-static void
-run_final(rb_objspace_t *objspace, VALUE obj)
-{
-    long i;
-    int status, critical_save = rb_thread_critical;
-    VALUE args[3], table, objid;
-
-    objid = rb_obj_id(obj);	/* make obj into id */
-    rb_thread_critical = Qtrue;
-    args[1] = 0;
-    args[2] = (VALUE)rb_safe_level();
-    if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
-	if (!args[1] && RARRAY_LEN(table) > 0) {
-	    args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
-	}
-	for (i=0; i<RARRAY_LEN(table); i++) {
-	    VALUE final = RARRAY_PTR(table)[i];
-	    args[0] = RARRAY_PTR(final)[1];
-	    args[2] = FIX2INT(RARRAY_PTR(final)[0]);
-	    rb_protect(run_single_final, (VALUE)args, &status);
-	}
-    }
-    rb_thread_critical = critical_save;
-}
-#endif
-
-#if WITH_OBJC
 static CFMutableArrayRef __exit_finalize = NULL;
 
 static void
@@ -2662,91 +1017,6 @@
     auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
 }
 
-#else /* WITH_OBJC */
-
-static void
-gc_finalize_deferred(rb_objspace_t *objspace)
-{
-    RVALUE *p = deferred_final_list;
-
-    during_gc++;
-    deferred_final_list = 0;
-    if (p) {
-	finalize_list(objspace, p);
-    }
-    free_unused_heaps(objspace);
-    during_gc = 0;
-}
-
-void
-rb_gc_finalize_deferred(void)
-{
-    gc_finalize_deferred(&rb_objspace);
-}
-
-void
-rb_gc_call_finalizer_at_exit(void)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-    RVALUE *p, *pend;
-    size_t i;
-
-    /* finalizers are part of garbage collection */
-    during_gc++;
-    /* run finalizers */
-    if (need_call_final) {
-	p = deferred_final_list;
-	deferred_final_list = 0;
-	finalize_list(objspace, p);
-	for (i = 0; i < heaps_used; i++) {
-	    p = heaps[i].slot; pend = p + heaps[i].limit;
-	    while (p < pend) {
-		if (FL_TEST(p, FL_FINALIZE)) {
-		    FL_UNSET(p, FL_FINALIZE);
-		    p->as.basic.klass = 0;
-		    run_final(objspace, (VALUE)p);
-		}
-		p++;
-	    }
-	}
-    }
-    /* run data object's finalizers */
-    for (i = 0; i < heaps_used; i++) {
-	p = heaps[i].slot; pend = p + heaps[i].limit;
-	while (p < pend) {
-	    if (BUILTIN_TYPE(p) == T_DATA &&
-		DATA_PTR(p) && RANY(p)->as.data.dfree &&
-		RANY(p)->as.basic.klass != rb_cThread) {
-		p->as.free.flags = 0;
-		if ((long)RANY(p)->as.data.dfree == -1) {
-		    RUBY_CRITICAL(free(DATA_PTR(p)));
-		}
-		else if (RANY(p)->as.data.dfree) {
-		    (*RANY(p)->as.data.dfree)(DATA_PTR(p));
-		}
-                VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-	    }
-	    else if (BUILTIN_TYPE(p) == T_FILE) {
-		if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
-		    p->as.free.flags = 0;
-                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-		}
-	    }
-	    p++;
-	}
-    }
-    during_gc = 0;
-}
-
-void
-rb_gc(void)
-{
-    rb_objspace_t *objspace = &rb_objspace;
-    garbage_collect(objspace);
-    gc_finalize_deferred(objspace);
-}
-#endif
-
 /*
  *  call-seq:
  *     ObjectSpace._id2ref(object_id) -> an_object
@@ -2768,9 +1038,6 @@
 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
 #define NUM2PTR(x) NUM2ULL(x)
 #endif
-#if !WITH_OBJC
-    rb_objspace_t *objspace = &rb_objspace;
-#endif
     VALUE ptr;
     void *p0;
 
@@ -2781,42 +1048,19 @@
     if (ptr == Qtrue) return Qtrue;
     if (ptr == Qfalse) return Qfalse;
     if (ptr == Qnil) return Qnil;
-#if WITH_OBJC
     if (FIXNUM_P(ptr) || SYMBOL_P(ptr))
 	return ptr;
-#else
-    if (FIXNUM_P(ptr)) return (VALUE)ptr;
-    ptr = objid ^ FIXNUM_FLAG;	/* unset FIXNUM_FLAG */
 
-    if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
-        ID symid = ptr / sizeof(RVALUE);
-        if (rb_id2name(symid) == 0)
-	    rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
-	return ID2SYM(symid);
-    }
-#endif
-
-#if WITH_OBJC
     if (auto_zone_is_valid_pointer(auto_zone(), p0)) {
 	auto_memory_type_t type = 
 	    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;
     }
     rb_raise(rb_eRangeError, "%p is not id value", p0);
-#else
-    if (!is_pointer_to_heap(objspace, (void *)ptr) ||
-	BUILTIN_TYPE(ptr) >= T_VALUES || BUILTIN_TYPE(ptr) == T_ICLASS) {
-	rb_raise(rb_eRangeError, "%p is not id value", p0);
-    }
-    if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
-	rb_raise(rb_eRangeError, "%p is recycled object", p0);
-    }
-    return (VALUE)ptr;
-#endif
 }
 
 /*
@@ -2849,47 +1093,7 @@
 VALUE
 rb_obj_id(VALUE obj)
 {
-    /*
-     *                32-bit VALUE space
-     *          MSB ------------------------ LSB
-     *  false   00000000000000000000000000000000
-     *  true    00000000000000000000000000000010
-     *  nil     00000000000000000000000000000100
-     *  undef   00000000000000000000000000000110
-     *  symbol  ssssssssssssssssssssssss00001110
-     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
-     *  fixnum  fffffffffffffffffffffffffffffff1
-     *
-     *                    object_id space
-     *                                       LSB
-     *  false   00000000000000000000000000000000
-     *  true    00000000000000000000000000000010
-     *  nil     00000000000000000000000000000100
-     *  undef   00000000000000000000000000000110
-     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
-     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
-     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
-     *
-     *  where A = sizeof(RVALUE)/4
-     *
-     *  sizeof(RVALUE) is
-     *  20 if 32-bit, double is 4-byte aligned
-     *  24 if 32-bit, double is 8-byte aligned
-     *  40 if 64-bit
-     */
-#if !WITH_OBJC
-    if (TYPE(obj) == T_SYMBOL) {
-        return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
-    }
-#endif
-    if (SPECIAL_CONST_P(obj)) {
-        return LONG2NUM((SIGNED_VALUE)obj);
-    }
-#if WITH_OBJC
     return (VALUE)LONG2NUM((SIGNED_VALUE)obj);
-#else
-    return (VALUE)((SIGNED_VALUE)obj|FIXNUM_FLAG);
-#endif
 }
 
 /*
@@ -2915,9 +1119,9 @@
 static VALUE
 count_objects(int argc, VALUE *argv, VALUE os)
 {
-#if WITH_OBJC
+    /* TODO implement me! */
     return rb_hash_new();
-#else
+#if 0
     rb_objspace_t *objspace = &rb_objspace;
     size_t counts[T_MASK+1];
     size_t freed = 0;
@@ -3003,18 +1207,12 @@
  *
  */
 
-#if WITH_OBJC
 static long _gc_count = 0;
-#endif
 
 static VALUE
 gc_count(VALUE self)
 {
-#if WITH_OBJC
     return UINT2NUM(_gc_count);
-#else
-    return UINT2NUM((&rb_objspace)->count);
-#endif
 }
 
 /*
@@ -3023,7 +1221,6 @@
  *  are also available via the <code>ObjectSpace</code> module.
  */
 
-#if WITH_OBJC
 static void (*old_batch_invalidate)(auto_zone_t *, 
     auto_zone_foreach_object_t, auto_zone_cursor_t, size_t);
 
@@ -3076,7 +1273,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);
@@ -3107,20 +1304,16 @@
      */
     _gc_count++;
 }
-#endif
 
 void
 Init_PreGC(void)
 {
-#if WITH_OBJC
     auto_collection_control_t *control;
 
     __auto_zone = auto_zone();
     
     if (__auto_zone == NULL)
 	rb_objc_no_gc_error();
-    
-    //auto_zone_register_thread(__auto_zone);
 
     control = auto_collection_parameters(__auto_zone);
     control->scan_external_callout = 
@@ -3130,19 +1323,16 @@
 		       | AUTO_LOG_UNUSUAL;
     old_batch_invalidate = control->batch_invalidate;
     control->batch_invalidate = rb_objc_batch_invalidate;
-#endif
 }
 
 void
 Init_PostGC(void)
 {
-#if WITH_OBJC
-# if 0
+#if 0
     /* It is better to let Foundation start the dedicated collection thread
      * when necessary. 
      */
     objc_startCollectorThread();
-# endif
 #endif
 }
 
@@ -3177,4 +1367,4 @@
     rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
 
     rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
-}
+}
\ No newline at end of file

Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/hash.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,30 +1,24 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's hash.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  hash.c -
-
-  $Author: knu $
-  created at: Mon Nov 22 18:51:18 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-  Copyright (C) 2000  Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/st.h"
 #include "ruby/util.h"
 #include "ruby/signal.h"
+#include "id.h"
 
-#ifdef __APPLE__
 #include <crt_externs.h>
-#endif
 
 static VALUE rb_hash_s_try_convert(VALUE, VALUE);
 
-#define HASH_DELETED  FL_USER1
-#define HASH_PROC_DEFAULT FL_USER2
-
 VALUE
 rb_hash_freeze(VALUE hash)
 {
@@ -32,95 +26,19 @@
 }
 
 VALUE rb_cHash;
-#if WITH_OBJC
 VALUE rb_cCFHash;
-VALUE rb_cHashRuby;
-#endif
+VALUE rb_cNSHash;
+VALUE rb_cNSMutableHash;
 
 static VALUE envtbl;
 static ID id_hash, id_yield, id_default;
 
-static VALUE
-eql(VALUE *args)
-{
-    return (VALUE)rb_eql(args[0], args[1]);
-}
-
-int
-rb_any_cmp(VALUE a, VALUE b)
-{
-    VALUE args[2];
-
-    if (a == b) return 0;
-    if (a == Qundef || b == Qundef) return -1;
-    if (FIXNUM_P(a) && FIXNUM_P(b)) {
-	return a != b;
-    }
-    if (SYMBOL_P(a) && SYMBOL_P(b)) {
-	return a != b;
-    }
-#if WITH_OBJC
-    if (TYPE(a) == T_STRING && TYPE(b) == T_STRING)
-	return rb_str_hash_cmp(a, b);
-#else
-    if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
-	TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
-	return rb_str_hash_cmp(a, b);
-    }
-#endif
-
-    args[0] = a;
-    args[1] = b;
-    return !rb_with_disable_interrupt(eql, (VALUE)args);
-}
-
 VALUE
 rb_hash(VALUE obj)
 {
     return rb_funcall(obj, id_hash, 0);
 }
 
-static int
-rb_any_hash(VALUE a)
-{
-    VALUE hval;
-    int hnum;
-
-    switch (TYPE(a)) {
-      case T_FIXNUM:
-      case T_SYMBOL:
-	hnum = (int)a;
-	break;
-
-      case T_STRING:
-	hnum = rb_str_hash(a);
-	break;
-
-      default:
-	hval = rb_funcall(a, id_hash, 0);
-	if (!FIXNUM_P(hval)) {
-	    hval = rb_funcall(hval, '%', 1, INT2FIX(536870923));
-	}
-	hnum = (int)FIX2LONG(hval);
-    }
-#if WITH_OBJC
-    return hnum;
-#else
-    hnum <<= 1;
-    return RSHIFT(hnum, 1);
-#endif
-}
-
-static const struct st_hash_type objhash = {
-    rb_any_cmp,
-    rb_any_hash,
-};
-
-static const struct st_hash_type identhash = {
-    st_numcmp,
-    st_numhash,
-};
-
 typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
 
 struct foreach_safe_arg {
@@ -155,67 +73,9 @@
     }
 }
 
-#if !WITH_OBJC
-typedef int rb_foreach_func(VALUE, VALUE, VALUE);
-
-struct hash_foreach_arg {
-    VALUE hash;
-    rb_foreach_func *func;
-    VALUE arg;
-};
-
-static int
-hash_foreach_iter(VALUE key, VALUE value, struct hash_foreach_arg *arg)
-{
-    int status;
-    st_table *tbl;
-
-    tbl = RHASH(arg->hash)->ntbl;
-    if (key == Qundef) return ST_CONTINUE;
-    status = (*arg->func)(key, value, arg->arg);
-    if (RHASH(arg->hash)->ntbl != tbl) {
-	rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
-    }
-    switch (status) {
-      case ST_DELETE:
-	st_delete_safe(tbl, (st_data_t*)&key, 0, Qundef);
-	FL_SET(arg->hash, HASH_DELETED);
-      case ST_CONTINUE:
-	break;
-      case ST_STOP:
-	return ST_STOP;
-    }
-    return ST_CHECK;
-}
-
-static VALUE
-hash_foreach_ensure(VALUE hash)
-{
-    RHASH(hash)->iter_lev--;
-
-    if (RHASH(hash)->iter_lev == 0) {
-	if (FL_TEST(hash, HASH_DELETED)) {
-	    st_cleanup_safe(RHASH(hash)->ntbl, Qundef);
-	    FL_UNSET(hash, HASH_DELETED);
-	}
-    }
-    return 0;
-}
-
-static VALUE
-hash_foreach_call(struct hash_foreach_arg *arg)
-{
-    if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) {
- 	rb_raise(rb_eRuntimeError, "hash modified during iteration");
-    }
-    return Qnil;
-}
-#endif
-
 void
 rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
 {
-#if WITH_OBJC
     CFIndex i, count;
     const void **keys;
     const void **values;
@@ -230,52 +90,14 @@
     CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
 
     for (i = 0; i < count; i++) {
-	if ((*func)((VALUE)keys[i], (VALUE)values[i], farg) != ST_CONTINUE)
+	if ((*func)(OC2RB(keys[i]), OC2RB(values[i]), farg) != ST_CONTINUE)
 	    break;
     }
-#else
-    struct hash_foreach_arg arg;
-
-    if (!RHASH(hash)->ntbl)
-        return;
-    RHASH(hash)->iter_lev++;
-    arg.hash = hash;
-    arg.func = (rb_foreach_func *)func;
-    arg.arg  = farg;
-    rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
-#endif
 }
 
-#if WITH_OBJC
-
 # define HASH_KEY_CALLBACKS(h) \
   ((CFDictionaryKeyCallBacks *)((uint8_t *)h + 52))
 
-static Boolean 
-rb_cfdictionary_equal_cb(const void *v1, const void *v2)
-{
-    return v1 == v2 || !rb_any_cmp((VALUE)v1, (VALUE)v2);
-}
-
-static CFHashCode
-rb_cfdictionary_hash_cb(const void *v)
-{
-    return (CFHashCode)rb_any_hash((VALUE)v); 
-}
-
-const void *
-rb_cfdictionary_retain_cb(CFAllocatorRef allocator, const void *v)
-{
-    rb_objc_retain(v);
-    return v;
-}
-
-void
-rb_cfdictionary_release_cb(CFAllocatorRef allocator, const void *v)
-{
-    rb_objc_release(v);
-}
-
 /* TODO optimize me */
 struct rb_objc_hash_struct {
     VALUE ifnone;
@@ -316,57 +138,46 @@
     GC_WB(&s->ifnone, ifnone);
     s->has_proc_default = has_proc_default;
 }
-#endif
 
 static VALUE
 hash_alloc(VALUE klass)
 {
-#if WITH_OBJC
-    CFDictionaryKeyCallBacks keys_cb;
-    CFDictionaryValueCallBacks values_cb;
-    VALUE hash;
+    CFMutableDictionaryRef hash;
 
-    memset(&keys_cb, 0, sizeof(keys_cb));
-    keys_cb.retain = rb_cfdictionary_retain_cb;
-    keys_cb.release = rb_cfdictionary_release_cb;
-    keys_cb.equal = rb_cfdictionary_equal_cb;
-    keys_cb.hash = rb_cfdictionary_hash_cb;
+    hash = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if (klass != 0 && klass != rb_cNSHash && klass != rb_cNSMutableHash)
+	*(Class *)hash = (Class)klass;
 
-    memset(&values_cb, 0, sizeof(values_cb));
-    values_cb.retain = rb_cfdictionary_retain_cb;
-    values_cb.release = rb_cfdictionary_release_cb;
-    values_cb.equal = rb_cfdictionary_equal_cb;
+    CFMakeCollectable(hash);
 
-    hash = (VALUE)CFDictionaryCreateMutable(NULL, 0, &keys_cb, &values_cb);
-    if (klass != 0 && klass != rb_cHash && klass != rb_cHashRuby)
-	*(Class *)hash = RCLASS_OCID(klass);
+    return (VALUE)hash;
+}
 
-    CFMakeCollectable((CFTypeRef)hash);
-    rb_gc_malloc_increase(sizeof(void *));
+VALUE
+rb_hash_dup(VALUE rcv)
+{
+    VALUE dup = (VALUE)CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)rcv);
+    if (OBJ_TAINTED(rcv))
+	OBJ_TAINT(dup);
+    CFMakeCollectable((CFTypeRef)dup);
+    return dup;
+}
 
-    return hash;
-#else
-    NEWOBJ(hash, struct RHash);
-    OBJSETUP(hash, klass, T_HASH);
-
-    hash->ifnone = Qnil;
-
-    return (VALUE)hash;
-#endif
+static VALUE
+rb_hash_clone(VALUE rcv)
+{
+    VALUE clone = rb_hash_dup(rcv);
+    if (OBJ_FROZEN(rcv))
+	OBJ_FREEZE(clone);
+    return clone;
 }
 
 VALUE
 rb_hash_new(void)
 {
-#if WITH_OBJC
     return hash_alloc(0);
-#else
-    return hash_alloc(rb_cHash);
-#endif
 }
 
-#if WITH_OBJC
-
 static inline void
 rb_hash_modify_check(VALUE hash)
 {
@@ -385,34 +196,6 @@
 
 #define rb_hash_modify rb_hash_modify_check
 
-#else
-
-static void
-rb_hash_modify_check(VALUE hash)
-{
-    if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
-    if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
-	rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
-}
-
-struct st_table *
-rb_hash_tbl(VALUE hash)
-{
-    if (!RHASH(hash)->ntbl) {
-	GC_WB(&RHASH(hash)->ntbl, st_init_table(&objhash));
-    }
-    return RHASH(hash)->ntbl;
-}
-
-static void
-rb_hash_modify(VALUE hash)
-{
-    rb_hash_modify_check(hash);
-    rb_hash_tbl(hash);
-}
-#endif
-
-
 /*
  *  call-seq:
  *     Hash.new                          => hash
@@ -453,26 +236,18 @@
 {
     VALUE ifnone;
 
-    rb_hash_modify(hash);
+    hash = (VALUE)objc_msgSend((id)hash, selInit);
+
     if (rb_block_given_p()) {
 	if (argc > 0) {
 	    rb_raise(rb_eArgError, "wrong number of arguments");
 	}
-#if WITH_OBJC
 	rb_objc_hash_set_struct(hash, rb_block_proc(), true);
-#else
-	RHASH(hash)->ifnone = rb_block_proc();
-	FL_SET(hash, HASH_PROC_DEFAULT);
-#endif
     }
     else {
 	rb_scan_args(argc, argv, "01", &ifnone);
-#if WITH_OBJC
 	if (ifnone != Qnil)
 	    rb_objc_hash_set_struct(hash, ifnone, false);
-#else
-	RHASH(hash)->ifnone = ifnone;
-#endif
     }
 
     return hash;
@@ -500,7 +275,6 @@
     if (argc == 1) {
 	tmp = rb_hash_s_try_convert(Qnil, argv[0]);
 	if (!NIL_P(tmp)) {
-#if WITH_OBJC
 	    CFIndex i, count;
 	    const void **keys;
 	    const void **values;
@@ -517,16 +291,9 @@
 
 	    for (i = 0; i < count; i++)
 		CFDictionarySetValue((CFMutableDictionaryRef)hash,
-			keys[i], values[i]);
+			RB2OC(keys[i]), RB2OC(values[i]));
 
 	    return hash;
-#else
-	    hash = hash_alloc(klass);
-	    if (RHASH(argv[0])->ntbl) {
-		GC_WB(&RHASH(hash)->ntbl, st_copy(RHASH(argv[0])->ntbl));
-	    }
-#endif
-	    return hash;
 	}
 
 	tmp = rb_check_array_type(argv[0]);
@@ -579,15 +346,6 @@
     return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
 }
 
-#if !WITH_OBJC
-static int
-rb_hash_rehash_i(VALUE key, VALUE value, st_table *tbl)
-{
-    if (key != Qundef) st_insert(tbl, key, value);
-    return ST_CONTINUE;
-}
-#endif
-
 /*
  *  call-seq:
  *     hsh.rehash -> hsh
@@ -611,7 +369,6 @@
 static VALUE
 rb_hash_rehash(VALUE hash)
 {
-#if WITH_OBJC
     CFIndex i, count;
     const void **keys;
     const void **values;
@@ -633,22 +390,6 @@
 	    (const void *)keys[i], (const void *)values[i]);
 
     return hash;
-#else
-    st_table *tbl;
-
-    if (RHASH(hash)->iter_lev > 0) {
-	rb_raise(rb_eRuntimeError, "rehash during iteration");
-    }
-    rb_hash_modify_check(hash);
-    if (!RHASH(hash)->ntbl)
-        return hash;
-    tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
-    rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl);
-    st_free_table(RHASH(hash)->ntbl);
-    GC_WB(&RHASH(hash)->ntbl, tbl);
-
-    return hash;
-#endif
 }
 
 /*
@@ -670,16 +411,11 @@
 {
     VALUE val;
 
-#if WITH_OBJC
-    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
 	(const void **)&val)) {
 	return rb_funcall(hash, id_default, 1, key);
     }
-#else
-    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
-	return rb_funcall(hash, id_default, 1, key);
-    }
-#endif
+    val = OC2RB(val);
     return val;
 }
 
@@ -688,16 +424,11 @@
 {
     VALUE val;
 
-#if WITH_OBJC
-    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
 	(const void **)&val)) {
 	return Qnil;
     }
-#else
-    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
-	return Qnil; /* without Hash#default */
-    }
-#endif
+    val = OC2RB(val);
     return val;
 }
 
@@ -743,19 +474,15 @@
     if (block_given && argc == 2) {
 	rb_warn("block supersedes default value argument");
     }
-#if WITH_OBJC
-    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+    if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
 	(const void **)&val)) {
-#else
-    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
-#endif
 	if (block_given) return rb_yield(key);
 	if (argc == 1) {
 	    rb_raise(rb_eKeyError, "key not found");
 	}
 	return if_none;
     }
-    return val;
+    return OC2RB(val);
 }
 
 /*
@@ -782,7 +509,6 @@
 static VALUE
 rb_hash_default(int argc, VALUE *argv, VALUE hash)
 {
-#if WITH_OBJC
     struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
     VALUE key;
 
@@ -795,16 +521,6 @@
 	return rb_funcall(s->ifnone, id_yield, 2, hash, key);
     }
     return s->ifnone;
-#else
-    VALUE key;
-
-    rb_scan_args(argc, argv, "01", &key);
-    if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
-	if (argc == 0) return Qnil;
-	return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
-    }
-    return RHASH(hash)->ifnone;
-#endif
 }
 
 /*
@@ -831,12 +547,7 @@
 rb_hash_set_default(VALUE hash, VALUE ifnone)
 {
     rb_hash_modify(hash);
-#if WITH_OBJC
     rb_objc_hash_set_struct(hash, ifnone, false);
-#else
-    RHASH(hash)->ifnone = ifnone;
-    FL_UNSET(hash, HASH_PROC_DEFAULT);
-#endif
     return ifnone;
 }
 
@@ -858,17 +569,10 @@
 static VALUE
 rb_hash_default_proc(VALUE hash)
 {
-#if WITH_OBJC
     struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
     if (s != NULL && s->has_proc_default)
 	return s->ifnone;
     return Qnil;
-#else
-    if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
-	return RHASH(hash)->ifnone;
-    }
-    return Qnil;
-#endif
 }
 
 static int
@@ -917,30 +621,15 @@
 static VALUE
 rb_hash_delete_key(VALUE hash, VALUE key)
 {
-#if WITH_OBJC
     VALUE val;
+    id ockey = RB2OC(key);
     if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
-	(const void *)key, (const void **)&val)) {
+	(const void *)ockey, (const void **)&val)) {
 	CFDictionaryRemoveValue((CFMutableDictionaryRef)hash, 
-	    (const void *)key);
-	return val;
+	    (const void *)ockey);
+	return OC2RB(val);
     }
     return Qundef;
-#else
-    st_data_t ktmp = (st_data_t)key, val;
-
-    if (!RHASH(hash)->ntbl)
-        return Qundef;
-    if (RHASH(hash)->iter_lev > 0) {
-	if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) {
-	    FL_SET(hash, HASH_DELETED);
-	    return (VALUE)val;
-	}
-    }
-    else if (st_delete(RHASH(hash)->ntbl, &ktmp, &val))
-	return (VALUE)val;
-    return Qundef;
-#endif
 }
 
 /*
@@ -975,32 +664,6 @@
     return Qnil;
 }
 
-#if !WITH_OBJC
-struct shift_var {
-    VALUE key;
-    VALUE val;
-};
-
-static int
-shift_i(VALUE key, VALUE value, struct shift_var *var)
-{
-    if (key == Qundef) return ST_CONTINUE;
-    if (var->key != Qundef) return ST_STOP;
-    var->key = key;
-    var->val = value;
-    return ST_DELETE;
-}
-
-static int
-shift_i_safe(VALUE key, VALUE value, struct shift_var *var)
-{
-    if (key == Qundef) return ST_CONTINUE;
-    var->key = key;
-    var->val = value;
-    return ST_STOP;
-}
-#endif
-
 /*
  *  call-seq:
  *     hsh.shift -> anArray or obj
@@ -1014,14 +677,11 @@
  *     h         #=> {2=>"b", 3=>"c"}
  */
 
-#if WITH_OBJC
 static VALUE rb_hash_keys(VALUE);
-#endif
 
 static VALUE
 rb_hash_shift(VALUE hash)
 {
-#if WITH_OBJC
     VALUE keys, key, val;
 
     keys = rb_hash_keys(hash);
@@ -1041,27 +701,6 @@
     rb_hash_delete(hash, key);
 
     return rb_assoc_new(key, val);
-#else
-    struct shift_var var;
-
-    rb_hash_modify(hash);
-    var.key = Qundef;
-    rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
-		    (st_data_t)&var);
-
-    if (var.key != Qundef) {
-	if (RHASH(hash)->iter_lev > 0) {
-	    rb_hash_delete_key(hash, var.key);
-	}
-	return rb_assoc_new(var.key, var.val);
-    }
-    else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
-	return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, Qnil);
-    }
-    else {
-	return RHASH(hash)->ifnone;
-    }
-#endif
 }
 
 static int
@@ -1106,7 +745,6 @@
 VALUE
 rb_hash_reject_bang(VALUE hash)
 {
-#if WITH_OBJC
     CFIndex n;
 
     RETURN_ENUMERATOR(hash, 0, 0);
@@ -1115,17 +753,6 @@
     if (n == CFDictionaryGetCount((CFDictionaryRef)hash))
 	return Qnil;
     return hash;
-#else
-    int n;
-
-    RETURN_ENUMERATOR(hash, 0, 0);
-    if (!RHASH(hash)->ntbl)
-        return Qnil;
-    n = RHASH(hash)->ntbl->num_entries;
-    rb_hash_delete_if(hash);
-    if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
-    return hash;
-#endif
 }
 
 /*
@@ -1198,14 +825,6 @@
     return result;
 }
 
-#if !WITH_OBJC
-static int
-clear_i(VALUE key, VALUE value, VALUE dummy)
-{
-    return ST_DELETE;
-}
-#endif
-
 /*
  *  call-seq:
  *     hsh.clear -> hsh
@@ -1221,18 +840,7 @@
 rb_hash_clear(VALUE hash)
 {
     rb_hash_modify_check(hash);
-#if WITH_OBJC
     CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
-#else
-    if (!RHASH(hash)->ntbl)
-        return hash;
-    if (RHASH(hash)->ntbl->num_entries > 0) {
-	if (RHASH(hash)->iter_lev > 0)
-	    rb_hash_foreach(hash, clear_i, 0);
-	else
-	    st_clear(RHASH(hash)->ntbl);
-    }
-#endif
 
     return hash;
 }
@@ -1259,18 +867,8 @@
 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
 {
     rb_hash_modify(hash);
-#if WITH_OBJC
-    CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)key,
-	(const void *)val);
-#else
-    if (RHASH(hash)->ntbl->type == &identhash ||
-	TYPE(key) != T_STRING || st_lookup(RHASH(hash)->ntbl, key, 0)) {
-	st_insert(RHASH(hash)->ntbl, key, val);
-    }
-    else {
-	st_add_direct(RHASH(hash)->ntbl, rb_str_new4(key), val);
-    }
-#endif
+    CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)RB2OC(key),
+	(const void *)RB2OC(val));
     return val;
 }
 
@@ -1303,21 +901,11 @@
     if (hash == hash2) return hash;
     rb_hash_clear(hash);
     rb_hash_foreach(hash2, replace_i, hash);
-#if WITH_OBJC
     {
 	struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash2);
 	if (s != NULL)
 	    rb_objc_hash_set_struct(hash, s->ifnone, s->has_proc_default);
     }
-#else
-    RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
-    if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
-	FL_SET(hash, HASH_PROC_DEFAULT);
-    }
-    else {
-	FL_UNSET(hash, HASH_PROC_DEFAULT);
-    }
-#endif
 
     return hash;
 }
@@ -1338,13 +926,7 @@
 static VALUE
 rb_hash_size(VALUE hash)
 {
-#if WITH_OBJC
     return INT2FIX(CFDictionaryGetCount((CFDictionaryRef)hash));
-#else
-    if (!RHASH(hash)->ntbl)
-        return INT2FIX(0);
-    return INT2FIX(RHASH(hash)->ntbl->num_entries);
-#endif
 }
 
 
@@ -1503,15 +1085,9 @@
     }
     str2 = rb_inspect(key);
     rb_str_buf_append(str, str2);
-#if !WITH_OBJC
-    OBJ_INFECT(str, str2);
-#endif
     rb_str_buf_cat2(str, "=>");
     str2 = rb_inspect(value);
     rb_str_buf_append(str, str2);
-#if !WITH_OBJC
-    OBJ_INFECT(str, str2);
-#endif
 
     return ST_CONTINUE;
 }
@@ -1642,33 +1218,12 @@
 static VALUE
 rb_hash_has_key(VALUE hash, VALUE key)
 {
-#if WITH_OBJC
-    if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)key))
+    if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)RB2OC(key)))
 	return Qtrue;
-#else
-    if (!RHASH(hash)->ntbl)
-        return Qfalse;
-    if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
-	return Qtrue;
-    }
-#endif
 
     return Qfalse;
 }
 
-#if !WITH_OBJC
-static int
-rb_hash_search_value(VALUE key, VALUE value, VALUE *data)
-{
-    if (key == Qundef) return ST_CONTINUE;
-    if (rb_equal(value, data[1])) {
-	data[0] = Qtrue;
-	return ST_STOP;
-    }
-    return ST_CONTINUE;
-}
-#endif
-
 /*
  *  call-seq:
  *     hsh.has_value?(value)    => true or false
@@ -1685,58 +1240,11 @@
 static VALUE
 rb_hash_has_value(VALUE hash, VALUE val)
 {
-#if WITH_OBJC
-    return CFDictionaryContainsValue((CFDictionaryRef)hash, (const void *)val)
+    return CFDictionaryContainsValue((CFDictionaryRef)hash, (const void *)RB2OC(val))
 	? Qtrue : Qfalse;
-#else
-    VALUE data[2];
-
-    data[0] = Qfalse;
-    data[1] = val;
-    rb_hash_foreach(hash, rb_hash_search_value, (st_data_t)data);
-    return data[0];
-#endif
 }
 
-#if !WITH_OBJC
-struct equal_data {
-    VALUE result;
-    st_table *tbl;
-    int eql;
-};
-
-static int
-eql_i(VALUE key, VALUE val1, struct equal_data *data)
-{
-    VALUE val2;
-
-    if (key == Qundef) return ST_CONTINUE;
-    if (!st_lookup(data->tbl, key, &val2)) {
-	data->result = Qfalse;
-	return ST_STOP;
-    }
-    if (!(data->eql ? rb_eql(val1, val2) : rb_equal(val1, val2))) {
-	data->result = Qfalse;
-	return ST_STOP;
-    }
-    return ST_CONTINUE;
-}
-
 static VALUE
-recursive_eql(VALUE hash, VALUE dt, int recur)
-{
-    struct equal_data *data;
-
-    if (recur) return Qfalse;
-    data = (struct equal_data*)dt;
-    data->result = Qtrue;
-    rb_hash_foreach(hash, eql_i, (st_data_t)data);
-
-    return data->result;
-}
-#endif
-
-static VALUE
 hash_equal(VALUE hash1, VALUE hash2, int eql)
 {
     if (hash1 == hash2) return Qtrue;
@@ -1751,23 +1259,7 @@
     }
     if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
 	return Qfalse;
-#if WITH_OBJC
     return CFEqual((CFTypeRef)hash1, (CFTypeRef)hash2) ? Qtrue : Qfalse;
-#else
-    if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
-        return Qtrue;
-    if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
-	return Qfalse;
-#if 0
-    if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
-	  FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
-	return Qfalse;
-#endif
-
-    data.tbl = RHASH(hash2)->ntbl;
-    data.eql = eql;
-    return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
-#endif
 }
 
 /*
@@ -1809,50 +1301,7 @@
     return hash_equal(hash1, hash2, Qtrue);
 }
 
-#if !WITH_OBJC
 static int
-hash_i(VALUE key, VALUE val, int *hval)
-{
-    if (key == Qundef) return ST_CONTINUE;
-    *hval ^= rb_hash(key);
-    *hval *= 137;
-    *hval ^= rb_hash(val);
-    return ST_CONTINUE;
-}
-
-static VALUE
-recursive_hash(VALUE hash, VALUE dummy, int recur)
-{
-    int hval;
-
-    if (recur) {
-	return LONG2FIX(0);
-    }
-    if (!RHASH(hash)->ntbl)
-        return LONG2FIX(0);
-    hval = RHASH(hash)->ntbl->num_entries;
-    rb_hash_foreach(hash, hash_i, (st_data_t)&hval);
-    return INT2FIX(hval);
-}
-#endif
-
-/*
- *  call-seq:
- *     array.hash   -> fixnum
- *
- *  Compute a hash-code for this array. Two arrays with the same content
- *  will have the same hash code (and will compare using <code>eql?</code>).
- */
-
-#if !WITH_OBJC
-static VALUE
-rb_hash_hash(VALUE hash)
-{
-    return rb_exec_recursive(recursive_hash, hash, 0);
-}
-#endif
-
-static int
 rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
 {
     if (key == Qundef) return ST_CONTINUE;
@@ -1955,7 +1404,7 @@
 static VALUE
 rb_hash_merge(VALUE hash1, VALUE hash2)
 {
-    return rb_hash_update(rb_obj_dup(hash1), hash2);
+    return rb_hash_update(rb_hash_dup(hash1), hash2);
 }
 
 static int
@@ -2080,12 +1529,7 @@
 rb_hash_compare_by_id(VALUE hash)
 {
     rb_hash_modify(hash);
-#if WITH_OBJC
     HASH_KEY_CALLBACKS(hash)->equal = NULL;
-#else
-    RHASH(hash)->ntbl->type = &identhash;
-    rb_hash_rehash(hash);
-#endif
     return hash;
 }
 
@@ -2101,37 +1545,16 @@
 static VALUE
 rb_hash_compare_by_id_p(VALUE hash)
 {
-#if WITH_OBJC
     return HASH_KEY_CALLBACKS(hash)->equal == NULL ? Qtrue : Qfalse;
-#else
-    if (!RHASH(hash)->ntbl)
-        return Qfalse;
-    if (RHASH(hash)->ntbl->type == &identhash) {
-	return Qtrue;
-    }
-    return Qfalse;
-#endif
 }
 
 static int path_tainted = -1;
 
 static char **origenviron;
-#ifdef _WIN32
-#define GET_ENVIRON(e) (e = rb_w32_get_environ())
-#define FREE_ENVIRON(e) rb_w32_free_environ(e)
-static char **my_environ;
 #undef environ
-#define environ my_environ
-#elif defined(__APPLE__)
-#undef environ
 #define environ (*_NSGetEnviron())
 #define GET_ENVIRON(e) (e)
 #define FREE_ENVIRON(e)
-#else
-extern char **environ;
-#define GET_ENVIRON(e) (e)
-#define FREE_ENVIRON(e)
-#endif
 
 static VALUE
 env_str_new(const char *ptr, long len)
@@ -2267,107 +1690,15 @@
     return path_tainted;
 }
 
-#if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
-static int
-envix(const char *nam)
-{
-    register int i, len = strlen(nam);
-    char **env;
-
-    env = GET_ENVIRON(environ);
-    for (i = 0; env[i]; i++) {
-	if (
-#ifdef ENV_IGNORECASE
-	    STRNCASECMP(env[i],nam,len) == 0
-#else
-	    memcmp(env[i],nam,len) == 0
-#endif
-	    && env[i][len] == '=')
-	    break;			/* memcmp must come first to avoid */
-    }					/* potential SEGV's */
-    FREE_ENVIRON(environ);
-    return i;
-}
-#endif
-
 void
 ruby_setenv(const char *name, const char *value)
 {
-#if defined(_WIN32)
-    /* The sane way to deal with the environment.
-     * Has these advantages over putenv() & co.:
-     *  * enables us to store a truly empty value in the
-     *    environment (like in UNIX).
-     *  * we don't have to deal with RTL globals, bugs and leaks.
-     *  * Much faster.
-     * Why you may want to enable USE_WIN32_RTL_ENV:
-     *  * environ[] and RTL functions will not reflect changes,
-     *    which might be an issue if extensions want to access
-     *    the env. via RTL.  This cuts both ways, since RTL will
-     *    not see changes made by extensions that call the Win32
-     *    functions directly, either.
-     * GSAR 97-06-07
-     *
-     * REMARK: USE_WIN32_RTL_ENV is already obsoleted since we don't use
-     *         RTL's environ global variable directly yet.
-     */
-    SetEnvironmentVariable(name,value);
-#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
 #undef setenv
 #undef unsetenv
     if (value)
 	setenv(name,value,1);
     else
 	unsetenv(name);
-#else  /* WIN32 */
-    size_t len;
-    int i=envix(name);		        /* where does it go? */
-
-    if (environ == origenviron) {	/* need we copy environment? */
-	int j;
-	int max;
-	char **tmpenv;
-
-	for (max = i; environ[max]; max++) ;
-	tmpenv = ALLOC_N(char*, max+2);
-	for (j=0; j<max; j++)		/* copy environment */
-	    tmpenv[j] = strdup(environ[j]);
-	tmpenv[max] = 0;
-	environ = tmpenv;		/* tell exec where it is now */
-    }
-    if (environ[i]) {
-	char **envp = origenviron;
-	while (*envp && *envp != environ[i]) envp++;
-	if (!*envp)
-	    free(environ[i]);
-	if (!value) {
-	    while (environ[i]) {
-		environ[i] = environ[i+1];
-		i++;
-	    }
-	    return;
-	}
-    }
-    else {			/* does not exist yet */
-	if (!value) return;
-	REALLOC_N(environ, char*, i+2);	/* just expand it a bit */
-	environ[i+1] = 0;	/* make sure it's null terminated */
-    }
-    len = strlen(name) + strlen(value) + 2;
-    environ[i] = ALLOC_N(char, len);
-#ifndef MSDOS
-    snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
-#else
-    /* MS-DOS requires environment variable names to be in uppercase */
-    /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
-     * some utilities and applications may break because they only look
-     * for upper case strings. (Fixed strupr() bug here.)]
-     */
-    strcpy(environ[i],name); strupr(environ[i]);
-    sprintf(environ[i] + strlen(name),"=%s", value);
-#endif /* MSDOS */
-
-#endif /* WIN32 */
 }
 
 void
@@ -2903,26 +2234,9 @@
     return env;
 }
 
-/*
- *  A <code>Hash</code> is a collection of key-value pairs. It is
- *  similar to an <code>Array</code>, except that indexing is done via
- *  arbitrary keys of any object type, not an integer index. The order
- *  in which you traverse a hash by either key or value may seem
- *  arbitrary, and will generally not be in the insertion order.
- *
- *  Hashes have a <em>default value</em> that is returned when accessing
- *  keys that do not exist in the hash. By default, that value is
- *  <code>nil</code>.
- *
- */
-
-#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 +2244,7 @@
 bool
 rb_objc_hash_is_pure(VALUE ary)
 {
-    return *(Class *)ary == NSCFDICTIONARY();
+    return *(Class *)ary == (Class)rb_cCFHash;
 }
 
 static CFIndex
@@ -3046,10 +2360,24 @@
     INSTALL_METHOD("isEqual:", imp_rb_hash_isEqual);
     INSTALL_METHOD("containsObject:", imp_rb_hash_containsObject);
 
+    rb_define_alloc_func((VALUE)klass, hash_alloc);
+
 #undef INSTALL_METHOD
 }
-#endif
 
+/*
+ *  A <code>Hash</code> is a collection of key-value pairs. It is
+ *  similar to an <code>Array</code>, except that indexing is done via
+ *  arbitrary keys of any object type, not an integer index. The order
+ *  in which you traverse a hash by either key or value may seem
+ *  arbitrary, and will generally not be in the insertion order.
+ *
+ *  Hashes have a <em>default value</em> that is returned when accessing
+ *  keys that do not exist in the hash. By default, that value is
+ *  <code>nil</code>.
+ *
+ */
+
 void
 Init_Hash(void)
 {
@@ -3057,19 +2385,18 @@
     id_yield = rb_intern("yield");
     id_default = rb_intern("default");
 
-#if WITH_OBJC
-    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);
-#endif
+    rb_cCFHash = (VALUE)objc_getClass("NSCFDictionary");
+    rb_cHash = rb_cNSHash = (VALUE)objc_getClass("NSDictionary");
+    rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
+    rb_set_class_path(rb_cNSMutableHash, rb_cObject, "NSMutableDictionary");
+    rb_const_set(rb_cObject, rb_intern("Hash"), rb_cNSMutableHash);
 
     rb_include_module(rb_cHash, rb_mEnumerable);
 
-    rb_define_alloc_func(rb_cHash, hash_alloc);
+    /* to return mutable copies */
+    rb_define_method(rb_cHash, "dup", rb_hash_dup, 0);
+    rb_define_method(rb_cHash, "clone", rb_hash_clone, 0);
+
     rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
     rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
     rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
@@ -3083,9 +2410,6 @@
 
     rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
     rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
-#if !WITH_OBJC
-    rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
-#endif
     rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
     rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
     rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
@@ -3116,6 +2440,10 @@
     rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
     rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
     rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
+
+    /* to override the private -[NSMutableDictionary invert] method */
+    rb_define_method(rb_cNSMutableHash,"invert", rb_hash_invert, 0);
+
     rb_define_method(rb_cHash,"update", rb_hash_update, 1);
     rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
     rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
@@ -3134,7 +2462,6 @@
     rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
     rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
 
-#ifndef __MACOS__ /* environment variables nothing on MacOS. */
     origenviron = environ;
     envtbl = rb_obj_alloc(rb_cObject);
     rb_extend_object(envtbl, rb_mEnumerable);
@@ -3180,8 +2507,4 @@
     rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
 
     rb_define_global_const("ENV", envtbl);
-#else /* __MACOS__ */
-	envtbl = rb_hash_s_new(0, NULL, rb_cHash);
-    rb_define_global_const("ENV", envtbl);
-#endif  /* ifndef __MACOS__  environment variables nothing on MacOS. */
 }

Modified: MacRuby/trunk/id.c
===================================================================
--- MacRuby/trunk/id.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/id.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -40,6 +40,31 @@
     idNot = rb_intern("!");
     idNeq = rb_intern("!=");
 
+#if WITH_OBJC
+    selPLUS = sel_registerName("+:");
+    selMINUS = sel_registerName("-:");
+    selMULT = sel_registerName("*:");
+    selDIV = sel_registerName("/:");
+    selMOD = sel_registerName("%:");
+    selEq = sel_registerName("==:");
+    selNeq = sel_registerName("!=:");
+    selLT = sel_registerName("<:");
+    selLE = sel_registerName("<=:");
+    selGT = sel_registerName(">:");
+    selGE = sel_registerName(">=:");
+    selLTLT = sel_registerName("<<:");
+    selAREF = sel_registerName("[]:");
+    selASET = sel_registerName("[]=:");
+    selLength = sel_registerName("length");
+    selSucc = sel_registerName("succ");
+    selNot = sel_registerName("!");
+    selInit = sel_registerName("init");
+    selCopy = sel_registerName("copy");
+    sel_ignored = sel_registerName("retain");
+    assert(sel_ignored == sel_registerName("release"));
+    sel_zone = sel_registerName("zone");
+#endif
+
     idAREF = rb_intern("[]");
     idASET = rb_intern("[]=");
 
@@ -66,4 +91,7 @@
 
     idRespond_to = rb_intern("respond_to?");
     idInitialize = rb_intern("initialize");
+
+    idIncludedModules = rb_intern("__included_modules__");
+    idIncludedInClasses = rb_intern("__included_in_classes__");
 }

Modified: MacRuby/trunk/id.h
===================================================================
--- MacRuby/trunk/id.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/id.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -52,4 +52,29 @@
 extern ID id__send__;
 extern ID idRespond_to;
 extern ID idInitialize;
+#if WITH_OBJC
+extern SEL selPLUS;
+extern SEL selMINUS;
+extern SEL selMULT;
+extern SEL selDIV;
+extern SEL selMOD;
+extern SEL selEq;
+extern SEL selNeq;
+extern SEL selLT;
+extern SEL selLE;
+extern SEL selGT;
+extern SEL selGE;
+extern SEL selLTLT;
+extern SEL selAREF;
+extern SEL selASET;
+extern SEL selLength;
+extern SEL selSucc;
+extern SEL selNot;
+extern SEL selInit;
+extern SEL selCopy;
+extern SEL sel_ignored;
+extern SEL sel_zone;
+extern ID idIncludedModules;
+extern ID idIncludedInClasses;
+#endif
 #endif /* RUBY_ID_H */

Modified: MacRuby/trunk/include/ruby/defines.h
===================================================================
--- MacRuby/trunk/include/ruby/defines.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/defines.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -296,7 +296,7 @@
 void rb_objc_wb(void *dst, void *newval);
 void rb_objc_wb_range(void *dest, size_t len);
 void rb_objc_root(void *addr);
-# define GC_WB(dst, newval) (rb_objc_wb((void *)dst, (void *)newval))
+# define GC_WB(dst, newval) (SPECIAL_CONST_P(newval) ? *(void **)dst = (void *)newval : rb_objc_wb((void *)dst, (void *)newval))
 # define GC_ROOT(dst) (rb_objc_root((void *)dst))
 # define GC_WEAK(dst) (rb_objc_weak((void *)dst))
 #else

Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/intern.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -77,6 +77,7 @@
 VALUE rb_ary_cmp(VALUE, VALUE);
 VALUE rb_ary_replace(VALUE copy, VALUE orig);
 VALUE rb_get_values_at(VALUE, long, int, VALUE*, VALUE(*)(VALUE,long));
+void rb_ary_insert(VALUE, long, VALUE);
 #if WITH_OBJC
 VALUE rb_ary_elt(VALUE, long);
 bool rb_objc_ary_is_pure(VALUE);
@@ -147,10 +148,9 @@
 #define rb_Complex2(x,y) rb_Complex(x, y)
 /* class.c */
 #if WITH_OBJC
-VALUE rb_objc_import_class(Class);
 VALUE rb_objc_create_class(const char *name, VALUE super);
-VALUE rb_objc_rename_class(VALUE klass, const char *name);
 bool rb_objc_install_primitives(Class ocklass, Class ocsuper);
+void rb_define_object_special_methods(VALUE klass);
 #endif
 VALUE rb_class_boot(VALUE);
 VALUE rb_class_new(VALUE);
@@ -279,7 +279,7 @@
 void rb_provide(const char*);
 VALUE rb_f_require(VALUE, VALUE);
 VALUE rb_require_safe(VALUE, int);
-void rb_obj_call_init(VALUE, int, VALUE*);
+VALUE rb_obj_call_init(VALUE, int, VALUE*);
 VALUE rb_class_new_instance(int, VALUE*, VALUE);
 VALUE rb_block_proc(void);
 VALUE rb_f_lambda(void);
@@ -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,9 +701,9 @@
 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);
+VALUE rb_objc_call(VALUE, SEL, int, VALUE *);
 #endif
 /* version.c */
 void ruby_show_version(void);

Modified: MacRuby/trunk/include/ruby/node.h
===================================================================
--- MacRuby/trunk/include/ruby/node.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/node.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -507,7 +507,10 @@
 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 *);
+NODE *rb_objc_method_node2(VALUE, SEL, IMP *);
+NODE *rb_objc_method_node3(IMP);
 #endif
 NODE *rb_node_newnode(enum node_type,VALUE,VALUE,VALUE);
 

Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/ruby.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -229,9 +229,15 @@
 
 #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
 
-#define SYMBOL_P(x) (((VALUE)(x)&~(~(VALUE)0<<RUBY_SPECIAL_SHIFT))==SYMBOL_FLAG)
-#define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
-#define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
+#if WITH_OBJC
+# define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
+# define ID2SYM(x) (rb_id2str((ID)x))
+# define SYM2ID(x) (RSYMBOL(x)->id)
+#else
+# define SYMBOL_P(x) (((VALUE)(x)&~(~(VALUE)0<<RUBY_SPECIAL_SHIFT))==SYMBOL_FLAG)
+# define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
+# define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
+#endif
 
 /* special contants - i.e. non-zero and non-fixnum constants */
 enum ruby_special_consts {
@@ -242,7 +248,9 @@
 
     RUBY_IMMEDIATE_MASK = 0x03,
     RUBY_FIXNUM_FLAG    = 0x01,
+#if !WITH_OBJC
     RUBY_SYMBOL_FLAG    = 0x0e,
+#endif
     RUBY_SPECIAL_SHIFT  = 8,
 };
 
@@ -252,7 +260,9 @@
 #define Qundef ((VALUE)RUBY_Qundef)	/* undefined value for placeholder */
 #define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK
 #define FIXNUM_FLAG RUBY_FIXNUM_FLAG
-#define SYMBOL_FLAG RUBY_SYMBOL_FLAG
+#if !WITH_OBJC
+# define SYMBOL_FLAG RUBY_SYMBOL_FLAG
+#endif
 
 #define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
 #define NIL_P(v) ((VALUE)(v) == Qnil)
@@ -283,6 +293,9 @@
     RUBY_T_FALSE  = 0x13,
     RUBY_T_SYMBOL = 0x14,
     RUBY_T_FIXNUM = 0x15,
+#if WITH_OBJC
+    RUBY_T_NATIVE = 0x16,
+#endif
 
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
@@ -306,6 +319,9 @@
 #define T_BIGNUM RUBY_T_BIGNUM
 #define T_FILE   RUBY_T_FILE
 #define T_FIXNUM RUBY_T_FIXNUM
+#if WITH_OBJC
+# define T_NATIVE RUBY_T_NATIVE
+#endif
 #define T_TRUE   RUBY_T_TRUE
 #define T_FALSE  RUBY_T_FALSE
 #define T_DATA   RUBY_T_DATA
@@ -416,20 +432,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 +448,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 +488,41 @@
     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 */
+# define RCLASS_IS_FROZEN	      0x1000  /* class is frozen */
+# define RCLASS_IS_TAINTED	      0x2000  /* class is tainted */
+# define RCLASS_IS_STRING_SUBCLASS    0x10000 /* class is a subclass of NSCFString */
+# define RCLASS_IS_ARRAY_SUBCLASS     0x20000 /* class is a subclass of NSCFArray */
+# define RCLASS_IS_HASH_SUBCLASS      0x40000 /* class is a subclass of NSCFDictionary */
+# 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_META(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_META(m) (_RCLASS_INFO(m) & CLS_META)
+# endif
+# 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)
+# define RCLASS_SINGLETON(m) ((RCLASS_VERSION(m) & RCLASS_IS_SINGLETON) == RCLASS_IS_SINGLETON)
+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 {
@@ -504,6 +532,20 @@
 #define RFLOAT_VALUE(v) (RFLOAT(v)->float_value)
 #define DOUBLE2NUM(dbl)  rb_float_new(dbl)
 
+#if WITH_OBJC
+struct RFixnum {
+    VALUE klass;
+    long value;
+};
+
+struct RSymbol {
+    VALUE klass;
+    char *str;
+    unsigned int len;
+    ID id;
+};
+#endif
+
 #define ELTS_SHARED FL_USER2
 
 #if !WITH_OBJC
@@ -576,7 +618,6 @@
  */
 const VALUE *rb_ary_ptr(VALUE);
 # define RARRAY_PTR(a) (rb_ary_ptr((VALUE)a)) 
-# define RARRAY_AT(a,i) ((VALUE)CFArrayGetValueAtIndex((CFArrayRef)a, (long)i))
 #endif
 
 struct RRegexp {
@@ -710,12 +751,16 @@
 #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))
+#if WITH_OBJC
+# define RFIXNUM(obj) (R_CAST(RFixnum)(obj))
+# define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
+#endif
 #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))
@@ -771,7 +816,7 @@
 #define FL_REVERSE(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags ^= (f);} while (0)
 
 #if WITH_OBJC
-# define OBJ_TAINTED(x) (rb_obj_tainted((VALUE)x))
+# define OBJ_TAINTED(x) (SPECIAL_CONST_P(x) || NATIVE(x) ? rb_obj_tainted((VALUE)x) : FL_TEST((x), FL_TAINT))
 # define OBJ_TAINT(x)   (rb_obj_taint((VALUE)x))
 #else
 # define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
@@ -781,7 +826,7 @@
 #define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
 
 #if WITH_OBJC
-# define OBJ_FROZEN(x) (rb_obj_frozen_p((VALUE)x))
+# define OBJ_FROZEN(x) (SPECIAL_CONST_P(x) || NATIVE(x) ? rb_obj_frozen_p((VALUE)x) : FL_TEST((x), FL_FREEZE))
 # define OBJ_FREEZE(x) (rb_obj_freeze((VALUE)x))
 #else
 # define OBJ_FROZEN(x) FL_TEST((x), FL_FREEZE)
@@ -839,9 +884,19 @@
 ID rb_intern(const char*);
 ID rb_intern2(const char*, long);
 ID rb_intern_str(VALUE str);
-const char *rb_id2name(ID);
 ID rb_to_id(VALUE);
 VALUE rb_id2str(ID);
+#if WITH_OBJC
+# define rb_sym2name(sym) (RSYMBOL(sym)->str)
+static inline
+const char *rb_id2name(ID val)
+{
+    VALUE s = rb_id2str(val);
+    return s == 0 ? NULL : rb_sym2name(s);
+}
+#else
+const char *rb_id2name(ID);
+#endif
 
 #ifdef __GNUC__
 /* __builtin_constant_p and statement expression is available
@@ -946,6 +1001,9 @@
 
 RUBY_EXTERN VALUE rb_cBasicObject;
 RUBY_EXTERN VALUE rb_cObject;
+#if WITH_OBJC
+RUBY_EXTERN VALUE rb_cNSObject;
+#endif
 RUBY_EXTERN VALUE rb_cArray;
 RUBY_EXTERN VALUE rb_cBignum;
 RUBY_EXTERN VALUE rb_cBinding;
@@ -984,6 +1042,19 @@
 RUBY_EXTERN VALUE rb_cVM;
 RUBY_EXTERN VALUE rb_cEnv;
 
+#if WITH_OBJC
+RUBY_EXTERN VALUE rb_cCFString;
+RUBY_EXTERN VALUE rb_cNSString;
+RUBY_EXTERN VALUE rb_cNSMutableString;
+RUBY_EXTERN VALUE rb_cCFArray;
+RUBY_EXTERN VALUE rb_cNSArray;
+RUBY_EXTERN VALUE rb_cNSMutableArray;
+RUBY_EXTERN VALUE rb_cCFHash;
+RUBY_EXTERN VALUE rb_cNSHash;
+RUBY_EXTERN VALUE rb_cNSMutableHash;
+RUBY_EXTERN VALUE rb_cCFNumber;
+#endif
+
 RUBY_EXTERN VALUE rb_eException;
 RUBY_EXTERN VALUE rb_eStandardError;
 RUBY_EXTERN VALUE rb_eSystemExit;
@@ -1019,19 +1090,75 @@
 RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
 
 #if WITH_OBJC
-static inline unsigned
-rb_objc_is_non_native(VALUE obj)
+static inline bool
+rb_is_native(VALUE obj) {
+    Class k = *(Class *)obj;
+    return k != NULL && (RCLASS_VERSION(k) & RCLASS_IS_OBJECT_SUBCLASS) != RCLASS_IS_OBJECT_SUBCLASS;
+}
+#define NATIVE(obj) (rb_is_native((VALUE)obj))
+
+VALUE rb_box_fixnum(VALUE);
+
+static inline id
+rb_rval_to_ocid(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);
+    if (SPECIAL_CONST_P(obj)) {
+        if (obj == Qtrue) {
+            return (id)kCFBooleanTrue;
+        }
+        if (obj == Qfalse) {
+            return (id)kCFBooleanFalse;
+        }
+        if (obj == Qnil) {
+            return (id)kCFNull;
+        }
+        if (FIXNUM_P(obj)) {
+	    return (id)rb_box_fixnum(obj);
+	}
     }
-    return 1;
+    return (id)obj;
 }
+
+static inline VALUE
+rb_ocid_to_rval(id obj)
+{
+    if (obj == (id)kCFBooleanTrue) {
+	return Qtrue;
+    }
+    if (obj == (id)kCFBooleanFalse) {
+	return Qfalse;
+    }
+    if (obj == (id)kCFNull) {
+	return Qnil;
+    }
+    if (*(Class *)obj == (Class)rb_cFixnum) {
+	return LONG2FIX(RFIXNUM(obj)->value);
+    }
+    if (*(Class *)obj == (Class)rb_cCFNumber) {
+	/* TODO NSNumber should implement the Numeric primitive methods */
+	if (CFNumberIsFloatType((CFNumberRef)obj)) {
+	    double v;
+	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberDoubleType, &v));
+	    extern VALUE rb_float_new(double);
+	    return rb_float_new(v);
+	}
+	else {
+	    long v;
+	    assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberLongType, &v));
+	    return LONG2FIX(v);
+	}
+    }
+    return (VALUE)obj;
+}
+#define RB2OC(obj) (rb_rval_to_ocid((VALUE)obj))
+#define OC2RB(obj) (rb_ocid_to_rval((id)obj))
+
+static inline VALUE
+rb_ary_elt_fast(CFArrayRef ary, long i)
+{
+    return OC2RB(CFArrayGetValueAtIndex(ary, i));
+}
+#define RARRAY_AT(a,i) (rb_ary_elt_fast((CFArrayRef)a, (long)i))
 #endif
 
 static inline VALUE
@@ -1040,36 +1167,27 @@
     if (IMMEDIATE_P(obj)) {
 	if (FIXNUM_P(obj)) return rb_cFixnum;
 	if (obj == Qtrue)  return rb_cTrueClass;
+#if !WITH_OBJC
 	if (SYMBOL_P(obj)) return rb_cSymbol;
+#endif
     }
     else if (!RTEST(obj)) {
 	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;
 }
 
 static inline int
 rb_type(VALUE obj)
 {
+    Class k;
     if (IMMEDIATE_P(obj)) {
 	if (FIXNUM_P(obj)) return T_FIXNUM;
 	if (obj == Qtrue) return T_TRUE;
+#if !WITH_OBJC
 	if (SYMBOL_P(obj)) return T_SYMBOL;
+#endif
 	if (obj == Qundef) return T_UNDEF;
     }
     else if (!RTEST(obj)) {
@@ -1077,20 +1195,26 @@
 	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 ((k = *(Class *)obj) != NULL) {
+	if (RCLASS_META(k)) {
+	    if (RCLASS_MODULE(obj)) return T_MODULE;
+	    else return T_CLASS;
 	}
+	if (k == (Class)rb_cSymbol) return T_SYMBOL;
+	if (k == (Class)rb_cCFString
+	    || (RCLASS_VERSION(k) & RCLASS_IS_STRING_SUBCLASS) 
+		== RCLASS_IS_STRING_SUBCLASS) 
+	    return T_STRING;
+	if (k == (Class)rb_cCFArray
+	    || (RCLASS_VERSION(k) & RCLASS_IS_ARRAY_SUBCLASS) 
+		== RCLASS_IS_ARRAY_SUBCLASS) 
+	    return T_ARRAY;
+	if (k == (Class)rb_cCFHash
+	    || (RCLASS_VERSION(k) & RCLASS_IS_HASH_SUBCLASS) 
+		== RCLASS_IS_HASH_SUBCLASS)
+	    return T_HASH;
+	if (k == (Class)rb_cFixnum) return T_FIXNUM;
+	if (NATIVE(obj)) return T_NATIVE;
     }
 #endif
     return BUILTIN_TYPE(obj);

Modified: MacRuby/trunk/insnhelper.h
===================================================================
--- MacRuby/trunk/insnhelper.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/insnhelper.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -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, recv, klass, mcache) do { \
+    VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, recv, klass, (struct rb_method_cache *)mcache); \
     if (v == Qundef) { \
 	RESTORE_REGS(); \
 	NEXT_INSN(); \
@@ -140,9 +140,13 @@
 #define BASIC_OP_UNREDEFINED_P(op) ((ruby_vm_redefined_flag & (op)) == 0)
 #define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
 
-#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)); \
+#define CALL_SIMPLE_METHOD(num, id, recv, asel) do { \
+    struct rb_method_cache mcache; \
+    mcache.flags = RB_MCACHE_RCALL_FLAG; \
+    mcache.as.rcall.sel = asel; \
+    mcache.as.rcall.klass = 0; \
+    mcache.as.rcall.node = NULL; \
+    CALL_METHOD(num, 0, 0, id, recv, CLASS_OF(recv), &mcache); \
 } while (0)
 
 #endif /* RUBY_INSNHELPER_H */

Modified: MacRuby/trunk/insns.def
===================================================================
--- MacRuby/trunk/insns.def	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/insns.def	2008-08-21 06:13:14 UTC (rev 459)
@@ -812,9 +812,21 @@
 	break;
       case DEFINED_METHOD:{
 	  VALUE klass = CLASS_OF(v);
+#if WITH_OBJC
+	  NODE *method;
+	  IMP imp;
+
+	  method = rb_objc_method_node(klass, SYM2ID(obj), &imp, NULL);
+
+	  if (method == NULL && imp != NULL) {
+	      expr_type = "method";
+	  }
+	  else if (method != NULL) {
+#else
 	  NODE *method = (NODE *) rb_method_node(klass, SYM2ID(obj));
 
 	  if (method) {
+#endif
 	      if (!(method->nd_noex & NOEX_PRIVATE)) {
 		  if (!((method->nd_noex & NOEX_PROTECTED) &&
 			!rb_obj_is_kind_of(GET_SELF(),
@@ -1023,11 +1035,13 @@
  */
 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, VALUE mcache)
 (...)
 (VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
 {
+#if !WITH_OBJC
     NODE *mn;
+#endif
     VALUE recv, klass;
     rb_block_t *blockptr = 0;
     rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc,
@@ -1038,17 +1052,16 @@
     /* get receiver */
     recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
     klass = CLASS_OF(recv);
+#if !WITH_OBJC
     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, recv, klass, mcache);
 }
 
 /**
@@ -1069,16 +1082,34 @@
     VALUE recv, klass;
     NODE *mn;
     ID id;
+    IMP imp;
+    SEL sel;
     const VALUE flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
 
     recv = GET_SELF();
-    vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass);
+    mn = NULL; imp = NULL; sel = 0;
+    vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass, &mn, &imp, &sel);
+#if !WITH_OBJC
     mn = rb_method_node(klass, id);
+#endif
+
 #if WITH_OBJC
-    vm_method_process_named_args(&id, &mn, recv, (rb_num_t *)&num, GET_CFP());
+    struct rb_method_cache mcache;
+    void *mcachep;
+
+    if (mn != NULL) {
+	mcache.flags = RB_MCACHE_RCALL_FLAG;
+	mcache.as.rcall.sel = sel;
+	mcache.as.rcall.klass = klass;
+	mcache.as.rcall.node = mn;
+	mcachep = &mcache;
+    }
+    else {
+	mcachep = NULL;
+    }
 #endif
 
-    CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
+    CALL_METHOD(num, blockptr, flag, id, recv, klass, mcachep);
 }
 
 /**
@@ -1298,8 +1329,9 @@
 	VALUE val;
 #if WITH_OBJC
 	if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
-	    (const void *)key,
+	    (const void *)RB2OC(key),
 	    (const void **)&val)) {
+	val = OC2RB(val);
 #else
 	if (st_lookup(RHASH_TBL(hash), key, &val)) {
 #endif
@@ -1405,7 +1437,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idPLUS, recv);
+	CALL_SIMPLE_METHOD(1, idPLUS, recv, selPLUS);
     }
 }
 
@@ -1439,7 +1471,7 @@
 	/* other */
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idMINUS, recv);
+	CALL_SIMPLE_METHOD(1, idMINUS, recv, selMINUS);
     }
 }
 
@@ -1492,7 +1524,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idMULT, recv);
+	CALL_SIMPLE_METHOD(1, idMULT, recv, selMULT);
     }
 }
 
@@ -1556,7 +1588,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idDIV, recv);
+	CALL_SIMPLE_METHOD(1, idDIV, recv, selDIV);
     }
 }
 
@@ -1635,7 +1667,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idMOD, recv);
+	CALL_SIMPLE_METHOD(1, idMOD, recv, selMOD);
     }
 }
 
@@ -1656,7 +1688,7 @@
 	/* other */
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idEq, recv);
+	CALL_SIMPLE_METHOD(1, idEq, recv, selEq);
     }
 }
 
@@ -1687,7 +1719,7 @@
 	/* other */
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idNeq, recv);
+	CALL_SIMPLE_METHOD(1, idNeq, recv, selNeq);
     }
 }
 
@@ -1716,7 +1748,7 @@
     else {
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idLT, recv);
+	CALL_SIMPLE_METHOD(1, idLT, recv, selLT);
     }
 }
 
@@ -1746,7 +1778,7 @@
 	/* other */
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idLE, recv);
+	CALL_SIMPLE_METHOD(1, idLE, recv, selLE);
     }
 }
 
@@ -1775,7 +1807,7 @@
     else {
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idGT, recv);
+	CALL_SIMPLE_METHOD(1, idGT, recv, selGT);
     }
 }
 
@@ -1804,7 +1836,7 @@
     else {
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idGE, recv);
+	CALL_SIMPLE_METHOD(1, idGE, recv, selGE);
     }
 }
 
@@ -1838,7 +1870,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idLTLT, recv);
+	CALL_SIMPLE_METHOD(1, idLTLT, recv, selLTLT);
     }
 }
 
@@ -1868,7 +1900,7 @@
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
 	PUSH(obj);
-	CALL_SIMPLE_METHOD(1, idAREF, recv);
+	CALL_SIMPLE_METHOD(1, idAREF, recv, selAREF);
     }
 }
 
@@ -1902,7 +1934,7 @@
 	PUSH(recv);
 	PUSH(obj);
 	PUSH(set);
-	CALL_SIMPLE_METHOD(2, idASET, recv);
+	CALL_SIMPLE_METHOD(2, idASET, recv, selASET);
     }
 }
 
@@ -1935,7 +1967,7 @@
     else {
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
-	CALL_SIMPLE_METHOD(0, idLength, recv);
+	CALL_SIMPLE_METHOD(0, idLength, recv, selLength);
     }
 }
 
@@ -1982,7 +2014,7 @@
     if (0) {
       INSN_LABEL(normal_dispatch):
 	PUSH(recv);
-	CALL_SIMPLE_METHOD(0, idSucc, recv);
+	CALL_SIMPLE_METHOD(0, idSucc, recv, selSucc);
     }
 }
 
@@ -2005,7 +2037,7 @@
     }
     else {
 	PUSH(recv);
-	CALL_SIMPLE_METHOD(0, idNot, recv);
+	CALL_SIMPLE_METHOD(0, idNot, recv, selNot);
     }
 }
 

Modified: MacRuby/trunk/instruby.rb
===================================================================
--- MacRuby/trunk/instruby.rb	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/instruby.rb	2008-08-21 06:13:14 UTC (rev 459)
@@ -501,22 +501,30 @@
   end
 end
 
-puts "fixing bridge support dylibs"
-unless File.exist?('markgc')
-  unless system("gcc markgc.c -std=gnu99 -o markgc")
-    $stderr.puts "cannot build the markgc tool"
-    exit 1
+touch_file = '/System/Library/Frameworks/.bridgesupport_dylib_gcmarked'
+if $destdir.empty? and File.exist?(touch_file)
+  puts "bridge support dylibs already fixed"
+else
+  puts "fixing bridge support dylibs"
+  unless File.exist?('markgc')
+    unless system("gcc markgc.c -std=gnu99 -o markgc")
+      $stderr.puts "cannot build the markgc tool"
+      exit 1
+    end
   end
-end
-Dir.glob('/System/Library/Frameworks/**/BridgeSupport/*.dylib').each do |p|
-  unless system("./markgc '#{p}' >& /dev/null")
-    $stderr.puts "cannot markgc #{p}"
-    exit 1
+  Dir.glob('/System/Library/Frameworks/**/BridgeSupport/*.dylib').each do |p|
+    unless system("./markgc '#{p}' >& /dev/null")
+      $stderr.puts "cannot markgc #{p}"
+      exit 1
+    end
+    unless $destdir.empty?
+      dirname = File.dirname(p)
+      mkdir_p(dirname)
+      install(p, dirname)
+    end
   end
-  unless $destdir.empty?
-    dirname = File.dirname(p)
-    mkdir_p(dirname)
-    install(p, dirname)
+  if $destdir.empty?
+    touch(touch_file)
   end
 end
 

Modified: MacRuby/trunk/io.c
===================================================================
--- MacRuby/trunk/io.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/io.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -3972,7 +3972,7 @@
         write_fptr->fd = write_fd;
         write_fptr->mode = (modef & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
         fptr->mode &= ~FMODE_WRITABLE;
-        fptr->tied_io_for_writing = write_port;
+        GC_WB(&fptr->tied_io_for_writing, write_port);
         rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
     }
 
@@ -4589,7 +4589,7 @@
     write_io = GetWriteIO(io);
     if (io != write_io) {
         write_io = rb_obj_dup(write_io);
-        fptr->tied_io_for_writing = write_io;
+        GC_WB(&fptr->tied_io_for_writing, write_io);
         rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
     }
 
@@ -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/trunk/lib/delegate.rb
===================================================================
--- MacRuby/trunk/lib/delegate.rb	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/lib/delegate.rb	2008-08-21 06:13:14 UTC (rev 459)
@@ -117,9 +117,8 @@
 class Delegator
   preserved = [
     :__id__, :object_id, :__send__, :public_send, :respond_to?, :send,
-    :instance_eval, :instance_exec, :extend,
+    :instance_eval, :instance_exec, :extend, :initialize
   ]
-  preserved.concat(NSObject.instance_methods)
   instance_methods.each do |m|
     next if preserved.include?(m)
     undef_method m

Modified: MacRuby/trunk/lib/fileutils.rb
===================================================================
--- MacRuby/trunk/lib/fileutils.rb	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/lib/fileutils.rb	2008-08-21 06:13:14 UTC (rev 459)
@@ -1507,7 +1507,8 @@
   end
 
   METHODS = singleton_methods() - [:private_module_function,
-      :commands, :options, :have_option?, :options_of, :collect_method]
+      :commands, :options, :have_option?, :options_of, 
+      :collect_method]
 
   # 
   # This module has all methods of FileUtils module, but it outputs messages

Modified: MacRuby/trunk/marshal.c
===================================================================
--- MacRuby/trunk/marshal.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/marshal.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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/trunk/numeric.c
===================================================================
--- MacRuby/trunk/numeric.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/numeric.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -83,6 +83,9 @@
 static ID id_coerce, id_to_i, id_eq;
 
 VALUE rb_cNumeric;
+#if WITH_OBJC
+VALUE rb_cCFNumber;
+#endif
 VALUE rb_cFloat;
 VALUE rb_cInteger;
 VALUE rb_cFixnum;
@@ -90,6 +93,45 @@
 VALUE rb_eZeroDivError;
 VALUE rb_eFloatDomainError;
 
+#if WITH_OBJC
+static CFMutableDictionaryRef fixnum_dict = NULL;
+static struct RFixnum *fixnum_cache = NULL;
+
+VALUE
+rb_box_fixnum(VALUE fixnum)
+{
+    struct RFixnum *val;
+    long value;
+
+    if (fixnum_dict == NULL)
+	fixnum_dict = CFDictionaryCreateMutable(kCFAllocatorMalloc, 0, NULL, NULL); 
+
+    value = FIX2LONG(fixnum);
+
+    if (value >= 0 && value <= 1000000) {
+	if (fixnum_cache == NULL) {
+	   fixnum_cache = (struct RFixnum *)calloc(1, sizeof(struct RFixnum) * 1000000);
+	}
+	val = &fixnum_cache[value];
+	if (val->klass == 0) {
+	    val->klass = rb_cFixnum;
+	    val->value = value;
+	}
+	return (VALUE)val;
+    }
+
+    val = (struct RFixnum *)CFDictionaryGetValue(fixnum_dict, (const void *)fixnum);
+    if (val == NULL) {
+	val = (struct RFixnum *)malloc(sizeof(struct RFixnum));
+	val->klass = rb_cFixnum;
+	val->value = FIX2LONG(fixnum);
+	CFDictionarySetValue(fixnum_dict, (const void *)fixnum, (const void *)val);
+    }
+
+    return (VALUE)val;
+}
+#endif
+
 void
 rb_num_zerodiv(void)
 {
@@ -3106,9 +3148,9 @@
 }
 
 static const char *
-imp_rb_integer_objCType(void *rcv, SEL sel)
+imp_rb_fixnum_objCType(void *rcv, SEL sel)
 {
-    return "q";
+    return "l";
 }
 
 static void
@@ -3119,10 +3161,10 @@
 }
 
 static void
-imp_rb_integer_getValue(void *rcv, SEL sel, void *buffer)
+imp_rb_fixnum_getValue(void *rcv, SEL sel, void *buffer)
 {
-    long long v = NUM2LL(rcv);
-    *(long long *)buffer = v;
+    long v = RFIXNUM(rcv)->value;
+    *(long *)buffer = v;
 }
 
 static double
@@ -3132,9 +3174,9 @@
 }
 
 static long long
-imp_rb_integer_longLongValue(void *rcv, SEL sel)
+imp_rb_fixnum_longValue(void *rcv, SEL sel)
 {
-    return NUM2LL(rcv);
+    return RFIXNUM(rcv)->value;
 }
 
 static inline void
@@ -3146,27 +3188,25 @@
 }
 
 static void
-rb_install_nsnumber_float_primitives(void)
+rb_install_nsnumber_primitives(void)
 {
-    Class klass = RCLASS_OCID(rb_cFloat);
+    Class klass;
+  
+    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:"), 
 	    (IMP)imp_rb_float_getValue);
     rb_objc_install_method(klass, sel_registerName("doubleValue"), 
 	    (IMP)imp_rb_float_doubleValue);
-}
 
-static void
-rb_install_nsnumber_integer_primitives(void)
-{
-    Class klass = RCLASS_OCID(rb_cNumeric);
+    klass = (Class)rb_cFixnum;
     rb_objc_install_method(klass, sel_registerName("objCType"),
-	    (IMP)imp_rb_integer_objCType);
+	    (IMP)imp_rb_fixnum_objCType);
     rb_objc_install_method(klass, sel_registerName("getValue:"), 
-	    (IMP)imp_rb_integer_getValue);
-    rb_objc_install_method(klass, sel_registerName("longLongValue"), 
-	    (IMP)imp_rb_integer_longLongValue);
+	    (IMP)imp_rb_fixnum_getValue);
+    rb_objc_install_method(klass, sel_registerName("longValue"),
+	    (IMP)imp_rb_fixnum_longValue);
 }
 #endif
 
@@ -3190,8 +3230,13 @@
     rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
     rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
 #if WITH_OBJC
-    rb_cNumeric = rb_define_class("Numeric",
-        rb_objc_import_class((void*)objc_getClass("NSNumber")));
+    rb_cCFNumber = (VALUE)objc_getClass("NSCFNumber");
+    rb_cNumeric = rb_define_class("Numeric", (VALUE)objc_getClass("NSNumber"));
+    RCLASS_SET_VERSION_FLAG(rb_cNumeric, RCLASS_IS_OBJECT_SUBCLASS);
+    rb_define_object_special_methods(rb_cNumeric);
+    /* overriding NSObject methods */
+    rb_define_method(rb_cNumeric, "class", rb_obj_class, 0);
+    rb_define_method(rb_cNumeric, "dup", rb_obj_dup, 0);
 #else
     rb_cNumeric = rb_define_class("Numeric", rb_cObject);
 #endif
@@ -3354,7 +3399,6 @@
     rb_define_method(rb_cFloat, "finite?",   flo_is_finite_p, 0);
 
 #if WITH_OBJC
-    rb_install_nsnumber_integer_primitives();
-    rb_install_nsnumber_float_primitives();
+    rb_install_nsnumber_primitives();
 #endif
 }

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/objc.m	2008-08-21 06:13:14 UTC (rev 459)
@@ -40,6 +40,7 @@
 #endif
 #include "vm_core.h"
 #include "vm.h"
+#include "eval_intern.h"
 
 typedef struct {
     bs_element_type_t type;
@@ -58,11 +59,9 @@
 static ID rb_ivar_type;
 
 static VALUE bs_const_magic_cookie = Qnil;
-static VALUE rb_objc_class_magic_cookie = Qnil;
 
 static struct st_table *bs_constants;
-static struct st_table *bs_functions;
-static struct st_table *bs_function_syms;
+struct st_table *bs_functions;
 static struct st_table *bs_boxeds;
 static struct st_table *bs_classes;
 static struct st_table *bs_inf_prot_cmethods;
@@ -401,56 +400,6 @@
     return NULL;
 }
 
-bool
-rb_objc_rval_to_ocid(VALUE rval, void **ocval, bool force_nsnil)
-{
-    if (SPECIAL_CONST_P(rval)) {
-	if (rval == Qtrue) {
-	    *(id *)ocval = (id)kCFBooleanTrue;
-	}
-	else if (rval == Qfalse) {
-	    *(id *)ocval = (id)kCFBooleanFalse;
-	}
-	else if (rval == Qnil) {
-	    *(id *)ocval = force_nsnil ? (id)kCFNull : nil;
-	}
-	else if (SYMBOL_P(rval)) {
-	    *(id *)ocval = (id)rb_id2str(SYM2ID(rval));
-	}
-	else if (FIXNUM_P(rval)) {
-#define FIXNUM_CFNUMBER_CACHE_SIZE 2000
-	    static void *fixnum_cfnumber_cache[FIXNUM_CFNUMBER_CACHE_SIZE];
-	    static bool fixnum_cfnumber_cache_init = false;
-	    long v = FIX2LONG(rval);
-	    CFNumberRef number;
-	    if (!fixnum_cfnumber_cache_init) {
-		memset(fixnum_cfnumber_cache, 0, sizeof(void *) * FIXNUM_CFNUMBER_CACHE_SIZE);
-		fixnum_cfnumber_cache_init = true;
-	    }
-	    /* cache -500..1500 */
-	    if (v >= -500 && v < 1500) {
-		number = fixnum_cfnumber_cache[v+500];
-		if (number == NULL) {
-		    number = CFNumberCreate(NULL, kCFNumberLongType, &v);
-		    fixnum_cfnumber_cache[v+500] = (void *)number;
-		}
-	    }
-	    else {
-		number = CFNumberCreate(NULL, kCFNumberLongType, &v);
-		CFMakeCollectable(number);	
-	    }
-	    *(id *)ocval = (id)number;
-	}
-    }
-    else if (class_isMetaClass(*(Class *)rval)) {
-	*(id *)ocval = (id)RCLASS_OCID(rval);
-    }
-    else {
-	*(id *)ocval = (id)rval;
-    }
-    return true;
-}
-
 static bool
 rb_objc_rval_to_ocsel(VALUE rval, void **ocval)
 {
@@ -467,7 +416,7 @@
 	    break;
 
 	case T_SYMBOL:
-	    cstr = rb_id2name(SYM2ID(rval));
+	    cstr = rb_sym2name(rval);
 	    break;
 
 	default:
@@ -697,7 +646,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 +662,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) {
@@ -725,7 +675,8 @@
     switch (*octype) {
 	case _C_ID:
 	case _C_CLASS:
-	    ok = rb_objc_rval_to_ocid(rval, ocval, false);
+	    *(id *)ocval = rval == Qnil ? NULL : RB2OC(rval);
+	    ok = true;
 	    break;
 
 	case _C_SEL:
@@ -851,39 +802,7 @@
 		 RSTRING_PTR(rb_inspect(rval)), octype);
 }
 
-VALUE
-rb_objc_boot_ocid(id ocid)
-{
-    if (rb_objc_is_non_native((VALUE)ocid)) {
-        /* Make sure the ObjC class is imported in Ruby. */ 
-        rb_objc_import_class(object_getClass(ocid)); 
-    }
-    else if (RBASIC(ocid)->klass == 0) {
-	/* This pure-Ruby object was created from Objective-C, we need to 
-	 * initialize the Ruby bits. 
-	 */
-	VALUE klass;
-        
-	klass = rb_objc_import_class(object_getClass(ocid)); 
-
-	RBASIC(ocid)->klass = klass;
-	RBASIC(ocid)->flags = 
-	    klass == rb_cString
-	    ? T_STRING
-	    : klass == rb_cArray
-	    ? T_ARRAY
-	    : klass == rb_cHash
-	    ? T_HASH
-	    : T_OBJECT;
-    }
-
-    return (VALUE)ocid;
-}
-
-static void
-rb_objc_ocval_to_rbval(void **ocval, const char *octype, VALUE *rbval);
-
-bool 
+static inline bool 
 rb_objc_ocid_to_rval(void **ocval, VALUE *rbval)
 {
     id ocid = *(id *)ocval;
@@ -892,7 +811,7 @@
 	*rbval = Qnil;
     }
     else {
-	*rbval = rb_objc_boot_ocid(ocid);
+	*rbval = (VALUE)ocid;
     }
 
     return true;
@@ -909,23 +828,23 @@
     {
 	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 = "@";
     }
-    
+   
     switch (*octype) {
 	case _C_ID:
-	    ok = rb_objc_ocid_to_rval(ocval, rbval);
-	    break;
-	
 	case _C_CLASS:
-	    *rbval = rb_objc_import_class(*(Class *)ocval);
+	    *rbval = *(void **)ocval == NULL ? Qnil : *(VALUE *)ocval;
+	    ok = true;
 	    break;
 
 	case _C_BOOL:
@@ -1024,9 +943,11 @@
     rb_raise(rb_eRuntimeError, "%s: %s", name, desc);
 }
 
-static bs_element_method_t *
+bs_element_method_t *
 rb_bs_find_method(Class klass, SEL sel)
 {
+    if (bs_classes == NULL)
+	return NULL;
     do {
 	bs_element_indexed_class_t *bs_class;
 	bs_element_method_t *bs_method;
@@ -1077,20 +998,8 @@
     return type;
 }
 
-extern NODE *rb_current_cfunc_node;
-
-struct objc_ruby_closure_context {
-    SEL selector;
-    bs_element_method_t *bs_method;
-    Method method;
-    ffi_cif *cif;
-    IMP imp;
-    Class klass;
-};
-
-static VALUE
-rb_objc_call_objc(int argc, VALUE *argv, id ocrcv, Class klass, 
-		  bool super_call, struct objc_ruby_closure_context *ctx)
+VALUE
+rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, int argc, VALUE *argv)
 {
     unsigned i, real_count, count;
     ffi_type *ffi_rettype, **ffi_argtypes;
@@ -1098,13 +1007,27 @@
     ffi_cif *cif;
     const char *type;
     char buf[128];
-    void *imp;
+    id ocrcv;
 
-    count = method_getNumberOfArguments(ctx->method);
+    /* XXX very special exceptions! */
+    if (recv == rb_cNSMutableHash && sel == @selector(new)) {
+	/* because Hash.new can accept a block */
+	return rb_class_new_instance(0, NULL, recv);
+    }
+    else if (RCLASS_META(klass) && sel == @selector(class)) {
+	/* because +[NSObject class] returns self */
+	return rb_cClass;
+    }
+
+    ocrcv = RB2OC(recv);
+
+    DLOG("OCALL", "%c[<%s %p> %s]", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)ocrcv, (char *)sel);
+
+    count = method_getNumberOfArguments(method);
     assert(count >= 2);
 
     real_count = count;
-    if (ctx->bs_method != NULL && ctx->bs_method->variadic) {
+    if (bs_method != NULL && bs_method->variadic) {
 	if (argc < count - 2)
 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		argc, count - 2);
@@ -1116,97 +1039,68 @@
     }
 
     if (count == 2) {
-	method_getReturnType(ctx->method, buf, sizeof buf);
-	if (buf[0] == '@' || buf[0] == 'v') {
+	method_getReturnType(method, buf, sizeof buf);
+	if (buf[0] == '@' || buf[0] == '#' || buf[0] == 'v') {
 	    /* Easy case! */
 	    @try {
-		if (super_call) {
+		if (klass == RCLASS_SUPER(*(Class *)ocrcv)) {
 		    struct objc_super s;
 		    s.receiver = ocrcv;
-		    s.class = klass;
-		    ffi_ret = objc_msgSendSuper(&s, ctx->selector);
+		    s.class = (Class)klass;
+		    ffi_ret = objc_msgSendSuper(&s, sel);
 		}
 		else {
-		    ffi_ret = objc_msgSend(ocrcv, ctx->selector);
+		    ffi_ret = objc_msgSend(ocrcv, sel);
 		}
 	    }
 	    @catch (id e) {
 		rb_objc_exc_raise(e);
 	    }
-	    return buf[0] == '@' ? (VALUE)ffi_ret : Qnil;
+	    if (buf[0] == '@' || buf[0] == '#')
+		return ffi_ret == NULL ? Qnil : (VALUE)ffi_ret;
+	    else
+		return Qnil;
 	}
     } 
 
-    if (ctx->cif == NULL) {
-	const size_t s = sizeof(ffi_type *) * (count + 1);
-	ffi_argtypes = ctx->bs_method != NULL && ctx->bs_method->variadic
-	    ? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
-	ffi_argtypes[0] = &ffi_type_pointer;
-	ffi_argtypes[1] = &ffi_type_pointer;
-    }
+    const size_t s = sizeof(ffi_type *) * (count + 1);
 
+    ffi_argtypes = bs_method != NULL && bs_method->variadic
+	? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
+    ffi_argtypes[0] = &ffi_type_pointer;
+    ffi_argtypes[1] = &ffi_type_pointer;
+
     ffi_args = (void **)alloca(sizeof(void *) * (count + 1));
     ffi_args[0] = &ocrcv;
-    ffi_args[1] = &ctx->selector;
+    ffi_args[1] = &sel;
 
-    if (super_call) {
-	Method smethod;
-	smethod = class_getInstanceMethod(klass, ctx->selector);
-	if (klass == ctx->klass)
-	    assert(smethod != ctx->method);
-	imp = method_getImplementation(smethod);
-	assert(imp != NULL);
-    }
-    else {
-	if (ctx->imp != NULL && ctx->klass == klass) {
-	    imp = ctx->imp;
-	}
-	else {
-	    ctx->imp = imp = method_getImplementation(ctx->method);
-	    ctx->klass = klass;
-	}
-    }
-
     for (i = 0; i < argc; i++) {
 	ffi_type *ffi_argtype;
 
-	type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method, 
+	type = rb_objc_method_get_type(method, real_count, bs_method,
 	    i, buf, sizeof buf);
 
-	if (ctx->cif == NULL) {
-	    ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
-	    assert(ffi_argtypes[i + 2]->size > 0);
-	    ffi_argtype = ffi_argtypes[i + 2];
-	}
-	else {
-	    ffi_argtype = ctx->cif->arg_types[i + 2];
-	}
-
+	ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
+	assert(ffi_argtypes[i + 2]->size > 0);
+	ffi_argtype = ffi_argtypes[i + 2];
 	ffi_args[i + 2] = (void *)alloca(ffi_argtype->size);
 	rb_objc_rval_to_ocval(argv[i], type, ffi_args[i + 2]);
     }
 
-    if (ctx->cif == NULL)
-	ffi_argtypes[count] = NULL;
+    ffi_argtypes[count] = NULL;
     ffi_args[count] = NULL;
 
-    type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method, 
+    type = rb_objc_method_get_type(method, real_count, bs_method, 
 	-1, buf, sizeof buf);
-    ffi_rettype = ctx->cif == NULL 
-	? rb_objc_octype_to_ffitype(type) : ctx->cif->rtype;
+    ffi_rettype = rb_objc_octype_to_ffitype(type);
 
-    cif = ctx->cif;
-    if (cif == NULL) {
-	if (ctx->bs_method != NULL && ctx->bs_method->variadic)
-	    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
-	else
-	    cif = ctx->cif = (ffi_cif *)malloc(sizeof(ffi_cif));
-	if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype, 
-			 ffi_argtypes) != FFI_OK) {
-	    rb_fatal("can't prepare cif for objc method type `%s'",
-		    method_getTypeEncoding(ctx->method));
-	}
+    cif = (ffi_cif *)alloca(sizeof(ffi_cif));
+    if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype, 
+		ffi_argtypes) != FFI_OK) {
+	rb_fatal("can't prepare cif for objc method type `%s'",
+		method_getTypeEncoding(method));
     }
+
     if (ffi_rettype != &ffi_type_void) {
 	ffi_ret = (void *)alloca(ffi_rettype->size);
     }
@@ -1231,75 +1125,89 @@
     }
 }
 
-static VALUE
-rb_objc_to_ruby_closure(int argc, VALUE *argv, VALUE rcv)
+VALUE
+rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv)
 {
-    id ocrcv;
-    bool super_call;
-    Class klass;
-    struct objc_ruby_closure_context *ctx;
+    VALUE klass;
+    Method method;
 
-    rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
-    super_call = (ruby_current_thread->cfp->flag >> FRAME_MAGIC_MASK_BITS) 
-	& VM_CALL_SUPER_BIT;
-    klass = *(Class *)ocrcv;
-    
-    assert(rb_current_cfunc_node != NULL);
+    klass = CLASS_OF(recv);
+    method = class_getInstanceMethod((Class)klass, sel);
 
-    if (rb_current_cfunc_node->u3.value == 0) {
-	const char *selname;
-	size_t selnamelen;
+    return rb_objc_call2(recv, klass, sel, method_getImplementation(method), method, NULL, argc, argv);
+}
 
-	ctx = (struct objc_ruby_closure_context *)xmalloc(sizeof(
-	    struct objc_ruby_closure_context));
+void
+rb_objc_alias(VALUE klass, ID name, ID def)
+{
+    const char *name_str, *def_str;
+    SEL name_sel, def_sel;
+    Method method, dest_method;
+    bool redo = false;
 
-	selname = rb_id2name(rb_frame_this_func());
-	selnamelen = strlen(selname);
-	if (argc == 1 && selname[selnamelen - 1] != ':') {
-	    char *tmp = alloca(selnamelen + 2);
-	    snprintf(tmp, selnamelen + 2, "%s:", selname);
-	    selname = (const char *)tmp;
+    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) {
+	size_t len = strlen(def_str);
+	if (def_str[len - 1] != ':') {
+	    char buf[100];
+
+	    snprintf(buf, sizeof buf, "%s:", def_str);
+	    def_sel = sel_registerName(buf);
+	    method = class_getInstanceMethod((Class)klass, def_sel);
+	    if (method == NULL) {
+		rb_print_undef(klass, def, 0);
+	    }
+	    len = strlen(name_str);
+	    if (name_str[len - 1] != ':') {
+		snprintf(buf, sizeof buf, "%s:", name_str);
+		name_sel = sel_registerName(buf);
+	    }
 	}
-	ctx->selector = sel_registerName(selname);
+    }
 
-	ctx->bs_method = rb_bs_find_method(*(Class *)ocrcv, ctx->selector);
-	GC_WB(&rb_current_cfunc_node->u3.value, ctx);
+alias_method:
+
+    dest_method = class_getInstanceMethod((Class)klass, name_sel);
+
+    DLOG("ALIAS", "%c[%s %s -> %s] types=%s direct_override=%d orig_node=%p", 
+	    class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (char *)name_sel, (char *)def_sel, method_getTypeEncoding(method), dest_method != NULL, rb_objc_method_node3(method_getImplementation(method)));
+
+    if (dest_method != NULL 
+	&& dest_method != class_getInstanceMethod((Class)RCLASS_SUPER(klass), name_sel)) {
+	method_setImplementation(dest_method, method_getImplementation(method));
     }
     else {
-	ctx = (struct objc_ruby_closure_context *)
-	    rb_current_cfunc_node->u3.value;
+	assert(class_addMethod((Class)klass, name_sel, 
+		    method_getImplementation(method), 
+		    method_getTypeEncoding(method)));
     }
-    ctx->method = class_getInstanceMethod(*(Class *)ocrcv, ctx->selector); 
-    assert(ctx->method != NULL);
-    ctx->cif = NULL;
-    ctx->imp = NULL;
-    ctx->klass = klass;
 
-    if (super_call) {
-	Class sklass = klass;
-	Method orig_method = ctx->klass == klass 
-	    ? ctx->method : class_getInstanceMethod(klass, ctx->selector);
-	for (;;) {
-	    Method smethod;
-	    sklass = class_getSuperclass(sklass);
-	    if (sklass == NULL)
-		break;
-	    smethod = class_getInstanceMethod(sklass, ctx->selector);
-	    if (smethod != orig_method) {
-		klass = sklass;
-	        break;
-	    }
-	}
-    }
-    
-//NSLog(@"Ruby -> ObjC [%@ klass=%@ sel=%s argc=%d super_call=%d", ocrcv, (id)klass, (char *)ctx->selector, argc, super_call);
+    if (!redo && name_str[strlen(name_str) - 1] != ':') {
+	char buf[100];
 
-    return rb_objc_call_objc(argc, argv, ocrcv, klass, super_call, ctx);
+	snprintf(buf, sizeof buf, "%s:", def_str);
+	def_sel = sel_registerName(buf);
+	method = class_getInstanceMethod((Class)klass, def_sel);
+	if (method != NULL) {
+	    snprintf(buf, sizeof buf, "%s:", name_str);
+	    name_sel = sel_registerName(buf);
+	    redo = true;
+	    goto alias_method;
+	}	
+    } 
 }
 
 static VALUE
 rb_super_objc_send(int argc, VALUE *argv, VALUE rcv)
 {
+    return Qnil;
+#if 0
     struct objc_ruby_closure_context fake_ctx;
     id ocrcv;
     ID mid;
@@ -1312,7 +1220,7 @@
     argv++;
     argc--;
 
-    rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
+    ocrcv = RB2OC(rcv);
     klass = class_getSuperclass(*(Class *)ocrcv);
 
     fake_ctx.selector = sel_registerName(rb_id2name(mid));
@@ -1324,6 +1232,7 @@
     fake_ctx.klass = NULL;
 
     return rb_objc_call_objc(argc, argv, ocrcv, klass, true, &fake_ctx);
+#endif
 }
 
 #define IGNORE_PRIVATE_OBJC_METHODS 1
@@ -1337,42 +1246,55 @@
     ID mid;
     VALUE rrcv, ret;
     Method method;
-    char type[128];
+    const char *type;
+    char buf[128];
     long i, argc;
-    VALUE *argv;
-    NODE *body;
+    VALUE *argv, klass;
+    NODE *body, *node;
+    bs_element_method_t *bs_method;
 
     rcv = (*(id **)args)[0];
     sel = (*(SEL **)args)[1];
     body = (NODE *)userdata;
+    node = body->nd_body;
 
     method = class_getInstanceMethod(*(Class *)rcv, sel);
     assert(method != NULL);
+    bs_method = rb_bs_find_method(*(Class *)rcv, sel);
 
-    argc = cif->nargs - 2;
-    argv = (VALUE *)alloca(sizeof(VALUE) * argc);
-    for (i = 0; i < argc; i++) {
-	VALUE val;
-        
-	method_getArgumentType(method, i + 2, type, sizeof type);
-	rb_objc_ocval_to_rbval(args[i + 2], type, &val);
-        argv[i] = val;
+    argc = method_getNumberOfArguments(method) - 2;
+    if (argc > 0) {
+	argv = (VALUE *)alloca(sizeof(VALUE) * argc);
+	for (i = 0; i < argc; i++) {
+	    VALUE val;
+
+	    type = rb_objc_method_get_type(method, cif->nargs, bs_method,
+		    i, buf, sizeof buf);
+
+	    rb_objc_ocval_to_rbval(args[i + 2], type, &val);
+	    argv[i] = val;
+	}
     }
+    else {
+	argv = NULL;
+    }
 
-    rb_objc_ocid_to_rval(&rcv, &rrcv);
+    rrcv = rcv == NULL ? Qnil : (VALUE)rcv;
 
     mid = rb_intern((const char *)sel);
+    klass = CLASS_OF(rrcv);
 
-//NSLog(@"ObjC -> Ruby [%@ mid=%s]\n", rrcv, rb_id2name(mid));
+    DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)rrcv, (char *)sel, body);
 
     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);
+    ret = rb_vm_call(GET_THREAD(), klass, rrcv, mid, Qnil,
+		     argc, argv, node, 0);
 
-    method_getReturnType(method, type, sizeof type);
+    type = rb_objc_method_get_type(method, cif->nargs, bs_method,
+	    -1, buf, sizeof buf);
     rb_objc_rval_to_ocval(ret, type, resp);
 }
 
@@ -1407,320 +1329,261 @@
 	!= FFI_OK)
 	rb_fatal("can't prepare ruby to objc closure");
 
+    rb_objc_retain(node);
+
     return closure;
 }
 
-void
-rb_objc_sync_ruby_method(VALUE mod, ID mid, NODE *node, unsigned override)
+NODE *
+rb_objc_method_node3(IMP imp)
 {
-    SEL sel;
-    Class ocklass;
-    Method method;
-    char *types;
-    int arity;
-    char *mid_str;
-    IMP imp;
-    bool direct_override;
+    if (imp == NULL || ((ffi_closure *)imp)->fun != rb_ruby_to_objc_closure_handler)
+	return NULL;
 
-    /* Do not expose C functions. */
-    if (bs_functions != NULL
-	&& mod == CLASS_OF(rb_mKernel)
-	&& st_lookup(bs_functions, (st_data_t)mid, NULL))
-	return;
-
-    arity = rb_node_arity(node);
-    mid_str = (char *)rb_id2name(mid);
-
-    if (arity < 0) {
-	//printf("mid %s has negative arity %d\n", mid_str, arity);
-	return;
-    }
-
-    if (arity == 1 && mid_str[strlen(mid_str) - 1] != ':') {
-	char buf[100];
-	snprintf(buf, sizeof buf, "%s:", mid_str);
-	sel = sel_registerName(buf);
-    }
-    else {
-	sel = sel_registerName(mid_str);
-    }
-
-    ocklass = RCLASS_OCID(mod);
-    direct_override = false;
-    method = class_getInstanceMethod(ocklass, sel);
-
-    if (method != NULL) {
-	void *klass;
-	if (!override)
-	    return;
-
-        /* 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)
-		return;
-	}
-
-	if (arity >= 0 && arity + 2 != method_getNumberOfArguments(method)) {
-	    rb_warning("cannot override Objective-C method `%s' in " \
-		       "class `%s' because of an arity mismatch (%d for %d)", 
-		       (char *)sel, 
-		       class_getName(ocklass), 
-		       arity + 2, 
-		       method_getNumberOfArguments(method));
-	    return;
-	}
-	types = (char *)method_getTypeEncoding(method);
-	klass = class_getSuperclass(ocklass);
-	direct_override = 
-	    klass == NULL || class_getInstanceMethod(klass, sel) != method;
-    }
-    else {
-	struct st_table *t = class_isMetaClass(ocklass)
-	    ? 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';
-	}
-    }
-
-//    printf("registering sel %s of types %s arity %d to class %s\n",
-//	   (char *)sel, types, arity, class_getName(ocklass));
-
-    imp = rb_ruby_to_objc_closure(types, arity, node);
-
-    if (method != NULL && direct_override) {
-	method_setImplementation(method, imp);
-    }
-    else {
-	assert(class_addMethod(ocklass, sel, imp, types));	
-    }
+    return ((ffi_closure *)imp)->user_data;
 }
 
-static int
-__rb_objc_add_ruby_method(ID mid, NODE *body, VALUE mod)
+NODE *
+rb_objc_method_node2(VALUE mod, SEL sel, IMP *pimp)
 {
-    if (mid == ID_ALLOCATOR)
-	return ST_CONTINUE;
-    
-    if (body == NULL || body->nd_body->nd_body == NULL)
-	return ST_CONTINUE;
+    IMP imp;
 
-    if ((body->nd_body->nd_noex & NOEX_MASK) != NOEX_PUBLIC)
-	return ST_CONTINUE;
+    if (pimp != NULL)
+	*pimp = NULL;
 
-    rb_objc_sync_ruby_method(mod, mid, body->nd_body->nd_body, 0);
+    imp = class_getMethodImplementation((Class)mod, sel);
+    extern void *_objc_msgForward;
+    if (imp == (IMP)&_objc_msgForward)
+	imp = NULL;
 
-    return ST_CONTINUE;
-}
+    if (pimp != NULL)
+	*pimp = imp;
 
-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;
-    }
-}
+    if (imp == NULL || ((ffi_closure *)imp)->fun != rb_ruby_to_objc_closure_handler)
+	return NULL;
 
-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
+    return ((ffi_closure *)imp)->user_data;
 }
 
-#if 0
-static void
-__rb_objc_sync_methods(VALUE mod, Class ocklass)
+NODE *
+rb_objc_method_node(VALUE mod, ID mid, IMP *pimp, SEL *psel)
 {
-    Method *methods;
-    unsigned int i, count;
-    char buffer[128];
-    VALUE imod;
+    SEL sel;
+    IMP imp;
+    NODE *node;
 
-    methods = class_copyMethodList(ocklass, &count);
+    if (mid == ID_ALLOCATOR)
+	sel = @selector(alloc);
+    else
+	sel = sel_registerName(rb_id2name(mid));
 
-    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
+    if (psel != NULL)
+	*psel = sel;
 
-    for (i = 0; i < count; i++) {
-	SEL sel;
-	ID mid;
-	st_data_t data;
-	NODE *node;
+    node = rb_objc_method_node2(mod, sel, &imp);
 
-	sel = method_getName(methods[i]);
-	if (is_ignored_selector(sel))
-	    continue;
-#if IGNORE_PRIVATE_OBJC_METHODS
-	if (*(char *)sel == '_')
-	    continue;
-#endif
+    if (pimp != NULL)
+	*pimp = imp;
 
-	rb_objc_sel_to_mid(sel, buffer, sizeof buffer);
-	mid = rb_intern(buffer);
+    if (imp == NULL) {
+    	char buf[100];
+	size_t slen;
 
-	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);
+	slen = strlen((char *)sel);
+	if (((char *)sel)[slen - 1] == ':') {
+	    return NULL;
+	}
+	strlcpy(buf, (char *)sel, sizeof buf);
+	strlcat(buf, ":", sizeof buf);
+	sel = sel_registerName(buf);
+	if (psel != NULL)
+	    *psel = sel;
+	return rb_objc_method_node2(mod, sel, pimp);
     }
 
-    free(methods);
+    return node;
 }
-#endif
 
-NODE *
-rb_objc_define_objc_mid_closure(VALUE recv, ID mid, ID alias_mid)
+void
+rb_objc_register_ruby_method(VALUE mod, ID mid, NODE *body)
 {
     SEL sel;
-    Class ocklass;
     Method method;
-    VALUE mod;
-    NODE *node, *data;
-    Method (*getMethod)(Class, SEL);
+    char *types;
+    int arity, oc_arity;
+    IMP imp;
+    bool direct_override;
+    NODE *node;
+    VALUE included_in_classes;
+    int included_in_classes_count = - 1;
 
-    assert(mid > 1);
+#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)
 
-    sel = sel_registerName(rb_id2name(mid));
+    if (body != NULL) {
+	if (nd_type(body) != NODE_METHOD) 
+	    rb_bug("non-method node (%d)", nd_type(body));
 
-    if (!rb_special_const_p(recv) && !rb_objc_is_non_native(recv) 
-	&& TYPE(recv) == T_CLASS) {
-	mod = recv;
-	getMethod = class_getClassMethod;
+	node = body->nd_body;
+	arity = oc_arity = rb_node_arity(node);
     }
     else {
-	mod = CLASS_OF(recv);
-	getMethod = class_getInstanceMethod;
+	node = NULL;
+	arity = oc_arity = 0;
     }
 
-    ocklass = RCLASS_OCID(mod);
+    if (mid == ID_ALLOCATOR) {
+	sel = @selector(alloc);
+    }
+    else {
+	char *mid_str;
+	size_t mid_str_len;
+	char buf[100];
 
-    if (class_isMetaClass(ocklass))
-	return NULL;
+	mid_str = (char *)rb_id2name(mid);
+	mid_str_len = strlen(mid_str);
 
-    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;
+	if ((arity < 0 || arity > 0) && mid_str[mid_str_len - 1] != ':') {
+	    assert(sizeof(buf) > mid_str_len + 1);
+	    snprintf(buf, sizeof buf, "%s:", mid_str);
+	    sel = sel_registerName(buf);
+	    oc_arity = 1;
+	}
+	else {
+	    sel = sel_registerName(mid_str);
+	    if (sel == sel_ignored || sel == sel_zone) {
+		assert(sizeof(buf) > mid_str_len + 7);
+		snprintf(buf, sizeof buf, "__rb_%s__", mid_str);
+		sel = sel_registerName(buf);
+	    }
+	}
     }
-    while (1);
 
-    if (RCLASS(mod)->ocklass != ocklass) {
-	mod = rb_objc_import_class(ocklass);
-	if (TYPE(recv) == T_CLASS)
-	    mod = CLASS_OF(mod);
-    }
+    included_in_classes = RCLASS_MODULE(mod) ? rb_attr_get(mod, idIncludedInClasses) : Qnil;
 
-    /* Already defined. */
-    node = rb_method_node(mod, mid);
-    if (node != NULL)
-	return node;
+    direct_override = false;
+    method = class_getInstanceMethod((Class)mod, sel);
 
-    node = NEW_CFUNC(rb_objc_to_ruby_closure, -1);
-    data = NEW_FBODY(NEW_METHOD(node, mod, 
-				NOEX_WITH_SAFE(NOEX_PUBLIC)), 0);
+    if (method != NULL) {
+	Class klass;
 
-    rb_add_method_direct(mod, mid, data);
+	if (oc_arity + 2 != method_getNumberOfArguments(method)) {
+	    rb_warn("cannot override Objective-C method `%s' in " \
+		    "class `%s' because of an arity mismatch (%d for %d)", 
+		    (char *)method_getName(method),
+		    class_getName((Class)mod), 
+		    oc_arity + 2, 
+		    method_getNumberOfArguments(method));
+	    return;
+	}
+	types = (char *)method_getTypeEncoding(method);
+	klass = (Class)RCLASS_SUPER(mod);
+	direct_override = 
+	    klass == NULL || class_getInstanceMethod(klass, sel) != method;
+    }
+    else {
+	struct st_table *t = class_isMetaClass((Class)mod)
+	    ? bs_inf_prot_cmethods
+	    : bs_inf_prot_imethods;
 
-    if (alias_mid != 0)
-	rb_add_method_direct(mod, alias_mid, data);
+	if (t == NULL || !st_lookup(t, (st_data_t)sel, (st_data_t *)&types)) {
+	    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';
+	    }
+	}
+    }
 
-    return data->nd_body;
-}
+    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);
 
-#if 0
-rb_objc_sync_objc_methods_into(VALUE mod, Class ocklass)
-{
-    /* Load instance methods */
-    __rb_objc_sync_methods(mod, ocklass);
+    imp = body == NULL ? NULL : rb_ruby_to_objc_closure(types, oc_arity, body);
 
-    /* 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;
-    VALUE ary;
-
-    ary = rb_ary_new();
-
-    for (klass = RCLASS(recv)->ocklass; klass != NULL; 
-	 klass = class_getSuperclass(klass)) {
-	rb_ary_push(ary, rb_str_new2(class_getName(klass)));		
+    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);
 
-    return ary;
-}
+    if (node != NULL) {
+	const char *sel_str = (const char *)sel;
+	const size_t sel_len = strlen(sel_str);
+	SEL new_sel;
+	char *new_types;
+	bool override;
 
-void 
-rb_objc_methods(VALUE ary, Class ocklass)
-{
-    while (ocklass != NULL) {
-	unsigned i, count;
-	Method *methods;
+	if (sel_str[sel_len - 1] == ':') {
+	    char buf[100];
+	    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 == -2;
+	    arity = 0;
+	}
+	else {
+	    char buf[100];
+	    strlcpy(buf, sel_str, sizeof buf);
+	    strlcat(buf, ":", sizeof buf);	
+	    new_sel = sel_registerName(buf);
+	    new_types = "@@:@";
+	    override = false;
+	    arity = -1;
+	}
 
- 	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))));
+	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);	
 	    }
-	    free(methods);
-    	}
-	ocklass = class_getSuperclass(ocklass);
+	    else { 
+		assert(class_addMethod((Class)mod, new_sel, imp, new_types));
+	    }
+	    forward_method_definition(included_in_classes, new_sel, imp, new_types);
+	}
     }
-
-    rb_funcall(ary, rb_intern("uniq!"), 0);
 }
 
-static bool
+static inline bool
 rb_objc_resourceful(VALUE obj)
 {
     /* TODO we should export this function in the runtime 
@@ -1738,36 +1601,21 @@
     return false;
 }
 
-static VALUE
-bs_function_dispatch(int argc, VALUE *argv, VALUE recv)
+VALUE
+rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv)
 {
-    ID callee;
-    bs_element_function_t *bs_func;
-    void *sym;
     unsigned i;
     ffi_type *ffi_rettype, **ffi_argtypes;
     void *ffi_ret, **ffi_args;
     ffi_cif *cif;
     VALUE resp;
 
-    callee = rb_frame_this_func();
-    assert(callee > 1);
-    if (!st_lookup(bs_functions, (st_data_t)callee, (st_data_t *)&bs_func))
-	rb_bug("bridgesupport function `%s' not in cache", rb_id2name(callee));
-
-    if (!st_lookup(bs_function_syms, (st_data_t)callee, (st_data_t *)&sym)
-	|| sym == NULL) {
-	sym = dlsym(RTLD_DEFAULT, bs_func->name);
-	if (sym == NULL)
-	    rb_bug("cannot locate symbol for bridgesupport function `%s'",
-		   bs_func->name);
-	st_insert(bs_function_syms, (st_data_t)callee, (st_data_t)sym);
-    }
-
     if (argc != bs_func->args_count)
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		 argc, bs_func->args_count);
 
+    DLOG("FCALL", "%s() sym=%p argc=%d", bs_func->name, sym, argc);
+
     ffi_argtypes = (ffi_type **)alloca(sizeof(ffi_type *) * argc + 1);
     ffi_args = (void **)alloca(sizeof(void *) * argc + 1);
 
@@ -1819,10 +1667,7 @@
     void *sym;
     bs_element_constant_t *bs_const;
 
-    if (v == rb_objc_class_magic_cookie) {
-	v = rb_objc_import_class(objc_getClass(rb_id2name(id)));
-    }
-    else if (v == bs_const_magic_cookie) { 
+    if (v == bs_const_magic_cookie) { 
 	if (!st_lookup(bs_constants, (st_data_t)id, (st_data_t *)&bs_const))
 	    rb_bug("unresolved bridgesupport constant `%s' not in cache",
 		    rb_id2name(id));
@@ -1833,15 +1678,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;
@@ -1901,13 +1741,18 @@
 static ID
 rb_bs_struct_field_ivar_id(void)
 {
+    const char *frame_str;
     char ivar_name[128];
-    int len;
+    size_t len;
 
-    len = snprintf(ivar_name, sizeof ivar_name, "@%s", 
-		   rb_id2name(rb_frame_this_func()));
+    frame_str = rb_id2name(rb_frame_this_func());
+    len = snprintf(ivar_name, sizeof ivar_name, "@%s", frame_str);
+	
+    if (ivar_name[len - 1] == ':')
+	len--;
     if (ivar_name[len - 1] == '=')
-	ivar_name[len - 1] = '\0';
+	len--;
+    ivar_name[len] = '\0';
 
     return rb_intern(ivar_name);
 }
@@ -2224,16 +2069,25 @@
 bs_parse_cb(const char *path, bs_element_type_t type, void *value, void *ctx)
 {
     bool do_not_free = false;
+    static CFMutableDictionaryRef rb_cObject_dict = NULL;
+
+    if (rb_cObject_dict == NULL) {
+	rb_cObject_dict = rb_class_ivar_dict(rb_cObject);
+	assert(rb_cObject_dict != NULL);
+    }
+
     switch (type) {
 	case BS_ELEMENT_ENUM:
 	{
 	    bs_element_enum_t *bs_enum = (bs_element_enum_t *)value;
 	    ID name = generate_const_name(bs_enum->name);
-	    if (!rb_const_defined(rb_cObject, name)) {
+	    if (!CFDictionaryGetValueIfPresent(
+		(CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
 		VALUE val = strchr(bs_enum->value, '.') != NULL
 		    ? rb_float_new(rb_cstr_to_dbl(bs_enum->value, 1))
 		    : rb_cstr_to_inum(bs_enum->value, 10, 1);
-		rb_const_set(rb_cObject, name, val); 
+		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
+			(const void *)val);
 	    }
 	    else {
 		rb_warning("bs: enum `%s' already defined", rb_id2name(name));
@@ -2245,9 +2099,11 @@
 	{
 	    bs_element_constant_t *bs_const = (bs_element_constant_t *)value;
 	    ID name = generate_const_name(bs_const->name);
-	    if (!rb_const_defined(rb_cObject, name)) {	
+	    if (!CFDictionaryGetValueIfPresent(
+		(CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
 		st_insert(bs_constants, (st_data_t)name, (st_data_t)bs_const);
-		rb_const_set(rb_cObject, name, bs_const_magic_cookie); 
+		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
+			(const void *)bs_const_magic_cookie);
 		do_not_free = true;
 	    }
 	    else {
@@ -2262,7 +2118,8 @@
 	    bs_element_string_constant_t *bs_strconst = 
 		(bs_element_string_constant_t *)value;
 	    ID name = generate_const_name(bs_strconst->name);
-	    if (!rb_const_defined(rb_cObject, name)) {	
+	    if (!CFDictionaryGetValueIfPresent(
+		(CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
 		VALUE val;
 	    	if (bs_strconst->nsstring) {
 		    CFStringRef string;
@@ -2273,7 +2130,8 @@
 	    	else {
 		    val = rb_str_new2(bs_strconst->value);
 	    	}
-		rb_const_set(rb_cObject, name, val);
+		CFDictionarySetValue(rb_cObject_dict, (const void *)name, 
+			(const void *)val);
 	    }
 	    else {
 		rb_warning("bs: string constant `%s' already defined", 
@@ -2286,11 +2144,8 @@
 	{
 	    bs_element_function_t *bs_func = (bs_element_function_t *)value;
 	    ID name = rb_intern(bs_func->name);
-	    if (1) {
+	    if (!st_lookup(bs_functions, (st_data_t)name, NULL)) {
 		st_insert(bs_functions, (st_data_t)name, (st_data_t)bs_func);
-		/* FIXME we should reuse the same node for all functions */
-		rb_define_global_function(
-		    bs_func->name, bs_function_dispatch, -1);
 		do_not_free = true;
 	    }
 	    else {
@@ -2303,8 +2158,19 @@
 	{
 	    bs_element_function_alias_t *bs_func_alias = 
 		(bs_element_function_alias_t *)value;
-	    rb_define_alias(CLASS_OF(rb_mKernel), bs_func_alias->name,
-			    bs_func_alias->original);
+	    bs_element_function_t *bs_func_original;
+	    if (st_lookup(bs_functions, 
+		(st_data_t)rb_intern(bs_func_alias->original), 
+		(st_data_t *)&bs_func_original)) {
+		st_insert(bs_functions, 
+			(st_data_t)rb_intern(bs_func_alias->name), 
+			(st_data_t)bs_func_original);
+	    }
+	    else {
+		rb_raise(rb_eRuntimeError, 
+			"cannot alias '%s' to '%s' because it doesn't exist", 
+			bs_func_alias->name, bs_func_alias->original);
+	    }
 	    break;
 	}
 
@@ -2433,7 +2299,7 @@
 	if (name[0] != '_') {
 	    ID id = rb_intern(name);
 	    if (!rb_const_defined(rb_cObject, id))
-		rb_const_set(rb_cObject, id, rb_objc_class_magic_cookie);
+		rb_const_set(rb_cObject, id, (VALUE)buf[i]);
 	}
     }
 
@@ -2592,18 +2458,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,57 +2507,8 @@
     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)
-{
-    const char *name;
-    size_t len;
-    char buf[100];
-
-    if (mid == 0)
-	return mid;
-
-    name = rb_id2name(mid);
-    if (name == NULL)
-	return mid;
-
-    len = strlen(name);
-    if (len == 0)
-	return mid;
-    
-    if (arity == 1 && name[len - 1] == '=') {
-	strlcpy(buf, "set", sizeof buf);
-	buf[3] = toupper(name[0]);
-	buf[4] = '\0';
-	strlcat(buf, &name[1], sizeof buf);
-	buf[len + 2] = ':';
-    }
-    else if (arity == 0 && name[len - 1] == '?') {
-	strlcpy(buf, "is", sizeof buf);
-	buf[2] = toupper(name[0]);
-	buf[3] = '\0';
-	strlcat(buf, &name[1], sizeof buf);
-	buf[len + 1] = '\0';
-    }
-    else if (arity >= 1 && name[len - 1] != ':' && len < sizeof buf) {
-	strlcpy(buf, name, sizeof buf);
-	buf[len] = ':';
-	buf[len + 1] = '\0';
-    }
-    else if (arity == 1 && name[len - 1] == ':' && len < sizeof buf) {
-	strlcpy(buf, name, sizeof buf);
-	buf[len - 1] = '\0';
-    }
-    else {
-	return mid;
-    }
-
-    //printf("new sel %s for %s\n", buf, name);
-
-    return rb_intern(buf);	
-}
-
 static const char *
 resources_path(char *path, size_t len)
 {
@@ -2752,7 +2570,6 @@
     const char *selname;
     char buf[128];
     size_t s;   
-    VALUE rvalue;
 
     selname = sel_getName(sel);
     buf[0] = '@';
@@ -2760,15 +2577,14 @@
     s = strlcpy(&buf[2], &selname[4], sizeof buf - 2);
     buf[s + 1] = '\0';
 
-    rb_objc_ocid_to_rval(&value, &rvalue);
-    rb_ivar_set((VALUE)recv, rb_intern(buf), rvalue);
+    rb_ivar_set((VALUE)recv, rb_intern(buf), value == NULL ? Qnil : (VALUE)value);
 }
 
 VALUE
 rb_mod_objc_ib_outlet(int argc, VALUE *argv, VALUE recv)
 {
     int i;
-    char buf[128];
+    char buf[100];
 
     buf[0] = 's'; buf[1] = 'e'; buf[2] = 't';
 
@@ -2777,7 +2593,7 @@
 	const char *symname;
 	
 	Check_Type(sym, T_SYMBOL);
-	symname = rb_id2name(SYM2ID(sym));
+	symname = rb_sym2name(sym);
 
 	if (strlen(symname) == 0)
 	    rb_raise(rb_eArgError, "empty symbol given");
@@ -2787,7 +2603,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",
@@ -3067,7 +2883,6 @@
 {
     rb_objc_retain(bs_constants = st_init_numtable());
     rb_objc_retain(bs_functions = st_init_numtable());
-    rb_objc_retain(bs_function_syms = st_init_numtable());
     rb_objc_retain(bs_boxeds = st_init_strtable());
     rb_objc_retain(bs_classes = st_init_strtable());
     rb_objc_retain(bs_inf_prot_cmethods = st_init_numtable());
@@ -3076,14 +2891,13 @@
 
     rb_objc_retain((const void *)(
 	bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie")));
-    rb_objc_retain((const void *)(
-	rb_objc_class_magic_cookie = rb_str_new2("rb_objc_class_magic_cookie")));
 
-    rb_cBoxed = rb_define_class("Boxed",
-	rb_objc_import_class(objc_getClass("NSValue")));
+    rb_cBoxed = rb_define_class("Boxed", (VALUE)objc_getClass("NSValue"));
+    RCLASS_SET_VERSION_FLAG(rb_cBoxed, RCLASS_IS_OBJECT_SUBCLASS);
     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 +2905,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 +2919,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/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/object.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,20 +1,19 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's object.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  object.c -
-
-  $Author: nobu $
-  created at: Thu Jul 15 12:01:24 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-  Copyright (C) 2000  Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/st.h"
 #include "ruby/util.h"
 #include "debug.h"
+#include "id.h"
 #include <stdio.h>
 #include <errno.h>
 #include <ctype.h>
@@ -23,6 +22,7 @@
 
 VALUE rb_cBasicObject;
 VALUE rb_mKernel;
+VALUE rb_cNSObject;
 VALUE rb_cObject;
 VALUE rb_cModule;
 VALUE rb_cClass;
@@ -128,7 +128,9 @@
 {
     if (cl == 0)
         return 0;
-    while ((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS) {
+    if (RCLASS_META(cl))
+	return rb_cClass;
+    while (RCLASS_SINGLETON(cl)) {
 	cl = RCLASS_SUPER(cl);
     }
     return cl;
@@ -157,13 +159,11 @@
 static void
 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;
     }
-#endif
     if (OBJ_FROZEN(dest)) {
         rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
     }
@@ -172,36 +172,58 @@
     rb_copy_generic_ivar(dest, obj);
     rb_gc_copy_finalizer(dest, obj);
     switch (TYPE(obj)) {
-      case T_OBJECT:
-        if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
-            xfree(ROBJECT_IVPTR(dest));
-            ROBJECT(dest)->as.heap.ivptr = 0;
-            ROBJECT(dest)->as.heap.numiv = 0;
-            ROBJECT(dest)->as.heap.iv_index_tbl = 0;
-        }
-        if (RBASIC(obj)->flags & ROBJECT_EMBED) {
-            MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX);
-            RBASIC(dest)->flags |= ROBJECT_EMBED;
-        }
-        else {
-            long len = ROBJECT(obj)->as.heap.numiv;
-            VALUE *ptr = ALLOC_N(VALUE, len);
-            MEMCPY(ptr, ROBJECT(obj)->as.heap.ivptr, VALUE, len);
-            ROBJECT(dest)->as.heap.ivptr = ptr;
-            ROBJECT(dest)->as.heap.numiv = len;
-            ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
-            RBASIC(dest)->flags &= ~ROBJECT_EMBED;
-        }
+      case T_NATIVE:
+	if (rb_objc_flag_check((const void *)obj, FL_TAINT))
+	    rb_objc_flag_set((const void *)dest, FL_TAINT, true);
         break;
+
+      case T_OBJECT:
+	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;
       case T_CLASS:
       case T_MODULE:
-	if (RCLASS_IV_TBL(dest)) {
-	    st_free_table(RCLASS_IV_TBL(dest));
-	    RCLASS_IV_TBL(dest) = 0;
+	{
+	    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);
+	    }
 	}
-	if (RCLASS_IV_TBL(obj)) {
-	    RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
-	}
         break;
     }
 call_init_copy:
@@ -232,6 +254,8 @@
  *  the class.
  */
 
+static VALUE rb_class_s_alloc(VALUE);
+
 VALUE
 rb_obj_clone(VALUE obj)
 {
@@ -240,23 +264,25 @@
     if (rb_special_const_p(obj)) {
         rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
     }
-#if WITH_OBJC
-    if (rb_objc_is_non_native(obj)) {
-        clone = rb_obj_alloc(rb_obj_class(obj));
-        init_copy(clone, obj);
-	if (OBJ_FROZEN(obj))
-	    OBJ_FREEZE(clone);
-	return clone;
+    switch (TYPE(obj)) {
+	case T_NATIVE:
+	    clone = rb_obj_alloc(rb_obj_class(obj));
+	    RBASIC(clone)->klass = rb_singleton_class_clone(obj);
+	    break;
+	case T_CLASS:
+	case T_MODULE:
+	    clone = rb_class_s_alloc(Qnil);
+	    break;
+	default:
+	    clone = rb_obj_alloc(rb_obj_class(obj));
+	    RBASIC(clone)->klass = rb_singleton_class_clone(obj);
+	    RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
+	    break;
     }
-#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);
-    RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+    if (OBJ_FROZEN(obj))
+	OBJ_FREEZE(clone);
 
     return clone;
 }
@@ -284,7 +310,7 @@
 {
     VALUE dup;
 
-    if (rb_special_const_p(obj)) {
+    if (rb_special_const_p(obj) || TYPE(obj) == T_SYMBOL) {
         rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
     }
     dup = rb_obj_alloc(rb_obj_class(obj));
@@ -293,13 +319,20 @@
     return dup;
 }
 
+static VALUE
+rb_nsobj_dup(VALUE obj)
+{
+    return (VALUE)objc_msgSend((id)obj, selCopy); 
+}
+
 /* :nodoc: */
 VALUE
 rb_obj_init_copy(VALUE obj, VALUE orig)
 {
     if (obj == orig) return obj;
     rb_check_frozen(obj);
-    if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
+    if (TYPE(obj) != TYPE(orig)) {
+	/* FIXME rb_obj_class(obj) != rb_obj_class(orig) */
 	rb_raise(rb_eTypeError, "initialize_copy should take same class object");
     }
     return obj;
@@ -347,11 +380,7 @@
     if (!rb_is_instance_id(id)) return ST_CONTINUE;
 
     if (cstr[0] == '-') { /* first element */
-#if WITH_OBJC
 	rb_str_update(str, 0, 0, rb_str_new2("#"));
-#else
-	RSTRING_BYTEPTR(str)[0] = '#';
-#endif
 	rb_str_cat2(str, " ");
     }
     else {
@@ -377,11 +406,7 @@
 	rb_ivar_foreach(obj, inspect_i, str);
     }
     rb_str_cat2(str, ">");
-#if WITH_OBJC
     rb_str_update(str, 0, 0, rb_str_new2("#"));
-#else
-    RSTRING_BYTEPTR(str)[0] = '#';
-#endif
     OBJ_INFECT(str, obj);
 
     return str;
@@ -406,17 +431,28 @@
 
     if (TYPE(obj) == T_OBJECT) {
         int has_ivar = 0;
-        VALUE *ptr = ROBJECT_IVPTR(obj);
-        long len = ROBJECT_NUMIV(obj);
-        long i;
+	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;
+	    }
 
-        for (i = 0; i < len; i++) {
-            if (ptr[i] != Qundef) {
-                has_ivar = 1;
-                break;
-            }
-        }
-
+	    case RB_IVAR_TBL:
+		has_ivar = 
+		    CFDictionaryGetCount(
+			(CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl)
+		    	    > 0;
+		break;
+	}
         if (has_ivar) {
             VALUE str;
             const char *c = rb_obj_classname(obj);
@@ -496,7 +532,7 @@
     }
 
     while (cl) {
-	if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
+	if (cl == c) // TODO check included modules
 	    return Qtrue;
 	cl = RCLASS_SUPER(cl);
     }
@@ -676,11 +712,9 @@
 VALUE
 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
     if (FL_TEST(obj, FL_TAINT))
 	return Qtrue;
     return Qfalse;
@@ -699,12 +733,10 @@
 rb_obj_taint(VALUE obj)
 {
     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;
     }
-#endif
     if (!OBJ_TAINTED(obj)) {
 	if (OBJ_FROZEN(obj)) {
 	    rb_error_frozen("object");
@@ -726,12 +758,10 @@
 rb_obj_untaint(VALUE obj)
 {
     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;
     }
-#endif
     if (OBJ_TAINTED(obj)) {
 	if (OBJ_FROZEN(obj)) {
 	    rb_error_frozen("object");
@@ -772,6 +802,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");
 	}
@@ -782,11 +813,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);
 	}
-#endif
+	else if ((type = TYPE(obj)) == T_CLASS || type == T_MODULE) {
+	    RCLASS_SET_VERSION_FLAG(obj, RCLASS_IS_FROZEN);
+	}
 	else {
 	    FL_SET(obj, FL_FREEZE);
 	}
@@ -813,15 +845,21 @@
 	if (st_lookup(immediate_frozen_tbl, obj, 0)) return Qtrue;
 	return Qfalse;
     }
-#if WITH_OBJC
-    if (rb_objc_is_non_native(obj)) {
-	return rb_objc_is_immutable(obj) 
-	    || rb_objc_flag_check((const void *)obj, FL_FREEZE)
-	    ? Qtrue : Qfalse;
+    switch (TYPE(obj)) {
+	case T_STRING:
+	case T_ARRAY:
+	case T_HASH:
+	case T_NATIVE:
+	    return rb_objc_is_immutable(obj) 
+		|| rb_objc_flag_check((const void *)obj, FL_FREEZE)
+		? Qtrue : Qfalse;
+	case T_CLASS:
+	case T_ICLASS:
+	case T_MODULE:
+	    return (RCLASS_VERSION(obj) & RCLASS_IS_FROZEN) == RCLASS_IS_FROZEN ? Qtrue : Qfalse;
+	default:
+	    return FL_TEST(obj, FL_FREEZE) ? Qtrue : Qfalse;
     }
-#endif
-    if (FL_TEST(obj, FL_FREEZE)) return Qtrue;
-    return Qfalse;
 }
 
 
@@ -1155,7 +1193,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__");
 
@@ -1231,13 +1269,13 @@
 	rb_raise(rb_eTypeError, "compared with non class/module");
     }
     while (mod) {
-	if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg))
+	if (mod == arg)
 	    return Qtrue;
 	mod = RCLASS_SUPER(mod);
     }
     /* not mod < arg; check if mod > arg */
     while (arg) {
-	if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start))
+	if (arg == start)
 	    return Qfalse;
 	arg = RCLASS_SUPER(arg);
     }
@@ -1343,10 +1381,7 @@
 static VALUE
 rb_module_s_alloc(VALUE klass)
 {
-    VALUE mod = rb_module_new();
-
-    RBASIC(mod)->klass = klass;
-    return mod;
+    return rb_module_new();
 }
 
 static VALUE
@@ -1378,7 +1413,7 @@
  *     a.meth2          #=> "bye"
  */
 
-static VALUE
+ VALUE
 rb_mod_initialize(VALUE module)
 {
     extern VALUE rb_mod_module_exec(int argc, VALUE *argv, VALUE mod);
@@ -1404,9 +1439,6 @@
 {
     VALUE super;
 
-    if (RCLASS_SUPER(klass) != 0) {
-	rb_raise(rb_eTypeError, "already initialized class");
-    }
     if (argc == 0) {
 	super = rb_cObject;
     }
@@ -1415,11 +1447,7 @@
 	rb_check_inheritable(super);
     }
     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);
-#endif
-    rb_make_metaclass(klass, RBASIC(super)->klass);
+    rb_objc_install_primitives((Class)klass, (Class)super);
     rb_class_inherited(super, klass);
     rb_mod_initialize(klass);
 
@@ -1443,26 +1471,13 @@
     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);
-#if !WITH_OBJC
-    if (rb_obj_class(obj) != rb_class_real(klass)) {
-	rb_raise(rb_eTypeError, "wrong instance allocation");
-    }
-#endif
     return obj;
 }
 
-static VALUE
-rb_class_allocate_instance(VALUE klass)
-{
-    NEWOBJ(obj, struct RObject);
-    OBJSETUP(obj, klass, T_OBJECT);
-    return (VALUE)obj;
-}
-
 /*
  *  call-seq:
  *     class.new(args, ...)    =>  obj
@@ -1478,56 +1493,25 @@
 VALUE
 rb_class_new_instance(int argc, VALUE *argv, VALUE klass)
 {
-    VALUE obj;
+    VALUE obj, init_obj, p;
 
-#if WITH_OBJC
-    if (FL_TEST(klass, RCLASS_OBJC_IMPORTED)) {
-	static SEL sel_new = 0;
-	if (sel_new == 0)
-	    sel_new = sel_registerName("new");
-	obj = (VALUE)objc_msgSend((id)RCLASS_OCID(klass), sel_new);
-	return obj;
-    }
-#endif
     obj = rb_obj_alloc(klass);
-    rb_obj_call_init(obj, argc, argv);
+    init_obj = rb_obj_call_init(obj, argc, argv);
 
+    if (init_obj != Qnil) {
+	p = CLASS_OF(init_obj);
+	while (p != 0) {
+	    if (p == klass)
+		return init_obj;
+	    p = RCLASS_SUPER(p);
+	}
+    }
+
     return obj;
 }
 
 /*
  *  call-seq:
- *     class.superclass -> a_super_class or nil
- *  
- *  Returns the superclass of <i>class</i>, or <code>nil</code>.
- *     
- *     File.superclass          #=> IO
- *     IO.superclass            #=> Object
- *     Object.superclass        #=> BasicObject
- *     BasicObject.superclass   #=> nil
- *     
- */
-
-static VALUE
-rb_class_superclass(VALUE klass)
-{
-    VALUE super = RCLASS_SUPER(klass);
-
-    if (!super) {
-	if (klass == rb_cBasicObject) return Qnil;
-	rb_raise(rb_eTypeError, "uninitialized class");
-    }
-    while (TYPE(super) == T_ICLASS) {
-	super = RCLASS_SUPER(super);
-    }
-    if (!super) {
-	return Qnil;
-    }
-    return super;
-}
-
-/*
- *  call-seq:
  *     attr_reader(symbol, ...)    => nil
  *     attr(symbol, ...)             => nil
  *  
@@ -1713,28 +1697,21 @@
 static VALUE
 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
 {
-  retry:
-    if (argc == 0) {
-	VALUE args[1];
-	VALUE ary;
+    VALUE recur, objc_methods;
+    VALUE args[2];
 
-	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;
+    if (argc == 0) {
+	recur = Qtrue;
+	objc_methods = Qfalse;
     }
     else {
-	VALUE recur;
-
-	rb_scan_args(argc, argv, "1", &recur);
-	if (RTEST(recur)) {
-	    argc = 0;
-	    goto retry;
-	}
-	return rb_obj_singleton_methods(argc, argv, obj);
+	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
     }
+
+    args[0] = recur;
+    args[1] = objc_methods;
+
+    return rb_class_instance_methods(2, args, CLASS_OF(obj));
 }
 
 /*
@@ -2347,26 +2324,23 @@
 {
     ID id = rb_intern(name);
     extern st_table *rb_class_tbl;
-#if WITH_OBJC
     VALUE obj = rb_objc_create_class(name, super);
-#else
-    VALUE obj = rb_class_boot(super);
-
-    rb_name_class(obj, id);
-#endif
     st_add_direct(rb_class_tbl, id, obj);
     rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
     return obj;
 }
 
-#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
 
+static VALUE
+rb_class_is_meta(VALUE klass)
+{
+    return RCLASS_META(klass) ? Qtrue : Qfalse;
+}
 
 /*
  *  Document-class: Class
@@ -2450,39 +2424,25 @@
 void
 Init_Object(void)
 {
-    VALUE metaclass;
-
-#if WITH_OBJC
-    rb_cBasicObject = rb_objc_import_class((Class)objc_getClass("NSObject"));
-#else
-    rb_cBasicObject = boot_defclass("BasicObject", 0);
-#endif
-    rb_cObject = boot_defclass("Object", rb_cBasicObject);
+    rb_cNSObject = rb_cObject = (VALUE)objc_getClass("NSObject");
+    rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
+    rb_cBasicObject = rb_cObject; // TODO
     rb_cModule = boot_defclass("Module", rb_cObject);
     rb_cClass =  boot_defclass("Class",  rb_cModule);
+    RCLASS_SUPER(*(Class *)rb_cNSObject) = rb_cClass;
 
-    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);
-
     rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
-    rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
-    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);
-    rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1);
+    rb_define_method(rb_cNSObject, "==", rb_obj_equal, 1);
+    rb_define_method(rb_cNSObject, "equal?", rb_obj_equal, 1);
+    rb_define_method(rb_cNSObject, "!", rb_obj_not, 0);
+    rb_define_method(rb_cNSObject, "!=", rb_obj_not_equal, 1);
 
     rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy, 1);
     rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy, 1);
     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,10 +2456,8 @@
     rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
     rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
 
-    rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
-    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);
+    rb_define_method(rb_cNSObject, "clone", rb_obj_clone, 0);
+    rb_define_method(rb_cNSObject, "dup", rb_nsobj_dup, 0);
 
     rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
     rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
@@ -2526,9 +2484,7 @@
     rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
     rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
 
-#if WITH_OBJC
-    rb_define_method(rb_mKernel, "__pure__?", rb_obj_is_pure, 0);
-#endif
+    rb_define_method(rb_mKernel, "__native__?", rb_obj_is_native, 0);
 
     rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
     rb_define_global_function("format", rb_f_sprintf, -1);  /* in sprintf.c */
@@ -2568,10 +2524,8 @@
     rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */
     rb_define_method(rb_cModule, "name", rb_mod_name, 0);  /* in variable.c */
     rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0); /* in class.c */
-#if WITH_OBJC
-    rb_define_method(rb_cModule, "objc_ancestors", rb_mod_objc_ancestors, 0); /* in objc.m */
     rb_define_private_method(rb_cModule, "ib_outlet", rb_mod_objc_ib_outlet, -1); /* in objc.m */
-#endif
+    rb_define_method(rb_cClass, "__meta__?", rb_class_is_meta, 0);
 
     rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
     rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
@@ -2608,7 +2562,6 @@
     rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
     rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
     rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
-    rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
     rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
     rb_undef_method(rb_cClass, "extend_object");
     rb_undef_method(rb_cClass, "append_features");

Modified: MacRuby/trunk/parse.y
===================================================================
--- MacRuby/trunk/parse.y	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/parse.y	2008-08-21 06:13:14 UTC (rev 459)
@@ -31,6 +31,7 @@
 #define YYREALLOC(ptr, size)	rb_parser_realloc(parser, ptr, size)
 #define YYCALLOC(nelem, size)	rb_parser_calloc(parser, nelem, size)
 #define YYFREE(ptr)		rb_parser_free(parser, ptr)
+static inline void *orig_malloc(size_t l) { return malloc(l); }
 #define malloc	YYMALLOC
 #define realloc	YYREALLOC
 #define calloc	YYCALLOC
@@ -8699,7 +8700,7 @@
 	     p != NULL; 
 	     p = p->nd_next, flip = !flip) {
 	    if (flip) {
-		strlcat(buf, rb_id2name(SYM2ID(p->nd_head->nd_lit)), 
+		strlcat(buf, rb_sym2name(p->nd_head->nd_lit),
 			sizeof buf);
 		strlcat(buf, ":", sizeof buf);
 	    }
@@ -9118,12 +9119,11 @@
 #if WITH_OBJC
     CFMutableDictionaryRef sym_id;
     CFMutableDictionaryRef id_str;
-    VALUE *op_sym;
 #else
     st_table *sym_id;
     st_table *id_str;
+#endif
     VALUE op_sym[tLAST_TOKEN];
-#endif
 } global_symbols = {tLAST_TOKEN >> ID_SCOPE_SHIFT};
 
 static const struct st_hash_type symhash = {
@@ -9164,10 +9164,9 @@
 	0, NULL, NULL);
     GC_ROOT(&global_symbols.sym_id);
     global_symbols.id_str = CFDictionaryCreateMutable(NULL,
-	0, NULL, &kCFTypeDictionaryValueCallBacks);
+	0, NULL, NULL);
     GC_ROOT(&global_symbols.id_str);
-    global_symbols.op_sym = xmalloc(sizeof(VALUE) * tLAST_TOKEN);
-    GC_ROOT(&global_symbols.op_sym);
+    rb_cSymbol = rb_objc_create_class("Symbol", (VALUE)objc_getClass("NSString"));
 #else
     global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
     global_symbols.id_str = st_init_numtable_with_size(1000);
@@ -9331,6 +9330,23 @@
     return *m ? Qfalse : Qtrue;
 }
 
+#if WITH_OBJC
+static inline VALUE
+rsymbol_new(const char *name, const int len, ID id)
+{
+    VALUE sym;
+
+    sym = (VALUE)orig_malloc(sizeof(struct RSymbol));
+    RSYMBOL(sym)->str = orig_malloc(len + 1);
+    RSYMBOL(sym)->klass = rb_cSymbol;
+    strcpy(RSYMBOL(sym)->str, name);
+    RSYMBOL(sym)->len = len;
+    RSYMBOL(sym)->id = id;
+    
+    return sym;
+}
+#endif
+
 ID
 rb_intern3(const char *name, long len, rb_encoding *enc)
 {
@@ -9364,6 +9380,17 @@
 	e = m + len;
     }
     SEL name_hash = sel_registerName(name);
+    if (name_hash == sel_ignored) {
+	if (strcmp(name, "retain") == 0) {
+	    name_hash = (SEL)0x1000;
+	}
+	else if (strcmp(name, "release") == 0) {
+	    name_hash = (SEL)0x2000;
+	}
+	else {
+	    assert(1==0);
+	}
+    }
     id = (ID)CFDictionaryGetValue((CFDictionaryRef)global_symbols.sym_id, 
 	(const void *)name_hash);
     if (id != 0)
@@ -9464,8 +9491,7 @@
   new_id:
     id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
   id_register:
-    str = rb_enc_str_new(name, len, enc);
-    OBJ_FREEZE(str);
+    str = rsymbol_new(name, len, id);
 #if WITH_OBJC
     CFDictionarySetValue(global_symbols.sym_id, (const void *)name_hash, 
 	(const void *)id);
@@ -9498,21 +9524,23 @@
 ID
 rb_intern_str(VALUE str)
 {
-    rb_encoding *enc;
     ID id;
 
 #if WITH_OBJC
+    const char *s = RSTRING_PTR(str);
+    id = rb_intern3(s, strlen(s), NULL);
+#else
+    rb_encoding *enc;
     enc = rb_enc_get(str);
-#else
     if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
 	enc = rb_usascii_encoding();
     }
     else {
 	enc = rb_enc_get(str);
     }
-#endif
     id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
     RB_GC_GUARD(str);
+#endif
     return id;
 }
 
@@ -9528,9 +9556,13 @@
 	    if (op_tbl[i].token == id) {
 		VALUE str = global_symbols.op_sym[i];
 		if (!str) {
+#if WITH_OBJC
+		    str = rsymbol_new(op_tbl[i].name, strlen(op_tbl[i].name), op_tbl[i].token);
+#else
 		    str = rb_usascii_str_new2(op_tbl[i].name);
 		    OBJ_FREEZE(str);
-		    GC_WB(&global_symbols.op_sym[i], str);
+#endif
+		    global_symbols.op_sym[i] = str;
 		}
 		return str;
 	    }
@@ -9581,6 +9613,7 @@
     return 0;
 }
 
+#if !WITH_OBJC
 const char *
 rb_id2name(ID id)
 {
@@ -9589,13 +9622,16 @@
     if (!str) return 0;
     return RSTRING_PTR(str);
 }
+#endif
 
+#if !WITH_OBJC
 static int
 symbols_i(VALUE sym, ID value, VALUE ary)
 {
     rb_ary_push(ary, ID2SYM(value));
     return ST_CONTINUE;
 }
+#endif
 
 /*
  *  call-seq:
@@ -9617,9 +9653,17 @@
 rb_sym_all_symbols(void)
 {
 #if WITH_OBJC
-    VALUE ary = rb_ary_new();
-    CFDictionaryApplyFunction((CFDictionaryRef)global_symbols.sym_id,
-	(CFDictionaryApplierFunction)symbols_i, (void *)ary);
+    const void **values;
+    long count;
+    VALUE ary;
+
+    ary = rb_ary_new();
+    count = CFDictionaryGetCount(global_symbols.id_str);
+    if (count == 0)
+	return ary;
+    values = alloca(sizeof(void *) * count);
+    CFDictionaryGetKeysAndValues(global_symbols.id_str, NULL, values);
+    CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, count);   
 #else
     VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
 

Modified: MacRuby/trunk/proc.c
===================================================================
--- MacRuby/trunk/proc.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/proc.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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)
@@ -770,7 +770,9 @@
     data->body = body;
     data->rclass = rclass;
     data->oid = oid;
+#if !WITH_OBJC
     OBJ_INFECT(method, klass);
+#endif
 
     return method;
 }
@@ -877,7 +879,9 @@
     data->body = orig->body;
     data->rclass = orig->rclass;
     data->oid = orig->oid;
+#if !WITH_OBJC
     OBJ_INFECT(method, obj);
+#endif
 
     return method;
 }
@@ -1080,7 +1084,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 +1303,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 +1439,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/trunk/process.c
===================================================================
--- MacRuby/trunk/process.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/process.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -3279,7 +3279,7 @@
 
     switch (TYPE(rtype)) {
       case T_SYMBOL:
-        name = rb_id2name(SYM2ID(rtype));
+        name = rb_sym2name(rtype);
         break;
 
       default:
@@ -3312,7 +3312,7 @@
 
     switch (TYPE(rval)) {
       case T_SYMBOL:
-        name = rb_id2name(SYM2ID(rval));
+        name = rb_sym2name(rval);
         break;
 
       default:

Modified: MacRuby/trunk/re.c
===================================================================
--- MacRuby/trunk/re.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/re.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1040,7 +1040,7 @@
         return NUM2INT(backref);
 
       case T_SYMBOL:
-        name = rb_id2name(SYM2ID(backref));
+        name = rb_sym2name(backref);
         break;
 
       case T_STRING:
@@ -1383,7 +1383,7 @@
     if (!reverse) {
 	range += RSTRING_LEN(str);
     }
-    MEMZERO(&regs, struct re_registers, 1);
+    MEMZERO(pregs, struct re_registers, 1);
     result = onig_search(RREGEXP(re)->ptr,
 			 (UChar*)cstr,
 			 ((UChar*)cstr + clen),
@@ -1728,7 +1728,7 @@
 
         switch (TYPE(idx)) {
           case T_SYMBOL:
-            p = rb_id2name(SYM2ID(idx));
+            p = rb_sym2name(idx);
             goto name_to_backref;
             break;
           case T_STRING:

Modified: MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb
===================================================================
--- MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb	2008-08-21 06:13:14 UTC (rev 459)
@@ -14,10 +14,7 @@
   
   def outlineView outlineView, objectValueForTableColumn:tableColumn, byItem:item
     if item
-      # relativePath returns an ASCII-8BIT file name
-      s = item.relativePath.dup
-      s.force_encoding('utf-8')
-      s
+      s = item.relativePath
     else
       '/'
     end

Modified: MacRuby/trunk/signal.c
===================================================================
--- MacRuby/trunk/signal.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/signal.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -247,7 +247,7 @@
 	}
     }
     else {
-	signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
+	signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
 	if (strncmp(signm, "SIG", 3) == 0) signm += 3;
 	signo = signm2signo(signm);
 	if (!signo) {
@@ -337,7 +337,7 @@
 	break;
 
       case T_SYMBOL:
-	s = rb_id2name(SYM2ID(argv[0]));
+	s = rb_sym2name(argv[0]);
 	if (!s) rb_raise(rb_eArgError, "bad signal");
 	goto str_signal;
 
@@ -797,7 +797,7 @@
 	break;
 
       case T_SYMBOL:
-	s = rb_id2name(SYM2ID(vsig));
+	s = rb_sym2name(vsig);
 	if (!s) rb_raise(rb_eArgError, "bad signal");
 	goto str_signal;
 

Modified: MacRuby/trunk/st.c
===================================================================
--- MacRuby/trunk/st.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/st.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -9,6 +9,7 @@
 #include "ruby/config.h"
 #include "ruby/defines.h"
 #include "ruby/st.h"
+#include "ruby/ruby.h"
 #endif
 
 #include <stdio.h>
@@ -173,7 +174,7 @@
     tbl->num_entries = 0;
     tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH;
     tbl->num_bins = size;
-    tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+    GC_WB(&tbl->bins, (st_table_entry **)Calloc(size, sizeof(st_table_entry*)));
     tbl->head = 0;
 
     return tbl;
@@ -472,8 +473,8 @@
     }
 
     *new_table = *old_table;
-    new_table->bins = (st_table_entry**)
-	Calloc((unsigned)num_bins, sizeof(st_table_entry*));
+    GC_WB(&new_table->bins, (st_table_entry**)
+	Calloc((unsigned)num_bins, sizeof(st_table_entry*)));
 
     if (new_table->bins == 0) {
 	free(new_table);
@@ -497,7 +498,7 @@
 	    *entry = *ptr;
 	    hash_val = entry->hash % num_bins;
 	    entry->next = new_table->bins[hash_val];
-	    new_table->bins[hash_val] = entry;
+	    GC_WB(&new_table->bins[hash_val], entry);
 	    entry->back = prev;
 	    *tail = prev = entry;
 	    tail = &entry->fore;

Modified: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/string.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -1,19 +1,18 @@
-/**********************************************************************
+/* 
+ * MacRuby implementation of Ruby 1.9's string.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ * 
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
 
-  string.c -
-
-  $Author: nobu $
-  created at: Mon Aug  9 17:12:58 JST 1993
-
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
-  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
-  Copyright (C) 2000  Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
 #include "ruby/ruby.h"
 #include "ruby/re.h"
 #include "ruby/encoding.h"
+#include "id.h"
 
 #define BEG(no) regs->beg[no]
 #define END(no) regs->end[no]
@@ -26,78 +25,11 @@
 #endif
 
 VALUE rb_cString;
-#if WITH_OBJC
 VALUE rb_cCFString;
-VALUE rb_cStringRuby;
-#endif
+VALUE rb_cNSString;
+VALUE rb_cNSMutableString;
 VALUE rb_cSymbol;
 
-#if !WITH_OBJC
-#define STR_TMPLOCK FL_USER7
-#define STR_NOEMBED FL_USER1
-#define STR_SHARED  FL_USER2 /* = ELTS_SHARED */
-#define STR_ASSOC   FL_USER3
-#define STR_SHARED_P(s) FL_ALL(s, STR_NOEMBED|ELTS_SHARED)
-#define STR_ASSOC_P(s)  FL_ALL(s, STR_NOEMBED|STR_ASSOC)
-#define STR_NOCAPA  (STR_NOEMBED|ELTS_SHARED|STR_ASSOC)
-#define STR_NOCAPA_P(s) (FL_TEST(s,STR_NOEMBED) && FL_ANY(s,ELTS_SHARED|STR_ASSOC))
-#define STR_UNSET_NOCAPA(s) do {\
-    if (FL_TEST(s,STR_NOEMBED)) FL_UNSET(s,(ELTS_SHARED|STR_ASSOC));\
-} while (0)
-				    
-
-#define STR_SET_NOEMBED(str) do {\
-    FL_SET(str, STR_NOEMBED);\
-    STR_SET_EMBED_LEN(str, 0);\
-} while (0)
-#define STR_SET_EMBED(str) FL_UNSET(str, STR_NOEMBED)
-#define STR_EMBED_P(str) (!FL_TEST(str, STR_NOEMBED))
-#define STR_SET_EMBED_LEN(str, n) do { \
-    long tmp_n = (n);\
-    RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\
-    RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
-} while (0)
-
-#define STR_SET_LEN(str, n) do { \
-    if (STR_EMBED_P(str)) {\
-	STR_SET_EMBED_LEN(str, n);\
-    }\
-    else {\
-	RSTRING(str)->as.heap.len = (n);\
-    }\
-} while (0) 
-
-#define STR_DEC_LEN(str) do {\
-    if (STR_EMBED_P(str)) {\
-	long n = RSTRING_BYTELEN(str);\
-	n--;\
-	STR_SET_EMBED_LEN(str, n);\
-    }\
-    else {\
-	RSTRING(str)->as.heap.len--;\
-    }\
-} while (0)
-
-#define RESIZE_CAPA(str,capacity) do {\
-    if (STR_EMBED_P(str)) {\
-	if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
-	    char *tmp = ALLOC_N(char, capacity+1);\
-	    memcpy(tmp, RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str));\
-	    GC_WB(&RSTRING(str)->as.heap.ptr, tmp); \
-	    RSTRING(str)->as.heap.len = RSTRING_BYTELEN(str);\
-            STR_SET_NOEMBED(str);\
-	    RSTRING(str)->as.heap.aux.capa = (capacity);\
-	}\
-    }\
-    else {\
-	REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\
-	if (!STR_NOCAPA_P(str))\
-	    RSTRING(str)->as.heap.aux.capa = (capacity);\
-    }\
-} while (0)
-
-#else
-
 static void *rb_str_cfdata_key;
 
 static inline void
@@ -213,253 +145,15 @@
 {
     return rb_objc_str_is_bytestring(str) ? Qtrue : Qfalse;
 }
-#endif
 
-#if WITH_OBJC
-/* TODO */
-# define is_ascii_string(str) (1)
-# define is_broken_string(str) (0)
-# define STR_ENC_GET(str) (NULL)
-#else
-# define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
-# define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
-# define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
-#endif
+#define is_ascii_string(str) (1)
+#define is_broken_string(str) (0)
+#define STR_ENC_GET(str) (NULL)
+#define str_mod_check(x,y,z)
 
-#if !WITH_OBJC
-static int
-single_byte_optimizable(VALUE str)
-{
-    rb_encoding *enc = STR_ENC_GET(str);
-
-    if (rb_enc_mbmaxlen(enc) == 1)
-        return 1;
-
-    /* Conservative.  It may be ENC_CODERANGE_UNKNOWN. */
-    if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
-        return 1;
-
-    /* Conservative.  Possibly single byte.
-     * "\xa1" in Shift_JIS for example. */
-    return 0;
-}
-#endif
-
 VALUE rb_fs;
 
-#if !WITH_OBJC
-static inline const char *
-search_nonascii(const char *p, const char *e)
-{
-#if SIZEOF_VALUE == 8
-# define NONASCII_MASK 0x8080808080808080LL
-#elif SIZEOF_VALUE == 4
-# define NONASCII_MASK 0x80808080UL
-#endif
-#ifdef NONASCII_MASK
-    if (sizeof(long) * 2 < e - p) {
-        const unsigned long *s, *t;
-        const VALUE lowbits = sizeof(unsigned long) - 1;
-        s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
-        while (p < (const char *)s) {
-            if (!ISASCII(*p))
-                return p;
-            p++;
-        }
-        t = (const unsigned long*)(~lowbits & (VALUE)e);
-        while (s < t) {
-            if (*s & NONASCII_MASK) {
-                t = s;
-                break;
-            }
-            s++;
-        }
-        p = (const char *)t;
-    }
-#endif
-    while (p < e) {
-        if (!ISASCII(*p))
-            return p;
-        p++;
-    }
-    return NULL;
-}
-
-static int
-coderange_scan(const char *p, long len, rb_encoding *enc)
-{
-    const char *e = p + len;
-
-    if (rb_enc_to_index(enc) == 0) {
-        /* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */
-        p = search_nonascii(p, e);
-        return p ? ENC_CODERANGE_VALID : ENC_CODERANGE_7BIT;
-    }
-
-    if (rb_enc_asciicompat(enc)) {
-        p = search_nonascii(p, e);
-        if (!p) {
-            return ENC_CODERANGE_7BIT;
-        }
-        while (p < e) {
-            int ret = rb_enc_precise_mbclen(p, e, enc);
-            if (!MBCLEN_CHARFOUND_P(ret)) {
-                return ENC_CODERANGE_BROKEN;
-            }
-            p += MBCLEN_CHARFOUND_LEN(ret);
-            if (p < e) {
-                p = search_nonascii(p, e);
-                if (!p) {
-                    return ENC_CODERANGE_VALID;
-                }
-            }
-        }
-        if (e < p) {
-            return ENC_CODERANGE_BROKEN;
-        }
-        return ENC_CODERANGE_VALID;
-    }
-
-    while (p < e) {
-        int ret = rb_enc_precise_mbclen(p, e, enc);
-
-        if (!MBCLEN_CHARFOUND_P(ret)) {
-            return ENC_CODERANGE_BROKEN;
-        }
-        p += MBCLEN_CHARFOUND_LEN(ret);
-    }
-    if (e < p) {
-        return ENC_CODERANGE_BROKEN;
-    }
-    return ENC_CODERANGE_VALID;
-}
-
-long
-rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding *enc, int *cr)
-{
-    const char *p = s;
-
-    if (*cr == ENC_CODERANGE_BROKEN)
-	return e - s;
-
-    if (rb_enc_to_index(enc) == 0) {
-	/* enc is ASCII-8BIT.  ASCII-8BIT string never be broken. */
-	p = search_nonascii(p, e);
-	*cr = (!p && *cr != ENC_CODERANGE_VALID) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
-	return e - s;
-    }
-    else if (rb_enc_asciicompat(enc)) {
-	p = search_nonascii(p, e);
-	if (!p) {
-	    if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT;
-	    return e - s;
-        }
-        while (p < e) {
-            int ret = rb_enc_precise_mbclen(p, e, enc);
-            if (!MBCLEN_CHARFOUND_P(ret)) {
-		*cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
-		return p - s;
-            }
-            p += MBCLEN_CHARFOUND_LEN(ret);
-            if (p < e) {
-                p = search_nonascii(p, e);
-                if (!p) {
-		    *cr = ENC_CODERANGE_VALID;
-		    return e - s;
-		}
-	    }
-	}
-	*cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID;
-	return p - s;
-    }
-    else {
-    while (p < e) {
-        int ret = rb_enc_precise_mbclen(p, e, enc);
-        if (!MBCLEN_CHARFOUND_P(ret)) {
-		*cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
-		return p - s;
-        }
-        p += MBCLEN_CHARFOUND_LEN(ret);
-    }
-	*cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID;
-	return p - s;
-    }
-}
-
-static void
-rb_enc_cr_str_copy_for_substr(VALUE dest, VALUE src)
-{
-    /* this function is designed for copying encoding and coderange
-     * from src to new string "dest" which is made from the part of src.
-     */
-    rb_enc_copy(dest, src);
-    switch (ENC_CODERANGE(src)) {
-      case ENC_CODERANGE_7BIT:
-	ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
-	break;
-      case ENC_CODERANGE_VALID:
-	if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
-	    search_nonascii(RSTRING_BYTEPTR(dest), RSTRING_END(dest)))
-	    ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
-	else
-	    ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
-	break;
-      default:
-	if (RSTRING_BYTELEN(dest) == 0) {
-	    if (!rb_enc_asciicompat(STR_ENC_GET(src)))
-		ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
-	    else
-		ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
-	}
-	break;
-    }
-    }
-
-static void
-rb_enc_cr_str_exact_copy(VALUE dest, VALUE src)
-{
-    rb_enc_copy(dest, src);
-    ENC_CODERANGE_SET(dest, ENC_CODERANGE(src));
-}
-
-int
-rb_enc_str_coderange(VALUE str)
-{
-    int cr = ENC_CODERANGE(str);
-
-    if (cr == ENC_CODERANGE_UNKNOWN) {
-	rb_encoding *enc = STR_ENC_GET(str);
-        cr = coderange_scan(RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str), enc);
-        ENC_CODERANGE_SET(str, cr);
-    }
-    return cr;
-}
-
-int
-rb_enc_str_asciionly_p(VALUE str)
-{
-    rb_encoding *enc = STR_ENC_GET(str);
-
-    if (!rb_enc_asciicompat(enc))
-        return Qfalse;
-    else if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
-        return Qtrue;
-    return Qfalse;
-}
-#endif
-
 static inline void
-str_mod_check(VALUE s, const char *p, long len)
-{
-#if !WITH_OBJC
-    /* TODO */
-    if (RSTRING_BYTEPTR(s) != p || RSTRING_BYTELEN(s) != len){
-	rb_raise(rb_eRuntimeError, "string modified");
-    }
-#endif
-}
-
-static inline void
 str_frozen_check(VALUE s)
 {
     if (OBJ_FROZEN(s)) {
@@ -470,33 +164,19 @@
 static VALUE
 str_alloc(VALUE klass)
 {
-#if WITH_OBJC
     VALUE str;
 
     str = (VALUE)CFStringCreateMutable(NULL, 0);
     if (klass != 0 
-	&& klass != rb_cString 
-	&& klass != rb_cStringRuby 
+	&& klass != rb_cNSString 
+	&& klass != rb_cNSMutableString
 	&& klass != rb_cSymbol)
-	*(Class *)str = RCLASS_OCID(klass);
+	*(Class *)str = (Class)klass;
     CFMakeCollectable((CFTypeRef)str);
-#else
-    NEWOBJ(str, struct RString);
-    OBJSETUP(str, klass, T_STRING);
 
-    if (klass == rb_cSymbol) {
-	/* need to be registered in table */
-	RBASIC(str)->klass = rb_cString;
-    }
-    str->as.heap.ptr = 0;
-    str->as.heap.len = 0;
-    str->as.heap.aux.capa = 0;
-#endif
-
     return (VALUE)str;
 }
 
-#if WITH_OBJC
 static void
 rb_objc_str_set_bytestring(VALUE str, const char *dataptr, long datalen)
 {
@@ -511,7 +191,6 @@
     rb_str_cfdata_set(str, data);
     CFMakeCollectable(data);
 }
-#endif
 
 static VALUE
 str_new(VALUE klass, const char *ptr, long len)
@@ -523,7 +202,6 @@
     }
 
     str = str_alloc(klass);
-#if WITH_OBJC
     bool need_padding = len > 0;
     if (ptr != NULL && len > 0) {
 	long slen;
@@ -561,18 +239,7 @@
     rb_gc_malloc_increase(32 + (sizeof(UniChar) * len));
     if (need_padding)
 	CFStringPad((CFMutableStringRef)str, CFSTR(" "), len, 0);
-#else
-    if (len > RSTRING_EMBED_LEN_MAX) {
-	RSTRING(str)->as.heap.aux.capa = len;
-	GC_WB(&RSTRING(str)->as.heap.ptr, ALLOC_N(char,len+1));
-	STR_SET_NOEMBED(str);
-    }
-    if (ptr) {
-	memcpy(RSTRING_BYTEPTR(str), ptr, len);
-    }
-    STR_SET_LEN(str, len);
-    RSTRING_BYTEPTR(str)[len] = '\0';
-#endif
+
     return str;
 }
 
@@ -587,7 +254,6 @@
 {
     VALUE str = str_new(rb_cString, ptr, len);
 
-    //ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
     return str;
 }
 
@@ -596,8 +262,6 @@
 {
     VALUE str = str_new(rb_cString, ptr, len);
 
-    // TODO we should pass the real encoding
-    //rb_enc_associate(str, enc);
     return str;
 }
 
@@ -637,112 +301,9 @@
     return str;
 }
 
-#if !WITH_OBJC
 static VALUE
-str_replace_shared(VALUE str2, VALUE str)
-{
-    if (RSTRING_BYTELEN(str) <= RSTRING_EMBED_LEN_MAX) {
-	STR_SET_EMBED(str2);
-	memcpy(RSTRING_BYTEPTR(str2), RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str)+1);
-	STR_SET_EMBED_LEN(str2, RSTRING_BYTELEN(str));
-    }
-    else {
-	FL_SET(str2, STR_NOEMBED);
-	RSTRING(str2)->as.heap.len = RSTRING_BYTELEN(str);
-	RSTRING(str2)->as.heap.ptr = RSTRING_BYTEPTR(str);
-	RSTRING(str2)->as.heap.aux.shared = str;
-	FL_SET(str2, ELTS_SHARED);
-    }
-    rb_enc_cr_str_exact_copy(str2, str);
-
-    return str2;
-}
-
-static VALUE
-str_new_shared(VALUE klass, VALUE str)
-{
-    return str_replace_shared(str_alloc(klass), str);
-}
-
-static VALUE
 str_new3(VALUE klass, VALUE str)
 {
-    return str_new_shared(klass, str);
-}
-
-VALUE
-rb_str_new3(VALUE str)
-{
-    VALUE str2 = str_new3(rb_obj_class(str), str);
-
-    OBJ_INFECT(str2, str);
-    return str2;
-}
-
-static VALUE
-str_new4(VALUE klass, VALUE str)
-{
-    VALUE str2;
-
-    str2 = str_alloc(klass);
-    STR_SET_NOEMBED(str2);
-    RSTRING(str2)->as.heap.len = RSTRING_BYTELEN(str);
-    RSTRING(str2)->as.heap.ptr = RSTRING_BYTEPTR(str);
-    if (STR_SHARED_P(str)) {
-	FL_SET(str2, ELTS_SHARED);
-	RSTRING(str2)->as.heap.aux.shared = RSTRING(str)->as.heap.aux.shared;
-    }
-    else {
-	FL_SET(str, ELTS_SHARED);
-	RSTRING(str)->as.heap.aux.shared = str2;
-    }
-    rb_enc_cr_str_exact_copy(str2, str);
-    OBJ_INFECT(str2, str);
-    return str2;
-}
-
-VALUE
-rb_str_new4(VALUE orig)
-{
-    VALUE klass, str;
-
-    if (OBJ_FROZEN(orig)) return orig;
-    klass = rb_obj_class(orig);
-    if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) {
-	long ofs;
-	ofs = RSTRING_BYTELEN(str) - RSTRING_BYTELEN(orig);
-	if ((ofs > 0) || (klass != RBASIC(str)->klass) ||
-	    (!OBJ_TAINTED(str) && OBJ_TAINTED(orig))) {
-	    str = str_new3(klass, str);
-	    RSTRING(str)->as.heap.ptr += ofs;
-	    RSTRING(str)->as.heap.len -= ofs;
-	}
-	rb_enc_cr_str_exact_copy(str, orig);
-	OBJ_INFECT(str, orig);
-    }
-    else if (STR_EMBED_P(orig)) {
-	str = str_new(klass, RSTRING_BYTEPTR(orig), RSTRING_BYTELEN(orig));
-	rb_enc_cr_str_exact_copy(str, orig);
-	OBJ_INFECT(str, orig);
-    }
-    else if (STR_ASSOC_P(orig)) {
-	VALUE assoc = RSTRING(orig)->as.heap.aux.shared;
-	FL_UNSET(orig, STR_ASSOC);
-	str = str_new4(klass, orig);
-	FL_SET(str, STR_ASSOC);
-	RSTRING(str)->as.heap.aux.shared = assoc;
-    }
-    else {
-	str = str_new4(klass, orig);
-    }
-    OBJ_FREEZE(str);
-    return str;
-}
-#else
-
-static VALUE
-str_new3(VALUE klass, VALUE str)
-{
     return rb_str_dup(str);
 }
 
@@ -751,7 +312,6 @@
 {
     VALUE str2 = str_new3(rb_obj_class(str), str);
 
-    // TODO OBJ_INFECT(str2, str);
     return str2;
 }
 
@@ -760,7 +320,6 @@
 {
     return rb_str_new3(orig);
 }
-#endif
 
 VALUE
 rb_str_new5(VALUE obj, const char *ptr, long len)
@@ -775,16 +334,6 @@
 {
     VALUE str = str_alloc(rb_cString);
 
-#if !WITH_OBJC
-    if (capa < STR_BUF_MIN_SIZE) {
-	capa = STR_BUF_MIN_SIZE;
-    }
-    FL_SET(str, STR_NOEMBED);
-    RSTRING(str)->as.heap.aux.capa = capa;
-    GC_WB(&RSTRING(str)->as.heap.ptr, ALLOC_N(char, capa+1));
-    RSTRING(str)->as.heap.ptr[0] = '\0';
-#endif
-
     return str;
 }
 
@@ -806,16 +355,6 @@
     return str_new(0, 0, len);
 }
 
-void
-rb_str_free(VALUE str)
-{
-#if !WITH_OBJC
-    if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) {
-	xfree(RSTRING(str)->as.heap.ptr);
-    }
-#endif
-}
-
 VALUE
 rb_str_to_str(VALUE str)
 {
@@ -825,46 +364,8 @@
 void
 rb_str_shared_replace(VALUE str, VALUE str2)
 {
-#if WITH_OBJC
     rb_str_modify(str);
     CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)str2);
-#else
-    rb_encoding *enc;
-    int cr;
-    if (str == str2) return;
-    enc = STR_ENC_GET(str2);
-    cr = ENC_CODERANGE(str2);
-    rb_str_modify(str);
-    if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
-    if (RSTRING_BYTELEN(str2) <= RSTRING_EMBED_LEN_MAX) {
-	STR_SET_EMBED(str);
-	memcpy(RSTRING_BYTEPTR(str), RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2)+1);
-	STR_SET_EMBED_LEN(str, RSTRING_BYTELEN(str2));
-        rb_enc_associate(str, enc);
-        ENC_CODERANGE_SET(str, cr);
-	return;
-    }
-    if (!STR_SHARED_P(str) && !STR_EMBED_P(str)) {
-	xfree(RSTRING_BYTEPTR(str));
-    }
-    STR_SET_NOEMBED(str);
-    STR_UNSET_NOCAPA(str);
-    RSTRING(str)->as.heap.ptr = RSTRING_BYTEPTR(str2);
-    RSTRING(str)->as.heap.len = RSTRING_BYTELEN(str2);
-    if (STR_NOCAPA_P(str2)) {
-	FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA);
-	RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared;
-    }
-    else {
-	RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
-    }
-    RSTRING(str2)->as.heap.ptr = 0;	/* abandon str2 */
-    RSTRING(str2)->as.heap.len = 0;
-    RSTRING(str2)->as.heap.aux.capa = 0;
-    STR_UNSET_NOCAPA(str2);
-    rb_enc_associate(str, enc);
-    ENC_CODERANGE_SET(str, cr);
-#endif
 }
 
 static ID id_to_s;
@@ -889,18 +390,31 @@
 VALUE
 rb_str_dup(VALUE str)
 {
-    VALUE dup = str_alloc(rb_obj_class(str));
-    rb_str_replace(dup, str);
-#if WITH_OBJC
-    {
-	void *data = rb_str_cfdata2(str);
-	if (data != NULL)
-	    rb_str_cfdata_set(dup, data);
-    }
-#endif
+    VALUE dup;
+    void *data;
+
+    dup = (VALUE)CFStringCreateMutableCopy(NULL, 0, (CFStringRef)str);
+
+    data = rb_str_cfdata2(str);
+    if (data != NULL)
+	rb_str_cfdata_set(dup, data);
+
+    if (OBJ_TAINTED(str))
+	OBJ_TAINT(dup);
+
+    CFMakeCollectable((CFTypeRef)dup);
+
     return dup;
 }
 
+static VALUE
+rb_str_clone(VALUE str)
+{
+    VALUE clone = rb_str_dup(str);
+    if (OBJ_FROZEN(str))
+	OBJ_FREEZE(clone);
+    return clone;
+}
 
 /*
  *  call-seq:
@@ -914,149 +428,18 @@
 {
     VALUE orig;
 
+    str = (VALUE)objc_msgSend((id)str, selInit);
+
     if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1)
 	rb_str_replace(str, orig);
     return str;
 }
 
-#if !WITH_OBJC
-long
-rb_enc_strlen(const char *p, const char *e, rb_encoding *enc)
-{
-    long c;
-    const char *q;
-
-    if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
-        return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc);
-    }
-    else if (rb_enc_asciicompat(enc)) {
-        c = 0;
-        while (p < e) {
-            if (ISASCII(*p)) {
-                q = search_nonascii(p, e);
-                if (!q)
-                    return c + (e - p);
-                c += q - p;
-                p = q;
-            }
-            p += rb_enc_mbclen(p, e, enc);
-            c++;
-        }
-        return c;
-    }
-
-    for (c=0; p<e; c++) {
-        p += rb_enc_mbclen(p, e, enc);
-    }
-    return c;
-}
-
-long
-rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr)
-{
-    long c;
-    const char *q;
-    int ret;
-
-    *cr = 0;
-    if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
-	return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc);
-    }
-    else if (rb_enc_asciicompat(enc)) {
-	c = 0;
-	while (p < e) {
-	    if (ISASCII(*p)) {
-		q = search_nonascii(p, e);
-		if (!q) {
-		    return c + (e - p);
-		}
-		c += q - p;
-		p = q;
-	    }
-	    ret = rb_enc_precise_mbclen(p, e, enc);
-	    if (MBCLEN_CHARFOUND_P(ret)) {
-		*cr |= ENC_CODERANGE_VALID;
-		p += MBCLEN_CHARFOUND_LEN(ret);
-	    }
-	    else {
-		*cr = ENC_CODERANGE_BROKEN;
-		p++;
-	    }
-	    c++;
-	}
-	if (!*cr) *cr = ENC_CODERANGE_7BIT;
-	return c;
-    }
-
-    for (c=0; p<e; c++) {
-	ret = rb_enc_precise_mbclen(p, e, enc);
-	if (MBCLEN_CHARFOUND_P(ret)) {
-	    *cr |= ENC_CODERANGE_VALID;
-	    p += MBCLEN_CHARFOUND_LEN(ret);
-	}
-	else {
-	    *cr = ENC_CODERANGE_BROKEN;
-	    p++;
-	}
-    }
-    if (!*cr) *cr = ENC_CODERANGE_7BIT;
-    return c;
-}
-#endif
-
 static long
 str_strlen(VALUE str, rb_encoding *enc)
 {
-#if WITH_OBJC
     /* TODO should use CFStringGetMaximumSizeForEncoding too */
     return RSTRING_LEN(str);
-#else
-    const char *p, *e;
-    int n, cr;
-
-    if (single_byte_optimizable(str)) return RSTRING_BYTELEN(str);
-    if (!enc) enc = STR_ENC_GET(str);
-    p = RSTRING_BYTEPTR(str);
-    e = RSTRING_END(str);
-#ifdef NONASCII_MASK
-    if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
-        enc == rb_utf8_encoding()) {
-        long len = 0;
-	if (sizeof(long) * 2 < e - p) {
-	    const unsigned long *s, *t;
-	    const VALUE lowbits = sizeof(unsigned long) - 1;
-	    s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
-	    t = (const unsigned long*)(~lowbits & (VALUE)e);
-	    for (len=0; p<(const char *)s; p++) {
-		if (((*p)&0xC0) != 0x80) len++;
-	    }
-	    while (s < t) {
-		unsigned long d = *s;
-		d = ~d | (d<<1);
-		d &= NONASCII_MASK;
-		d >>= 7;
-		d += (d>>8);
-		d += (d>>16);
-#if NONASCII_MASK == 0x8080808080808080UL
-		d = d + (d>>32);
-#endif
-		len += (long)(d&0xF);
-		s++;
-	    }
-	    p = (const char *)t;
-	}
-	for (; p<e; p++) {
-	    if (((*p)&0xC0) != 0x80) len++;
-	}
-	return len;
-    }
-#endif
-    n = rb_enc_strlen_cr(p, e, enc, &cr);
-    if (cr) {
-        ENC_CODERANGE_SET(str, cr);
-    }
-    return n;
-#endif
 }
 
 /*
@@ -1120,29 +503,11 @@
 VALUE
 rb_str_plus(VALUE str1, VALUE str2)
 {
-#if WITH_OBJC
     VALUE str3 = rb_str_new(0, 0);
     rb_str_buf_append(str3, str1);
     rb_str_buf_append(str3, str2);
     if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
 	OBJ_TAINT(str3);
-#else
-    VALUE str3;
-    rb_encoding *enc;
-
-    StringValue(str2);
-    enc = rb_enc_check(str1, str2);
-    str3 = rb_str_new(0, RSTRING_BYTELEN(str1)+RSTRING_BYTELEN(str2));
-    memcpy(RSTRING_BYTEPTR(str3), RSTRING_BYTEPTR(str1), RSTRING_BYTELEN(str1));
-    memcpy(RSTRING_BYTEPTR(str3) + RSTRING_BYTELEN(str1),
-	   RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2));
-    RSTRING_BYTEPTR(str3)[RSTRING_BYTELEN(str3)] = '\0';
-
-    if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
-	OBJ_TAINT(str3);
-    ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
-			   ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
-#endif
     return str3;
 }
 
@@ -1171,24 +536,9 @@
 	rb_raise(rb_eArgError, "argument too big");
     }
 
-#if WITH_OBJC
     str2 = rb_str_new(NULL, 0);
     CFStringPad((CFMutableStringRef)str2, (CFStringRef)str,
 	len * n, 0);
-#else
-    str2 = rb_str_new5(str, 0, len *= n);
-    if (len) {
-        memcpy(RSTRING_BYTEPTR(str2), RSTRING_BYTEPTR(str), n);
-        while (n <= len/2) {
-            memcpy(RSTRING_BYTEPTR(str2) + n, RSTRING_BYTEPTR(str2), n);
-            n *= 2;
-        }
-        memcpy(RSTRING_BYTEPTR(str2) + n, RSTRING_BYTEPTR(str2), len-n);
-    }
-    RSTRING_BYTEPTR(str2)[RSTRING_BYTELEN(str2)] = '\0';
-    OBJ_INFECT(str2, str);
-    rb_enc_cr_str_copy_for_substr(str2, str);
-#endif
 
     return str2;
 }
@@ -1221,49 +571,14 @@
 static inline void
 str_modifiable(VALUE str)
 {
-#if WITH_OBJC
     bool __CFStringIsMutable(void *);
     if (!__CFStringIsMutable((void *)str)) 
 	rb_raise(rb_eRuntimeError, "can't modify immutable string");
-#else
-    if (FL_TEST(str, STR_TMPLOCK)) {
-	rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
-    }
-#endif
     if (OBJ_FROZEN(str)) rb_error_frozen("string");
     if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
 	rb_raise(rb_eSecurityError, "Insecure: can't modify string");
 }
 
-#if !WITH_OBJC
-static int
-str_independent(VALUE str)
-{
-    str_modifiable(str);
-    if (!STR_SHARED_P(str)) return 1;
-    if (STR_EMBED_P(str)) return 1;
-    return 0;
-}
-
-static void
-str_make_independent(VALUE str)
-{
-    char *ptr;
-    long len = RSTRING_BYTELEN(str);
-
-    ptr = ALLOC_N(char, len+1);
-    if (RSTRING_BYTEPTR(str)) {
-	memcpy(ptr, RSTRING_BYTEPTR(str), len);
-    }
-    STR_SET_NOEMBED(str);
-    ptr[len] = 0;
-    GC_WB(&RSTRING(str)->as.heap.ptr, ptr);
-    RSTRING(str)->as.heap.len = len;
-    RSTRING(str)->as.heap.aux.capa = len;
-    STR_UNSET_NOCAPA(str);
-}
-#endif
-
 void
 rb_str_modify(VALUE str)
 {
@@ -1281,43 +596,11 @@
 {
     /* sanity check */
     if (OBJ_FROZEN(str)) rb_error_frozen("string");
-#if !WITH_OBJC
-    if (STR_ASSOC_P(str)) {
-	/* already associated */
-	rb_ary_concat(RSTRING(str)->as.heap.aux.shared, add);
-    }
-    else {
-	if (STR_SHARED_P(str)) {
-	    VALUE assoc = RSTRING(str)->as.heap.aux.shared;
-	    str_make_independent(str);
-	    if (STR_ASSOC_P(assoc)) {
-		assoc = RSTRING(assoc)->as.heap.aux.shared;
-		rb_ary_concat(assoc, add);
-		add = assoc;
-	    }
-	}
-	else if (STR_EMBED_P(str)) {
-	    str_make_independent(str);
-	}
-	else if (RSTRING(str)->as.heap.aux.capa != RSTRING_BYTELEN(str)) {
-	    RESIZE_CAPA(str, RSTRING_BYTELEN(str));
-	}
-	FL_SET(str, STR_ASSOC);
-	RBASIC(add)->klass = 0;
-	RSTRING(str)->as.heap.aux.shared = add;
-    }
-#endif
 }
 
 VALUE
 rb_str_associated(VALUE str)
 {
-#if !WITH_OBJC
-    if (STR_SHARED_P(str)) str = RSTRING(str)->as.heap.aux.shared;
-    if (STR_ASSOC_P(str)) {
-	return RSTRING(str)->as.heap.aux.shared;
-    }
-#endif
     return Qfalse;
 }
 
@@ -1338,7 +621,6 @@
     return (char *)RSTRING_PTR(rb_string_value(ptr));
 }
 
-#if WITH_OBJC
 const char *
 rb_str_cstr(VALUE ptr)
 {
@@ -1346,6 +628,7 @@
     const char *cptr;
    
     data = (CFDataRef)rb_str_cfdata2(ptr);
+    cptr = NULL;
     if (data == NULL) {
 	cptr = CFStringGetCStringPtr((CFStringRef)ptr, 0);
     	if (cptr == NULL) {
@@ -1368,22 +651,12 @@
 	? CFStringGetLength((CFStringRef)ptr) 
 	: CFDataGetLength(data);
 }
-#endif
 
 char *
 rb_string_value_cstr(volatile VALUE *ptr)
 {
-#if WITH_OBJC
     VALUE str = rb_string_value(ptr);
     return (char *)rb_str_cstr(str);
-#else
-    char *s = RSTRING_BYTEPTR(str);
-
-    if (!s || RSTRING_BYTELEN(str) != strlen(s)) {
-	rb_raise(rb_eArgError, "string contains null byte");
-    }
-    return s;
-#endif
 }
 
 VALUE
@@ -1410,143 +683,16 @@
     return rb_check_string_type(str);
 }
 
-#if !WITH_OBJC
-char*
-rb_enc_nth(const char *p, const char *e, int nth, rb_encoding *enc)
-{
-    if (rb_enc_mbmaxlen(enc) == 1) {
-        p += nth;
-    }
-    else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
-        p += nth * rb_enc_mbmaxlen(enc);
-    }
-    else if (rb_enc_asciicompat(enc)) {
-        const char *p2, *e2;
-        int n;
-
-        while (p < e && 0 < nth) {
-            e2 = p + nth;
-            if (e < e2)
-                return (char *)e;
-            if (ISASCII(*p)) {
-                p2 = search_nonascii(p, e2);
-                if (!p2)
-                    return (char *)e2;
-                nth -= p2 - p;
-                p = p2;
-            }
-            n = rb_enc_mbclen(p, e, enc);
-            p += n;
-            nth--;
-        }
-        if (nth != 0)
-            return (char *)e;
-        return (char *)p;
-    }
-    else {
-        while (p<e && nth--) {
-            p += rb_enc_mbclen(p, e, enc);
-        }
-    }
-    if (p > e) p = e;
-    return (char*)p;
-}
-
-static char*
-str_nth(const char *p, const char *e, int nth, rb_encoding *enc, int singlebyte)
-{
-    if (singlebyte)
-	p += nth;
-    else {
-	p = rb_enc_nth(p, e, nth, enc);
-    }
-    if (!p) return 0;
-    if (p > e) p = e;
-    return (char *)p;
-}
-
-/* char offset to byte offset */
-static int
-str_offset(const char *p, const char *e, int nth, rb_encoding *enc, int singlebyte)
-{
-    const char *pp = str_nth(p, e, nth, enc, singlebyte);
-    if (!pp) return e - p;
-    return pp - p;
-}
-
-#ifdef NONASCII_MASK
-static char *
-str_utf8_nth(const char *p, const char *e, int nth)
-{
-    if (sizeof(long) * 2 < nth) {
-	const unsigned long *s, *t;
-	const VALUE lowbits = sizeof(unsigned long) - 1;
-	s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
-	t = (const unsigned long*)(~lowbits & (VALUE)e);
-	for (; p<(const char *)s && 0<nth; p++) {
-	    if (((*p)&0xC0) != 0x80) nth--;
-	}
-	while (s < t) {
-	    unsigned long d = *s++;
-	    d = ~d | (d<<1);
-	    d &= NONASCII_MASK;
-	    d >>= 7;
-	    d += (d>>8);
-	    d += (d>>16);
-#if NONASCII_MASK == 0x8080808080808080UL
-	    d += (d>>32);
-#endif
-	    nth -= (long)(d&0xF);
-	    if (nth < 8) {
-		t = s;
-		break;
-	    }
-	}
-	p = (char *)t;
-    }
-    if (0 < nth) {
-	while (p < e) {
-	    if (((*p)&0xC0) != 0x80) {
-		nth--;
-		if (nth < 0)
-		    break;
-	    }
-	    p++;
-	}
-    }
-    return (char *)p;
-}
-
-static int
-str_utf8_offset(const char *p, const char *e, int nth)
-{
-    const char *pp = str_utf8_nth(p, e, nth);
-    if (!pp) return e - p;
-    return pp - p;
-}
-#endif /* NONASCII_MASK */
-#endif /* WITH_OBJC */
-
 /* byte offset to char offset */
 long
 rb_str_sublen(VALUE str, long pos)
 {
-#if WITH_OBJC
     return pos;
-#else
-    if (single_byte_optimizable(str) || pos < 0)
-        return pos;
-    else {
-	char *p = RSTRING_BYTEPTR(str);
-        return rb_enc_strlen(p, p + pos, STR_ENC_GET(str));
-    }
-#endif
 }
 
 VALUE
 rb_str_subseq(VALUE str, long beg, long len)
 {
-#if WITH_OBJC
     CFDataRef data;
     CFMutableStringRef substr;
     long n;
@@ -1602,157 +748,38 @@
     }
     CFMakeCollectable(substr);
     return (VALUE)substr;
-#else
-    VALUE str2 = rb_str_new5(str, RSTRING_BYTEPTR(str)+beg, len);
-
-    rb_enc_cr_str_copy_for_substr(str2, str);
-    OBJ_INFECT(str2, str);
-
-    return str2;
-#endif
 }
 
 VALUE
 rb_str_substr(VALUE str, long beg, long len)
 {
-#if WITH_OBJC
     return rb_str_subseq(str, beg, len);
-#else
-    rb_encoding *enc = STR_ENC_GET(str);
-    VALUE str2;
-    char *p, *s = RSTRING_BYTEPTR(str), *e = s + RSTRING_BYTELEN(str);
-    int singlebyte = single_byte_optimizable(str);
-
-    if (len < 0) return Qnil;
-    if (!RSTRING_BYTELEN(str)) {
-	len = 0;
-    }
-    if (beg < 0) {
-	if (len > -beg) len = -beg;
-	if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_BYTELEN(str) / 8) {
-	    beg = -beg;
-	    while (beg-- > len && (e = rb_enc_prev_char(s, e, enc)) != 0);
-	    p = e;
-	    if (!p) return Qnil;
-	    while (len-- > 0 && (p = rb_enc_prev_char(s, p, enc)) != 0);
-	    if (!p) return Qnil;
-	    len = e - p;
-	    goto sub;
-	}
-	else {
-	    beg += str_strlen(str, enc);
-	    if (beg < 0) return Qnil;
-	}
-    }
-    else if (beg > 0 && beg > str_strlen(str, enc)) {
-	return Qnil;
-    }
-    if (len == 0) {
-	p = 0;
-    }
-#ifdef NONASCII_MASK
-    else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
-        enc == rb_utf8_encoding()) {
-        p = str_utf8_nth(s, e, beg);
-        len = str_utf8_offset(p, e, len);
-    }
-#endif
-    else if ((p = str_nth(s, e, beg, enc, singlebyte)) == e) {
-	len = 0;
-    }
-    else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
-        if (len * rb_enc_mbmaxlen(enc) > e - p)
-            len = e - p;
-	else
-	    len *= rb_enc_mbmaxlen(enc);
-    }
-    else {
-	len = str_offset(p, e, len, enc, singlebyte);
-    }
-  sub:
-    if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_BYTELEN(str)) {
-	str2 = rb_str_new4(str);
-	str2 = str_new3(rb_obj_class(str2), str2);
-	RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len;
-	RSTRING(str2)->as.heap.len = len;
-    }
-    else {
-	str2 = rb_str_new5(str, p, len);
-	rb_enc_cr_str_copy_for_substr(str2, str);
-	OBJ_INFECT(str2, str);
-    }
-
-    return str2;
-#endif
 }
 
-#if !WITH_OBJC
 VALUE
-rb_str_freeze(VALUE str)
-{
-    if (STR_ASSOC_P(str)) {
-	VALUE ary = RSTRING(str)->as.heap.aux.shared;
-	OBJ_FREEZE(ary);
-    }
-    return rb_obj_freeze(str);
-}
-#endif
-
-VALUE
 rb_str_dup_frozen(VALUE str)
 {
-#if WITH_OBJC
     str = rb_str_dup(str);
     rb_str_freeze(str);
     return str;
-#else
-    if (STR_SHARED_P(str) && RSTRING(str)->as.heap.aux.shared) {
-	VALUE shared = RSTRING(str)->as.heap.aux.shared;
-	if (RSTRING_BYTELEN(shared) == RSTRING_BYTELEN(str)) {
-	    OBJ_FREEZE(shared);
-	    return shared;
-	}
-    }
-    if (OBJ_FROZEN(str)) return str;
-    str = rb_str_dup(str);
-    OBJ_FREEZE(str);
-    return str;
-#endif
 }
 
 VALUE
 rb_str_locktmp(VALUE str)
 {
-#if !WITH_OBJC
-    if (FL_TEST(str, STR_TMPLOCK)) {
-	rb_raise(rb_eRuntimeError, "temporal locking already locked string");
-    }
-    FL_SET(str, STR_TMPLOCK);
-#endif
     return str;
 }
 
 VALUE
 rb_str_unlocktmp(VALUE str)
 {
-#if !WITH_OBJC
-    if (!FL_TEST(str, STR_TMPLOCK)) {
-	rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
-    }
-    FL_UNSET(str, STR_TMPLOCK);
-#endif
     return str;
 }
 
 void
 rb_str_set_len(VALUE str, long len)
 {
-#if WITH_OBJC
     rb_str_resize(str, len);    
-#else
-    STR_SET_LEN(str, len);
-    RSTRING_BYTEPTR(str)[len] = '\0';
-#endif
 }
 
 VALUE
@@ -1765,7 +792,6 @@
     }
 
     rb_str_modify(str);
-#if WITH_OBJC
     slen = RSTRING_LEN(str);
     if (slen != len) {
 	void *cfdata;
@@ -1776,44 +802,9 @@
 	if (cfdata != NULL)
 	    CFDataSetLength((CFMutableDataRef)cfdata, len); 
     }
-#else
-    slen = RSTRING_BYTELEN(str);
-    if (len != slen) {
-	if (STR_EMBED_P(str)) {
-	    char *ptr;
-	    if (len <= RSTRING_EMBED_LEN_MAX) {
-		STR_SET_EMBED_LEN(str, len);
-		RSTRING(str)->as.ary[len] = '\0';
-		return str;
-	    }
-	    ptr = ALLOC_N(char,len+1);
-	    MEMCPY(ptr, RSTRING(str)->as.ary, char, slen);
-	    GC_WB(&RSTRING(str)->as.heap.ptr, ptr);
-	    STR_SET_NOEMBED(str);
-	}
-	else if (len <= RSTRING_EMBED_LEN_MAX) {
-	    char *ptr = RSTRING(str)->as.heap.ptr;
-	    STR_SET_EMBED(str);
-	    if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, len);
-	    RSTRING(str)->as.ary[len] = '\0';
-	    STR_SET_EMBED_LEN(str, len);
-	    xfree(ptr);
-	    return str;
-	}
-	else if (slen < len || slen - len > 1024) {
-	    REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1);
-	}
-	if (!STR_NOCAPA_P(str)) {
-	    RSTRING(str)->as.heap.aux.capa = len;
-	}
-	RSTRING(str)->as.heap.len = len;
-	RSTRING(str)->as.heap.ptr[len] = '\0';	/* sentinel */
-    }
-#endif
     return str;
 }
 
-#if WITH_OBJC
 static void
 rb_objc_str_cat(VALUE str, const char *ptr, long len, int cfstring_encoding)
 {
@@ -1845,43 +836,12 @@
 	}
     }
 }
-#endif
 
 VALUE
 rb_str_buf_cat(VALUE str, const char *ptr, long len)
 {
-#if WITH_OBJC
     rb_objc_str_cat(str, ptr, len, kCFStringEncodingASCII);
-#else
-    long capa, total;
 
-    if (len == 0) return str;
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative string size (or size too big)");
-    }
-    rb_str_modify(str);
-    if (STR_ASSOC_P(str)) {
-	FL_UNSET(str, STR_ASSOC);
-	capa = RSTRING(str)->as.heap.aux.capa = RSTRING_BYTELEN(str);
-    }
-    else if (STR_EMBED_P(str)) {
-	capa = RSTRING_EMBED_LEN_MAX;
-    }
-    else {
-	capa = RSTRING(str)->as.heap.aux.capa;
-    }
-    total = RSTRING_BYTELEN(str)+len;
-    if (capa <= total) {
-	while (total > capa) {
-	    capa = (capa + 1) * 2;
-	}
-	RESIZE_CAPA(str, capa);
-    }
-    memcpy(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), ptr, len);
-    STR_SET_LEN(str, total);
-    RSTRING_BYTEPTR(str)[total] = '\0'; /* sentinel */
-#endif
-
     return str;
 }
 
@@ -1897,17 +857,6 @@
     if (len < 0) {
 	rb_raise(rb_eArgError, "negative string size (or size too big)");
     }
-#if !WITH_OBJC
-    if (STR_ASSOC_P(str)) {
-	rb_str_modify(str);
-	if (STR_EMBED_P(str)) str_make_independent(str);
-	REALLOC_N(RSTRING(str)->as.heap.ptr, char, RSTRING(str)->as.heap.len+len);
-	memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len, ptr, len);
-	RSTRING(str)->as.heap.len += len;
-	RSTRING(str)->as.heap.ptr[RSTRING(str)->as.heap.len] = '\0'; /* sentinel */
-	return str;
-    }
-#endif
 
     return rb_str_buf_cat(str, ptr, len);
 }
@@ -1918,173 +867,23 @@
     return rb_str_cat(str, ptr, strlen(ptr));
 }
 
-#if !WITH_OBJC
-static VALUE
-rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
-    int ptr_encindex, int ptr_cr, int *ptr_cr_ret)
-{
-    long capa, total, off = -1;
-
-    int str_encindex = ENCODING_GET(str);
-    int res_encindex;
-    int str_cr, res_cr;
-    int str_a8 = ENCODING_IS_ASCII8BIT(str);
-    int ptr_a8 = ptr_encindex == 0;
-
-    str_cr = ENC_CODERANGE(str);
-
-    if (str_encindex == ptr_encindex) {
-        if (str_cr == ENC_CODERANGE_UNKNOWN ||
-            (ptr_a8 && str_cr != ENC_CODERANGE_7BIT)) {
-            ptr_cr = ENC_CODERANGE_UNKNOWN;
-        }
-        else if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
-            ptr_cr = coderange_scan(ptr, len, rb_enc_from_index(ptr_encindex));
-        }
-    }
-    else {
-        rb_encoding *str_enc = rb_enc_from_index(str_encindex);
-        rb_encoding *ptr_enc = rb_enc_from_index(ptr_encindex);
-        if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
-            if (len == 0)
-                return str;
-            if (RSTRING_BYTELEN(str) == 0) {
-                rb_str_buf_cat(str, ptr, len);
-                ENCODING_CODERANGE_SET(str, ptr_encindex, ptr_cr);
-                return str;
-            }
-            goto incompatible;
-        }
-	if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
-	    ptr_cr = coderange_scan(ptr, len, ptr_enc);
-	}
-        if (str_cr == ENC_CODERANGE_UNKNOWN) {
-            if (str_a8 || ptr_cr != ENC_CODERANGE_7BIT) {
-                str_cr = rb_enc_str_coderange(str);
-            }
-        }
-    }
-    if (ptr_cr_ret)
-        *ptr_cr_ret = ptr_cr;
-
-    if (str_encindex != ptr_encindex &&
-        str_cr != ENC_CODERANGE_7BIT &&
-        ptr_cr != ENC_CODERANGE_7BIT) {
-      incompatible:
-        rb_raise(rb_eArgError, "append incompatible encoding strings: %s and %s",
-            rb_enc_name(rb_enc_from_index(str_encindex)),
-            rb_enc_name(rb_enc_from_index(ptr_encindex)));
-    }
-
-    if (str_cr == ENC_CODERANGE_UNKNOWN) {
-        res_encindex = str_encindex;
-        res_cr = ENC_CODERANGE_UNKNOWN;
-    }
-    else if (str_cr == ENC_CODERANGE_7BIT) {
-        if (ptr_cr == ENC_CODERANGE_7BIT) {
-            res_encindex = !str_a8 ? str_encindex : ptr_encindex;
-            res_cr = ENC_CODERANGE_7BIT;
-        }
-        else {
-            res_encindex = ptr_encindex;
-            res_cr = ptr_cr;
-        }
-    }
-    else if (str_cr == ENC_CODERANGE_VALID) {
-        res_encindex = str_encindex;
-        res_cr = str_cr;
-    }
-    else { /* str_cr == ENC_CODERANGE_BROKEN */
-        res_encindex = str_encindex;
-        res_cr = str_cr;
-        if (0 < len) res_cr = ENC_CODERANGE_UNKNOWN;
-    }
-
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative string size (or size too big)");
-    }
-    if (ptr >= RSTRING_BYTEPTR(str) && ptr <= RSTRING_END(str)) {
-        off = ptr - RSTRING_BYTEPTR(str);
-    }
-    rb_str_modify(str);
-    if (len == 0) {
-        ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
-        return str;
-    }
-    if (STR_ASSOC_P(str)) {
-	FL_UNSET(str, STR_ASSOC);
-	capa = RSTRING(str)->as.heap.aux.capa = RSTRING_BYTELEN(str);
-    }
-    else if (STR_EMBED_P(str)) {
-	capa = RSTRING_EMBED_LEN_MAX;
-    }
-    else {
-	capa = RSTRING(str)->as.heap.aux.capa;
-    }
-    total = RSTRING_BYTELEN(str)+len;
-    if (capa <= total) {
-	while (total > capa) {
-	    capa = (capa + 1) * 2;
-	}
-	RESIZE_CAPA(str, capa);
-    }
-    if (off != -1) {
-        ptr = RSTRING_BYTEPTR(str) + off;
-    }
-    memcpy(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), ptr, len);
-    STR_SET_LEN(str, total);
-    RSTRING_BYTEPTR(str)[total] = '\0'; // sentinel
-
-    ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
-    return str;
-}
-#endif
-
 VALUE
 rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *ptr_enc)
 {
-#if WITH_OBJC
     rb_objc_str_cat(str, ptr, len, kCFStringEncodingUTF8);
     return str;
-#else
-    return rb_enc_cr_str_buf_cat(str, ptr, len,
-        rb_enc_to_index(ptr_enc), ENC_CODERANGE_UNKNOWN, NULL);
-#endif
 }
 
 VALUE
 rb_str_buf_cat_ascii(VALUE str, const char *ptr)
 {
-#if WITH_OBJC
     rb_objc_str_cat(str, ptr, strlen(ptr), kCFStringEncodingASCII);
     return str;
-#else
-    /* ptr must reference NUL terminated ASCII string. */
-    int encindex = ENCODING_GET(str);
-    rb_encoding *enc = rb_enc_from_index(encindex);
-    if (rb_enc_asciicompat(enc)) {
-        return rb_enc_cr_str_buf_cat(str, ptr, strlen(ptr),
-            encindex, ENC_CODERANGE_7BIT, 0);
-    }
-    else {
-        char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc));
-        while (*ptr) {
-            int c = (unsigned char)*ptr;
-            int len = rb_enc_codelen(c, enc);
-            rb_enc_mbcput(c, buf, enc);
-            rb_enc_cr_str_buf_cat(str, buf, len,
-                encindex, ENC_CODERANGE_VALID, 0);
-            ptr++;
-        }
-        return str;
-    }
-#endif
 }
 
 VALUE
 rb_str_buf_append(VALUE str, VALUE str2)
 {
-#if WITH_OBJC
     CFMutableDataRef mdata;
     CFDataRef data;
     long str2len;
@@ -2112,18 +911,7 @@
 	}
     }
     rb_gc_malloc_increase(sizeof(UniChar) * str2len);
-#else
-    int str2_cr;
 
-    str2_cr = ENC_CODERANGE(str2);
-
-    rb_enc_cr_str_buf_cat(str, RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2),
-        ENCODING_GET(str2), str2_cr, &str2_cr);
-
-    OBJ_INFECT(str, str2);
-    ENC_CODERANGE_SET(str2, str2_cr);
-#endif
-
     return str;
 }
 
@@ -2131,27 +919,6 @@
 rb_str_append(VALUE str, VALUE str2)
 {
     StringValue(str2);
-#if !WITH_OBJC
-    if (RSTRING_BYTELEN(str2) > 0 && STR_ASSOC_P(str)) {
-	rb_encoding *enc;
-	int cr, cr2;
-
-        long len = RSTRING_BYTELEN(str)+RSTRING_BYTELEN(str2);
-        enc = rb_enc_check(str, str2);
-        cr = ENC_CODERANGE(str);
-        if ((cr2 = ENC_CODERANGE(str2)) > cr) cr = cr2;
-        rb_str_modify(str);
-        REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1);
-	GC_WB(&RSTRING(str)->as.heap.ptr, RSTRING(str)->as.heap.ptr);
-        memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len,
-               RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2)+1);
-        RSTRING(str)->as.heap.len = len;
-        rb_enc_associate(str, enc);
-        ENC_CODERANGE_SET(str, cr);
-        OBJ_INFECT(str, str2);
-        return str;
-    }
-#endif
     return rb_str_buf_append(str, str2);
 }
 
@@ -2176,7 +943,6 @@
 rb_str_concat(VALUE str1, VALUE str2)
 {
     if (FIXNUM_P(str2)) {
-#if WITH_OBJC
         int c = FIX2INT(str2);
 	char buf[2];
 
@@ -2186,172 +952,14 @@
 	CFStringAppendCString((CFMutableStringRef)str1, buf, 
 			      kCFStringEncodingUTF8);
 	rb_gc_malloc_increase(sizeof(UniChar));
-#else
-	rb_encoding *enc = STR_ENC_GET(str1);
-	int c = FIX2INT(str2);
-	int pos = RSTRING_BYTELEN(str1);
-	int len = rb_enc_codelen(c, enc);
-	int cr = ENC_CODERANGE(str1);
-
-	rb_str_resize(str1, pos+len);
-	rb_enc_mbcput(c, RSTRING_BYTEPTR(str1)+pos, enc);
-	ENC_CODERANGE_SET(str1, cr);
-#endif
 	return str1;
     }
     return rb_str_append(str1, str2);
 }
 
-#if !WITH_OBJC
-
-typedef  unsigned int  ub4;   /* unsigned 4-byte quantities */
-typedef  unsigned char ub1;   /* unsigned 1-byte quantities */
-
-#define hashsize(n) ((ub4)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-
-/*
---------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-For every delta with one or two bits set, and the deltas of all three
-  high bits or all three low bits, whether the original value of a,b,c
-  is almost all zero or is uniformly distributed,
-* If mix() is run forward or backward, at least 32 bits in a,b,c
-  have at least 1/4 probability of changing.
-* If mix() is run forward, every bit of c will change between 1/3 and
-  2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
-mix() was built out of 36 single-cycle latency instructions in a 
-  structure that could supported 2x parallelism, like so:
-      a -= b; 
-      a -= c; x = (c>>13);
-      b -= c; a ^= x;
-      b -= a; x = (a<<8);
-      c -= a; b ^= x;
-      c -= b; x = (b>>13);
-      ...
-  Unfortunately, superscalar Pentiums and Sparcs can't take advantage 
-  of that parallelism.  They've also turned some of those single-cycle
-  latency instructions into multi-cycle latency instructions.  Still,
-  this is the fastest good hash I could find.  There were about 2^^68
-  to choose from.  I only looked at a billion or so.
---------------------------------------------------------------------
-*/
-#define mix(a,b,c) \
-{ \
-  a -= b; a -= c; a ^= (c>>13); \
-  b -= c; b -= a; b ^= (a<<8); \
-  c -= a; c -= b; c ^= (b>>13); \
-  a -= b; a -= c; a ^= (c>>12);  \
-  b -= c; b -= a; b ^= (a<<16); \
-  c -= a; c -= b; c ^= (b>>5); \
-  a -= b; a -= c; a ^= (c>>3);  \
-  b -= c; b -= a; b ^= (a<<10); \
-  c -= a; c -= b; c ^= (b>>15); \
-}
-
-/*
---------------------------------------------------------------------
-hash() -- hash a variable-length key into a 32-bit value
-  k       : the key (the unaligned variable-length array of bytes)
-  len     : the length of the key, counting by bytes
-  initval : can be any 4-byte value
-Returns a 32-bit value.  Every bit of the key affects every bit of
-the return value.  Every 1-bit and 2-bit delta achieves avalanche.
-About 6*len+35 instructions.
-
-The best hash table sizes are powers of 2.  There is no need to do
-mod a prime (mod is sooo slow!).  If you need less than 32 bits,
-use a bitmask.  For example, if you need only 10 bits, do
-  h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
-  for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
-
-By Bob Jenkins, 1996.  bob_jenkins at burtleburtle.net.  You may use this
-code any way you wish, private, educational, or commercial.  It's free.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^^32 is
-acceptable.  Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-static ub4
-hash(const ub1 *k, ub4 length, ub4 initval)
-    /* k: the key */
-    /* length: the length of the key */
-    /* initval: the previous hash, or an arbitrary value */
-{
-    register ub4 a,b,c,len;
-
-    /* Set up the internal state */
-    len = length;
-    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
-    c = initval;         /* the previous hash value */
-
-   /*---------------------------------------- handle most of the key */
-    while (len >= 12) {
-	a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
-	b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
-	c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
-	mix(a,b,c);
-	k += 12; len -= 12;
-    }
-
-    /*------------------------------------- handle the last 11 bytes */
-    c += length;
-    switch(len)              /* all the case statements fall through */
-    {
-      case 11: c+=((ub4)k[10]<<24);
-      case 10: c+=((ub4)k[9]<<16);
-      case 9 : c+=((ub4)k[8]<<8);
-	/* the first byte of c is reserved for the length */
-      case 8 : b+=((ub4)k[7]<<24);
-      case 7 : b+=((ub4)k[6]<<16);
-      case 6 : b+=((ub4)k[5]<<8);
-      case 5 : b+=k[4];
-      case 4 : a+=((ub4)k[3]<<24);
-      case 3 : a+=((ub4)k[2]<<16);
-      case 2 : a+=((ub4)k[1]<<8);
-      case 1 : a+=k[0];
-	/* case 0: nothing left to add */
-    }
-    mix(a,b,c);
-    /*-------------------------------------------- report the result */
-    return c;
-}
-
 int
 rb_memhash(const void *ptr, long len)
 {
-    return hash(ptr, len, 0);
-}
-
-int
-rb_str_hash(VALUE str)
-{
-    return hash((const void *)RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str), 0);
-}
-
-int
-rb_str_hash_cmp(VALUE str1, VALUE str2)
-{
-    int len;
-
-    if (!rb_str_comparable(str1, str2)) return 1;
-    if (RSTRING_BYTELEN(str1) == (len = RSTRING_BYTELEN(str2)) &&
-	memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len) == 0) {
-	return 0;
-    }
-    return 1;
-}
-
-#else
-
-int
-rb_memhash(const void *ptr, long len)
-{
     CFDataRef data;
     int code;
 
@@ -2373,83 +981,21 @@
     return CFEqual((CFTypeRef)str1, (CFTypeRef)str2) ? 0 : 1;
 }
 
-#endif
-
-/*
- * call-seq:
- *    str.hash   => fixnum
- *
- * Return a hash based on the string's length and content.
- */
-
-static VALUE
-rb_str_hash_m(VALUE str)
-{
-    int hval = rb_str_hash(str);
-    return INT2FIX(hval);
-}
-
 #define lesser(a,b) (((a)>(b))?(b):(a))
 
 int
 rb_str_comparable(VALUE str1, VALUE str2)
 {
-#if WITH_OBJC
     return Qtrue;
-#else
-    int idx1 = ENCODING_GET(str1);
-    int idx2 = ENCODING_GET(str2);
-    int rc1, rc2;
-
-    if (idx1 == idx2) return Qtrue;
-    rc1 = rb_enc_str_coderange(str1);
-    rc2 = rb_enc_str_coderange(str2);
-    if (rc1 == ENC_CODERANGE_7BIT) {
-	if (rc2 == ENC_CODERANGE_7BIT) return Qtrue;
-	if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
-	    return Qtrue;
-    }
-    if (rc2 == ENC_CODERANGE_7BIT) {
-	if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
-	    return Qtrue;
-    }
-    return Qfalse;
-#endif
 }
 
 int
 rb_str_cmp(VALUE str1, VALUE str2)
 {
-#if WITH_OBJC
     return CFStringCompare((CFStringRef)str1, (CFStringRef)str2, 0);
-#else
-    long len;
-    int retval;
-    rb_encoding *enc;
-
-    enc = rb_enc_compatible(str1, str2);
-    len = lesser(RSTRING_BYTELEN(str1), RSTRING_BYTELEN(str2));
-    retval = memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len);
-    if (retval == 0) {
-	if (RSTRING_BYTELEN(str1) == RSTRING_BYTELEN(str2)) {
-	    if (!enc) {
-		if (ENCODING_GET(str1) - ENCODING_GET(str2) > 0)
-		    return 1;
-		return -1;
-	    }
-	    return 0;
-	}
-	if (RSTRING_BYTELEN(str1) > RSTRING_BYTELEN(str2)) return 1;
-	return -1;
-    }
-    if (retval > 0) return 1;
-    return -1;
-#endif
 }
 
-#if WITH_OBJC
 bool rb_objc_str_is_pure(VALUE);
-#endif
 
 /*
  *  call-seq:
@@ -2472,7 +1018,6 @@
 	}
 	return rb_equal(str2, str1);
     }
-#if WITH_OBJC
     len = RSTRING_LEN(str1);
     if (len != RSTRING_LEN(str2))
 	return Qfalse;
@@ -2488,13 +1033,6 @@
     }
     if (CFEqual((CFTypeRef)str1, (CFTypeRef)str2))
 	return Qtrue;
-#else
-    if (!rb_str_comparable(str1, str2)) return Qfalse;
-    if (RSTRING_BYTELEN(str1) == (len = RSTRING_BYTELEN(str2)) &&
-	memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len) == 0) {
-	return Qtrue;
-    }
-#endif
 
     return Qfalse;
 }
@@ -2512,15 +1050,8 @@
     if (TYPE(str2) != T_STRING || RSTRING_BYTELEN(str1) != RSTRING_BYTELEN(str2))
 	return Qfalse;
 
-#if WITH_OBJC
     if (CFEqual((CFTypeRef)str1, (CFTypeRef)str2))
 	return Qtrue;
-#else
-    if (!rb_str_comparable(str1, str2)) return Qfalse;
-    if (memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2),
-	       lesser(RSTRING_BYTELEN(str1), RSTRING_BYTELEN(str2))) == 0)
-	return Qtrue;
-#endif
 
     return Qfalse;
 }
@@ -2591,46 +1122,13 @@
 static VALUE
 rb_str_casecmp(VALUE str1, VALUE str2)
 {
-#if WITH_OBJC
     return INT2FIX(CFStringCompare((CFStringRef)str1, (CFStringRef)str2,
 	kCFCompareCaseInsensitive));
-#else
-    long len;
-    rb_encoding *enc;
-    char *p1, *p1end, *p2, *p2end;
-
-    StringValue(str2);
-    enc = rb_enc_compatible(str1, str2);
-    if (!enc) {
-	return Qnil;
-    }
-
-    p1 = RSTRING_BYTEPTR(str1); p1end = RSTRING_END(str1);
-    p2 = RSTRING_BYTEPTR(str2); p2end = RSTRING_END(str2);
-    while (p1 < p1end && p2 < p2end) {
-	int c1 = rb_enc_codepoint(p1, p1end, enc);
-	int c2 = rb_enc_codepoint(p2, p2end, enc);
-
-	if (c1 != c2) {
-	    c1 = rb_enc_toupper(c1, enc);
-	    c2 = rb_enc_toupper(c2, enc);
-	    if (c1 > c2) return INT2FIX(1);
-	    if (c1 < c2) return INT2FIX(-1);
-	}
-	len = rb_enc_codelen(c1, enc);
-	p1 += len;
-	p2 += len;
-    }
-    if (RSTRING_BYTELEN(str1) == RSTRING_BYTELEN(str2)) return INT2FIX(0);
-    if (RSTRING_BYTELEN(str1) > RSTRING_BYTELEN(str2)) return INT2FIX(1);
-    return INT2FIX(-1);
-#endif
 }
 
 static long
 rb_str_index(VALUE str, VALUE sub, long offset)
 {
-#if WITH_OBJC
     CFRange r;
     return (CFStringFindWithOptions((CFStringRef)str, 
 		(CFStringRef)sub,
@@ -2638,45 +1136,6 @@
 		0,
 		&r))
 	? r.location : -1;
-#else
-    long pos;
-    char *s, *sptr;
-    long len, slen;
-    rb_encoding *enc;
-
-    enc = rb_enc_check(str, sub);
-    if (is_broken_string(sub)) {
-	return -1;
-    }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
-    if (offset < 0) {
-	offset += len;
-	if (offset < 0) return -1;
-    }
-    if (len - offset < slen) return -1;
-    s = RSTRING_BYTEPTR(str);
-    if (offset) {
-	offset = str_offset(s, RSTRING_END(str), offset, enc, single_byte_optimizable(str));
-	s += offset;
-    }
-    if (slen == 0) return offset;
-    /* need proceed one character at a time */
-    sptr = RSTRING_BYTEPTR(sub);
-    slen = RSTRING_BYTELEN(sub);
-    len = RSTRING_BYTELEN(str) - offset;
-    for (;;) {
-	char *t;
-	pos = rb_memsearch(sptr, slen, s, len);
-	if (pos < 0) return pos;
-	t = rb_enc_right_char_head(s, s+pos, enc);
-	if (t == s) break;
-	if ((len -= t - s) <= 0) return -1;
-	offset += t - s;
-	s = t;
-    }
-    return pos + offset;
-#endif
 }
 
 /*
@@ -2752,7 +1211,6 @@
 static long
 rb_str_rindex(VALUE str, VALUE sub, long pos)
 {
-#if WITH_OBJC
     CFRange r;
     long sublen, strlen;
     sublen = RSTRING_LEN(sub);
@@ -2768,41 +1226,6 @@
 		kCFCompareBackwards,
 		&r))
 	? r.location : -1;
-#else
-    long len, slen;
-    char *s, *sbeg, *e, *t;
-    rb_encoding *enc;
-    int singlebyte = single_byte_optimizable(str);
-
-    enc = rb_enc_check(str, sub);
-    if (is_broken_string(sub)) {
-	return -1;
-    }
-    len = str_strlen(str, enc);
-    slen = str_strlen(sub, enc);
-    /* substring longer than string */
-    if (len < slen) return -1;
-    if (len - pos < slen) {
-	pos = len - slen;
-    }
-    if (len == 0) {
-	return pos;
-    }
-    sbeg = RSTRING_BYTEPTR(str);
-    e = RSTRING_END(str);
-    t = RSTRING_BYTEPTR(sub);
-    slen = RSTRING_BYTELEN(sub);
-    for (;;) {
-	s = str_nth(sbeg, e, pos, enc, singlebyte);
-	if (!s) return -1;
-	if (memcmp(s, t, slen) == 0) {
-	    return pos;
-	}
-	if (pos == 0) break;
-	pos--;
-    }
-    return -1;
-#endif
 }
 
 
@@ -2957,146 +1380,7 @@
     return result;
 }
 
-enum neighbor_char {
-    NEIGHBOR_NOT_CHAR,
-    NEIGHBOR_FOUND,
-    NEIGHBOR_WRAPPED
-};
-
-#if !WITH_OBJC
-static enum neighbor_char
-enc_succ_char(char *p, int len, rb_encoding *enc)
-{
-    int i, l;
-    while (1) {
-        for (i = len-1; 0 <= i && (unsigned char)p[i] == 0xff; i--)
-            p[i] = '\0';
-        if (i < 0)
-            return NEIGHBOR_WRAPPED;
-        ++((unsigned char*)p)[i];
-        l = rb_enc_precise_mbclen(p, p+len, enc);
-        if (MBCLEN_CHARFOUND_P(l)) {
-            l = MBCLEN_CHARFOUND_LEN(l);
-            if (l == len) {
-                return NEIGHBOR_FOUND;
-            }
-            else {
-                memset(p+l, 0xff, len-l);
-            }
-        }
-        if (MBCLEN_INVALID_P(l) && i < len-1) {
-            int len2, l2;
-            for (len2 = len-1; 0 < len2; len2--) {
-                l2 = rb_enc_precise_mbclen(p, p+len2, enc);
-                if (!MBCLEN_INVALID_P(l2))
-                    break;
-            }
-            memset(p+len2+1, 0xff, len-(len2+1));
-        }
-    }
-}
-
-static enum neighbor_char
-enc_pred_char(char *p, int len, rb_encoding *enc)
-{
-    int i, l;
-    while (1) {
-        for (i = len-1; 0 <= i && (unsigned char)p[i] == 0; i--)
-            p[i] = '\xff';
-        if (i < 0)
-            return NEIGHBOR_WRAPPED;
-        --((unsigned char*)p)[i];
-        l = rb_enc_precise_mbclen(p, p+len, enc);
-        if (MBCLEN_CHARFOUND_P(l)) {
-            l = MBCLEN_CHARFOUND_LEN(l);
-            if (l == len) {
-                return NEIGHBOR_FOUND;
-            }
-            else {
-                memset(p+l, 0, len-l);
-            }
-        }
-        if (MBCLEN_INVALID_P(l) && i < len-1) {
-            int len2, l2;
-            for (len2 = len-1; 0 < len2; len2--) {
-                l2 = rb_enc_precise_mbclen(p, p+len2, enc);
-                if (!MBCLEN_INVALID_P(l2))
-                    break;
-            }
-            memset(p+len2+1, 0, len-(len2+1));
-        }
-    }
-}
-#endif
-
 /*
-  overwrite +p+ by succeeding letter in +enc+ and returns
-  NEIGHBOR_FOUND or NEIGHBOR_WRAPPED.
-  When NEIGHBOR_WRAPPED, carried-out letter is stored into carry.
-  assuming each ranges are successive, and mbclen
-  never change in each ranges.
-  NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one
-  character.
- */
-#if !WITH_OBJC
-static enum neighbor_char
-enc_succ_alnum_char(char *p, int len, rb_encoding *enc, char *carry)
-{
-    enum neighbor_char ret;
-    int c;
-    int ctype;
-    int range;
-    char save[ONIGENC_CODE_TO_MBC_MAXLEN];
-
-    c = rb_enc_mbc_to_codepoint(p, p+len, enc);
-    if (rb_enc_isctype(c, ONIGENC_CTYPE_DIGIT, enc))
-        ctype = ONIGENC_CTYPE_DIGIT;
-    else if (rb_enc_isctype(c, ONIGENC_CTYPE_ALPHA, enc))
-        ctype = ONIGENC_CTYPE_ALPHA;
-    else
-        return NEIGHBOR_NOT_CHAR;
-
-    MEMCPY(save, p, char, len);
-    ret = enc_succ_char(p, len, enc);
-    if (ret == NEIGHBOR_FOUND) {
-        c = rb_enc_mbc_to_codepoint(p, p+len, enc);
-        if (rb_enc_isctype(c, ctype, enc))
-            return NEIGHBOR_FOUND;
-    }
-    MEMCPY(p, save, char, len);
-    range = 1;
-    while (1) {
-        MEMCPY(save, p, char, len);
-        ret = enc_pred_char(p, len, enc);
-        if (ret == NEIGHBOR_FOUND) {
-            c = rb_enc_mbc_to_codepoint(p, p+len, enc);
-            if (!rb_enc_isctype(c, ctype, enc)) {
-                MEMCPY(p, save, char, len);
-                break;
-            }
-        }
-        else {
-            MEMCPY(p, save, char, len);
-            break;
-        }
-        range++;
-    }
-    if (range == 1) {
-        return NEIGHBOR_NOT_CHAR;
-    }
-
-    if (ctype != ONIGENC_CTYPE_DIGIT) {
-        MEMCPY(carry, p, char, len);
-        return NEIGHBOR_WRAPPED;
-    }
-
-    MEMCPY(carry, p, char, len);
-    enc_succ_char(carry, len, enc);
-    return NEIGHBOR_WRAPPED;
-}
-#endif
-
-/*
  *  call-seq:
  *     str.succ   => new_str
  *     str.next   => new_str
@@ -3124,7 +1408,6 @@
 VALUE
 rb_str_succ(VALUE orig)
 {
-#if WITH_OBJC
     UniChar *buf;
     UniChar carry;
     long i, len;
@@ -3186,79 +1469,6 @@
     CFMakeCollectable(newstr);
 
     return (VALUE)newstr;
-#else
-    rb_encoding *enc;
-    VALUE str;
-    char *sbeg, *s, *e;
-    int c = -1;
-    long l;
-    char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
-    int carry_pos = 0, carry_len = 1;
-
-    str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
-#if !WITH_OBJC
-    rb_enc_cr_str_copy_for_substr(str, orig);
-    OBJ_INFECT(str, orig);
-#endif
-    if (RSTRING_LEN(str) == 0) return str;
-
-    enc = STR_ENC_GET(orig);
-    sbeg = RSTRING_BYTEPTR(str);
-    s = e = sbeg + RSTRING_BYTELEN(str);
-
-    while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
-        enum neighbor_char neighbor;
-	if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
-        neighbor = enc_succ_alnum_char(s, l, enc, carry);
-        if (neighbor == NEIGHBOR_NOT_CHAR)
-            continue;
-        if (neighbor == NEIGHBOR_FOUND) {
-	    RSTRING_SYNC(str);
-            return str;
-	}
-        c = 1;
-        carry_pos = s - sbeg;
-        carry_len = l;
-    }
-    if (c == -1) {		/* str contains no alnum */
-	s = e;
-	while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
-            enum neighbor_char neighbor;
-            if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
-            neighbor = enc_succ_char(s, l, enc);
-	    if (neighbor == NEIGHBOR_FOUND) {
-		RSTRING_SYNC(str);
-		return str;
-	    }
-            if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
-                /* wrapped to \0...\0.  search next valid char. */
-                enc_succ_char(s, l, enc);
-            }
-            if (!rb_enc_asciicompat(enc)) {
-                MEMCPY(carry, s, char, l);
-                carry_len = l;
-            }
-            carry_pos = s - sbeg;
-	}
-    }
-#if WITH_OBJC
-    CFMutableDataRef data = (CFMutableDataRef)rb_str_cfdata(str);
-    CFDataSetLength(data, RSTRING_BYTELEN(str) + carry_len);
-    s = (char *)CFDataGetMutableBytePtr(data);
-    memmove(s + carry_len, s, RSTRING_BYTELEN(str) - carry_pos);
-    memmove(s, carry, carry_len);
-    RSTRING_SYNC(str);
-#else
-    RESIZE_CAPA(str, RSTRING_BYTELEN(str) + carry_len);
-    s = RSTRING_BYTEPTR(str) + carry_pos;
-    memmove(s + carry_len, s, RSTRING_BYTELEN(str) - carry_pos);
-    memmove(s, carry, carry_len);
-    STR_SET_LEN(str, RSTRING_BYTELEN(str) + carry_len);
-    RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-    rb_enc_str_coderange(str);
-#endif
-    return str;
-#endif
 }
 
 
@@ -3308,15 +1518,11 @@
     VALUE current, after_end;
     ID succ;
     int n, excl;
-#if !WITH_OBJC
-    rb_encoding *enc;
-#endif
 
     rb_scan_args(argc, argv, "11", &end, &exclusive);
     excl = RTEST(exclusive);
     succ = rb_intern("succ");
     StringValue(end);
-#if WITH_OBJC
     if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
 	UniChar c = CFStringGetCharacterAtIndex((CFStringRef)beg, 0);
 	UniChar e = CFStringGetCharacterAtIndex((CFStringRef)end, 0);
@@ -3336,22 +1542,6 @@
 		break;
 	}
 	return beg;
-#else
-    enc = rb_enc_check(beg, end);
-    if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 &&
-	is_ascii_string(beg) && is_ascii_string(end)) {
-	char c = RSTRING_PTR(beg)[0];
-	char e = RSTRING_PTR(end)[0];
-
-	if (c > e || (excl && c == e)) return beg;
-	for (;;) {
-	    rb_yield(rb_enc_str_new(&c, 1, enc));
-	    if (!excl && c == e) break;
-	    c++;
-	    if (excl && c == e) break;
-	}
-	return beg;
-#endif
     }
     n = rb_str_cmp(beg, end);
     if (n > 0 || (excl && n == 0)) return beg;
@@ -3492,54 +1682,20 @@
 rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
 {
     rb_str_modify(str);
-#if WITH_OBJC
     CFStringReplace((CFMutableStringRef)str, CFRangeMake(beg, len), 
 	(CFStringRef)val);
-#else
-    if (len < RSTRING_BYTELEN(val)) {
-	/* expand string */
-	RESIZE_CAPA(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(val) - len + 1);
-    }
-
-    if (RSTRING_BYTELEN(val) != len) {
-	memmove(RSTRING_BYTEPTR(str) + beg + RSTRING_BYTELEN(val),
-		RSTRING_BYTEPTR(str) + beg + len,
-		RSTRING_BYTELEN(str) - (beg + len));
-    }
-    if (RSTRING_BYTELEN(val) < beg && len < 0) {
-	MEMZERO(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), char, -len);
-    }
-    if (RSTRING_BYTELEN(val) > 0) {
-	memmove(RSTRING_BYTEPTR(str)+beg, RSTRING_BYTEPTR(val), RSTRING_BYTELEN(val));
-    }
-    STR_SET_LEN(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(val) - len);
-    if (RSTRING_BYTEPTR(str)) {
-	RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-    }
-    OBJ_INFECT(str, val);
-#endif
 }
 
 static void
 rb_str_splice(VALUE str, long beg, long len, VALUE val)
 {
     long slen;
-#if !WITH_OBJC
-    char *p, *e;
-    rb_encoding *enc;
-    int singlebyte = single_byte_optimizable(str);
-#endif
 
     if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
 
     StringValue(val);
     rb_str_modify(str);
-#if WITH_OBJC
     slen = CFStringGetLength((CFStringRef)str);
-#else
-    enc = rb_enc_check(str, val);
-    slen = str_strlen(str, enc);
-#endif
 
     if (slen < beg) {
       out_of_range:
@@ -3554,19 +1710,7 @@
     if (slen < len || slen < beg + len) {
 	len = slen - beg;
     }
-#if WITH_OBJC
     rb_str_splice_0(str, beg, len, val);
-#else
-    p = str_nth(RSTRING_BYTEPTR(str), RSTRING_END(str), beg, enc, singlebyte);
-    if (!p) p = RSTRING_END(str);
-    e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
-    if (!e) e = RSTRING_END(str);
-    /* error check */
-    beg = p - RSTRING_BYTEPTR(str);	/* physical position */
-    len = e - p;		/* physical length */
-    rb_str_splice_0(str, beg, len, val);
-    rb_enc_associate(str, enc);
-#endif
 }
 
 void
@@ -3580,9 +1724,6 @@
 {
     VALUE match;
     long start, end, len;
-#if !WITH_OBJC
-    rb_encoding *enc;
-#endif
     struct re_registers *regs;
 
     if (rb_reg_search(re, str, 0, 0) < 0) {
@@ -3608,13 +1749,7 @@
     end = END(nth);
     len = end - start;
     StringValue(val);
-#if !WITH_OBJC
-    enc = rb_enc_check(str, val);
-#endif
     rb_str_splice_0(str, start, len, val);
-#if !WITH_OBJC
-    rb_enc_associate(str, enc);
-#endif
 }
 
 static VALUE
@@ -3835,18 +1970,11 @@
 
     pat = get_pat(argv[0], 1);
     if (rb_reg_search(pat, str, 0, 0) >= 0) {
-#if !WITH_OBJC
-	rb_encoding *enc;
-	int cr = ENC_CODERANGE(str);
-#endif
 
 	match = rb_backref_get();
 	regs = RMATCH_REGS(match);
 
 	if (iter || !NIL_P(hash)) {
-#if !WITH_OBJC
-	    char *p = RSTRING_BYTEPTR(str); long len = RSTRING_BYTELEN(str);
-#endif
 
             if (iter) {
                 rb_match_busy(match);
@@ -3856,56 +1984,18 @@
                 repl = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
                 repl = rb_obj_as_string(repl);
             }
-#if !WITH_OBJC
-	    str_mod_check(str, p, len);
-#endif
 	    str_frozen_check(str);
 	    if (iter) rb_backref_set(match);
 	}
 	else {
 	    repl = rb_reg_regsub(repl, str, regs, pat);
 	}
-#if !WITH_OBJC
-        enc = rb_enc_compatible(str, repl);
-        if (!enc) {
-            rb_encoding *str_enc = STR_ENC_GET(str);
-            if (coderange_scan(RSTRING_BYTEPTR(str), BEG(0), str_enc) != ENC_CODERANGE_7BIT ||
-                coderange_scan(RSTRING_BYTEPTR(str)+END(0),
-			       RSTRING_BYTELEN(str)-END(0), str_enc) != ENC_CODERANGE_7BIT) {
-                rb_raise(rb_eArgError, "character encodings differ: %s and %s",
-			 rb_enc_name(str_enc),
-			 rb_enc_name(STR_ENC_GET(repl)));
-            }
-            enc = STR_ENC_GET(repl);
-        }
-#endif
+
 	rb_str_modify(str);
-#if WITH_OBJC
 	RSTRING_SYNC(str);
 	rb_str_splice_0(str, BEG(0), END(0) - BEG(0), repl);
 	if (OBJ_TAINTED(repl)) tainted = 1;
-#else
-	rb_enc_associate(str, enc);
-	if (OBJ_TAINTED(repl)) tainted = 1;
-	if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
-	    int cr2 = ENC_CODERANGE(repl);
-	    if (cr2 == ENC_CODERANGE_UNKNOWN || cr2 > cr) cr = cr2;
-	}
-	plen = END(0) - BEG(0);
-	if (RSTRING_BYTELEN(repl) > plen) {
-	    RESIZE_CAPA(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(repl) - plen);
-	}
-	if (RSTRING_BYTELEN(repl) != plen) {
-	    memmove(RSTRING_BYTEPTR(str) + BEG(0) + RSTRING_BYTELEN(repl),
-		    RSTRING_BYTEPTR(str) + BEG(0) + plen,
-		    RSTRING_BYTELEN(str) - BEG(0) - plen);
-	}
-	memcpy(RSTRING_BYTEPTR(str) + BEG(0),
-	       RSTRING_BYTEPTR(repl), RSTRING_BYTELEN(repl));
-	STR_SET_LEN(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(repl) - plen);
-	RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-	ENC_CODERANGE_SET(str, cr);
-#endif
+
 	if (tainted) OBJ_TAINT(str);
 
 	return str;
@@ -3990,20 +2080,11 @@
 	return rb_str_dup(str);
     }
 
-#if WITH_OBJC
     dest = rb_str_new5(str, NULL, 0);
     slen = RSTRING_LEN(str);
     sp = RSTRING_PTR(str);
     cp = sp;
     str_enc = NULL;
-#else
-    blen = RSTRING_BYTELEN(str) + 30; /* len + margin */
-    dest = rb_str_buf_new(blen);
-    sp = RSTRING_BYTEPTR(str);
-    slen = RSTRING_BYTELEN(str);
-    cp = sp;
-    str_enc = STR_ENC_GET(str);
-#endif
 
     do {
 	n++;
@@ -4045,11 +2126,7 @@
 	     * in order to prevent infinite loops.
 	     */
 	    if (slen <= END(0)) break;
-#if WITH_OBJC
 	    len = 1;
-#else
-	    len = rb_enc_mbclen(sp+END(0), sp+slen, str_enc);
-#endif
             rb_enc_str_buf_cat(dest, sp+END(0), len, str_enc);
 	    offset = END(0) + len;
 	}
@@ -4061,7 +2138,6 @@
         rb_enc_str_buf_cat(dest, cp, slen - offset, str_enc);
     }
     rb_backref_set(match);
-#if WITH_OBJC
     if (bang) {
 	rb_str_modify(str);
 	RSTRING_SYNC(str);
@@ -4073,17 +2149,6 @@
 	    tainted = 1;
 	str = dest;
     }
-#else
-    if (bang) {
-        rb_str_shared_replace(str, dest);
-    }
-    else {
-	RBASIC(dest)->klass = rb_obj_class(str);
-	RBASIC(dest)->isa = RCLASS_OCID(RBASIC(dest)->klass);
-	OBJ_INFECT(dest, str);
-	str = dest;
-    }
-#endif
 
     if (tainted) OBJ_TAINT(str);
     return str;
@@ -4161,7 +2226,6 @@
 rb_str_replace(VALUE str, VALUE str2)
 {
     if (str == str2) return str;
-#if WITH_OBJC
     rb_str_modify(str);
     CFDataRef data = (CFDataRef)rb_str_cfdata2(str2);
     if (data != NULL) {
@@ -4176,31 +2240,6 @@
     rb_gc_malloc_increase(CFStringGetLength((CFStringRef)str2) * sizeof(UniChar));
     if (OBJ_TAINTED(str2))
 	OBJ_TAINT(str);
-#else
-    StringValue(str2);
-    len = RSTRING_BYTELEN(str2);
-    if (STR_ASSOC_P(str2)) {
-	str2 = rb_str_new4(str2);
-    }
-    if (STR_SHARED_P(str2)) {
-	if (str_independent(str) && !STR_EMBED_P(str)) {
-	    xfree(RSTRING_BYTEPTR(str));
-	}
-	STR_SET_NOEMBED(str);
-	RSTRING(str)->as.heap.len = len;
-	RSTRING(str)->as.heap.ptr = RSTRING_BYTEPTR(str2);
-	FL_SET(str, ELTS_SHARED);
-	FL_UNSET(str, STR_ASSOC);
-	RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared;
-    }
-    else {
-	rb_str_modify(str);
-	str_replace_shared(str, rb_str_new4(str2));
-    }
-
-    OBJ_INFECT(str, str2);
-    rb_enc_cr_str_exact_copy(str, str2);
-#endif
     return str;
 }
 
@@ -4217,20 +2256,9 @@
 static VALUE
 rb_str_clear(VALUE str)
 {
-#if WITH_OBJC
     rb_str_modify(str);
     CFStringDelete((CFMutableStringRef)str, 
 	CFRangeMake(0, CFStringGetLength((CFStringRef)str)));
-#else
-    /* rb_str_modify() */	/* no need for str_make_independent */
-    if (str_independent(str) && !STR_EMBED_P(str)) {
-	free(RSTRING_BYTEPTR(str));
-    }
-    STR_SET_EMBED(str);
-    STR_SET_EMBED_LEN(str, 0);
-    RSTRING_BYTEPTR(str)[0] = 0;
-    ENC_CODERANGE_CLEAR(str);
-#endif
     return str;
 }
 
@@ -4291,9 +2319,7 @@
         pos += n;
 
     RSTRING_BYTEPTR(str)[pos] = byte;
-#if WITH_OBJC
     RSTRING_SYNC(str);
-#endif
 
     return value;
 }
@@ -4309,7 +2335,6 @@
 static VALUE
 rb_str_reverse_bang(VALUE str)
 {
-#if WITH_OBJC
     CFIndex i, n;
     UniChar *buffer;
 
@@ -4326,26 +2351,7 @@
     }
     CFStringDelete((CFMutableStringRef)str, CFRangeMake(0, n));
     CFStringAppendCharacters((CFMutableStringRef)str, (const UniChar *)buffer, n);
-#else
-    char *s, *e, c;
 
-    if (RSTRING_BYTELEN(str) > 1) {
-	rb_str_modify(str);
-	s = RSTRING_BYTEPTR(str);
-	e = RSTRING_END(str) - 1;
-
-	if (single_byte_optimizable(str)) {
-	    while (s < e) {
-		c = *s;
-		*s++ = *e;
- 		*e-- = c;
-	    }
-	}
-	else {
-	    rb_str_shared_replace(str, rb_str_reverse(str));
-	}
-    }
-#endif
     return str;
 }
 
@@ -4361,43 +2367,9 @@
 static VALUE
 rb_str_reverse(VALUE str)
 {
-#if WITH_OBJC
     VALUE obj = rb_str_dup(str);
     rb_str_reverse_bang(obj);
     return obj;
-#else
-    rb_encoding *enc;
-    VALUE obj;
-    char *s, *e, *p;
-
-    if (RSTRING_BYTELEN(str) <= 1) return rb_str_dup(str);
-    enc = STR_ENC_GET(str);
-    obj = rb_str_new5(str, 0, RSTRING_BYTELEN(str));
-    s = RSTRING_BYTEPTR(str); e = RSTRING_END(str);
-    p = RSTRING_END(obj);
-
-    if (RSTRING_BYTELEN(str) > 1) {
-	if (single_byte_optimizable(str)) {
-	    while (s < e) {
-		*--p = *s++;
-	    }
-	}
-	else {
-	    while (s < e) {
-		int clen = rb_enc_mbclen(s, e, enc);
-
-		p -= clen;
-		memcpy(p, s, clen);
-		s += clen;
-	    }
-	}
-    }
-    STR_SET_LEN(obj, RSTRING_BYTELEN(str));
-    OBJ_INFECT(obj, str);
-    rb_enc_cr_str_copy_for_substr(obj, str);
-
-    return obj;
-#endif
 }
 
 /*
@@ -4498,11 +2470,7 @@
 static VALUE
 rb_str_to_s(VALUE str)
 {
-#if WITH_OBJC
     if (!rb_objc_str_is_pure(str)) {
-#else
-    if (rb_obj_class(str) != rb_cString) {
-#endif
 	VALUE dup = str_alloc(rb_cString);
 	rb_str_replace(dup, str);
 	return dup;
@@ -4513,18 +2481,10 @@
 static void
 str_cat_char(VALUE str, int c, rb_encoding *enc)
 {
-#if WITH_OBJC
     char buf[2];
     buf[0] = (char)c;
     buf[1] = '\0';
     CFStringAppendCString((CFMutableStringRef)str, buf, kCFStringEncodingUTF8);
-#else
-    char s[16];
-    int n = rb_enc_codelen(c, enc);
-
-    rb_enc_mbcput(c, s, enc);
-    rb_enc_str_buf_cat(str, s, n, enc);
-#endif
 }
 
 static void
@@ -4553,7 +2513,6 @@
     const char *p, *pend;
     VALUE result;
 
-#if WITH_OBJC
     if (rb_objc_str_is_bytestring(str)) {
 	p = (const char *)RSTRING_BYTEPTR(str); 
 	pend = (const char *)RSTRING_END(str);
@@ -4564,46 +2523,21 @@
     }
     if (p == NULL)
 	return rb_str_new2("\"\"");
-#else
-    p = RSTRING_BYTEPTR(str); pend = RSTRING_END(str);
-#endif
     result = rb_str_buf_new2("");
-#if !WITH_OBJC
-    if (!rb_enc_asciicompat(enc)) enc = rb_usascii_encoding();
-    rb_enc_associate(result, enc);
-#endif
     str_cat_char(result, '"', enc);
     while (p < pend) {
 	int c;
 	int n;
 	int cc;
 
-#if WITH_OBJC
 	c = *p;
 	n = 1;
-#else
-        n = rb_enc_precise_mbclen(p, pend, enc);
-        if (!MBCLEN_CHARFOUND_P(n)) {
-            p++;
-            n = 1;
-            goto escape_codepoint;
-        }
-        n = MBCLEN_CHARFOUND_LEN(n);
 
-	c = rb_enc_codepoint(p, pend, enc);
-	n = rb_enc_codelen(c, enc);
-#endif
-
 	p += n;
 	if (c == '"'|| c == '\\' ||
 	    (c == '#' &&
              p < pend &&
-#if WITH_OBJC
 	     ((cc = *p),
-#else
-             MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
-             (cc = rb_enc_codepoint(p,pend,enc),
-#endif
               (cc == '$' || cc == '@' || cc == '{')))) {
 	    prefix_escape(result, c, enc);
 	}
@@ -4639,9 +2573,6 @@
 	    char *s;
             const char *q;
 
-#if !WITH_OBJC
-	  escape_codepoint:
-#endif
             for (q = p-n; q < p; q++) {
                 s = buf;
                 sprintf(buf, "\\x%02X", *q & 0377);
@@ -4652,8 +2583,8 @@
 	}
     }
     str_cat_char(result, '"', enc);
+    RSTRING_SYNC(result);
 
-    OBJ_INFECT(result, str);
     return result;
 }
 
@@ -4677,7 +2608,6 @@
     VALUE result;
 
     len = 2;			/* "" */
-#if WITH_OBJC
     if (rb_objc_str_is_bytestring(str)) {
 	p = RSTRING_BYTEPTR(str); 
 	pend = RSTRING_END(str);
@@ -4686,9 +2616,6 @@
 	p = RSTRING_PTR(str); 
 	pend = p + RSTRING_LEN(str);
     }
-#else
-    p = RSTRING_BYTEPTR(str); pend = p + RSTRING_BYTELEN(str);
-#endif
     while (p < pend) {
 	unsigned char c = *p++;
 	switch (c) {
@@ -4778,16 +2705,11 @@
     *q++ = '"';
     if (!rb_enc_asciicompat(enc0)) {
 	sprintf(q, ".force_encoding(\"%s\")", rb_enc_name(enc0));
-#if !WITH_OBJC
-	enc0 = rb_ascii8bit_encoding();
-#endif
+
     }
 
-    OBJ_INFECT(result, str);
     /* result from dump is ASCII */
-#if !WITH_OBJC
-    rb_enc_associate(result, enc0);
-#endif
+
     RSTRING_SYNC(result);
     return result;
 }
@@ -4805,7 +2727,6 @@
 static VALUE
 rb_str_upcase_bang(VALUE str)
 {
-#if WITH_OBJC
     CFHashCode h;
     rb_str_modify(str);
     h = CFHash((CFTypeRef)str);
@@ -4813,30 +2734,6 @@
     if (h == CFHash((CFTypeRef)str))
 	return Qnil;
     return str;
-#else
-    rb_encoding *enc;
-    char *s, *send;
-    int modify = 0;
-    int cr = ENC_CODERANGE(str);
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-
-	if (rb_enc_islower(c, enc)) {
-	    /* assuming toupper returns codepoint with same size */
-	    rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
-	    modify = 1;
-	}
-	s += rb_enc_codelen(c, enc);
-    }
-
-    ENC_CODERANGE_SET(str, cr);
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 
@@ -4873,7 +2770,6 @@
 static VALUE
 rb_str_downcase_bang(VALUE str)
 {
-#if WITH_OBJC
     CFHashCode h;
     rb_str_modify(str);
     h = CFHash((CFTypeRef)str);
@@ -4881,30 +2777,6 @@
     if (h == CFHash((CFTypeRef)str))
 	return Qnil;
     return str;
-#else
-    rb_encoding *enc;
-    char *s, *send;
-    int modify = 0;
-    int cr = ENC_CODERANGE(str);
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-
-	if (rb_enc_isupper(c, enc)) {
-	    /* assuming toupper returns codepoint with same size */
-	    rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
-	    modify = 1;
-	}
-	s += rb_enc_codelen(c, enc);
-    }
-
-    ENC_CODERANGE_SET(str, cr);
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 
@@ -4946,7 +2818,6 @@
 static VALUE
 rb_str_capitalize_bang(VALUE str)
 {
-#if WITH_OBJC
     CFStringRef tmp;
     long i, n;
     bool changed;
@@ -4975,37 +2846,6 @@
     CFStringReplaceAll((CFMutableStringRef)str, tmp);
     CFRelease(tmp);
     return str;
-#else
-    rb_encoding *enc;
-    char *s, *send;
-    int modify = 0;
-    int c;
-    int cr = ENC_CODERANGE(str);
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    if (RSTRING_BYTELEN(str) == 0 || !RSTRING_BYTEPTR(str)) return Qnil;
-    s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-
-    c = rb_enc_codepoint(s, send, enc);
-    if (rb_enc_islower(c, enc)) {
-	rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
-	modify = 1;
-    }
-    s += rb_enc_codelen(c, enc);
-    while (s < send) {
-	c = rb_enc_codepoint(s, send, enc);
-	if (rb_enc_isupper(c, enc)) {
-	    rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
-	    modify = 1;
-	}
-	s += rb_enc_codelen(c, enc);
-    }
-
-    ENC_CODERANGE_SET(str, cr);
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 
@@ -5043,7 +2883,6 @@
 static VALUE
 rb_str_swapcase_bang(VALUE str)
 {
-#if WITH_OBJC
     CFIndex i, n;
     UniChar *buffer;
     bool changed;
@@ -5076,35 +2915,6 @@
     CFStringDelete((CFMutableStringRef)str, CFRangeMake(0, n));
     CFStringAppendCharacters((CFMutableStringRef)str, (const UniChar *)buffer, n);
     return str;
-#else
-    rb_encoding *enc;
-    char *s, *send;
-    int modify = 0;
-    int cr = ENC_CODERANGE(str);
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-
-	if (rb_enc_isupper(c, enc)) {
-	    /* assuming toupper returns codepoint with same size */
-	    rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
-	    modify = 1;
-	}
-	else if (rb_enc_islower(c, enc)) {
-	    /* assuming toupper returns codepoint with same size */
-	    rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
-	    modify = 1;
-	}
-	s += rb_enc_codelen(c, enc);
-    }
-
-    ENC_CODERANGE_SET(str, cr);
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 
@@ -5128,51 +2938,6 @@
     return str;
 }
 
-#if !WITH_OBJC
-typedef unsigned char *USTR;
-
-struct tr {
-    int gen, now, max;
-    char *p, *pend;
-};
-
-static int
-trnext(struct tr *t, rb_encoding *enc)
-{
-    for (;;) {
-	if (!t->gen) {
-	    if (t->p == t->pend) return -1;
-	    if (t->p < t->pend - 1 && *t->p == '\\') {
-		t->p++;
-	    }
-	    t->now = rb_enc_codepoint(t->p, t->pend, enc);
-	    t->p += rb_enc_codelen(t->now, enc);
-	    if (t->p < t->pend - 1 && *t->p == '-') {
-		t->p++;
-		if (t->p < t->pend) {
-		    int c = rb_enc_codepoint(t->p, t->pend, enc);
-		    t->p += rb_enc_codelen(c, enc);
-		    if (t->now > c) continue;
-		    t->gen = 1;
-		    t->max = c;
-		}
-	    }
-	    return t->now;
-	}
-	else if (++t->now < t->max) {
-	    return t->now;
-	}
-	else {
-	    t->gen = 0;
-	    return t->max;
-	}
-    }
-}
-
-static VALUE rb_str_delete_bang(int,VALUE*,VALUE);
-#endif
-
-#if WITH_OBJC
 typedef void str_charset_find_cb
 (CFRange *, const CFRange *, CFStringRef, UniChar, void *);
 
@@ -5480,12 +3245,10 @@
     }
     _ctx->changed = true;
 }
-#endif
 
 static VALUE
 tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
 {
-#if WITH_OBJC
     struct tr_trans_cb_ctx _ctx;
 
     StringValue(src);
@@ -5516,205 +3279,6 @@
 	CFRelease(_ctx.opt);
 
     return _ctx.changed ? str : Qnil;
-#else
-    SIGNED_VALUE trans[256];
-    rb_encoding *enc, *e1, *e2;
-    struct tr trsrc, trrepl;
-    int cflag = 0;
-    int c, last = 0, modify = 0, i;
-    char *s, *send;
-    VALUE hash = 0;
-
-    StringValue(src);
-    StringValue(repl);
-    if (RSTRING_BYTELEN(str) == 0 || !RSTRING_BYTEPTR(str)) return Qnil;
-    trsrc.p = RSTRING_BYTEPTR(src); trsrc.pend = trsrc.p + RSTRING_BYTELEN(src);
-    if (RSTRING_BYTELEN(src) >= 2 && RSTRING_BYTEPTR(src)[0] == '^') {
-	cflag++;
-	trsrc.p++;
-    }
-    if (RSTRING_BYTELEN(repl) == 0) {
-	return rb_str_delete_bang(1, &src, str);
-    }
-    e1 = rb_enc_check(str, src);
-    e2 = rb_enc_check(str, repl);
-    if (e1 == e2) {
-	enc = e1;
-    }
-    else {
-	enc = rb_enc_check(src, repl);
-    }
-    trrepl.p = RSTRING_BYTEPTR(repl);
-    trrepl.pend = trrepl.p + RSTRING_BYTELEN(repl);
-    trsrc.gen = trrepl.gen = 0;
-    trsrc.now = trrepl.now = 0;
-    trsrc.max = trrepl.max = 0;
-
-    if (cflag) {
-	for (i=0; i<256; i++) {
-	    trans[i] = 1;
-	}
-	while ((c = trnext(&trsrc, enc)) >= 0) {
-	    if (c < 256) {
-		trans[c] = -1;
-	    }
-	    else {
-		if (!hash) hash = rb_hash_new();
-		rb_hash_aset(hash, INT2NUM(c), Qtrue);
-	    }
-	}
-	while ((c = trnext(&trrepl, enc)) >= 0)
-	    /* retrieve last replacer */;
-	last = trrepl.now;
-	for (i=0; i<256; i++) {
-	    if (trans[i] >= 0) {
-		trans[i] = last;
-	    }
-	}
-    }
-    else {
-	int r;
-
-	for (i=0; i<256; i++) {
-	    trans[i] = -1;
-	}
-	while ((c = trnext(&trsrc, enc)) >= 0) {
-	    r = trnext(&trrepl, enc);
-	    if (r == -1) r = trrepl.now;
-	    if (c < 256) {
-		trans[c] = INT2NUM(r);
-	    }
-	    else {
-		if (!hash) hash = rb_hash_new();
-		rb_hash_aset(hash, INT2NUM(c), INT2NUM(r));
-	    }
-	}
-    }
-
-    rb_str_modify(str);
-    s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-    if (sflag) {
-	int clen, tlen, max = RSTRING_BYTELEN(str);
-	int offset, save = -1;
-	char *buf = ALLOC_N(char, max), *t = buf;
-	VALUE v;
-
-	if (cflag) tlen = rb_enc_codelen(last, enc);
-	while (s < send) {
-	    c = rb_enc_codepoint(s, send, enc);
-	    tlen = clen = rb_enc_codelen(c, enc);
-
-	    s += clen;
-	    if (c < 256) {
-		v = trans[c] >= 0 ? trans[c] : Qnil;
-	    }
-	    else {
-		v = hash ? rb_hash_aref(hash, INT2NUM(c)) : Qnil;
-	    }
-	    if (!NIL_P(v)) {
-		if (!cflag) {
-		    c = NUM2INT(v);
-		    if (save == c) continue;
-		    save = c;
-		    tlen = rb_enc_codelen(c, enc);
-		    modify = 1;
-		}
-		else {
-		    save = c = last;
-		    modify = 1;
-		}
-	    }
-	    else {
-		save = -1;
-	    }
-	    while (t - buf + tlen >= max) {
-		offset = t - buf;
-		max *= 2;
-		REALLOC_N(buf, char, max);
-		t = buf + offset;
-	    }
-	    rb_enc_mbcput(c, t, enc);
-	    t += tlen;
-	}
-	*t = '\0';
-	GC_WB(&RSTRING(str)->as.heap.ptr, buf);
-	RSTRING(str)->as.heap.len = t - buf;
-	STR_SET_NOEMBED(str);
-	RSTRING(str)->as.heap.aux.capa = max;
-    }
-    else if (rb_enc_mbmaxlen(enc) == 1) {
-	while (s < send) {
-	    c = (unsigned char)*s;
-	    if (trans[c] >= 0) {
-		if (!cflag) {
-		    c = FIX2INT(trans[c]);
-		    *s = c;
-		    modify = 1;
-		}
-		else {
-		    *s = last;
-		    modify = 1;
-		}
-	    }
-	    s++;
-	}
-    }
-    else {
-	int clen, tlen, max = RSTRING_BYTELEN(str) * 1.2;
-	int offset;
-	char *buf = ALLOC_N(char, max), *t = buf;
-	VALUE v;
-
-	if (cflag) tlen = rb_enc_codelen(last, enc);
-	while (s < send) {
-	    c = rb_enc_codepoint(s, send, enc);
-	    tlen = clen = rb_enc_codelen(c, enc);
-
-	    if (c < 256) {
-		v = trans[c] >= 0 ? trans[c] : Qnil;
-	    }
-	    else {
-		v = hash ? rb_hash_aref(hash, INT2NUM(c)) : Qnil;
-	    }
-	    if (!NIL_P(v)) {
-		if (!cflag) {
-		    c = NUM2INT(v);
-		    tlen = rb_enc_codelen(c, enc);
-		    modify = 1;
-		}
-		else {
-		    c = last;
-		    modify = 1;
-		}
-	    }
-	    while (t - buf + tlen >= max) {
-		offset = t - buf;
-		max *= 2;
-		REALLOC_N(buf, char, max);
-		t = buf + offset;
-	    }
-	    if (s != t) rb_enc_mbcput(c, t, enc);
-	    s += clen;
-	    t += tlen;
-	}
-	if (!STR_EMBED_P(str)) {
-	    xfree(RSTRING(str)->as.heap.ptr);
-	}
-	*t = '\0';
-	GC_WB(&RSTRING(str)->as.heap.ptr, buf);
-	RSTRING(str)->as.heap.len = t - buf;
-	STR_SET_NOEMBED(str);
-	RSTRING(str)->as.heap.aux.capa = max;
-    }
-    
-    if (modify) {
-#if !WITH_OBJC
-	rb_enc_associate(str, enc);
-#endif
-	return str;
-    }
-    return Qnil;
-#endif
 }
 
 /*
@@ -5758,84 +3322,6 @@
     return str;
 }
 
-#if !WITH_OBJC
-static void
-tr_setup_table(VALUE str, char stable[256], int first, 
-	       VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
-{
-    char buf[256];
-    struct tr tr;
-    int c, l;
-    VALUE table = 0, ptable = 0;
-    int i, cflag = 0;
-
-    tr.p = RSTRING_BYTEPTR(str); tr.pend = tr.p + RSTRING_BYTELEN(str);
-    tr.gen = tr.now = tr.max = 0;
-    
-    if (RSTRING_BYTELEN(str) > 1 && rb_enc_ascget(tr.p, tr.pend, &l, enc) == '^') {
-	cflag = 1;
-	tr.p += l;
-    }
-    if (first) {
-	for (i=0; i<256; i++) {
-	    stable[i] = 1;
-	}
-    }
-    for (i=0; i<256; i++) {
-	buf[i] = cflag;
-    }
-
-    while ((c = trnext(&tr, enc)) >= 0) {
-	if (c < 256) {
-	    buf[c & 0xff] = !cflag;
-	}
-	else {
-	    VALUE key = INT2NUM(c);
-
-	    if (!table) {
-		table = rb_hash_new();
-		if (cflag) {
-		    ptable = *ctablep;
-		    *ctablep = table;
-		}
-		else {
-		    ptable = *tablep;
-		    *tablep = table;
-		}
-	    }
-	    if (!ptable || !NIL_P(rb_hash_aref(ptable, key))) {
-		rb_hash_aset(table, key, Qtrue);
-	    }
-	}
-    }
-    for (i=0; i<256; i++) {
-	stable[i] = stable[i] && buf[i];
-    }
-}
-
-
-static int
-tr_find(int c, char table[256], VALUE del, VALUE nodel)
-{
-    if (c < 256) {
-	return table[c] ? Qtrue : Qfalse;
-    }
-    else {
-	VALUE v = INT2NUM(c);
-
-	if (!del || NIL_P(rb_hash_lookup(del, v))) {
-	    return Qfalse;
-	}
-	if (nodel && NIL_P(rb_hash_lookup(nodel, v)))
-	    return Qfalse;
-	return Qtrue;
-    }
-}
-
-#else
-
-#endif
-
 /*
  *  call-seq:
  *     str.delete!([other_str]+)   => str or nil
@@ -5844,7 +3330,6 @@
  *  <code>nil</code> if <i>str</i> was not modified.
  */
 
-#if WITH_OBJC
 static void
 rb_str_delete_bang_cb(CFRange *search_range, const CFRange *result_range, 
     CFStringRef str, UniChar character, void *ctx)
@@ -5855,12 +3340,10 @@
     search_range->location = result_range->location;
     *(bool *)ctx = true;
 }
-#endif
 
 static VALUE
 rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
 {
-#if WITH_OBJC
     bool changed;
     if (argc < 1)
 	rb_raise(rb_eArgError, "wrong number of arguments");
@@ -5871,50 +3354,6 @@
     if (!changed)
     	return Qnil;
     return str;
-#else
-    char squeez[256];
-    rb_encoding *enc = 0;
-    char *s, *send, *t;
-    VALUE del = 0, nodel = 0;
-    int modify = 0;
-    int i;
-    int cr = ENC_CODERANGE(str);
-
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-    for (i=0; i<argc; i++) {
-	VALUE s = argv[i];
-
-	StringValue(s);
-	enc = rb_enc_check(str, s);
-	tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
-    }
-
-    rb_str_modify(str);
-    s = t = RSTRING_BYTEPTR(str);
-    if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
-    send = RSTRING_END(str);
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-	int clen = rb_enc_codelen(c, enc);
-
-	if (tr_find(c, squeez, del, nodel)) {
-	    modify = 1;
-	}
-	else {
-	    if (t != s) rb_enc_mbcput(c, t, enc);
-	    t += clen;
-	}
-	s += clen;
-    }
-    *t = '\0';
-    STR_SET_LEN(str, t - RSTRING_BYTEPTR(str));
-
-    ENC_CODERANGE_SET(str, cr);
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 /*
@@ -5948,7 +3387,6 @@
  *  <code>nil</code> if no changes were made.
  */
 
-#if WITH_OBJC
 static void
 rb_str_squeeze_bang_cb(CFRange *search_range, const CFRange *result_range, 
     CFStringRef str, UniChar character, void *ctx)
@@ -5963,12 +3401,10 @@
 	*(bool *)ctx = true;
     }
 }
-#endif
 
 static VALUE
 rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
 {
-#if WITH_OBJC
     bool changed;
     VALUE all_chars;
     if (argc == 0) {
@@ -5983,52 +3419,6 @@
     if (!changed)
     	return Qnil;
     return str;
-#else
-    char squeez[256];
-    rb_encoding *enc = 0;
-    VALUE del = 0, nodel = 0;
-    char *s, *send, *t;
-    int save, modify = 0;
-    int i;
-
-    if (argc == 0) {
-	enc = STR_ENC_GET(str);
-    }
-    else {
-	for (i=0; i<argc; i++) {
-	    VALUE s = argv[i];
-
-	    StringValue(s);
-	    enc = rb_enc_check(str, s);
-	    tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
-	}
-    }
-
-    rb_str_modify(str);
-    s = t = RSTRING_BYTEPTR(str);
-    if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
-    send = RSTRING_END(str);
-    save = -1;
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-	int clen = rb_enc_codelen(c, enc);
-
-	if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
-	    if (t != s) rb_enc_mbcput(c, t, enc);
-	    save = c;
-	    t += clen;
-	}
-	s += clen;
-    }
-    *t = '\0';
-    if (t - RSTRING_BYTEPTR(str) != RSTRING_BYTELEN(str)) {
-	STR_SET_LEN(str, t - RSTRING_BYTEPTR(str));
-	modify = 1;
-    }
-
-    if (modify) return str;
-    return Qnil;
-#endif
 }
 
 
@@ -6109,19 +3499,16 @@
  *     a.count "ej-m"          #=> 4
  */
 
-#if WITH_OBJC
 static void
 rb_str_count_cb(CFRange *search_range, const CFRange *result_range, 
     CFStringRef str, UniChar character, void *ctx)
 {
     (*(int *)ctx) += result_range->length;
 }
-#endif
 
 static VALUE
 rb_str_count(int argc, VALUE *argv, VALUE str)
 {
-#if WITH_OBJC
     int count;
     if (argc < 1)
 	rb_raise(rb_eArgError, "wrong number of arguments");
@@ -6129,42 +3516,8 @@
     str_charset_find((CFStringRef)str, argv, argc, false,
 	rb_str_count_cb, &count); 
     return INT2NUM(count);
-#else
-    char table[256];
-    rb_encoding *enc = 0;
-    VALUE del = 0, nodel = 0;
-    char *s, *send;
-    int i;
-
-    if (argc < 1) {
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-    for (i=0; i<argc; i++) {
-	VALUE s = argv[i];
-
-	StringValue(s);
-	enc = rb_enc_check(str, s);
-	tr_setup_table(s, table,i==0, &del, &nodel, enc);
-    }
-
-    s = RSTRING_BYTEPTR(str);
-    if (!s || RSTRING_BYTELEN(str) == 0) return INT2FIX(0);
-    send = RSTRING_END(str);
-    i = 0;
-    while (s < send) {
-	int c = rb_enc_codepoint(s, send, enc);
-	int clen = rb_enc_codelen(c, enc);
-
-	if (tr_find(c, table, del, nodel)) {
-	    i++;
-	}
-	s += clen;
-    }
-    return INT2NUM(i);
-#endif
 }
 
-
 /*
  *  call-seq:
  *     str.split(pattern=$;, [limit])   => anArray
@@ -6220,9 +3573,6 @@
     VALUE result, tmp;
     long clen;
 
-#if !WITH_OBJC
-    cstr = RSTRING_PTR(str);
-#endif
     clen = RSTRING_LEN(str);
 
     if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
@@ -6248,35 +3598,11 @@
     else {
       fs_set:
 	if (TYPE(spat) == T_STRING) {
-#if WITH_OBJC
 	    spat_string = Qtrue;
 	    if (RSTRING_LEN(spat) == 1
 		&& CFStringGetCharacterAtIndex((CFStringRef)spat, 0) == ' ') {
 		awk_split = Qtrue;
 	    }
-#else
-	    const char *spat_cstr;
-	    long spat_clen;
-	    rb_encoding *enc2 = STR_ENC_GET(spat);
-
-	    spat_cstr = RSTRING_PTR(spat);
-	    spat_clen = RSTRING_LEN(spat);
-	    if (rb_enc_mbminlen(enc2) == 1) {
-		if (spat_clen == 1 && spat_cstr[0] == ' '){
-		    awk_split = Qtrue;
-		}
-	    }
-	    else {
-		int l;
-		if (rb_enc_ascget(spat_cstr, spat_cstr+spat_clen, &l, enc2) == ' ' &&
-		    spat_clen == l) {
-		    awk_split = Qtrue;
-		}
-	    }
-	    if (!awk_split) {
-		spat = rb_reg_regcomp(rb_reg_quote(spat));
-	    }
-#endif
 	}
 	else {
 	    spat = get_pat(spat, 1);
@@ -6284,7 +3610,6 @@
     }
 
     beg = 0;
-#if WITH_OBJC
     if (awk_split || spat_string) {
 	CFRange search_range;
 	CFCharacterSetRef charset = NULL;
@@ -6338,41 +3663,6 @@
 	}
 	while ((limit == Qnil || --lim > 1));
 	beg = search_range.location;
-#else
-    if (awk_split) {
-	const char *ptr = cstr;
-	const char *eptr = cstr+clen;
-	const char *bptr = ptr;
-	int skip = 1;
-	int c;
-
-	end = beg;
-	while (ptr < eptr) {
-	    c = rb_enc_codepoint(ptr, eptr, enc);
-	    ptr += rb_enc_mbclen(ptr, eptr, enc);
-	    if (skip) {
-		if (rb_enc_isspace(c, enc)) {
-		    beg = ptr - bptr;
-		}
-		else {
-		    end = ptr - bptr;
-		    skip = 0;
-		    if (!NIL_P(limit) && lim <= i) break;
-		}
-	    }
-	    else {
-		if (rb_enc_isspace(c, enc)) {
-		    rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
-		    skip = 1;
-		    beg = ptr - bptr;
-		    if (!NIL_P(limit)) ++i;
-		}
-		else {
-		    end = ptr - bptr;
-		}
-	    }
-	}
-#endif
     }
     else {
 	long start = beg;
@@ -6383,34 +3673,18 @@
 	while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
 	    regs = RMATCH_REGS(rb_backref_get());
 	    if (start == end && BEG(0) == END(0)) {
-#if WITH_OBJC
 		if (0) {
-#else
-		if (!cstr) {
-		    rb_ary_push(result, rb_str_new("", 0));
-#endif
 		    break;
 		}
 		else if (last_null == 1) {
-#if WITH_OBJC
 		    rb_ary_push(result, rb_str_subseq(str, beg, 1));
-#else
-		    rb_ary_push(result, rb_str_subseq(str, beg,
-						      rb_enc_mbclen(cstr+beg,
-								    cstr+clen,
-								    enc)));
-#endif
 		    beg = start;
 		}
 		else {
                     if (start == clen)
                         start++;
                     else
-#if WITH_OBJC
 			start += 1;
-#else
-                        start += rb_enc_mbclen(cstr+start,cstr+clen,enc);
-#endif
 		    last_null = 1;
 		    continue;
 		}
@@ -6516,7 +3790,6 @@
 static VALUE
 rb_str_each_line(int argc, VALUE *argv, VALUE str)
 {
-#if WITH_OBJC
     VALUE rs;
     long n;
     CFStringRef substr;
@@ -6581,98 +3854,8 @@
 #undef YIELD_SUBSTR
 
     return str;
-#else
-    rb_encoding *enc;
-    VALUE rs;
-    int newline;
-    char *p, *pend, *s, *ptr;
-    long len, rslen; 
-    VALUE line;
-    int n;
-
-    if (argc == 0) {
-	rs = rb_rs;
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &rs);
-    }
-    RETURN_ENUMERATOR(str, argc, argv);
-    if (NIL_P(rs)) {
-	rb_yield(str);
-	return str;
-    }
-    str = rb_str_new4(str);
-    ptr = p = s = RSTRING_BYTEPTR(str);
-    pend = p + RSTRING_BYTELEN(str);
-    len = RSTRING_BYTELEN(str);
-    StringValue(rs);
-    if (rs == rb_default_rs) {
-	enc = rb_enc_get(str);
-	while (p < pend) {
-	    char *p0;
-
-	    p = memchr(p, '\n', pend - p);
-	    if (!p) break;
-	    p0 = rb_enc_left_char_head(s, p, enc);
-	    if (!rb_enc_is_newline(p0, pend, enc)) {
-		p++;
-		continue;
-	    }
-	    p = p0 + rb_enc_mbclen(p0, pend, enc);
-	    line = rb_str_new5(str, s, p - s);
-	    OBJ_INFECT(line, str);
-	    rb_enc_cr_str_copy_for_substr(line, str);
-	    rb_yield(line);
-	    str_mod_check(str, ptr, len);
-	    s = p;
-	}
-	goto finish;
-    }
-
-    enc = rb_enc_check(str, rs);
-    rslen = RSTRING_BYTELEN(rs);
-    if (rslen == 0) {
-	newline = '\n';
-    }
-    else {
-	newline = rb_enc_codepoint(RSTRING_BYTEPTR(rs), RSTRING_END(rs), enc);
-    }
-
-    while (p < pend) {
-	int c = rb_enc_codepoint(p, pend, enc);
-
-	n = rb_enc_codelen(c, enc);
-	if (rslen == 0 && c == newline) {
-	    while (p < pend && rb_enc_codepoint(p, pend, enc) == newline) {
-		p += n;
-	    }
-	    p -= n;
-	}
-	if (c == newline &&
-	    (rslen <= 1 || memcmp(RSTRING_BYTEPTR(rs), p, rslen) == 0)) {
-	    line = rb_str_new5(str, s, p - s + (rslen ? rslen : n));
-	    OBJ_INFECT(line, str);
-	    rb_enc_cr_str_copy_for_substr(line, str);
-	    rb_yield(line);
-	    str_mod_check(str, ptr, len);
-	    s = p + (rslen ? rslen : n);
-	}
-	p += n;
-    }
-
-  finish:
-    if (s != pend) {
-	line = rb_str_new5(str, s, pend - s);
-	OBJ_INFECT(line, str);
-	rb_enc_cr_str_copy_for_substr(line, str);
-	rb_yield(line);
-    }
-
-    return str;
-#endif
 }
 
-
 /*
  *  Document-method: bytes
  *  call-seq:
@@ -6745,7 +3928,6 @@
 static VALUE
 rb_str_each_char(VALUE str)
 {
-#if WITH_OBJC
     CFStringInlineBuffer buf;
     long i, n;
 
@@ -6762,44 +3944,8 @@
 	rb_yield(s);
     }
     return str;
-#else
-    int i, len, n;
-    const char *ptr;
-    rb_encoding *enc;
-
-    RETURN_ENUMERATOR(str, 0, 0);
-    str = rb_str_new4(str);
-    ptr = RSTRING_BYTEPTR(str);
-    len = RSTRING_BYTELEN(str);
-    enc = rb_enc_get(str);
-    for (i = 0; i < len; i += n) {
-	n = rb_enc_mbclen(ptr + i, ptr + len, enc);
-	rb_yield(rb_str_subseq(str, i, n));
-    }
-    return str;
-#endif
 }
 
-#if !WITH_OBJC
-static long
-chopped_length(VALUE str)
-{
-    rb_encoding *enc = STR_ENC_GET(str);
-    const char *p, *p2, *beg, *end;
-
-    beg = RSTRING_BYTEPTR(str);
-    end = beg + RSTRING_BYTELEN(str);
-    if (beg > end) return 0;
-    p = rb_enc_prev_char(beg, end, enc);
-    if (!p) return 0;
-    if (p > beg && rb_enc_codepoint(p, end, enc) == '\n') {
-	p2 = rb_enc_prev_char(beg, p, enc);
-	if (p2 && rb_enc_codepoint(p2, end, enc) == '\r') p = p2;
-    }
-    return p - beg;
-}
-#endif
-
 /*
  *  call-seq:
  *     str.chop!   => str or nil
@@ -6812,7 +3958,6 @@
 static VALUE
 rb_str_chop_bang(VALUE str)
 {
-#if WITH_OBJC
     long n;
     const char *p;
     CFRange r;
@@ -6832,17 +3977,6 @@
     }
     CFStringDelete((CFMutableStringRef)str, r);
     return str;
-#else
-    if (RSTRING_BYTELEN(str) > 0) {
-	long len;
-	rb_str_modify(str);
-	len = chopped_length(str);
-	STR_SET_LEN(str, len);
-	RSTRING_BYTEPTR(str)[len] = '\0';
-	return str;
-    }
-    return Qnil;
-#endif
 }
 
 
@@ -6866,16 +4000,9 @@
 static VALUE
 rb_str_chop(VALUE str)
 {
-#if WITH_OBJC
     VALUE str2 = rb_str_dup(str);
     rb_str_chop_bang(str2);
     return str2;
-#else
-    VALUE str2 = rb_str_new5(str, RSTRING_BYTEPTR(str), chopped_length(str));
-    rb_enc_cr_str_copy_for_substr(str2, str);
-    OBJ_INFECT(str2, str);
-    return str2;
-#endif
 }
 
 
@@ -6890,7 +4017,6 @@
 static VALUE
 rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
 {
-#if WITH_OBJC
     VALUE rs;
     long len, rslen;
     CFRange range_result;
@@ -6934,99 +4060,6 @@
 	return Qnil;
     CFStringDelete((CFMutableStringRef)str, range_result);
     return str;
-#else
-    rb_encoding *enc;
-    VALUE rs;
-    int newline;
-    char *p, *pp, *e;
-    long len, rslen;
-
-	len = RSTRING_BYTELEN(str);
-	if (len == 0) return Qnil;
-	p = RSTRING_BYTEPTR(str);
-    e = p + len;
-    if (argc == 0) {
-	rs = rb_rs;
-	if (rs == rb_default_rs) {
-	  smart_chomp:
-	    rb_str_modify(str);
-	    enc = rb_enc_get(str);
-	    if (rb_enc_mbminlen(enc) > 1) {
-		pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), enc);
-		if (rb_enc_is_newline(pp, e, enc)) {
-		    e = pp;
-		}
-		pp = e - rb_enc_mbminlen(enc);
-		if (pp >= p) {
-		    pp = rb_enc_left_char_head(p, pp, enc);
-		    if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
-			e = pp;
-		    }
-		}
-		if (e == RSTRING_END(str)) {
-		    return Qnil;
-		}
-		len = e - RSTRING_BYTEPTR(str);
-		STR_SET_LEN(str, len);
-	    }
-	    else {
-	    if (RSTRING_BYTEPTR(str)[len-1] == '\n') {
-		STR_DEC_LEN(str);
-		if (RSTRING_BYTELEN(str) > 0 &&
-		    RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)-1] == '\r') {
-		    STR_DEC_LEN(str);
-		}
-	    }
-	    else if (RSTRING_BYTEPTR(str)[len-1] == '\r') {
-		STR_DEC_LEN(str);
-	    }
-	    else {
-		return Qnil;
-	    }
-	    }
-	    RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-	    return str;
-	}
-    }
-    if (NIL_P(rs)) return Qnil;
-    StringValue(rs);
-    rslen = RSTRING_BYTELEN(rs);
-    if (rslen == 0) {
-	while (len>0 && p[len-1] == '\n') {
-	    len--;
-	    if (len>0 && p[len-1] == '\r')
-		len--;
-	}
-	if (len < RSTRING_BYTELEN(str)) {
-	    rb_str_modify(str);
-	    STR_SET_LEN(str, len);
-	    RSTRING_BYTEPTR(str)[len] = '\0';
-	    return str;
-	}
-	return Qnil;
-    }
-    if (rslen > len) return Qnil;
-    newline = RSTRING_BYTEPTR(rs)[rslen-1];
-    if (rslen == 1 && newline == '\n')
-	goto smart_chomp;
-
-    enc = rb_enc_check(str, rs);
-    if (is_broken_string(rs)) {
-	return Qnil;
-    }
-    pp = e - rslen;
-    if (p[len-1] == newline &&
-	(rslen <= 1 ||
-	 memcmp(RSTRING_BYTEPTR(rs), pp, rslen) == 0)) {
-	if (rb_enc_left_char_head(p, pp, enc) != pp)
-	    return Qnil;
-	rb_str_modify(str);
-	STR_SET_LEN(str, RSTRING_BYTELEN(str) - rslen);
-	RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-	return str;
-    }
-    return Qnil;
-#endif
 }
 
 
@@ -7069,7 +4102,6 @@
  *     "hello".lstrip!      #=> nil
  */
 
-#if WITH_OBJC
 static VALUE
 rb_str_strip_bang2(VALUE str, int direction)
 {
@@ -7113,39 +4145,11 @@
 
     return orig_n != n ? str : Qnil;
 }
-#endif
 
 static VALUE
 rb_str_lstrip_bang(VALUE str)
 {
-#if WITH_OBJC
     return rb_str_strip_bang2(str, -1);
-#else
-    rb_encoding *enc;
-    char *s, *t, *e;
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    s = RSTRING_BYTEPTR(str);
-    if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
-    e = t = RSTRING_END(str);
-    /* remove spaces at head */
-    while (s < e) {
-	int cc = rb_enc_codepoint(s, e, enc);
-	
-	if (!rb_enc_isspace(cc, enc)) break;
-	s += rb_enc_codelen(cc, enc);
-    }
-
-    if (s > RSTRING_BYTEPTR(str)) {
-	rb_str_modify(str);
-	STR_SET_LEN(str, t-s);
-	memmove(RSTRING_BYTEPTR(str), s, RSTRING_BYTELEN(str));
-	RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-	return str;
-    }
-    return Qnil;
-#endif
 }
 
 
@@ -7184,39 +4188,7 @@
 static VALUE
 rb_str_rstrip_bang(VALUE str)
 {
-#if WITH_OBJC
     return rb_str_strip_bang2(str, 1);
-#else
-    rb_encoding *enc;
-    char *s, *t, *e;
-    int space_seen = Qfalse;
-
-    rb_str_modify(str);
-    enc = STR_ENC_GET(str);
-    s = RSTRING_BYTEPTR(str);
-    if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
-    t = e = RSTRING_END(str);
-    while (s < e) {
-	int cc = rb_enc_codepoint(s, e, enc);
-
-	if (!cc || rb_enc_isspace(cc, enc)) {
-	    if (!space_seen) t = s;
-	    space_seen = Qtrue;
-	}
-	else {
-	    space_seen = Qfalse;
-	}
-	s += rb_enc_codelen(cc, enc);
-    }
-    if (!space_seen) t = s;
-    if (t < e) {
-	rb_str_modify(str);
-	STR_SET_LEN(str, t-RSTRING_BYTEPTR(str));
-	RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
-	return str;
-    }
-    return Qnil;
-#endif
 }
 
 
@@ -7251,15 +4223,7 @@
 static VALUE
 rb_str_strip_bang(VALUE str)
 {
-#if WITH_OBJC
     return rb_str_strip_bang2(str, 0);
-#else
-    VALUE l = rb_str_lstrip_bang(str);
-    VALUE r = rb_str_rstrip_bang(str);
-
-    if (NIL_P(l) && NIL_P(r)) return Qnil;
-    return str;
-#endif
 }
 
 
@@ -7284,14 +4248,10 @@
 static VALUE
 scan_once(VALUE str, VALUE pat, long *start, long strlen, bool pat_is_string)
 {
-#if !WITH_OBJC
-    rb_encoding *enc;
-#endif
     VALUE result, match;
     struct re_registers *regs;
     long i;
 
-#if WITH_OBJC
     if (pat_is_string) {
 	/* XXX this is sometimes slower than the regexp search, especially for
 	 * long pattern strings 
@@ -7314,11 +4274,7 @@
 	}
 	return result;
     }
-#endif
 
-#if !WITH_OBJC
-    enc = STR_ENC_GET(str);
-#endif
     if (rb_reg_search(pat, str, *start, 0) >= 0) {
 	match = rb_backref_get();
 	regs = RMATCH_REGS(match);
@@ -7326,12 +4282,6 @@
 	    /*
 	     * Always consume at least one character of the input string
 	     */
-#if !WITH_OBJC
-	    if (RSTRING_BYTELEN(str) > END(0))
-		*start = END(0)+rb_enc_mbclen(RSTRING_BYTEPTR(str)+END(0),
-					      RSTRING_END(str), enc);
-	    else
-#endif
 		*start = END(0)+1;
 	}
 	else {
@@ -7409,9 +4359,6 @@
 	match = rb_backref_get();
 	rb_match_busy(match);
 	rb_yield(result);
-#if !WITH_OBJC
-	str_mod_check(str, p, len);
-#endif
 	rb_backref_set(match);	/* restore $~ value */
     }
     rb_backref_set(match);
@@ -7496,8 +4443,6 @@
     if (s == NULL)
 	s = "";
     result = rb_str_new2(crypt(s, RSTRING_BYTEPTR(salt)));
-    OBJ_INFECT(result, str);
-    OBJ_INFECT(result, salt);
     return result;
 }
 
@@ -7525,11 +4470,7 @@
 VALUE
 rb_str_intern(VALUE s)
 {
-#if WITH_OBJC
     VALUE str = s;
-#else
-    VALUE str = RB_GC_GUARD(s);
-#endif
     ID id;
 
     if (OBJ_TAINTED(str) && rb_safe_level() >= 1) {
@@ -7551,16 +4492,9 @@
 VALUE
 rb_str_ord(VALUE s)
 {
-#if WITH_OBJC
     if (CFStringGetLength((CFStringRef)s) == 0)
 	rb_raise(rb_eArgError, "empty string");
     return INT2NUM(CFStringGetCharacterAtIndex((CFStringRef)s, 0));
-#else
-    int c;
-
-    c = rb_enc_codepoint(RSTRING_BYTEPTR(s), RSTRING_END(s), STR_ENC_GET(s));
-    return INT2NUM(c);
-#endif
 }
 
 /*
@@ -7624,7 +4558,6 @@
     }
 }
 
-#if WITH_OBJC
 static inline void
 rb_str_justify0(VALUE str, VALUE pad, long width, long padwidth, long index)
 {
@@ -7641,12 +4574,10 @@
     }
     while (width > 0);
 }
-#endif
 
 static VALUE
 rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
 {
-#if WITH_OBJC
     VALUE w, pad;
     long n, width, padwidth;
 
@@ -7683,82 +4614,6 @@
     }
 
     return str;
-#else
-    rb_encoding *enc;
-    VALUE w;
-    long width, len, flen = 1, fclen = 1;
-    VALUE res;
-    char *p, *f = " ";
-    long n, llen, rlen;
-    volatile VALUE pad;
-    int singlebyte = 1;
-
-    rb_scan_args(argc, argv, "11", &w, &pad);
-    enc = STR_ENC_GET(str);
-    width = NUM2LONG(w);
-    if (argc == 2) {
-	StringValue(pad);
-	enc = rb_enc_check(str, pad);
-	f = RSTRING_BYTEPTR(pad);
-	flen = RSTRING_BYTELEN(pad);
-	fclen = str_strlen(pad, enc);
-	singlebyte = single_byte_optimizable(pad);
-	if (flen == 0 || fclen == 0) {
-	    rb_raise(rb_eArgError, "zero width padding");
-	}
-    }
-    len = str_strlen(str, enc);
-    if (width < 0 || len >= width) return rb_str_dup(str);
-    n = width - len;
-    llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
-    rlen = n - llen;
-    res = rb_str_new5(str, 0, RSTRING_BYTELEN(str)+n*flen/fclen+2);
-    p = RSTRING_BYTEPTR(res);
-    while (llen) {
-	if (flen <= 1) {
-	    *p++ = *f;
-	    llen--;
-	}
-	else if (llen > fclen) {
-	    memcpy(p,f,flen);
-	    p += flen;
-	    llen -= fclen;
-	}
-	else {
-	    char *fp = str_nth(f, f+flen, llen, enc, singlebyte);
-	    n = fp - f;
-	    memcpy(p,f,n);
-	    p+=n;
-	    break;
-	}
-    }
-    memcpy(p, RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str));
-    p+=RSTRING_BYTELEN(str);
-    while (rlen) {
-	if (flen <= 1) {
-	    *p++ = *f;
-	    rlen--;
-	}
-	else if (rlen > fclen) {
-	    memcpy(p,f,flen);
-	    p += flen;
-	    rlen -= fclen;
-	}
-	else {
-	    char *fp = str_nth(f, f+flen, rlen, enc, singlebyte);
-	    n = fp - f;
-	    memcpy(p,f,n);
-	    p+=n;
-	    break;
-	}
-    }
-    *p = '\0';
-    STR_SET_LEN(res, p-RSTRING_BYTEPTR(res));
-    OBJ_INFECT(res, str);
-    if (!NIL_P(pad)) OBJ_INFECT(res, pad);
-    rb_enc_associate(res, enc);
-    return res;
-#endif
 }
 
 
@@ -7935,15 +4790,8 @@
     for (i=0; i<argc; i++) {
 	VALUE tmp = rb_check_string_type(argv[i]);
 	if (NIL_P(tmp)) continue;
-#if WITH_OBJC
 	if (CFStringHasPrefix((CFStringRef)str, (CFStringRef)tmp))
 	    return Qtrue;
-#else
-	rb_enc_check(str, tmp);
-	if (RSTRING_BYTELEN(str) < RSTRING_BYTELEN(tmp)) continue;
-	if (memcmp(RSTRING_BYTEPTR(str), RSTRING_BYTEPTR(tmp), RSTRING_BYTELEN(tmp)) == 0)
-	    return Qtrue;
-#endif
     }
     return Qfalse;
 }
@@ -7959,27 +4807,12 @@
 rb_str_end_with(int argc, VALUE *argv, VALUE str)
 {
     int i;
-#if !WITH_OBJC
-    char *p, *s;
-    rb_encoding *enc;
-#endif
 
     for (i=0; i<argc; i++) {
 	VALUE tmp = rb_check_string_type(argv[i]);
 	if (NIL_P(tmp)) continue;
-#if WITH_OBJC
 	if (CFStringHasSuffix((CFStringRef)str, (CFStringRef)tmp))
 	    return Qtrue;
-#else
-	enc = rb_enc_check(str, tmp);
-	if (RSTRING_BYTELEN(str) < RSTRING_BYTELEN(tmp)) continue;
-	p = RSTRING_BYTEPTR(str);
-	s = p + RSTRING_BYTELEN(str) - RSTRING_BYTELEN(tmp);
-	if (rb_enc_left_char_head(p, s, enc) != s)
-	    continue;
-	if (memcmp(s, RSTRING_BYTEPTR(tmp), RSTRING_BYTELEN(tmp)) == 0)
-	    return Qtrue;
-#endif
     }
     return Qfalse;
 }
@@ -8005,8 +4838,7 @@
 rb_str_force_encoding(VALUE str, VALUE enc)
 {
     str_modifiable(str);
-#if WITH_OBJC
-# if 0
+#if 0
     CFDataRef data = rb_str_cfdata2(str);
     if (data != NULL) {
 	CFStringRef substr;
@@ -8023,9 +4855,6 @@
 	    rb_str_cfdata_set(str, NULL);
 	}
     }
-# endif
-#else
-    rb_enc_associate(str, rb_to_encoding(enc));
 #endif
     return str;
 }
@@ -8044,13 +4873,7 @@
 static VALUE
 rb_str_valid_encoding_p(VALUE str)
 {
-#if WITH_OBJC
     rb_notimplement();
-#else
-    int cr = rb_enc_str_coderange(str);
-
-    return cr == ENC_CODERANGE_BROKEN ? Qfalse : Qtrue;
-#endif
 }
 
 /*
@@ -8066,16 +4889,9 @@
 static VALUE
 rb_str_is_ascii_only_p(VALUE str)
 {
-#if WITH_OBJC
     rb_notimplement();
-#else
-    int cr = rb_enc_str_coderange(str);
-
-    return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
-#endif
 }
 
-#if WITH_OBJC
 static VALUE
 rb_str_transform_bang(VALUE str, VALUE transform_name)
 {
@@ -8104,8 +4920,6 @@
     return str;
 }
 
-#endif
-
 /**********************************************************************
  * Document-class: Symbol
  *
@@ -8169,38 +4983,16 @@
 static VALUE
 sym_inspect(VALUE sym)
 {
-#if WITH_OBJC
-    ID id = SYM2ID(sym);
     VALUE str;
 
-    sym = rb_id2str(id);
+#if 0
     if (!rb_enc_symname_p(RSTRING_PTR(sym), NULL)) {
 	sym = rb_str_inspect(sym);
     }
-    str = rb_str_new(":", 1);
+#endif
+    str = rb_str_new2(":");
     rb_str_buf_append(str, sym);
     return str;
-#else
-    VALUE str, klass = Qundef;
-    ID id = SYM2ID(sym);
-    rb_encoding *enc;
-
-    sym = rb_id2str(id);
-    enc = STR_ENC_GET(sym);
-    str = rb_enc_str_new(0, RSTRING_BYTELEN(sym)+1, enc);
-    RSTRING_BYTEPTR(str)[0] = ':';
-    memcpy(RSTRING_BYTEPTR(str)+1, RSTRING_BYTEPTR(sym), RSTRING_BYTELEN(sym));
-    if (RSTRING_BYTELEN(sym) != strlen(RSTRING_BYTEPTR(sym)) ||
-	!rb_enc_symname_p(RSTRING_BYTEPTR(sym), enc)) {	
-	str = rb_str_inspect(str);
-	strncpy(RSTRING_BYTEPTR(str), ":\"", 2);
-    }
-    if (klass != Qundef) {
-	rb_str_cat2(str, "/");
-	rb_str_append(str, rb_inspect(klass));
-    }
-    return str;
-#endif
 }
 
 
@@ -8218,9 +5010,7 @@
 VALUE
 rb_sym_to_s(VALUE sym)
 {
-    ID id = SYM2ID(sym);
-
-    return str_new3(rb_cString, rb_id2str(id));
+    return rb_str_new2(RSYMBOL(sym)->str);
 }
 
 
@@ -8267,92 +5057,6 @@
     return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
 }
 
-
-static VALUE
-sym_succ(VALUE sym)
-{
-    return rb_str_intern(rb_str_succ(rb_sym_to_s(sym)));
-}
-
-static VALUE
-sym_cmp(VALUE sym, VALUE other)
-{
-    if (!SYMBOL_P(other)) {
-	return Qnil;
-    }
-    return rb_str_cmp_m(rb_sym_to_s(sym), rb_sym_to_s(other));
-}
-
-static VALUE
-sym_casecmp(VALUE sym, VALUE other)
-{
-    if (!SYMBOL_P(other)) {
-	return Qnil;
-    }
-    return rb_str_casecmp(rb_sym_to_s(sym), rb_sym_to_s(other));
-}
-
-static VALUE
-sym_match(VALUE sym, VALUE other)
-{
-    return rb_str_match(rb_sym_to_s(sym), other);
-}
-
-static VALUE
-sym_eqq(VALUE sym, VALUE other)
-{
-    if (sym == other) return Qtrue;
-    return rb_str_equal(rb_sym_to_s(sym), other);
-}
-
-static VALUE
-sym_aref(int argc, VALUE *argv, VALUE sym)
-{
-    return rb_str_aref_m(argc, argv, rb_sym_to_s(sym));
-}
-
-static VALUE
-sym_length(VALUE sym)
-{
-    return rb_str_length(rb_id2str(SYM2ID(sym)));
-}
-
-static VALUE
-sym_empty(VALUE sym)
-{
-    return rb_str_empty(rb_id2str(SYM2ID(sym)));
-}
-
-static VALUE
-sym_upcase(VALUE sym)
-{
-    return rb_str_intern(rb_str_upcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_downcase(VALUE sym)
-{
-    return rb_str_intern(rb_str_downcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_capitalize(VALUE sym)
-{
-    return rb_str_intern(rb_str_capitalize(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_swapcase(VALUE sym)
-{
-    return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_encoding(VALUE sym)
-{
-    return rb_obj_encoding(rb_id2str(SYM2ID(sym)));
-}
-
 ID
 rb_to_id(VALUE name)
 {
@@ -8364,7 +5068,7 @@
 	tmp = rb_check_string_type(name);
 	if (NIL_P(tmp)) {
 	    rb_raise(rb_eTypeError, "%s is not a symbol",
-		     RSTRING_BYTEPTR(rb_inspect(name)));
+		     RSTRING_PTR(rb_inspect(name)));
 	}
 	name = tmp;
 	/* fall through */
@@ -8377,12 +5081,9 @@
     return id;
 }
 
-#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 +5091,7 @@
 bool
 rb_objc_str_is_pure(VALUE str)
 {
-    return *(Class *)str == NSCFSTRING();
+    return *(Class *)str == (Class)rb_cCFString;
 }
 
 static CFIndex
@@ -8472,9 +5173,6 @@
     return flag;
 }
 
-void
-rb_objc_install_string_primitives(Class klass)
-{
 #define INSTALL_METHOD(selname, imp)                            \
     do {                                                        \
         SEL sel = sel_registerName(selname);                    \
@@ -8485,6 +5183,9 @@
     }                                                           \
     while(0)
 
+void
+rb_objc_install_string_primitives(Class klass)
+{
     INSTALL_METHOD("length", imp_rb_str_length);
     INSTALL_METHOD("characterAtIndex:", imp_rb_str_characterAtIndex);
     INSTALL_METHOD("getCharacters:range:", imp_rb_str_getCharactersRange);
@@ -8495,11 +5196,51 @@
     INSTALL_METHOD("_fastestEncodingInCFStringEncoding",
 	imp_rb_str_fastestEncodingInCFStringEncoding);
     INSTALL_METHOD("isEqual:", imp_rb_str_isEqual);
+    
+    rb_define_alloc_func((VALUE)klass, str_alloc);
+}
 
-#undef INSTALL_METHOD
+static CFIndex
+imp_rb_symbol_length(void *rcv, SEL sel)
+{
+    return RSYMBOL(rcv)->len;
 }
-#endif
 
+static UniChar
+imp_rb_symbol_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
+{
+    if (idx < 0 || idx > RSYMBOL(rcv)->len)
+	rb_bug("[Symbol characterAtIndex:] out of bounds");
+    return RSYMBOL(rcv)->str[idx];
+}
+
+static void
+imp_rb_symbol_getCharactersRange(void *rcv, SEL sel, UniChar *buffer, 
+			      CFRange range)
+{
+    int i;
+
+    if (range.location + range.length > RSYMBOL(rcv)->len)
+	rb_bug("[Symbol getCharacters:range:] out of bounds");
+
+    for (i = range.location; i < range.length; i++) {
+	*buffer = RSYMBOL(rcv)->str[i];
+	buffer++;
+    }
+}
+
+static void
+install_symbol_primitives(void)
+{
+    Class klass = (Class)rb_cSymbol;
+
+    INSTALL_METHOD("length", imp_rb_symbol_length);
+    INSTALL_METHOD("characterAtIndex:", imp_rb_symbol_characterAtIndex);
+    INSTALL_METHOD("getCharacters:range:", imp_rb_symbol_getCharactersRange);
+}
+
+#undef INSTALL_METHOD
+
 /*
  *  A <code>String</code> object holds and manipulates an arbitrary sequence of
  *  bytes, typically representing characters. String objects may be created
@@ -8516,29 +5257,21 @@
 void
 Init_String(void)
 {
-#if WITH_OBJC
-    rb_cCFString = rb_objc_import_class((Class)objc_getClass("NSCFString"));
-    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_cCFString = (VALUE)objc_getClass("NSCFString");
+    rb_cString = rb_cNSString = (VALUE)objc_getClass("NSString");
+    rb_cNSMutableString = (VALUE)objc_getClass("NSMutableString");
+    rb_const_set(rb_cObject, rb_intern("String"), rb_cNSMutableString);
+    rb_set_class_path(rb_cNSMutableString, rb_cObject, "NSMutableString");
     rb_define_method(rb_cString, "__bytestring__?", rb_str_bytestring_m, 0);
-#else
-    rb_cString  = rb_define_class("String", rb_cObject);
-#endif
+
     rb_include_module(rb_cString, rb_mComparable);
-    rb_define_alloc_func(rb_cString, str_alloc);
+
     rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
     rb_define_method(rb_cString, "initialize", rb_str_init, -1);
     rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
     rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
     rb_define_method(rb_cString, "==", rb_str_equal, 1);
     rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
-#if 1 
-    /* FIXME remove me once we use the objc dispatch for everything */
-    rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
-#endif
     rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
     rb_define_method(rb_cString, "+", rb_str_plus, 1);
     rb_define_method(rb_cString, "*", rb_str_times, 1);
@@ -8546,12 +5279,6 @@
     rb_define_method(rb_cString, "[]", rb_str_aref_m, -1);
     rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1);
     rb_define_method(rb_cString, "insert", rb_str_insert, 2);
-#if !WITH_OBJC
-    /* This method cannot be defined because it exists in 
-     * NSString already. 
-     */
-    rb_define_method(rb_cString, "length", rb_str_length, 0);
-#endif
     rb_define_method(rb_cString, "size", rb_str_length, 0);
     rb_define_method(rb_cString, "bytesize", rb_str_bytesize, 0);
     rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
@@ -8656,49 +5383,34 @@
     rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);
     rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);
 
-#if WITH_OBJC
     rb_define_method(rb_cString, "transform", rb_str_transform, 1);
     rb_define_method(rb_cString, "transform!", rb_str_transform_bang, 1);
-#endif
 
+    /* to return mutable copies */
+    rb_define_method(rb_cString, "dup", rb_str_dup, 0);
+    rb_define_method(rb_cString, "clone", rb_str_clone, 0);
+
     id_to_s = rb_intern("to_s");
 
     rb_fs = Qnil;
     rb_define_variable("$;", &rb_fs);
     rb_define_variable("$-F", &rb_fs);
 
-    rb_cSymbol = rb_define_class("Symbol", rb_cObject);
-    rb_include_module(rb_cSymbol, rb_mComparable);
+    /* rb_cSymbol is defined in parse.y because it's needed early */
+    rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
     rb_undef_alloc_func(rb_cSymbol);
     rb_undef_method(CLASS_OF(rb_cSymbol), "new");
     rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
 
     rb_define_method(rb_cSymbol, "==", sym_equal, 1);
     rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
+    rb_define_method(rb_cSymbol, "description", sym_inspect, 0);
+    rb_define_method(rb_cSymbol, "dup", rb_obj_dup, 0);
+    rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
     rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0);
     rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0);
     rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
     rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
-    rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
-    rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
-    rb_define_method(rb_cSymbol, "next", sym_succ, 0);
 
-    rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
-    rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
-    rb_define_method(rb_cSymbol, "=~", sym_match, 1);
-    rb_define_method(rb_cSymbol, "===", sym_eqq, 1);
-
-    rb_define_method(rb_cSymbol, "[]", sym_aref, -1);
-    rb_define_method(rb_cSymbol, "slice", sym_aref, -1);
-    rb_define_method(rb_cSymbol, "length", sym_length, 0);
-    rb_define_method(rb_cSymbol, "size", sym_length, 0);
-    rb_define_method(rb_cSymbol, "empty?", sym_empty, 0);
-    rb_define_method(rb_cSymbol, "match", sym_match, 1);
-
-    rb_define_method(rb_cSymbol, "upcase", sym_upcase, 0);
-    rb_define_method(rb_cSymbol, "downcase", sym_downcase, 0);
-    rb_define_method(rb_cSymbol, "capitalize", sym_capitalize, 0);
-    rb_define_method(rb_cSymbol, "swapcase", sym_swapcase, 0);
-
-    rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
+    install_symbol_primitives();
 }

Modified: MacRuby/trunk/struct.c
===================================================================
--- MacRuby/trunk/struct.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/struct.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -181,7 +181,9 @@
     OBJ_FREEZE(members);
     if (NIL_P(name)) {
 	nstr = rb_class_new(klass);
+#if !WITH_OBJC
 	rb_make_metaclass(nstr, RBASIC(klass)->klass);
+#endif
 	rb_class_inherited(klass, nstr);
     }
     else {

Modified: MacRuby/trunk/thread.c
===================================================================
--- MacRuby/trunk/thread.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/thread.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/variable.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -15,14 +15,53 @@
 #include "ruby/node.h"
 #include "ruby/st.h"
 #include "ruby/util.h"
+#include "debug.h"
+#include "id.h"
 
 void rb_vm_change_state(void);
 st_table *rb_global_tbl;
 st_table *rb_class_tbl;
+static ID autoload, classpath, tmp_classpath;
 #if WITH_OBJC
-st_table *rb_objc_class_tbl;
+static const void *
+retain_cb(CFAllocatorRef allocator, const void *v)
+{
+    rb_objc_retain(v);
+    return v;
+}
+
+static void
+release_cb(CFAllocatorRef allocator, const void *v)
+{
+    rb_objc_release(v);
+}
+
+static void
+ivar_dict_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
+{
+    CFIndex i, count;
+    const void **keys;
+    const void **values;
+
+    count = CFDictionaryGetCount((CFDictionaryRef)hash);
+    if (count == 0)
+	return;
+
+    keys = (const void **)alloca(sizeof(void *) * count);
+    values = (const void **)alloca(sizeof(void *) * count);
+
+    CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
+
+    for (i = 0; i < count; i++) {
+	if ((*func)(keys[i], values[i], farg) != ST_CONTINUE)
+	    break;
+    }
+}
+
+static CFDictionaryValueCallBacks rb_cfdictionary_value_cb = {
+    0, retain_cb, release_cb, NULL, NULL
+};
 #endif
-static ID autoload, classpath, tmp_classpath;
 
 void
 Init_var_tables(void)
@@ -31,10 +70,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 +91,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 +125,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 +147,18 @@
 	    arg.klass = res->klass;
 	    arg.track = value;
 	    arg.prev = res;
+#if WITH_OBJC
+	    ivar_dict_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,20 +176,43 @@
     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) {
+	ivar_dict_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;
     }
+#if WITH_OBJC
+    if (!RCLASS_RUBY(klass)) {
+	VALUE name = rb_str_new2(class_getName((Class)klass));
+	iv_dict = rb_class_ivar_dict_or_create(klass);
+	CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)name);
+	CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
+	return name;
+    }
+#endif
     return Qnil;
 }
 
@@ -149,6 +222,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(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 +252,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 +284,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 {
@@ -231,9 +326,6 @@
     }
     OBJ_FREEZE(str);
     rb_ivar_set(klass, classpath, str);
-#if WITH_OBJC
-    rb_objc_rename_class(klass, RSTRING_PTR(str));
-#endif
 }
 
 VALUE
@@ -313,10 +405,13 @@
     struct trace_var *trace;
 };
 
+#if !WITH_OBJC
+/* defined in vm_core.h, imported by debug.h */
 struct global_entry {
     struct global_variable *var;
     ID id;
 };
+#endif
 
 static VALUE undef_getter(ID id);
 static void  undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
@@ -390,7 +485,7 @@
 static void
 val_setter(VALUE val, ID id, void *data, struct global_variable *var)
 {
-    var->data = (void*)val;
+    GC_WB(&var->data, (void*)val);
 }
 
 static void
@@ -786,8 +881,6 @@
 
 #if WITH_OBJC
 static CFMutableDictionaryRef generic_iv_dict = NULL;
-const void * rb_cfdictionary_retain_cb(CFAllocatorRef, const void *);
-void rb_cfdictionary_release_cb(CFAllocatorRef, const void *);
 #else
 static int special_generic_ivar = 0;
 static st_table *generic_iv_tbl;
@@ -854,13 +947,7 @@
 	    rb_error_frozen("object");
     }
     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);
+	generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
 	obj_dict = NULL;
     }
     else {
@@ -868,13 +955,7 @@
 	    (CFDictionaryRef)generic_iv_dict, (const void *)obj);
     }
     if (obj_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;
-
-	obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+	obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
 	CFDictionarySetValue(generic_iv_dict, (const void *)obj, 
 	    (const void *)obj_dict);
 	CFMakeCollectable(obj_dict);
@@ -1078,21 +1159,98 @@
 #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) {
+	    generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_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) {
+	dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_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;
-
-#if WITH_OBJC
-    if (!rb_special_const_p(obj) && rb_objc_is_non_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,14 +1258,30 @@
         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;
+#if WITH_OBJC
+      case T_NATIVE:
+	return generic_ivar_get(obj, id, warn);
+#endif
       default:
 	if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
 	    return generic_ivar_get(obj, id, warn);
@@ -1134,23 +1308,90 @@
 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)) {
-	rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
-	generic_ivar_set(obj, id, val);
-	return val;
-    }
-#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;
+			tbl = CFDictionaryCreateMutable(NULL, 0, NULL, 
+				&rb_cfdictionary_value_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);
+
+			CFDictionarySetValue(tbl, (const void *)id, 
+				(const void *)val);
+
+			xfree(ROBJECT(obj)->ivars.as.ary);
+			GC_WB(&ROBJECT(obj)->ivars.as.tbl, tbl);
+			CFMakeCollectable(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 +1441,29 @@
             }
         }
         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
+#if WITH_OBJC
+      case T_NATIVE:
+	rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
+	generic_ivar_set(obj, id, val);
+	break;
+#endif
       default:
 	generic_ivar_set(obj, id, val);
 	FL_SET(obj, FL_EXIVAR);
@@ -1220,28 +1476,63 @@
 rb_ivar_defined(VALUE obj, ID id)
 {
     VALUE val;
+#if !WITH_OBJC
     struct st_table *iv_index_tbl;
     st_data_t index;
-#if WITH_OBJC
-    if (!rb_special_const_p(obj) && rb_objc_is_non_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
+#if WITH_OBJC
+      case T_NATIVE:
+	return generic_ivar_defined(obj, id);
+#endif
       default:
 	if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
 	    return generic_ivar_defined(obj, id);
@@ -1256,6 +1547,7 @@
     st_data_t arg;
 };
 
+#if !WITH_OBJC
 static int
 obj_ivar_i(ID key, VALUE index, struct obj_ivar_tag *data)
 {
@@ -1284,23 +1576,53 @@
 
     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))
-	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)
+	      ivar_dict_foreach((VALUE)iv_dict, func, arg);
+      }
+#else
 	if (RCLASS_IV_TBL(obj)) {
 	    st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
 	}
+#endif
 	return;
+#if WITH_OBJC
+      case T_NATIVE:
+	goto generic;
+#endif
     }
     if (!FL_TEST(obj, FL_EXIVAR) && !rb_special_const_p(obj))
 	return;
@@ -1390,8 +1712,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 +1726,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 +1762,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 +1849,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 +1878,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 +1915,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 +1933,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 +1965,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 +1994,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 +2008,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 +2036,13 @@
     tmp = klass;
   retry:
     while (RTEST(tmp)) {
+#if WITH_OBJC
+	CFDictionaryRef iv_dict;
+	while ((iv_dict = rb_class_ivar_dict(tmp)) != NULL
+	       && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value)) {
+#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;
@@ -1643,6 +2057,17 @@
 	    return value;
 	}
 	if (!recurse && klass != rb_cObject) break;
+#if WITH_OBJC
+	VALUE inc_mods = rb_attr_get(tmp, idIncludedModules);
+	if (inc_mods != Qnil) {
+	    int i, count = RARRAY_LEN(inc_mods);
+	    for (i = 0; i < count; i++) {
+		iv_dict = rb_class_ivar_dict(RARRAY_AT(inc_mods, i));
+		if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value))
+		    return rb_objc_resolve_const_value(value, klass, id);
+	    }
+	}
+#endif
 	tmp = RCLASS_SUPER(tmp);
     }
     if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
@@ -1659,11 +2084,8 @@
      */
     {
 	Class k = (Class)objc_getClass(rb_id2name(id));
-	if (k != NULL) {
-	    tmp = rb_objc_import_class(k);
-	    if (!NIL_P(tmp))
-		return tmp;
-	}
+	if (k != NULL)
+	    return (VALUE)k;
     }
 #endif
 
@@ -1712,7 +2134,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 +2174,15 @@
     if (!tbl) {
 	tbl = st_init_numtable();
     }
+#if WITH_OBJC
+    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+    if (iv_dict != NULL)
+	ivar_dict_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 +2265,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 +2320,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 +2343,15 @@
 	}
     }
 
-    if(isconst){
+    if (isconst) {
 	rb_vm_change_state();
     }
+#if WITH_OBJC
+    DLOG("CONS", "%s::%s <- %p", class_getName((Class)klass), rb_id2name(id), (void *)val);
+    CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
+#else
     st_insert(RCLASS_IV_TBL(klass), id, val);
+#endif
 }
 
 void
@@ -1938,11 +2392,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 +2418,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,8 +2429,15 @@
 rb_cvar_set(VALUE klass, ID id, VALUE val)
 {
     VALUE tmp, front = 0, target = 0;
+#if WITH_OBJC
+    CFMutableDictionaryRef iv_dict;
+#endif
 
     tmp = klass;
+#if WITH_OBJC
+    if (!RCLASS_META(klass)) 
+	tmp = klass = *(VALUE *)klass;
+#endif
     CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
     if (target) {
 	if (front && target != front) {
@@ -1981,8 +2448,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,8 +2467,15 @@
 rb_cvar_get(VALUE klass, ID id)
 {
     VALUE value, tmp, front = 0, target = 0;
+#if WITH_OBJC
+    CFMutableDictionaryRef iv_dict;
+#endif
 
     tmp = klass;
+#if WITH_OBJC
+    if (!RCLASS_META(klass)) 
+	tmp = klass = *(VALUE *)klass;
+#endif
     CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
     if (!target) {
 	rb_name_error(id,"uninitialized class variable %s in %s",
@@ -2012,7 +2490,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,7 +2503,14 @@
 VALUE
 rb_cvar_defined(VALUE klass, ID id)
 {
+#if WITH_OBJC
+    CFMutableDictionaryRef iv_dict;
+#endif
     if (!klass) return Qfalse;
+#if WITH_OBJC
+    if (!RCLASS_META(klass)) 
+	klass = *(VALUE *)klass;
+#endif
     CVAR_LOOKUP(0,return Qtrue);
     return Qfalse;
 }
@@ -2090,9 +2579,15 @@
 {
     VALUE ary = rb_ary_new();
 
+#if WITH_OBJC
+    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+    if (iv_dict != NULL)
+	ivar_dict_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 +2624,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/trunk/version.c
===================================================================
--- MacRuby/trunk/version.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/version.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -23,6 +23,7 @@
 const int ruby_patchlevel = RUBY_PATCHLEVEL;
 const char ruby_description[] = RUBY_DESCRIPTION;
 const char ruby_copyright[] = RUBY_COPYRIGHT;
+const char ruby_engine[] = RUBY_ENGINE;
 
 void
 Init_version(void)
@@ -34,6 +35,7 @@
     rb_define_global_const("RUBY_REVISION", INT2FIX(RUBY_REVISION));
     rb_define_global_const("RUBY_DESCRIPTION", MKSTR(description));
     rb_define_global_const("RUBY_COPYRIGHT", MKSTR(copyright));
+    rb_define_global_const("RUBY_ENGINE", MKSTR(engine));
 #if WITH_OBJC
     rb_define_global_const("MACRUBY_VERSION", rb_float_new(MACRUBY_VERSION));
 #endif

Modified: MacRuby/trunk/version.h
===================================================================
--- MacRuby/trunk/version.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/version.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -46,9 +46,9 @@
 #endif
 
 #if WITH_OBJC
-# define RUBY_IMPL_NAME "MacRuby"
+# define RUBY_ENGINE "macruby"
 #else
-# define RUBY_IMPL_NAME "ruby"
+# define RUBY_ENGINE "ruby"
 #endif
 
 #if WITH_OBJC

Modified: MacRuby/trunk/vm.c
===================================================================
--- MacRuby/trunk/vm.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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"
@@ -95,7 +91,7 @@
 		  th->cfp->sp, block->lfp, iseq->local_size);
 
     if (cref) {
-	th->cfp->dfp[-1] = (VALUE)cref;
+	GC_WB(&th->cfp->dfp[-1], (VALUE)cref);
     }
 }
 
@@ -250,8 +246,8 @@
 
     env->env_size = local_size + 1 + 2;
     env->local_size = local_size;
-    env->env = ALLOC_N(VALUE, env->env_size);
-    env->prev_envval = penvval;
+    GC_WB(&env->env, ALLOC_N(VALUE, env->env_size));
+    GC_WB(&env->prev_envval, penvval);
 
     for (i = 0; i <= local_size; i++) {
 	env->env[i] = envptr[-local_size + i];
@@ -857,19 +853,26 @@
 static void
 rb_vm_check_redefinition_opt_method(const NODE *node)
 {
+#if !WITH_OBJC
     VALUE bop;
 
-    if (st_lookup(vm_opt_method_table, (st_data_t)node, &bop)) {
+    if (vm_opt_method_table != NULL 
+	&& st_lookup(vm_opt_method_table, (st_data_t)node, &bop)) {
 	ruby_vm_redefined_flag |= bop;
     }
+#endif
 }
 
 static void
 add_opt_method(VALUE klass, ID mid, VALUE bop)
 {
     NODE *node;
+#if WITH_OBJC
+    if ((node = rb_method_node(klass, mid)) != NULL) {
+#else
     if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&node) &&
 	nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
+#endif
 	st_insert(vm_opt_method_table, (st_data_t)node, (st_data_t)bop);
     }
     else {
@@ -899,9 +902,7 @@
     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
+#if !WITH_OBJC
     OP(Length, LENGTH), (C(Array), C(String), C(Hash));
 #endif
     OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
@@ -1724,11 +1725,12 @@
 	rb_iseq_t *iseq;
 
 	/* create vm object */
-	vm->self = Data_Wrap_Struct(rb_cVM, rb_vm_mark, vm_free, vm);
+	GC_WB(&vm->self, Data_Wrap_Struct(rb_cVM, rb_vm_mark, vm_free, vm));
 
 	/* create main thread */
-	th_self = th->self = Data_Wrap_Struct(rb_cThread, rb_thread_mark,
+	th_self = Data_Wrap_Struct(rb_cThread, rb_thread_mark,
 					      thread_free, th);
+	GC_WB(&th->self, th_self);
 	vm->main_thread = th;
 	vm->running_thread = th;
 	th->vm = vm;
@@ -1736,10 +1738,11 @@
 	th->top_self = rb_vm_top_self();
 	rb_thread_set_current(th);
 
-	vm->living_threads = st_init_numtable();
+	GC_WB(&vm->living_threads, st_init_numtable());
 	st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
 
 	rb_register_mark_object(iseqval);
+	rb_objc_retain((void *)iseqval);	
 	GetISeqPtr(iseqval, iseq);
 	th->cfp->iseq = iseq;
 	th->cfp->pc = iseq->iseq_encoded;

Modified: MacRuby/trunk/vm_core.h
===================================================================
--- MacRuby/trunk/vm_core.h	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_core.h	2008-08-21 06:13:14 UTC (rev 459)
@@ -543,6 +543,35 @@
 #define ic_vmstat u3.cnt
 typedef NODE *IC;
 
+#if WITH_OBJC
+# include "bs.h"
+struct rb_method_cache {
+    unsigned int flags;
+#define RB_MCACHE_RCALL_FLAG		0x10
+#define RB_MCACHE_OCALL_FLAG		0x20
+#define RB_MCACHE_CFUNC_FLAG		0x40
+#define RB_MCACHE_NOT_CFUNC_FLAG	0x100
+    union {
+	struct {
+	    SEL sel;
+	    VALUE klass;
+	    NODE *node;
+	} rcall;
+	struct {
+	    SEL sel;
+	    VALUE klass;
+	    IMP imp;
+	    Method method;
+	    bs_element_method_t *bs_method;
+	} ocall;
+	struct {
+	    bs_element_function_t *bs_func;
+	    void *sym;
+	} cfunc;
+    } as;
+};
+#endif
+
 void rb_vm_change_state(void);
 
 typedef VALUE CDHASH;

Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_eval.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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,56 @@
     NODE *body, *method;
     int noex;
     ID id = mid;
+#if !WITH_OBJC
     struct cache_entry *ent;
+#endif
     rb_thread_t *th = GET_THREAD();
-#if WITH_OBJC
-    unsigned redo = 0;
-#endif
 
-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;
+
+    if (argc > 0 && mid != ID_ALLOCATOR) {
+	const char *mid_str;
+	char buf[100];
+	size_t len;
+
+	mid_str = rb_id2name(mid);
+	len = strlen(mid_str);
+	if (mid_str[len - 1] != ':') {
+	    snprintf(buf, sizeof buf, "%s:", mid_str);
+	    mid = rb_intern(buf);
+	}
+    }
+
+    method = rb_objc_method_node(klass, mid, &imp, &sel);    
+
+    if (imp != NULL && method == NULL)
+	return rb_objc_call(recv, sel, argc, (VALUE *)argv);
+
+    DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)sel, method);
+    
+    if (method == NULL) {
+	int missing_scope = scope == 2 ? NOEX_VCALL : scope == 3 ? NOEX_SUPER : NOEX_VCALL;
+	return method_missing(recv, mid, argc, argv, missing_scope);
+    }
+    else {
+	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);
 	}
@@ -238,15 +246,14 @@
 	body = method->nd_body;
     }
     else {
-	REDO_PERHAPS();
 	if (scope == 3) {
 	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
 	}
 	return method_missing(recv, mid, argc, argv,
 			      scope == 2 ? NOEX_VCALL : 0);
     }
+#endif
     
-
     if (mid != missing) {
 	/* receiver specified form for private method */
 	if (UNLIKELY(noex)) {
@@ -1334,11 +1341,18 @@
 
     rb_define_global_function("loop", rb_f_loop, 0);
 
+#if WITH_OBJC
+    rb_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
+    rb_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
+    rb_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
+    rb_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
+#else
     rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
     rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
     rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
+    rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
+#endif
 
-    rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
     rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
 

Modified: MacRuby/trunk/vm_insnhelper.c
===================================================================
--- MacRuby/trunk/vm_insnhelper.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_insnhelper.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -13,6 +13,10 @@
 
 #include <math.h>
 
+#if WITH_OBJC
+# include <dlfcn.h>
+#endif
+
 /* control stack frame */
 
 
@@ -371,13 +375,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");
@@ -485,15 +483,220 @@
     }
 }
 
+static inline void
+vm_send_optimize(rb_control_frame_t * const reg_cfp, NODE ** const mn,
+		 rb_num_t * const flag, rb_num_t * const num,
+		 ID * const id, const VALUE klass)
+{
+    if (*mn && nd_type((*mn)->nd_body) == NODE_CFUNC) {
+	NODE *node = (*mn)->nd_body;
+	extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
+
+	if (node->nd_cfnc == rb_f_send) {
+	    int i = *num - 1;
+	    VALUE sym = TOPN(i);
+	    *id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
+
+	    /* shift arguments */
+	    if (i > 0) {
+		MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
+	    }
+
+	    *mn = rb_method_node(klass, *id);
+	    *num -= 1;
+	    DEC_SP(1);
+	    *flag |= VM_CALL_FCALL_BIT;
+	}
+    }
+}
+
+bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
+VALUE rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, int argc, VALUE *argv);
+
 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*/ int num, rb_block_t * const blockptr, const VALUE flag,
+	       /*const*/ ID id, const VALUE recv, VALUE klass, 
+	       struct rb_method_cache *mcache)
 {
     VALUE val;
+#if WITH_OBJC
+    NODE *mn;
+#if ENABLE_DEBUG_LOGGING
+    bool cached = false;
+#endif
 
-  start_method_dispatch:
+    mn = NULL;
 
+    if (mcache != NULL) {
+	if (mcache->flags & RB_MCACHE_RCALL_FLAG) {
+	    if (mcache->as.rcall.klass == klass && mcache->as.rcall.node != NULL) {
+		mn = mcache->as.rcall.node;
+#if ENABLE_DEBUG_LOGGING
+		cached = true;
+#endif
+		goto rcall_dispatch;
+	    }
+	    else {
+		IMP imp;
+		char *p, *mname;
+
+		mn = rb_objc_method_node2(klass, mcache->as.rcall.sel, &imp);
+		if (mn == NULL) {
+		    if (imp != NULL) {
+			mcache->flags = RB_MCACHE_OCALL_FLAG;
+			mcache->as.ocall.klass = klass;
+			mcache->as.ocall.imp = imp;
+			mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+			mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+			goto ocall_dispatch;
+		    }
+
+		    if ((mcache->flags & RB_MCACHE_NOT_CFUNC_FLAG) == 0) {
+			extern struct st_table *bs_functions;
+			bs_element_function_t *bs_func;
+
+			if (!st_lookup(bs_functions, (st_data_t)id, (st_data_t *)&bs_func)) {
+			    mcache->flags |= RB_MCACHE_NOT_CFUNC_FLAG;
+			    goto rcall_missing;
+			}
+
+			mcache->flags = RB_MCACHE_CFUNC_FLAG;
+			mcache->as.cfunc.bs_func = bs_func;
+			mcache->as.cfunc.sym = dlsym(RTLD_DEFAULT, bs_func->name);
+			if (mcache->as.cfunc.sym == NULL)
+			    rb_bug("bs func sym '%s' is NULL", bs_func->name);
+			goto cfunc_dispatch;
+		    }
+rcall_missing:
+		    mname = (char *)mcache->as.rcall.sel;
+		    if (num > 1 
+			&& (p = strchr(mname, ':')) != NULL
+			&& p + 1 != '\0') {
+			char *tmp = alloca(p - mname + 1);
+			NODE *new_mn;
+
+			strncpy(tmp, mname, p - mname + 1);
+			tmp[p - mname + 1] = '\0';
+			new_mn = rb_objc_method_node2(klass, sel_registerName(tmp), &imp);
+			if (new_mn == NULL) {
+			    goto rcall_dispatch;
+			}
+
+			VALUE *argv = cfp->sp - num;
+			VALUE h = rb_hash_new();
+			int i;
+
+			mname = p + 1;
+			for (i = 1; i < num; i++) {
+			    char buf[100];
+
+			    p = strchr(mname, ':');
+			    if (p == NULL) {
+				goto rcall_dispatch;
+			    }
+			    strlcpy(buf, mname, sizeof buf);
+			    buf[p - mname] = '\0';
+			    mname = p + 1;
+			    rb_hash_aset(h, ID2SYM(rb_intern(buf)), argv[i]);
+			}
+
+			VALUE new_argv[2];
+			new_argv[0] = argv[0];
+			new_argv[1] = h;
+
+			memcpy(cfp->sp - 2, new_argv, sizeof(void *) * 2);
+			cfp->bp -= 2 - num;
+			mn = new_mn;
+			id = rb_intern(tmp);
+			num = 2;
+			goto rcall_dispatch;
+		    }
+		}
+		mcache->as.rcall.node = mn;
+		mcache->as.rcall.klass = klass;
+	    }
+	}
+	else if (mcache->flags & RB_MCACHE_OCALL_FLAG) {
+	    rb_control_frame_t *reg_cfp;
+	    rb_control_frame_t *_cfp;
+	   
+ocall_dispatch: 
+	    reg_cfp = cfp;
+	    _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+		    recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
+
+	    _cfp->method_id = id;
+	    _cfp->method_class = klass;
+
+	    reg_cfp->sp -= num + 1;
+
+
+	    val = rb_objc_call2(recv, klass, mcache->as.rcall.sel, mcache->as.ocall.imp, mcache->as.ocall.method, mcache->as.ocall.bs_method, num, reg_cfp->sp + 1);
+
+	    if (reg_cfp != th->cfp + 1)
+		rb_bug("cfp consistency error - send");
+
+	    vm_pop_frame(th);
+
+	    return val;
+	}
+	else if (mcache->flags & RB_MCACHE_CFUNC_FLAG) {
+	    rb_control_frame_t *reg_cfp;
+	    rb_control_frame_t *_cfp;
+	  
+cfunc_dispatch: 
+	    reg_cfp = cfp;
+	    _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+		    recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
+
+	    _cfp->method_id = id;
+	    _cfp->method_class = klass;
+
+	    reg_cfp->sp -= num + 1;
+
+	    VALUE rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv);
+
+	    val = rb_bsfunc_call(mcache->as.cfunc.bs_func, mcache->as.cfunc.sym, num, reg_cfp->sp + 1);
+
+	    if (reg_cfp != th->cfp + 1)
+		rb_bug("cfp consistency error - send");
+
+	    vm_pop_frame(th);
+
+	    return val;
+	}
+	else {
+	    rb_bug("invalid cache flag");
+	}
+    }
+    else {
+	SEL sel;
+	IMP imp;
+	mn = rb_objc_method_node(klass, id, &imp, &sel);
+	if (mn == NULL && imp != NULL) {
+	    static struct rb_method_cache mcache_s;
+	    mcache = &mcache_s;
+	    mcache->as.ocall.sel = sel;
+	    mcache->as.ocall.klass = klass;
+	    mcache->as.ocall.imp = imp;
+	    mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+	    mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+	    goto ocall_dispatch;
+	}
+    }
+
+rcall_dispatch:
+
+    if (flag & VM_CALL_SEND_BIT) {
+	vm_send_optimize(cfp, (NODE **)&mn, (rb_num_t *)&flag, (rb_num_t *)&num, (ID *)&id, klass);  
+    }
+
+    DLOG("RCALL", "%c[<%s %p> %s] node=%p cached=%d", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)rb_id2name(id), mn, cached);
+#endif
+
+start_method_dispatch:
+
     if (mn != 0) {
 	if ((mn->nd_noex == 0)) {
 	    /* dispatch method */
@@ -588,19 +791,69 @@
 	}
     }
     else {
+#if WITH_OBJC
+	if (flag & VM_CALL_SUPER_BIT) {
+	    VALUE k;
+	    for (k = CLASS_OF(recv); k != 0; k = RCLASS_SUPER(k)) {
+		VALUE ary = rb_attr_get(k, idIncludedModules);
+		if (ary != Qnil) {
+		    int i, count = RARRAY_LEN(ary);
+		    for (i = 0; i < count; i++) {
+			VALUE imod = RARRAY_AT(ary, i);
+			mn = rb_objc_method_node(imod, id, NULL, NULL);
+			if (mn != NULL) {
+			    goto start_method_dispatch;
+			}
+		    }
+		}
+	    }
+	}
+	else if (mcache != NULL) {
+	    const char *p = (const char *)mcache->as.rcall.sel;
+	    size_t len = strlen(p);
+	    if (len >= 3) {
+		char buf[100];
+		SEL sel = 0;
+		if (isalpha(p[len - 3]) && p[len - 2] == '=' && p[len - 1] == ':') {
+		    /* foo=: -> setFoo: shortcut */
+		    snprintf(buf, sizeof buf, "set%s", p);
+		    buf[3] = toupper(buf[3]);
+		    buf[len + 1] = ':';
+		    buf[len + 2] = '\0';
+		    sel = sel_registerName(buf);
+		}
+		else if (isalpha(p[len - 2]) && p[len - 1] == '?') {
+		    /* foo?: -> isFoo: shortcut */
+		    snprintf(buf, sizeof buf, "is%s", p);
+		    buf[2] = toupper(buf[2]);
+		    buf[len + 1] = '\0';
+		    sel = sel_registerName(buf);
+		}
+		if (sel != 0) {
+		    Method method = class_getInstanceMethod((Class)klass, sel);
+		    if (method != NULL) {
+			IMP imp = method_getImplementation(method);
+			if (rb_objc_method_node3(imp) == NULL) {
+			    assert(class_addMethod((Class)klass, mcache->as.rcall.sel, imp,
+					method_getTypeEncoding(method)));
+			    mcache->flags = RB_MCACHE_OCALL_FLAG;
+			    mcache->as.ocall.klass = klass;
+			    mcache->as.ocall.imp = imp;
+			    mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+			    mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+			    goto ocall_dispatch;
+			}
+		    }
+		}
+	    }
+	}
+#endif
 	/* method missing */
 	if (id == idMethodMissing) {
 	    rb_bug("method missing");
 	}
 	else {
 	    int stat = 0;
-#if 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,
-				      mn, recv, klass);
-	    }
-#endif
 	    if (flag & VM_CALL_VCALL_BIT) {
 		stat |= NOEX_VCALL;
 	    }
@@ -615,33 +868,6 @@
     return val;
 }
 
-static inline void
-vm_send_optimize(rb_control_frame_t * const reg_cfp, NODE ** const mn,
-		 rb_num_t * const flag, rb_num_t * const num,
-		 ID * const id, const VALUE klass)
-{
-    if (*mn && nd_type((*mn)->nd_body) == NODE_CFUNC) {
-	NODE *node = (*mn)->nd_body;
-	extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
-
-	if (node->nd_cfnc == rb_f_send) {
-	    int i = *num - 1;
-	    VALUE sym = TOPN(i);
-	    *id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
-
-	    /* shift arguments */
-	    if (i > 0) {
-		MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
-	    }
-
-	    *mn = rb_method_node(klass, *id);
-	    *num -= 1;
-	    DEC_SP(1);
-	    *flag |= VM_CALL_FCALL_BIT;
-	}
-    }
-}
-
 /* yield */
 
 static inline int
@@ -997,6 +1223,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 +1239,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 +1291,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,66 +1348,6 @@
     INC_VM_STATE_VERSION();
 }
 
-#if 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) 
-{
-    VALUE *argv = cfp->sp - *pnum;
-    NODE *mn;
-    ID id;
-
-    if (*pmn == NULL) {
-	const char *p, *mname;
-	long i;
-	mn = rb_objc_define_objc_mid_closure(recv, *pid, 0);
-	if (mn != NULL) {
-	    *pmn = mn;
-	    return;
-	}
-	mname = rb_id2name(*pid);
-	if (*pid > 1 && (p = strchr(mname, ':')) != NULL) {
-	    char buf[512];
-	    strlcpy(buf, mname, sizeof buf);
-	    buf[p - mname] = '\0';
-	    mname = p + 1;
-	    id = rb_intern(buf);
-	    mn = rb_method_node(CLASS_OF(recv), id);
-	    if (mn != NULL) {
-		VALUE h = rb_hash_new();
-		VALUE new_argv[2];
-		for (i = 1; i < *pnum; i++) {
-		    p = strchr(mname, ':');
-		    if (p == NULL)
-			return;
-		    strlcpy(buf, mname, sizeof buf);
-		    buf[p - mname] = '\0';
-		    mname = p + 1;
-		    rb_hash_aset(h, ID2SYM(rb_intern(buf)), argv[i]);
-		}
-		new_argv[0] = argv[0];
-		new_argv[1] = h;
-		memcpy(cfp->sp - 2, new_argv, sizeof(void *) * 2);
-		cfp->bp -= 2 - *pnum;
-		*pmn = mn;
-		*pid = id;
-		*pnum = 2;
-		return;
-	    }
-	}
-	id = rb_objc_missing_sel(*pid, *pnum);
-	if (id != *pid) {
-	    mn = rb_objc_define_objc_mid_closure(recv, id, *pid);
-	    if (mn != NULL) {
-		*pmn = mn;
-		*pid = id;
-		return;
-	    }
-	}
-    }
-}
-#endif
-
 static inline NODE *
 vm_method_search(VALUE id, VALUE klass, IC ic)
 {
@@ -1201,13 +1375,13 @@
 static inline VALUE
 vm_search_normal_superclass(VALUE klass, VALUE recv)
 {
-    if (BUILTIN_TYPE(klass) == T_CLASS) {
+    if (TYPE(klass) == T_CLASS) {
 	klass = RCLASS_SUPER(klass);
     }
-    else if (BUILTIN_TYPE(klass) == T_MODULE) {
+    else if (TYPE(klass) == T_MODULE) {
 	VALUE k = CLASS_OF(recv);
 	while (k) {
-	    if (BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) {
+	    if (TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) {
 		klass = RCLASS_SUPER(k);
 		break;
 	    }
@@ -1217,10 +1391,41 @@
     return klass;
 }
 
+#if WITH_OBJC
+static VALUE previous_sklass = Qnil;
+static inline VALUE
+vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, IMP *impp, SEL *selp)
+{
+    VALUE ary = rb_attr_get(klass, idIncludedModules);
+    if (ary != Qnil) {
+	int i, count = RARRAY_LEN(ary);
+	for (i = 0; i < count; i++) {
+	    VALUE imod = RARRAY_AT(ary, i);
+	    NODE *mn;
+	    IMP imp;
+	    SEL sel;
+	    mn = rb_objc_method_node(imod, mid, &imp, &sel);
+	    if (imp != NULL) {
+		previous_sklass = klass;
+		*mnp = mn;
+		*impp = imp;
+		*selp = sel;
+		return imod;
+	    }
+	}
+    }
+    if (previous_sklass != Qnil) {
+	klass = previous_sklass;
+	previous_sklass = Qnil;
+    }
+    return vm_search_normal_superclass(klass, recv);
+}
+#endif
+
 static void
 vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *ip,
 		     VALUE recv, VALUE sigval,
-		     ID *idp, VALUE *klassp)
+		     ID *idp, VALUE *klassp, NODE **mnp, IMP *impp, SEL *selp)
 {
     ID id;
     VALUE klass;
@@ -1250,7 +1455,7 @@
 	}
 
 	id = lcfp->method_id;
-	klass = vm_search_normal_superclass(lcfp->method_class, recv);
+	klass = vm_search_normal_superclass2(lcfp->method_class, recv, id, mnp, impp, selp);
 
 	if (sigval == Qfalse) {
 	    /* zsuper */
@@ -1258,7 +1463,7 @@
 	}
     }
     else {
-	klass = vm_search_normal_superclass(ip->klass, recv);
+	klass = vm_search_normal_superclass2(ip->klass, recv, id, mnp, impp, selp);
     }
 
     *idp = id;

Modified: MacRuby/trunk/vm_method.c
===================================================================
--- MacRuby/trunk/vm_method.c	2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_method.c	2008-08-21 06:13:14 UTC (rev 459)
@@ -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));
 	}
@@ -210,7 +202,7 @@
 {
     Check_Type(klass, T_CLASS);
     rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
-		  NOEX_PRIVATE);
+		  NOEX_PUBLIC);
 }
 
 void
@@ -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_method_node(klass, id);
+    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,38 @@
     }
 
     return body;
+#endif
 }
 
 NODE *
 rb_method_node(VALUE klass, ID id)
 {
+#if WITH_OBJC
+    NODE *node = rb_objc_method_node(klass, id, NULL, NULL);
+    if (node == NULL && id != ID_ALLOCATOR) {
+	const char *id_str = rb_id2name(id);
+	size_t slen = strlen(id_str);
+
+	if (strcmp(id_str, "retain") == 0
+	    || strcmp(id_str, "release") == 0
+	    || strcmp(id_str, "zone") == 0) {
+	    char buf[100];
+	    snprintf(buf, sizeof buf, "__rb_%s__", id_str);
+	    return rb_method_node(klass, rb_intern(buf));
+	}
+	else {
+	    if (id_str[slen - 1] == ':') {
+		return NULL;
+	    }
+	    else {
+		char buf[100];
+		snprintf(buf, sizeof buf, "%s:", id_str);
+		return rb_method_node(klass, rb_intern(buf));
+	    }
+	}
+    }
+    return node;
+#else
     struct cache_entry *ent;
 
     ent = cache + EXPR1(klass, id);
@@ -314,12 +348,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 +370,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 +380,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 +391,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,6 +449,32 @@
     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;
+    }
+    if (fbody == NULL) {
+	rb_print_undef(klass, name, 0);
+    }
+    if (fbody->nd_noex != noex) {
+	if (nd_type(fbody->nd_body) == NODE_CFUNC) {
+	    rb_vm_check_redefinition_opt_method(fbody);
+	}
+	if (klass == origin) {
+	    fbody->nd_noex = noex;
+	}
+	else {
+	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
+	}
+    }
+#else
     fbody = search_method(klass, name, &origin);
     if (!fbody && TYPE(klass) == T_MODULE) {
 	fbody = search_method(rb_cObject, name, &origin);
@@ -426,6 +493,7 @@
 	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
 	}
     }
+#endif
 }
 
 int
@@ -500,21 +568,15 @@
     if (id == object_id || id == __send__ || id == idInitialize) {
 	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
     }
-#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),
-				 sel_registerName(rb_id2name(id)))) {
-	rb_warn("undefining `NSObject#%s' may cause serious problem", 
-		rb_id2name(id));
-    }
-#endif
+    /* TODO: warn if a very important method of NSObject is undefined 
+     * by default, pure objc methods are not exposed by introspections API 
+     */
     body = search_method(klass, id, &origin);
     if (!body || !body->nd_body) {
 	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 +589,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 +814,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 +863,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) {
@@ -1074,18 +1126,32 @@
 	    if (fbody == 0) {
 		fbody = search_method(rb_cObject, id, &m);
 	    }
+#if WITH_OBJC
+	    if (fbody == 0) {
+		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+	    }
+	    if (nd_type(fbody->nd_body) != NODE_ZSUPER) {
+		break;		/* normal case: need not to follow 'super' link */
+	    }
+#else
 	    if (fbody == 0 || fbody->nd_body == 0) {
 		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
 	    }
 	    if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
 		break;		/* normal case: need not to follow 'super' link */
 	    }
+#endif
 	    m = RCLASS_SUPER(m);
 	    if (!m)
 		break;
 	}
+#if WITH_OBJC
+	rb_add_method(rb_singleton_class(module), id, fbody->nd_body,
+		      NOEX_PUBLIC);
+#else
 	rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
 		      NOEX_PUBLIC);
+#endif
     }
     return module;
 }
@@ -1104,6 +1170,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)CLASS_OF(obj), sel); 
+#else
     VALUE klass = CLASS_OF(obj);
 
     if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
@@ -1117,6 +1187,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/20080820/c9bc4dd4/attachment-0001.html 


More information about the macruby-changes mailing list