[macruby-changes] [2274] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Aug 10 23:19:47 PDT 2009


Revision: 2274
          http://trac.macosforge.org/projects/ruby/changeset/2274
Author:   lsansonetti at apple.com
Date:     2009-08-10 23:19:45 -0700 (Mon, 10 Aug 2009)
Log Message:
-----------
adding a new optimized Array for default allocations plus various optimizations / bug fixes

Modified Paths:
--------------
    MacRuby/trunk/array.c
    MacRuby/trunk/class.c
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/enum.c
    MacRuby/trunk/gc.c
    MacRuby/trunk/hash.c
    MacRuby/trunk/include/ruby/defines.h
    MacRuby/trunk/include/ruby/intern.h
    MacRuby/trunk/include/ruby/ruby.h
    MacRuby/trunk/numeric.c
    MacRuby/trunk/object.c
    MacRuby/trunk/onig/regint.h
    MacRuby/trunk/rakelib/builder.rake
    MacRuby/trunk/rakelib/builder.rb
    MacRuby/trunk/spec/frozen/tags/macruby/core/array/union_tags.txt
    MacRuby/trunk/sprintf.cpp
    MacRuby/trunk/vm.cpp

Added Paths:
-----------
    MacRuby/trunk/llvm.h

Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/array.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -24,26 +24,170 @@
 #endif
 VALUE rb_cNSArray;
 VALUE rb_cNSMutableArray;
-
-#if 0
 VALUE rb_cRubyArray;
 
+#define ARY_DEFAULT_SIZE 16
+
 typedef struct {
-    Class klass;
-    long len;
-    long capacity;
+    struct RBasic basic;
+    size_t len;
+    size_t cap;
     VALUE *elements;
 } rb_ary_t;
 
+// RubyArray primitives.
+
+static VALUE
+rary_elt(rb_ary_t *ary, size_t idx)
+{
+    assert(idx < ary->len);
+    return ary->elements[idx];	
+}
+
 static void
-Init_RubyArray(void)
+rary_reserve(rb_ary_t *ary, size_t newcap)
 {
-    rb_cRubyArray = rb_define_class("RubyArray", rb_cNSMutableArray);
+    if (newcap > ary->cap) {
+#if MAC_OS_X_VERSION_MAX_ALLOWED <1060
+	VALUE *new_elements = (VALUE *)xmalloc(sizeof(VALUE) * newcap);
+	for (size_t i = 0; i < ary->len; i++) {
+	    GC_WB(&new_elements[i], ary->elements[i]);
+	}
+	GC_WB(&ary->elements, new_elements);
+#else
+	VALUE *new_elements = xrealloc(ary->elements, sizeof(VALUE) * newcap);
+	if (new_elements != ary->elements) {
+	    GC_WB(&ary->elements, new_elements);
+	}
+#endif
+	ary->cap = newcap;
+    }
 }
-#endif
 
-#define ARY_DEFAULT_SIZE 16
+static void
+rary_append(rb_ary_t *ary, VALUE item)
+{
+    if (ary->len + 1 > ary->cap) {
+	rary_reserve(ary, (ary->cap + 1) * 10);
+    }
+    GC_WB(&ary->elements[ary->len], item);
+    ary->len++;
+}
 
+static void
+rary_insert(rb_ary_t *ary, size_t idx, VALUE item)
+{
+    assert(idx <= ary->len);
+    if (idx < ary->len) {
+	if (ary->len + 1 > ary->cap) {
+	    rary_reserve(ary, ary->cap + 10);
+	}
+	for (size_t i = ary->len; i > idx; i--) {
+	    GC_WB(&ary->elements[i], ary->elements[i - 1]);
+	}
+	GC_WB(&ary->elements[idx], item);
+	ary->len++;
+    }
+    else {
+	rary_append(ary, item);
+    }
+}
+
+static VALUE
+rary_erase(rb_ary_t *ary, size_t idx, size_t len)
+{
+    assert(idx + len <= ary->len);
+    VALUE item = ary->elements[idx];
+    for (size_t i = idx; i < ary->len - len; i++) {
+	GC_WB(&ary->elements[i], ary->elements[i + len]);
+    }
+    for (size_t i = 0; i < len; i++) {
+	ary->elements[ary->len - i - 1] = Qnil;
+    }
+    ary->len -= len;
+    return item;
+}
+
+static void
+rary_replace(rb_ary_t *ary, size_t idx, VALUE item)
+{
+    assert(idx < ary->len);
+    GC_WB(&ary->elements[idx], item);
+}
+
+static void
+rary_store(rb_ary_t *ary, size_t idx, VALUE item)
+{
+    if (idx >= ary->len) {
+	rary_reserve(ary, idx + 1);
+	for (size_t i = ary->len; i < idx + 1; i++) {
+	    ary->elements[i] = Qnil;
+	}
+	ary->len = idx + 1;
+    }
+    rary_replace(ary, idx, item);
+}
+
+static void
+rary_resize(rb_ary_t *ary, size_t newlen)
+{
+    if (newlen > ary->cap) {
+	rary_reserve(ary, newlen);
+    }
+    for (size_t i = ary->len; i < newlen; i++) {
+	ary->elements[i] = Qnil;
+    }
+    ary->len = newlen;
+}
+
+static void
+rary_concat(rb_ary_t *ary, rb_ary_t *other, size_t beg, size_t len)
+{
+    rary_reserve(ary, ary->len + len + 16);
+    for (size_t i = 0; i < len; i++) {
+	GC_WB(&ary->elements[i + ary->len], other->elements[beg + i]);
+    }
+    ary->len += len;
+}
+
+static void
+rary_reverse(rb_ary_t *ary)
+{
+    if (ary->len > 1) {
+	for (size_t i = 0; i < ary->len / 2; i++) {
+	    const size_t j = ary->len - i - 1;
+	    VALUE elem = ary->elements[i];
+	    GC_WB(&ary->elements[i], ary->elements[j]);
+	    GC_WB(&ary->elements[j], elem);
+	}
+    }
+}
+
+static void
+rary_clear(rb_ary_t *ary)
+{
+    memset(ary->elements, 0, sizeof(VALUE) * ary->len);
+    ary->len = 0;
+}
+
+#define NOT_FOUND LONG_MAX
+
+size_t
+rary_index_of_item(rb_ary_t *ary, size_t origin, VALUE item)
+{
+    assert(origin < ary->len);
+    for (size_t i = origin; i < ary->len; i++) {
+	VALUE item2 = ary->elements[i];
+	if (item == item2 || rb_equal(item, item2) == Qtrue) {
+	    return i;
+	}
+    }
+    return NOT_FOUND;
+}
+
+#define IS_RARY(x) (*(VALUE *)x == rb_cRubyArray)
+#define RARY(x) ((rb_ary_t *)x)
+
 void
 rb_mem_clear(register VALUE *mem, register long size)
 {
@@ -53,16 +197,21 @@
 }
 
 static inline void
-rb_ary_modify_check(VALUE ary)
+__rb_ary_modify(VALUE ary)
 {
     long mask;
+    if (IS_RARY(ary)) {
+	mask = RBASIC(ary)->flags;
+    }
+    else {
 #ifdef __LP64__
-    mask = RCLASS_RC_FLAGS(ary);
+	mask = RCLASS_RC_FLAGS(ary);
 #else
-    mask = rb_objc_flag_get_mask((void *)ary);
+	mask = rb_objc_flag_get_mask((void *)ary);
 #endif
-    if (RARRAY_IMMUTABLE(ary)) {
-	mask |= FL_FREEZE;
+	if (RARRAY_IMMUTABLE(ary)) {
+	    mask |= FL_FREEZE;
+	}
     }
     if ((mask & FL_FREEZE) == FL_FREEZE) {
 	rb_raise(rb_eRuntimeError, "can't modify frozen/immutable array");
@@ -71,15 +220,27 @@
 	rb_raise(rb_eSecurityError, "Insecure: can't modify array");
     }
 }
-#define rb_ary_modify rb_ary_modify_check
 
+#define rb_ary_modify(ary) \
+    do { \
+	if (!IS_RARY(ary) || RBASIC(ary)->flags != 0) { \
+	    __rb_ary_modify(ary); \
+	} \
+    } \
+    while (0)
+
 extern void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap);
 
 static inline void
 rb_ary_set_capacity(VALUE ary, long len)
 {
     if (RARRAY_LEN(ary) < len) {
-	_CFArraySetCapacity((CFMutableArrayRef)ary, len);
+	if (IS_RARY(ary)) {
+	    rary_reserve(RARY(ary), len);
+	}
+	else {
+	    _CFArraySetCapacity((CFMutableArrayRef)ary, len);
+	}
     }
 }
 
@@ -114,16 +275,24 @@
 static inline VALUE
 ary_alloc(VALUE klass)
 {
-    CFMutableArrayRef ary;
-
-    ary = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (klass != 0 && klass != rb_cNSArray && klass != rb_cNSMutableArray) {
-	*(Class *)ary = (Class)klass;
+    if ((klass == 0 || klass == rb_cRubyArray || klass == rb_cNSMutableArray)
+	    && rb_cRubyArray != 0) {
+	NEWOBJ(ary, rb_ary_t);
+	ary->basic.flags = 0;
+	ary->basic.klass = rb_cRubyArray;
+        ary->len = ary->cap = 0;
+	ary->elements = NULL;
+	return (VALUE)ary;
     }
-
-    CFMakeCollectable(ary);
-
-    return (VALUE)ary;
+    else {
+	CFMutableArrayRef ary = CFArrayCreateMutable(NULL, 0,
+		&kCFTypeArrayCallBacks);
+	if (klass != 0 && klass != rb_cNSArray && klass != rb_cNSMutableArray) {
+	    *(Class *)ary = (Class)klass;
+	}
+	CFMakeCollectable(ary);
+	return (VALUE)ary;
+    }
 }
 
 VALUE
@@ -133,14 +302,12 @@
 
     if (argc > 0) {
 	va_list ar;
-	int i;
 
-	rb_ary_set_capacity(ary, argc);
+	rary_reserve(RARY(ary), argc);
 	va_start(ar, argc);
-	for (i = 0; i < argc; i++) {
+	for (int i = 0; i < argc; i++) {
 	    VALUE item = va_arg(ar, VALUE);
-	    CFArrayAppendValue((CFMutableArrayRef)ary,
-		    (const void *)RB2OC(item));
+	    rary_append(RARY(ary), item);
 	}
 	va_end(ar);
     }
@@ -148,19 +315,26 @@
     return ary;
 }
 
-static VALUE
-ary_new(VALUE klass, long len)
+static inline void
+assert_ary_len(const long len)
 {
-    VALUE ary;
-
     if (len < 0) {
 	rb_raise(rb_eArgError, "negative array size (or size too big)");
     }
-    if (len > LONG_MAX / sizeof(VALUE)) {
+    if ((unsigned long)len > (LONG_MAX / sizeof(VALUE))) {
 	rb_raise(rb_eArgError, "array size too big");
     }
-    ary = ary_alloc(klass);
+}
 
+static VALUE
+ary_new(VALUE klass, long len)
+{
+    assert_ary_len(len);
+
+    VALUE ary = ary_alloc(klass);
+    if (IS_RARY(ary)) {
+	rary_reserve(RARY(ary), len);
+    }
     return ary;
 }
 
@@ -181,14 +355,11 @@
 VALUE
 rb_ary_new3(long n, ...)
 {
+    VALUE ary = rb_ary_new2(n);
+
     va_list ar;
-    VALUE ary;
-    long i;
-
-    ary = rb_ary_new2(n);
-
     va_start(ar, n);
-    for (i=0; i<n; i++) {
+    for (long i = 0; i < n; i++) {
 	rb_ary_insert(ary, i, va_arg(ar, VALUE));
     }
     va_end(ar);
@@ -203,12 +374,20 @@
 
     ary = rb_ary_new2(n);
     if (n > 0 && elts != NULL) {
-	long i;
-	void **vals = (void **)alloca(n * sizeof(void *));
-	for (i = 0; i < n; i++) {
-	    vals[i] = RB2OC(elts[i]);
+	if (IS_RARY(ary)) {
+	    for (long i = 0; i < n; i++) {
+		rary_append(RARY(ary), elts[i]);
+	    }
 	}
-	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)vals, n);
+	else {
+	    void **vals = (void **)alloca(n * sizeof(void *));
+
+	    for (long i = 0; i < n; i++) {
+		vals[i] = RB2OC(elts[i]);
+	    }
+	    CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0),
+		    (const void **)vals, n);
+	}
     }
 
     return ary;
@@ -232,6 +411,89 @@
     return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
 }
 
+long
+rb_ary_len(VALUE ary)
+{
+    if (IS_RARY(ary)) {
+	return RARY(ary)->len;
+    }
+    else {
+	return CFArrayGetCount((CFArrayRef)ary); 
+    }
+}
+
+VALUE
+rb_ary_elt(VALUE ary, long offset)
+{
+    if (IS_RARY(ary)) {
+	if (offset < RARY(ary)->len) {
+	    return rary_elt(RARY(ary), offset);
+	}
+    }
+    else {
+	if (offset < CFArrayGetCount((CFArrayRef)ary)) {
+	    return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
+	}
+    }
+    return Qnil;
+}
+
+VALUE
+rb_ary_erase(VALUE ary, long offset)
+{
+    if (IS_RARY(ary)) {
+	return rary_erase(RARY(ary), offset, 1);
+    }
+    else {
+	VALUE item = OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
+	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, offset);
+	return item;
+    }
+}
+
+VALUE
+rb_ary_push(VALUE ary, VALUE item) 
+{
+    rb_ary_modify(ary);
+    if (IS_RARY(ary)) {
+	rary_append(RARY(ary), item);
+    }
+    else {
+	CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(item));
+    }
+    return ary;
+}
+
+inline static void
+rb_ary_append(VALUE ary, int argc, VALUE *argv)
+{
+    rb_ary_modify(ary);
+    if (IS_RARY(ary)) {
+	rary_reserve(RARY(ary), argc);
+	for (int i = 0; i < argc; i++) {
+	    rary_append(RARY(ary), argv[i]);
+	}
+    }
+    else {
+	for (int i = 0; i < argc; i++) {
+	    CFArrayAppendValue((CFMutableArrayRef)ary,
+		    (const void *)RB2OC(argv[i]));
+	}
+    }
+}
+
+static inline void
+rb_ary_resize(VALUE ary, long new_len)
+{
+    if (IS_RARY(ary)) {
+	rary_resize(RARY(ary), new_len);
+    }
+    else {
+	// TODO
+	abort();	
+    }
+}
+
 /*
  *  call-seq:
  *     Array.try_convert(obj) -> array or nil
@@ -299,9 +561,6 @@
 static VALUE
 rb_ary_initialize(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    long len;
-    VALUE size, val;
-
     ary = (VALUE)objc_msgSend((id)ary, selInit);
 
     if (argc ==  0) {
@@ -311,6 +570,8 @@
 	rb_ary_clear(ary);
 	return ary;
     }
+
+    VALUE size, val;
     rb_scan_args(argc, argv, "02", &size, &val);
     if (argc == 1 && !FIXNUM_P(size)) {
 	val = rb_check_array_type(size);
@@ -320,44 +581,31 @@
 	}
     }
 
-    len = NUM2LONG(size);
-    if (len < 0) {
-	rb_raise(rb_eArgError, "negative array size");
-    }
-    if (len > LONG_MAX / sizeof(VALUE)) {
-	rb_raise(rb_eArgError, "array size too big");
-    }
-    rb_ary_set_capacity(ary, len);
+    long len = NUM2LONG(size);
+    assert_ary_len(len);
+
+    rb_ary_modify(ary);
+
     if (rb_block_given_p()) {
-	long i;
-
 	if (argc == 2) {
 	    rb_warn("block supersedes default value argument");
 	}
 	rb_ary_clear(ary);
-	for (i = 0; i < len; i++) {
+	for (long i = 0; i < len; i++) {
 	    VALUE v = rb_yield(LONG2NUM(i));
 	    RETURN_IF_BROKEN();
-	    rb_ary_store(ary, i, v);
+	    rb_ary_push(ary, v);
 	}
     }
     else {
-	long i;
-	const void **values = alloca(sizeof(void *) * len);
-	void *ocval = RB2OC(val);
-
-	rb_ary_modify(ary);
-	for (i = 0; i < len; i++) {
-	    values[i] = ocval;
+	rb_ary_resize(ary, len);
+	for (long i = 0; i < len; i++) {
+	    rb_ary_store(ary, i, val);
 	}
-
-	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0),
-		values, len); 
     }
     return ary;
 }
 
-
 /* 
 * Returns a new array populated with the given objects. 
 *
@@ -369,17 +617,14 @@
 static VALUE
 rb_ary_s_create(VALUE klass, SEL sel, int argc, VALUE *argv)
 {
-    int i;
-
     VALUE ary = ary_alloc(klass);
 
     if (argc < 0) {
 	rb_raise(rb_eArgError, "negative array size");
     }
-    for (i = 0; i < argc; i++) {
-	CFArrayAppendValue((CFMutableArrayRef)ary, RB2OC(argv[i]));
-    }
-    
+
+    rb_ary_append(ary, argc, argv);
+
     return ary;
 }
 
@@ -394,65 +639,71 @@
 	}
     }
 
-    rb_ary_modify(ary);
-
-    CFArrayInsertValueAtIndex((CFMutableArrayRef)ary, idx, 
-	(const void *)RB2OC(val));
+    if (IS_RARY(ary)) {
+	if (idx > RARY(ary)->len) {
+	    rary_resize(RARY(ary), idx + 1);
+	    rary_store(RARY(ary), idx, val);
+	}
+	else {
+	    rary_insert(RARY(ary), idx, val);
+	}
+    }
+    else {
+	CFArrayInsertValueAtIndex((CFMutableArrayRef)ary, idx, 
+		(const void *)RB2OC(val));
+    }
 }
 
 void
 rb_ary_store(VALUE ary, long idx, VALUE val)
 {
-    long len = RARRAY_LEN(ary);
     if (idx < 0) {
+	const long len = RARRAY_LEN(ary);
 	idx += len;
 	if (idx < 0) {
 	    rb_raise(rb_eIndexError, "index %ld out of array",
 		    idx - len);
 	}
     }
-
-    rb_ary_modify(ary);
-
-    if (idx > len) {
-	long i;
-	if ((idx - len) * (long)sizeof(VALUE) <= idx - len) {
-	    rb_raise(rb_eArgError, "index too big");
-	}
-	for (i = 0; i < (idx - len); i++) {
-	    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
-	}
-	CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(val));	
+    if (IS_RARY(ary)) {
+	rary_store(RARY(ary), idx, val);
     }
     else {
-        CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx, (const void *)RB2OC(val));
+	CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx,
+		(const void *)RB2OC(val));
     }
 }
 
 static VALUE
-ary_shared_first(int argc, VALUE *argv, VALUE ary, int last, bool remove)
+ary_shared_first(int argc, VALUE *argv, VALUE ary, bool last, bool remove)
 {
-    VALUE nv, result;
-    long n;
-    long offset = 0;
-    long ary_len;
+    VALUE nv;
+    rb_scan_args(argc, argv, "1", &nv);
+    long n = NUM2LONG(nv);
 
-    rb_scan_args(argc, argv, "1", &nv);
-    n = NUM2LONG(nv);
-    ary_len = RARRAY_LEN(ary);
+    const long ary_len = RARRAY_LEN(ary);
     if (n > ary_len) {
 	n = ary_len;
     }
     else if (n < 0) {
 	rb_raise(rb_eArgError, "negative array size");
     }
+
+    long offset = 0;
     if (last) {
 	offset = ary_len - n;
     }
-    result = rb_ary_new();
-    CFArrayAppendArray((CFMutableArrayRef)result, (CFArrayRef)ary, CFRangeMake(offset, n));
+    VALUE result = rb_ary_new();
+
+    for (long i = 0; i < n; i++) {
+	VALUE item = rb_ary_elt(ary, i + offset);
+	rary_append(RARY(result), item);
+    }
+
     if (remove) {
-	CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(offset, n), NULL, 0);
+	for (long i = 0; i < n; i++) {
+	    rb_ary_erase(ary, offset);
+	}
     }
 
     return result;
@@ -471,24 +722,10 @@
  *
  */
 
-static inline VALUE
-rb_ary_push0(VALUE ary, VALUE item)
-{
-    rb_ary_modify(ary);
-    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(item));
-    return ary;
-}
-
-VALUE
-rb_ary_push(VALUE ary, VALUE item) 
-{
-    return rb_ary_push0(ary, item);
-}
-
 static VALUE
 rb_ary_push_imp(VALUE ary, SEL sel, VALUE item)
 {
-    return rb_ary_push0(ary, item);
+    return rb_ary_push(ary, item);
 }
 
 /* 
@@ -523,17 +760,12 @@
 VALUE
 rb_ary_pop(VALUE ary)
 {
-    long n;
-    rb_ary_modify_check(ary);
-    n = RARRAY_LEN(ary);
+    rb_ary_modify(ary);
+    const long n = RARRAY_LEN(ary);
     if (n == 0) {
 	return Qnil;
     }
-    else {
-	VALUE val = RARRAY_AT(ary, n - 1);
-	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, n - 1);
-	return val;
-    }
+    return rb_ary_erase(ary, n - 1);
 }
 
 /*
@@ -556,29 +788,23 @@
 static VALUE
 rb_ary_pop_m(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    VALUE result;
-
     if (argc == 0) {
 	return rb_ary_pop(ary);
     }
 
-    rb_ary_modify_check(ary);
-    result = ary_shared_first(argc, argv, ary, Qtrue, true);
-    return result;
+    rb_ary_modify(ary);
+    return ary_shared_first(argc, argv, ary, true, true);
 }
 
 VALUE
 rb_ary_shift(VALUE ary)
 {
-    VALUE top;
-
-    rb_ary_modify_check(ary);
+    rb_ary_modify(ary);
     if (RARRAY_LEN(ary) == 0) {
 	return Qnil;
     }
-    top = RARRAY_AT(ary, 0);
-    CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, 0);
-    return top;
+
+    return rb_ary_erase(ary, 0);
 }
 
 /*
@@ -605,16 +831,12 @@
 static VALUE
 rb_ary_shift_m(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    VALUE result;
-
     if (argc == 0) {
 	return rb_ary_shift(ary);
     }
 
-    rb_ary_modify_check(ary);
-    result = ary_shared_first(argc, argv, ary, Qfalse, true);
-
-    return result;
+    rb_ary_modify(ary);
+    return ary_shared_first(argc, argv, ary, false, true);
 }
 
 /*
@@ -634,16 +856,10 @@
 {
     rb_ary_modify(ary);
 
-    if (argc == 0) {
-	return ary;
+    for (int i = argc - 1; i >= 0; i--) {
+	rb_ary_insert(ary, 0, argv[i]);
     }
 
-    int i;
-    for (i = argc - 1; i >= 0; i--) {
-	CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
-	    0, (const void *)RB2OC(argv[i]));
-    }
-
     return ary;
 }
 
@@ -653,78 +869,86 @@
     return rb_ary_unshift_m(ary, 0, 1, &item);
 }
 
-/* faster version - use this if you don't need to treat negative offset */
-VALUE
-rb_ary_elt(VALUE ary, long offset)
-{
-    long n = RARRAY_LEN(ary);
-    if (n == 0) {
-	return Qnil;
-    }
-    if (offset < 0 || n <= offset) {
-	return Qnil;
-    }
-    return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
-}
-
 static void *rb_objc_ary_cptr_assoc_key = NULL;
 
 const VALUE *
 rb_ary_ptr(VALUE ary)
 {
-    /* FIXME we could inline __CFArrayGetBucketsPtr for non-store arrays,
-     * for performance reasons.
-     */
-    VALUE *values;
-    long i, len;
+    if (IS_RARY(ary)) {
+	return RARY(ary)->elements;
+    }
 
-    len = RARRAY_LEN(ary);
-    if (len == 0)
+    const long len = RARRAY_LEN(ary);
+    if (len == 0) {
 	return NULL;
-    values = (VALUE *)xmalloc(sizeof(VALUE) * len);
+    }
+
+    VALUE *values = (VALUE *)xmalloc(sizeof(VALUE) * len);
     CFArrayGetValues((CFArrayRef)ary, CFRangeMake(0, len), 
-	(const void **)values);
-    for (i = 0; i < len; i++) {
+	    (const void **)values);
+
+    for (long i = 0; i < len; i++) {
 	values[i] = OC2RB(values[i]);
     }
-    rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_cptr_assoc_key, values);
+    rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_cptr_assoc_key,
+	    values);
+
     return values;
 }
 
 VALUE
 rb_ary_entry(VALUE ary, long offset)
 {
+    const long n = RARRAY_LEN(ary);
+    if (n == 0) {
+	return Qnil;
+    }
     if (offset < 0) {
-	offset += RARRAY_LEN(ary);
+	offset += n;
     }
+    if (offset < 0 || n <= offset) {
+	return Qnil;
+    }
     return rb_ary_elt(ary, offset);
 }
 
 VALUE
 rb_ary_subseq(VALUE ary, long beg, long len)
 {
-    long n;
-    VALUE newary;
-    VALUE klass;
-
-    if (beg < 0 || len < 0)
+    if (beg < 0 || len < 0) {
 	return Qnil;
+    }
 
-    n = RARRAY_LEN(ary);
-    if (beg > n)
+    const long n = RARRAY_LEN(ary);
+    if (beg > n) {
 	return Qnil;
+    }
 
-    if (n < len || n < beg + len)
+    if (n < len || n < beg + len) {
 	len = n - beg;
+    }
 
-    klass = rb_obj_class(ary);
-    newary = ary_alloc(klass);
+    VALUE newary = ary_alloc(rb_obj_class(ary));
     if (len > 0) {
-	const void **values;
-	values = alloca(sizeof(void *) * len);
-	CFArrayGetValues((CFArrayRef)ary, CFRangeMake(beg, len), values);
-	CFArrayReplaceValues((CFMutableArrayRef)newary, CFRangeMake(0, 0), 
-	    values, len);
+	if (IS_RARY(newary)) {
+	    if (IS_RARY(ary)) {
+		rary_concat(RARY(newary), RARY(ary), beg, len);
+	    }
+	    else {
+		rary_reserve(RARY(newary), len);
+		for (long i = 0; i < len; i++) {
+		    VALUE item = rb_ary_elt(ary, beg + i);
+		    rary_append(RARY(newary), item);
+		}
+	    }	
+	}
+	else {
+	    void **values = (void **)alloca(sizeof(void *) * len);
+	    CFArrayGetValues((CFArrayRef)ary, CFRangeMake(beg, len),
+		    (const void **)values);
+	    CFArrayReplaceValues((CFMutableArrayRef)newary, CFRangeMake(0, 0), 
+		    (const void **)values, len);
+	}
     }	
     return newary;
 }
@@ -764,7 +988,6 @@
 VALUE
 rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    VALUE arg;
     long beg, len;
 
     if (argc == 2) {
@@ -778,19 +1001,19 @@
     if (argc != 1) {
 	rb_scan_args(argc, argv, "11", 0, 0);
     }
-    arg = argv[0];
+    VALUE arg = argv[0];
     /* special case - speeding up */
     if (FIXNUM_P(arg)) {
 	return rb_ary_entry(ary, FIX2LONG(arg));
     }
     /* check if idx is Range */
     switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
-      case Qfalse:
-	break;
-      case Qnil:
-	return Qnil;
-      default:
-	return rb_ary_subseq(ary, beg, len);
+	case Qfalse:
+	    break;
+	case Qnil:
+	    return Qnil;
+	default:
+	    return rb_ary_subseq(ary, beg, len);
     }
     return rb_ary_entry(ary, NUM2LONG(arg));
 }
@@ -832,11 +1055,13 @@
 rb_ary_first(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     if (argc == 0) {
-	if (RARRAY_LEN(ary) == 0) return Qnil;
+	if (RARRAY_LEN(ary) == 0) {
+	    return Qnil;
+	}
 	return RARRAY_AT(ary, 0);
     }
     else {
-	return ary_shared_first(argc, argv, ary, Qfalse, false);
+	return ary_shared_first(argc, argv, ary, false, false);
     }
 }
 
@@ -857,12 +1082,14 @@
 rb_ary_last(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     if (argc == 0) {
-	long n = RARRAY_LEN(ary);
-	if (n == 0) return Qnil;
+	const long n = RARRAY_LEN(ary);
+	if (n == 0) {
+	    return Qnil;
+	}
 	return RARRAY_AT(ary, n - 1);
     }
     else {
-	return ary_shared_first(argc, argv, ary, Qtrue, false);
+	return ary_shared_first(argc, argv, ary, true, false);
     }
 }
 
@@ -890,21 +1117,21 @@
 rb_ary_fetch(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     VALUE pos, ifnone;
-    long block_given;
-    long idx;
 
     rb_scan_args(argc, argv, "11", &pos, &ifnone);
-    block_given = rb_block_given_p();
+    const bool block_given = rb_block_given_p();
     if (block_given && argc == 2) {
 	rb_warn("block supersedes default value argument");
     }
-    idx = NUM2LONG(pos);
 
+    long idx = NUM2LONG(pos);
     if (idx < 0) {
 	idx +=  RARRAY_LEN(ary);
     }
     if (idx < 0 || RARRAY_LEN(ary) <= idx) {
-	if (block_given) return rb_yield(pos);
+	if (block_given) {
+	    return rb_yield(pos);
+	}
 	if (argc == 1) {
 	    rb_raise(rb_eIndexError, "index %ld out of array", idx);
 	}
@@ -935,12 +1162,11 @@
 rb_ary_index(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     VALUE val;
-    long n, i;
 
-    n = RARRAY_LEN(ary);
+    const long n = RARRAY_LEN(ary);
     if (rb_scan_args(argc, argv, "01", &val) == 0) {
 	RETURN_ENUMERATOR(ary, 0, 0);
-	for (i=0; i<n; i++) {
+	for (long i = 0; i < n; i++) {
 	    VALUE v = rb_yield(RARRAY_AT(ary, i));
 	    RETURN_IF_BROKEN();
 	    if (RTEST(v)) {
@@ -948,12 +1174,20 @@
 	    }
 	}
     }
-    else {
-	CFIndex idx;
-	idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n), 
-	    (const void *)RB2OC(val));
-	if (idx != -1)
-	    return LONG2NUM(idx);
+    else if (n > 0) {
+	if (IS_RARY(ary)) {
+	    size_t pos = rary_index_of_item(RARY(ary), 0, val);
+	    if (pos != NOT_FOUND) {
+		return LONG2NUM(pos);
+	    }
+	}
+	else {
+	    CFIndex idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
+		    CFRangeMake(0, n), (const void *)RB2OC(val));
+	    if (idx != -1) {
+		return LONG2NUM(idx);
+	    }
+	}
     }
     return Qnil;
 }
@@ -976,10 +1210,8 @@
 static VALUE
 rb_ary_rindex(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    VALUE val;
-    long i, n;
-   
-    i = n = RARRAY_LEN(ary);
+    const long n = RARRAY_LEN(ary);
+    long i = n;
 
     if (argc == 0) {
 	RETURN_ENUMERATOR(ary, 0, 0);
@@ -995,11 +1227,15 @@
 	}
     }
     else {
+	VALUE val;
  	rb_scan_args(argc, argv, "01", &val);
+	
+	// TODO: optimize for RARY
 	i = CFArrayGetLastIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
 	   (const void *)RB2OC(val));
-	if (i != -1)
+	if (i != -1) {
 	    return LONG2NUM(i);
+	}
     }
     return Qnil;
 }
@@ -1019,9 +1255,7 @@
 static void
 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
 {
-    long n, rlen;
-
-    n = RARRAY_LEN(ary);
+    const long n = RARRAY_LEN(ary);
     if (len < 0) {
 	rb_raise(rb_eIndexError, "negative length (%ld)", len);
     }
@@ -1036,6 +1270,7 @@
 	len = n - beg;
     }
 
+    long rlen;
     if (rpl == Qundef) {
 	rlen = 0;
     }
@@ -1043,30 +1278,58 @@
 	rpl = rb_ary_to_ary(rpl);
 	rlen = RARRAY_LEN(rpl);
     }
+
     rb_ary_modify(ary);
-    if (beg >= n) {
-	long i;
-	for (i = n; i < beg; i++) {
-	    CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
+    if (IS_RARY(ary) && (rpl == Qundef || IS_RARY(rpl))) {
+	if (ary == rpl) {
+	    rpl = rb_ary_dup(rpl);
 	}
-	if (rlen > 0)  {
-	    CFArrayAppendArray((CFMutableArrayRef)ary, (CFArrayRef)rpl,
-		    CFRangeMake(0, rlen));
+	if (beg >= n) {
+	    for (long i = n; i < beg; i++) {
+		rary_append(RARY(ary), Qnil);
+	    }
+	    if (rlen > 0) {
+		rary_concat(RARY(ary), RARY(rpl), 0, rlen);
+	    }
 	}
+	else if (len == rlen) {
+	    for (long i = 0; i < len; i++) {
+		rary_store(RARY(ary), beg + i, RARY(rpl)->elements[i]);	
+	    }	
+	}
+	else {
+	    rary_erase(RARY(ary), beg, len);
+	    for (long i = 0; i < rlen; i++) {
+		rary_insert(RARY(ary), beg + i, RARY(rpl)->elements[i]);
+	    }
+	}
     }
     else {
-	const void **values;
-	if (rlen > 0) {
-	    values = (void *)alloca(sizeof(void *) * rlen);
-	    CFArrayGetValues((CFArrayRef)rpl, CFRangeMake(0, rlen), values);
+	if (beg >= n) {
+	    for (long i = n; i < beg; i++) {
+		CFArrayAppendValue((CFMutableArrayRef)ary,
+			(const void *)kCFNull);
+	    }
+	    if (rlen > 0)  {
+		CFArrayAppendArray((CFMutableArrayRef)ary, (CFArrayRef)rpl,
+			CFRangeMake(0, rlen));
+	    }
 	}
 	else {
-	    values = NULL;
+	    void **values;
+	    if (rlen > 0) {
+		values = (void **)alloca(sizeof(void *) * rlen);
+		CFArrayGetValues((CFArrayRef)rpl, CFRangeMake(0, rlen),
+			(const void **)values);
+	    }
+	    else {
+		values = NULL;
+	    }
+	    CFArrayReplaceValues((CFMutableArrayRef)ary,
+		    CFRangeMake(beg, len),
+		    (const void **)values,
+		    rlen);
 	}
-	CFArrayReplaceValues((CFMutableArrayRef)ary,
-		CFRangeMake(beg, len),
-		values,
-		rlen);
     }
 }
 
@@ -1141,8 +1404,6 @@
 static VALUE
 rb_ary_insert_m(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    long pos;
-
     if (argc == 1) {
 	rb_ary_modify(ary);
 	return ary;
@@ -1150,14 +1411,20 @@
     if (argc < 1) {
 	rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
     }
-    pos = NUM2LONG(argv[0]);
+    long pos = NUM2LONG(argv[0]);
     if (pos == -1) {
 	pos = RARRAY_LEN(ary);
     }
     if (pos < 0) {
 	pos++;
     }
-    rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
+    rb_ary_modify(ary);
+    if (argc == 2) {
+	rb_ary_insert(ary, pos, argv[1]);
+    }
+    else {
+	rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
+    }
     return ary;
 }
 
@@ -1262,8 +1529,7 @@
 static VALUE
 rb_ary_length(VALUE ary, SEL sel)
 {
-    long len = RARRAY_LEN(ary);
-    return LONG2NUM(len);
+    return LONG2NUM(RARRAY_LEN(ary));
 }
 
 /*
@@ -1286,16 +1552,22 @@
 {
     VALUE dup;
 
-    dup = (VALUE)CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)ary);
-    if (*(Class *)ary != (Class)rb_cCFArray) {
-	*(Class *)dup = *(Class *)ary;
+    if (IS_RARY(ary)) {
+	dup = rb_ary_new();
+	rary_concat(RARY(dup), RARY(ary), 0, RARY(ary)->len);
     }
+    else {
+	dup = (VALUE)CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)ary);
+	if (*(Class *)ary != (Class)rb_cCFArray) {
+	    *(Class *)dup = *(Class *)ary;
+	}
+	CFMakeCollectable((CFMutableArrayRef)dup);
+    }
+
     if (OBJ_TAINTED(ary)) {
 	OBJ_TAINT(dup);
     }
 
-    CFMakeCollectable((CFMutableArrayRef)dup);
-
     return dup;
 }
 
@@ -1398,7 +1670,9 @@
     VALUE sep;
 
     rb_scan_args(argc, argv, "01", &sep);
-    if (NIL_P(sep)) sep = rb_output_fs;
+    if (NIL_P(sep)) {
+	sep = rb_output_fs;
+    }
     
     return rb_ary_join(ary, sep);
 }
@@ -1406,18 +1680,16 @@
 static VALUE
 inspect_ary(VALUE ary, VALUE dummy, int recur)
 {
-    int tainted = OBJ_TAINTED(ary);
-    long i;
-    VALUE s, str;
-
     if (recur) {
 	return rb_tainted_str_new2("[...]");
     }
-    str = rb_str_buf_new2("[");
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	s = rb_inspect(RARRAY_AT(ary, i));
+
+    bool tainted = OBJ_TAINTED(ary);
+    VALUE str = rb_str_buf_new2("[");
+    for (long i = 0; i < RARRAY_LEN(ary); i++) {
+	VALUE s = rb_inspect(RARRAY_AT(ary, i));
 	if (OBJ_TAINTED(s)) {
-	    tainted = Qtrue;
+	    tainted = true;
 	}
 	if (i > 0) {
 	    rb_str_buf_cat2(str, ", ");
@@ -1425,6 +1697,7 @@
 	rb_str_buf_append(str, s);
     }
     rb_str_buf_cat2(str, "]");
+
     if (tainted) {
 	OBJ_TAINT(str);
     }
@@ -1442,7 +1715,9 @@
 static VALUE
 rb_ary_inspect(VALUE ary, SEL sel)
 {
-    if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
+    if (RARRAY_LEN(ary) == 0) {
+	return rb_usascii_str_new2("[]");
+    }
     return rb_exec_recursive(inspect_ary, ary, 0);
 }
 
@@ -1487,24 +1762,26 @@
 VALUE
 rb_ary_reverse(VALUE ary)
 {
-    long n;
-
     rb_ary_modify(ary);
-    n = RARRAY_LEN(ary);
-    if (n > 0) {
-	void **values;
-	CFRange range;
-	long i;
+    if (IS_RARY(ary)) {
+	rary_reverse(RARY(ary));
+    }
+    else {
+	const long n = RARRAY_LEN(ary);
+	if (n > 0) {
+	    void **values = (void **)alloca(sizeof(void *) * n);
+	    CFRange range = CFRangeMake(0, n);
+	    CFArrayGetValues((CFArrayRef)ary, range, (const void **)values);
 
-	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;
+	    long i;
+	    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);
 	}
-	CFArrayReplaceValues((CFMutableArrayRef)ary, range, (const void **)values, n);
     }
     return ary;
 }
@@ -1543,10 +1820,11 @@
 }
 
 static int
-sort_1(const void *ap, const void *bp, void *dummy)
+sort_1(void *dummy, const void *ap, const void *bp)
 {
     if (*(VALUE *)dummy == 0) {
-	VALUE a = (VALUE)ap, b = (VALUE)bp;
+	VALUE a = *(VALUE *)ap;
+	VALUE b = *(VALUE *)bp;
 	VALUE retval = rb_yield_values(2, a, b);
 
 	VALUE v = rb_vm_pop_broken_value();
@@ -1564,9 +1842,10 @@
 }
 
 static int
-sort_2(const void *ap, const void *bp, void *dummy)
+sort_2(void *dummy, const void *ap, const void *bp)
 {
-    VALUE a = (VALUE)ap, b = (VALUE)bp;
+    VALUE a = *(VALUE *)ap;
+    VALUE b = *(VALUE *)bp;
 
     /* FIXME optimize!!! */
     if (TYPE(a) == T_STRING) {
@@ -1579,6 +1858,22 @@
     return rb_cmpint(retval, a, b);
 }
 
+static int
+cf_sort_1(const void *a, const void *b, void *dummy)
+{
+    VALUE ra = OC2RB(a);
+    VALUE rb = OC2RB(b);
+    return sort_1(dummy, &ra, &rb);
+}
+
+static int
+cf_sort_2(const void *a, const void *b, void *dummy)
+{
+    VALUE ra = OC2RB(a);
+    VALUE rb = OC2RB(b);
+    return sort_2(dummy, &ra, &rb);
+}
+
 /*
  *  call-seq:
  *     array.sort!                   -> array
@@ -1598,15 +1893,23 @@
 static VALUE
 rb_ary_sort_bang1(VALUE ary, bool is_dup)
 {
-    long n = RARRAY_LEN(ary);
+    const long n = RARRAY_LEN(ary);
     if (n > 1) {
 	if (rb_block_given_p()) {
 	    VALUE tmp = is_dup ? ary : rb_ary_dup(ary);
 	    VALUE break_val = 0;
-	    CFArraySortValues((CFMutableArrayRef)tmp,
-		    CFRangeMake(0, n),
-		    (CFComparatorFunction)sort_1,
-		    &break_val);
+
+	    if (IS_RARY(ary)) {
+		qsort_r(RARY(tmp)->elements, n, sizeof(VALUE), &break_val,
+			sort_1);
+	    }
+	    else {
+		CFArraySortValues((CFMutableArrayRef)tmp,
+			CFRangeMake(0, n),
+			(CFComparatorFunction)cf_sort_1,
+			&break_val);
+	    }
+
 	    if (break_val != 0) {
 		return break_val;
 	    }
@@ -1615,10 +1918,15 @@
 	    }
 	}
 	else {
-	    CFArraySortValues((CFMutableArrayRef)ary,
-		    CFRangeMake(0, n),
-		    (CFComparatorFunction)sort_2,
-		    NULL);
+	    if (IS_RARY(ary)) {
+		qsort_r(RARY(ary)->elements, n, sizeof(VALUE), NULL, sort_2);
+	    }
+	    else {
+		CFArraySortValues((CFMutableArrayRef)ary,
+			CFRangeMake(0, n),
+			(CFComparatorFunction)cf_sort_2,
+			NULL);
+	    }
 	}
     }
     return ary;
@@ -1831,23 +2139,32 @@
 static VALUE
 rb_ary_delete_imp(VALUE ary, SEL sel, VALUE item)
 {
-    long k, n, i;
-    CFRange r;
-    const void *ocitem;
-
     rb_ary_modify(ary);
 
-    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);
-	r.location = i;
-	r.length = --n - i;
-	k++;
+    bool changed = false;
+    if (IS_RARY(ary)) {
+	size_t pos = 0;
+	while (pos < RARY(ary)->len
+		&& (pos = rary_index_of_item(RARY(ary), pos, item))
+		!= NOT_FOUND) {
+	    rary_erase(RARY(ary), pos, 1);
+	    changed = true;
+	}
     }
-    if (k == 0) {
+    else {
+	const void *ocitem = (const void *)RB2OC(item);
+	long n = RARRAY_LEN(ary);
+	CFRange r = CFRangeMake(0, n);
+	long i = 0;
+	while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r, ocitem))
+		!= -1) {
+	    CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
+	    r.location = i;
+	    r.length = --n - i;
+	    changed = true;
+	}
+    }
+    if (!changed) {
 	if (rb_block_given_p()) {
 	    return rb_yield(item);
 	}
@@ -1865,20 +2182,26 @@
 VALUE
 rb_ary_delete_at(VALUE ary, long pos)
 {
-    long len = RARRAY_LEN(ary);
-    VALUE del;
-
-    if (pos >= len) return Qnil;
+    const long len = RARRAY_LEN(ary);
+    if (pos >= len) {
+	return Qnil;
+    }
     if (pos < 0) {
 	pos += len;
-	if (pos < 0) return Qnil;
+	if (pos < 0) {
+	    return Qnil;
+	}
     }
 
     rb_ary_modify(ary);
-    del = RARRAY_AT(ary, pos);
-    CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, pos);
-
-    return del;
+    if (IS_RARY(ary)) {
+	return rary_erase(RARY(ary), pos, 1);
+    }
+    else {
+	VALUE del = RARRAY_AT(ary, pos);
+	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, pos);
+	return del;
+    }
 }
 
 /*
@@ -1925,17 +2248,18 @@
 {
     VALUE arg1, arg2;
     long pos, len;
-    long alen;
 
-    rb_ary_modify_check(ary);
-    alen = RARRAY_LEN(ary);
+    rb_ary_modify(ary);
+    const long alen = RARRAY_LEN(ary);
     if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
 	pos = NUM2LONG(arg1);
 	len = NUM2LONG(arg2);
-      delete_pos_len:
+delete_pos_len:
 	if (pos < 0) {
 	    pos = alen + pos;
-	    if (pos < 0) return Qnil;
+	    if (pos < 0) {
+		return Qnil;
+	    }
 	}
 	if (alen < len || alen < pos + len) {
 	    len = alen - pos;
@@ -1947,15 +2271,15 @@
 
     if (!FIXNUM_P(arg1)) {
 	switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
-	  case Qtrue:
-	    /* valid range */
-	    goto delete_pos_len;
-	  case Qnil:
-	    /* invalid range */
-	    return Qnil;
-	  default:
-	    /* not a range */
-	    break;
+	    case Qtrue:
+		/* valid range */
+		goto delete_pos_len;
+	    case Qnil:
+		/* invalid range */
+		return Qnil;
+	    default:
+		/* not a range */
+		break;
 	}
     }
 
@@ -1975,11 +2299,13 @@
 static VALUE
 rb_ary_reject_bang(VALUE ary, SEL sel)
 {
-    long orign, n, i1, i2;
+    RETURN_ENUMERATOR(ary, 0, 0);
 
-    RETURN_ENUMERATOR(ary, 0, 0);
     rb_ary_modify(ary);
-    orign = n = RARRAY_LEN(ary);
+
+    long n = RARRAY_LEN(ary);
+    const long orign = n;
+    long i1, i2;
     for (i1 = i2 = 0; i1 < n; i1++) {
 	VALUE v = RARRAY_AT(ary, i1);
 	VALUE v2 = rb_yield(v);
@@ -1987,13 +2313,14 @@
 	if (!RTEST(v2)) {
 	    continue;
 	}
-	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i1);
+	rb_ary_erase(ary, i1);	
 	n--;
 	i1--;
     }
 
-    if (n == orign) 
+    if (n == orign) {
 	return Qnil;
+    }
     return ary;
 }
 
@@ -2059,7 +2386,8 @@
     args[0] = result;
     args[1] = (VALUE)n;
     
-    rb_objc_block_call(obj, selEach, cacheEach, 0, 0, take_i, (VALUE)args);
+    rb_objc_block_call(obj, selEach, cacheEach, 0, 0,
+	    (VALUE(*)(ANYARGS))take_i, (VALUE)args);
 
     return result;
 }
@@ -2088,24 +2416,22 @@
 static VALUE
 rb_ary_zip(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    int i, j;
-    long len;
-    VALUE result = Qnil;
-
-    len = RARRAY_LEN(ary);
-    for (i=0; i<argc; i++) {
+    const long len = RARRAY_LEN(ary);
+    for (int i = 0; i < argc; i++) {
 	argv[i] = take_items(argv[i], len);
     }
+    VALUE result = Qnil;
     if (!rb_block_given_p()) {
 	result = rb_ary_new2(len);
     }
 
-    for (i=0; i<RARRAY_LEN(ary); i++) {
-	VALUE tmp = rb_ary_new2(argc+1);
+    for (int i = 0; i < RARRAY_LEN(ary); i++) {
+	VALUE tmp = rb_ary_new2(argc + 1);
 
 	rb_ary_push(tmp, rb_ary_elt(ary, i));
-	for (j=0; j<argc; j++) {
-	    rb_ary_push(tmp, rb_ary_elt(argv[j], i));
+	for (int j = 0; j < argc; j++) {
+	    VALUE item = rb_ary_elt(argv[j], i);
+	    rb_ary_push(tmp, item);
 	}
 	if (NIL_P(result)) {
 	    rb_yield(tmp);
@@ -2132,17 +2458,19 @@
 static VALUE
 rb_ary_transpose(VALUE ary, SEL sel)
 {
-    long elen = -1, alen, i, j;
-    VALUE tmp, result = 0;
+    const long alen = RARRAY_LEN(ary);
+    if (alen == 0) {
+	return rb_ary_dup(ary);
+    }
 
-    alen = RARRAY_LEN(ary);
-    if (alen == 0) return rb_ary_dup(ary);
-    for (i=0; i<alen; i++) {
-	tmp = to_ary(rb_ary_elt(ary, i));
+    long elen = -1;
+    VALUE result = Qnil;
+    for (long i = 0; i < alen; i++) {
+	VALUE tmp = to_ary(rb_ary_elt(ary, i));
 	if (elen < 0) {		/* first element */
 	    elen = RARRAY_LEN(tmp);
 	    result = rb_ary_new2(elen);
-	    for (j=0; j<elen; j++) {
+	    for (long j = 0; j < elen; j++) {
 		rb_ary_store(result, j, rb_ary_new2(alen));
 	    }
 	}
@@ -2150,7 +2478,7 @@
 	    rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
 		     RARRAY_LEN(tmp), elen);
 	}
-	for (j=0; j<elen; j++) {
+	for (long j = 0; j < elen; j++) {
 	    rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
 	}
     }
@@ -2173,15 +2501,22 @@
 rb_ary_replace(VALUE copy, VALUE orig)
 {
     orig = to_ary(orig);
-    rb_ary_modify_check(copy);
+    rb_ary_modify(copy);
     if (copy == orig) {
 	return copy;
     }
-    CFArrayRemoveAllValues((CFMutableArrayRef)copy);
-    CFArrayAppendArray((CFMutableArrayRef)copy,
-	(CFArrayRef)orig,
-	CFRangeMake(0, RARRAY_LEN(orig)));
 
+    if (IS_RARY(copy) && IS_RARY(orig)) {
+	rary_clear(RARY(copy));
+	rary_concat(RARY(copy), RARY(orig), 0, RARY(orig)->len);
+    }
+    else {
+	CFArrayRemoveAllValues((CFMutableArrayRef)copy);
+	CFArrayAppendArray((CFMutableArrayRef)copy,
+		(CFArrayRef)orig,
+		CFRangeMake(0, RARRAY_LEN(orig)));
+    }
+
     return copy;
 }
 
@@ -2205,7 +2540,12 @@
 rb_ary_clear_imp(VALUE ary, SEL sel)
 {
     rb_ary_modify(ary);
-    CFArrayRemoveAllValues((CFMutableArrayRef)ary);
+    if (IS_RARY(ary)) {
+	rary_clear(RARY(ary));
+    }
+    else {
+	CFArrayRemoveAllValues((CFMutableArrayRef)ary);
+    }
     return ary;
 }
 
@@ -2243,38 +2583,40 @@
 rb_ary_fill(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
     VALUE item, arg1, arg2;
-    long beg = 0, end = 0, len = 0, n;
-    int block_p = Qfalse;
-
-    n = RARRAY_LEN(ary);
-
+    const long n = RARRAY_LEN(ary);
+    bool block_p = false;
     if (rb_block_given_p()) {
-	block_p = Qtrue;
+	block_p = true;
 	rb_scan_args(argc, argv, "02", &arg1, &arg2);
 	argc += 1;		/* hackish */
     }
     else {
 	rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
     }
+
+    long beg = 0, end = 0, len = 0;
     switch (argc) {
-      case 1:
-	beg = 0;
-	len = n;
-	break;
-      case 2:
-	if (rb_range_beg_len(arg1, &beg, &len, n, 1)) {
+	case 1:
+	    beg = 0;
+	    len = n;
 	    break;
-	}
-	/* fall through */
-      case 3:
-	beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
-	if (beg < 0) {
-	    beg = n + beg;
-	    if (beg < 0) beg = 0;
-	}
-	len = NIL_P(arg2) ? n - beg : NUM2LONG(arg2);
-	break;
+	case 2:
+	    if (rb_range_beg_len(arg1, &beg, &len, n, 1)) {
+		break;
+	    }
+	    /* fall through */
+	case 3:
+	    beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
+	    if (beg < 0) {
+		beg = n + beg;
+		if (beg < 0) {
+		    beg = 0;
+		}
+	    }
+	    len = NIL_P(arg2) ? n - beg : NUM2LONG(arg2);
+	    break;
     }
+
     rb_ary_modify(ary);
     if (len < 0) {
 	return ary;
@@ -2285,18 +2627,14 @@
     }
 
     if (block_p) {
-	VALUE v;
-	long i;
-
-	for (i=beg; i<end; i++) {
-	    v = rb_yield(LONG2NUM(i));
+	for (long i = beg; i < end; i++) {
+	    VALUE v = rb_yield(LONG2NUM(i));
 	    RETURN_IF_BROKEN();
 	    rb_ary_store(ary, i, v);
 	}
     }
     else {
-	long i;
-	for (i=beg; i<end; i++) {
+	for (long i = beg; i < end; i++) {
 	    rb_ary_store(ary, i, item);
 	}
     }
@@ -2313,6 +2651,20 @@
  *     [ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
  */
 
+VALUE
+rb_ary_concat(VALUE x, VALUE y)
+{
+    if (IS_RARY(x) && IS_RARY(y)) {
+	rary_concat(RARY(x), RARY(y), 0, RARY(y)->len);
+    }
+    else {
+	const size_t len = RARRAY_LEN(y);
+	CFArrayAppendArray((CFMutableArrayRef)x, (CFArrayRef)y,
+		CFRangeMake(0, len));    
+    }
+    return x;
+}
+
 static VALUE
 rb_ary_plus_imp(VALUE x, SEL sel, VALUE y)
 {
@@ -2320,12 +2672,10 @@
 
     y = to_ary(y);
     z = rb_ary_new2(0);
-    const size_t x_len = RARRAY_LEN(x);
-    const size_t y_len = RARRAY_LEN(y);
-    rb_ary_set_capacity(z, x_len + y_len);
-    CFArrayAppendArray((CFMutableArrayRef)z, (CFArrayRef)x, CFRangeMake(0, x_len));    
-    CFArrayAppendArray((CFMutableArrayRef)z, (CFArrayRef)y, CFRangeMake(0, y_len));    
 
+    rb_ary_concat(z, x);
+    rb_ary_concat(z, y);
+
     return z;
 }
 
@@ -2347,24 +2697,12 @@
 static VALUE
 rb_ary_concat_imp(VALUE x, SEL sel, VALUE y)
 {
+    rb_ary_modify(x);
     y = to_ary(y);
-    if (RARRAY_LEN(y) > 0) {
-	rb_ary_splice(x, RARRAY_LEN(x), 0, y);
-    }
-    else {
-	// Even if we do nothing since the given array is empty, we still need
-	// to check if the receiver is modifiable, for RubySpec compliance.
-	rb_ary_modify(x);
-    }
+    rb_ary_concat(x, y);
     return x;
 }
 
-VALUE
-rb_ary_concat(VALUE x, VALUE y)
-{
-    return rb_ary_concat_imp(x, 0, y);
-}
-
 /* 
  *  call-seq:
  *     array * int     ->    an_array
@@ -2383,38 +2721,30 @@
 static VALUE
 rb_ary_times(VALUE ary, SEL sel, VALUE times)
 {
-    VALUE ary2, tmp;
-    long n, i, len;
-
-    tmp = rb_check_string_type(times);
+    VALUE tmp = rb_check_string_type(times);
     if (!NIL_P(tmp)) {
 	return rb_ary_join(ary, tmp);
     }
 
-    len = NUM2LONG(times);
-    if (len == 0) {
-	ary2 = ary_new(rb_obj_class(ary), 0);
+    const long len = NUM2LONG(times);
+    if (len < 0) {
+	rb_raise(rb_eArgError, "negative argument");
     }
-    else {
-	if (len < 0) {
-	    rb_raise(rb_eArgError, "negative argument");
-	}
-	n = RARRAY_LEN(ary);
+    VALUE ary2 = ary_new(rb_obj_class(ary), 0);
+    if (len > 0) {
+	const long n = RARRAY_LEN(ary);
 	if (LONG_MAX/len < n) {
 	    rb_raise(rb_eArgError, "argument too big");
 	}
-	ary2 = ary_new(rb_obj_class(ary), 0);
-	for (i = 0; i < len; i++) {
-	    CFArrayAppendArray((CFMutableArrayRef)ary2,
-		    (CFArrayRef)ary,
-		    CFRangeMake(0, n));
+
+	for (long i = 0; i < len; i++) {
+	    rb_ary_concat(ary2, ary);
 	}
     }
 
     if (OBJ_TAINTED(ary)) {
 	OBJ_TAINT(ary2);
     }
-
     return ary2;
 }
 
@@ -2441,14 +2771,11 @@
 static VALUE
 rb_ary_assoc(VALUE ary, SEL sel, VALUE key)
 {
-    long i;
-    VALUE v;
-
-    for (i = 0; i < RARRAY_LEN(ary); ++i) {
-	v = rb_check_array_type(RARRAY_AT(ary, i));
-	if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
-	    rb_equal(RARRAY_AT(v, 0), key))
+    for (long i = 0; i < RARRAY_LEN(ary); ++i) {
+	VALUE v = rb_check_array_type(RARRAY_AT(ary, i));
+	if (!NIL_P(v) && RARRAY_LEN(v) > 0 && rb_equal(RARRAY_AT(v, 0), key)) {
 	    return v;
+	}
     }
     return Qnil;
 }
@@ -2470,15 +2797,12 @@
 static VALUE
 rb_ary_rassoc(VALUE ary, SEL sel, VALUE value)
 {
-    long i;
-    VALUE v;
-
-    for (i = 0; i < RARRAY_LEN(ary); ++i) {
-	v = RARRAY_AT(ary, i);
-	if (TYPE(v) == T_ARRAY &&
-	    RARRAY_LEN(v) > 1 &&
-	    rb_equal(RARRAY_AT(v, 1), value))
+    for (long i = 0; i < RARRAY_LEN(ary); ++i) {
+	VALUE v = RARRAY_AT(ary, i);
+	if (TYPE(v) == T_ARRAY && RARRAY_LEN(v) > 1
+	    && rb_equal(RARRAY_AT(v, 1), value)) {
 	    return v;
+	}
     }
     return Qnil;
 }
@@ -2497,8 +2821,32 @@
  *
  */
 
+VALUE
+rb_ary_equal(VALUE ary1, VALUE ary2)
+{
+    if (IS_RARY(ary1) && IS_RARY(ary2)) {
+	if (RARY(ary1)->len != RARY(ary2)->len) {
+	    return Qfalse;
+	}
+	for (size_t i = 0; i < RARY(ary1)->len; i++) {
+	    VALUE item1 = RARY(ary1)->elements[i];
+	    VALUE item2 = RARY(ary2)->elements[i];
+
+	    if ((FIXFLOAT_P(item1) && isnan(FIXFLOAT2DBL(item1)))
+		|| FIXFLOAT_P(item2) && isnan(FIXFLOAT2DBL(item2))) {
+		return Qfalse;
+	    }
+	    if (item1 != item2 && rb_equal(item1, item2) == Qfalse) {
+		return Qfalse;
+	    }
+	}
+	return Qtrue;
+    }
+    return CFEqual((CFTypeRef)ary1, (CFTypeRef)ary2) ? Qtrue : Qfalse;
+}
+
 static VALUE
-rb_ary_equal(VALUE ary1, SEL sel, VALUE ary2)
+rb_ary_equal_imp(VALUE ary1, SEL sel, VALUE ary2)
 {
     if (ary1 == ary2) {
 	return Qtrue;
@@ -2509,16 +2857,16 @@
 	}
 	return rb_equal(ary2, ary1);
     }
-    return CFEqual((CFTypeRef)ary1, (CFTypeRef)ary2) ? Qtrue : Qfalse;
+    return rb_ary_equal(ary1, ary2);
 }
 
 static VALUE
 recursive_eql(VALUE ary1, VALUE ary2, int recur)
 {
-    long i;
-
-    if (recur) return Qfalse;
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
+    if (recur) {
+	return Qfalse;
+    }
+    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
 	if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
 	    return Qfalse;
     }
@@ -2536,9 +2884,15 @@
 static VALUE
 rb_ary_eql(VALUE ary1, SEL sel, VALUE ary2)
 {
-    if (ary1 == ary2) return Qtrue;
-    if (TYPE(ary2) != T_ARRAY) return Qfalse;
-    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
+    if (ary1 == ary2) {
+	return Qtrue;
+    }
+    if (TYPE(ary2) != T_ARRAY) {
+	return Qfalse;
+    }
+    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) {
+	return Qfalse;
+    }
     return rb_exec_recursive(recursive_eql, ary1, ary2);
 }
 
@@ -2558,8 +2912,19 @@
 static VALUE
 rb_ary_includes_imp(VALUE ary, SEL sel, VALUE item)
 {
-    return CFArrayContainsValue((CFArrayRef)ary, 
-	CFRangeMake(0, RARRAY_LEN(ary)), (const void *)RB2OC(item)) ? Qtrue : Qfalse;
+    if (IS_RARY(ary)) {
+	if (RARY(ary)->len == 0) {
+	    return Qfalse;
+	}
+	return rary_index_of_item(RARY(ary), 0, item) != NOT_FOUND
+	    ? Qtrue : Qfalse;
+    }
+    else {
+	const long len = RARRAY_LEN(ary);
+	const void *ocitem = RB2OC(item);
+	return CFArrayContainsValue((CFArrayRef)ary, CFRangeMake(0, len),
+		ocitem) ? Qtrue : Qfalse;
+    }
 }
 
 VALUE
@@ -2571,14 +2936,16 @@
 static VALUE
 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
 {
-    long i, len;
+    if (recur) {
+	return Qnil;
+    }
 
-    if (recur) return Qnil;
-    len = RARRAY_LEN(ary1);
+    long len = RARRAY_LEN(ary1);
     if (len > RARRAY_LEN(ary2)) {
 	len = RARRAY_LEN(ary2);
     }
-    for (i=0; i<len; i++) {
+
+    for (long i = 0; i < len; i++) {
 	VALUE v = rb_objs_cmp(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i));
 	if (v != INT2FIX(0)) {
 	    return v;
@@ -2610,30 +2977,29 @@
 static VALUE
 rb_ary_cmp(VALUE ary1, SEL sel, VALUE ary2)
 {
-    long len;
-    VALUE v;
+    ary2 = to_ary(ary2);
+    if (ary1 == ary2) {
+	return INT2FIX(0);
+    }
 
-    ary2 = to_ary(ary2);
-    if (ary1 == ary2) return INT2FIX(0);
-    v = rb_exec_recursive(recursive_cmp, ary1, ary2);
-    if (v != Qundef) return v;
-    len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
-    if (len == 0) return INT2FIX(0);
-    if (len > 0) return INT2FIX(1);
-    return INT2FIX(-1);
+    VALUE v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+    if (v != Qundef) {
+	return v;
+    }
+    
+    const long len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
+    return len == 0 ? INT2FIX(0) : len > 0 ? INT2FIX(1) : INT2FIX(-1);
 }
 
 static VALUE
 ary_make_hash(VALUE ary1, VALUE ary2)
 {
     VALUE hash = rb_hash_new();
-    long i;
-
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
+    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
 	rb_hash_aset(hash, RARRAY_AT(ary1, i), Qtrue);
     }
     if (ary2) {
-	for (i=0; i<RARRAY_LEN(ary2); i++) {
+	for (long i = 0; i < RARRAY_LEN(ary2); i++) {
 	    rb_hash_aset(hash, RARRAY_AT(ary2, i), Qtrue);
 	}
     }
@@ -2655,18 +3021,14 @@
 static VALUE
 rb_ary_diff(VALUE ary1, SEL sel, VALUE ary2)
 {
-    VALUE ary3;
-    volatile VALUE hash;
-    long i;
+    VALUE hash = ary_make_hash(to_ary(ary2), 0);
+    VALUE ary3 = rb_ary_new();
 
-    hash = ary_make_hash(to_ary(ary2), 0);
-    ary3 = rb_ary_new();
-
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
-	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));
+    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
+	VALUE v = RARRAY_AT(ary1, i);
+	if (rb_hash_has_key(hash, v) == Qfalse) {
+	    rb_ary_push(ary3, rb_ary_elt(ary1, i));
+	}
     }
     return ary3;
 }
@@ -2681,31 +3043,28 @@
  *     [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
  */
 
+static void
+filter_diff(VALUE ary1, VALUE ary3, VALUE hash)
+{
+    for (long i = 0; i < RARRAY_LEN(ary1); i++) {
+	VALUE v = RARRAY_AT(ary1, i);
+	if (rb_hash_delete_key(hash, v) != Qundef) {
+	    rb_ary_push(ary3, v);
+	}
+    }
+}
 
 static VALUE
 rb_ary_and(VALUE ary1, SEL sel, VALUE ary2)
 {
-    VALUE hash, ary3, v, vv;
-    long i;
-
     ary2 = to_ary(ary2);
-    ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
+    VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
 	    RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
-    hash = ary_make_hash(ary2, 0);
-
-    if (RHASH_EMPTY_P(hash))
+    VALUE hash = ary_make_hash(ary2, 0);
+    if (RHASH_EMPTY_P(hash)) {
         return ary3;
-
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
-	v = vv = rb_ary_elt(ary1, i);
-	id ocvv = RB2OC(vv);
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
-	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)ocvv);
-	    rb_ary_push(ary3, v);
-	}
     }
-
+    filter_diff(ary1, ary3, hash);
     return ary3;
 }
 
@@ -2723,32 +3082,12 @@
 static VALUE
 rb_ary_or(VALUE ary1, SEL sel, VALUE ary2)
 {
-    VALUE hash, ary3;
-    VALUE v, vv;
-    long i;
-
     ary2 = to_ary(ary2);
-    ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
-    hash = ary_make_hash(ary1, ary2);
+    VALUE ary3 = rb_ary_new2(RARRAY_LEN(ary1) + RARRAY_LEN(ary2));
+    VALUE hash = ary_make_hash(ary1, ary2);
 
-    for (i=0; i<RARRAY_LEN(ary1); i++) {
-	v = vv = rb_ary_elt(ary1, i);
-	id ocvv = RB2OC(vv);
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
-	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)ocvv);
-	    rb_ary_push(ary3, v);
-	}
-    }
-    for (i=0; i<RARRAY_LEN(ary2); i++) {
-	v = vv = rb_ary_elt(ary2, i);
-	id ocvv = RB2OC(vv);
-	if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
-	    CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
-		(const void *)ocvv);
-	    rb_ary_push(ary3, v);
-	}
-    }
+    filter_diff(ary1, ary3, hash);
+    filter_diff(ary2, ary3, hash);
     return ary3;
 }
 
@@ -2769,31 +3108,40 @@
 static VALUE
 rb_ary_uniq_bang(VALUE ary, SEL sel)
 {
-    long i, n;
-    bool changed;
-
     rb_ary_modify(ary);
-    n = RARRAY_LEN(ary);
-    for (i = 0, changed = false; i < n; i++) {
-	VALUE e;
-	id oce;
-	long idx;
-     	CFRange r;
+    long n = RARRAY_LEN(ary);
+    bool changed = false;
 
-        e = RARRAY_AT(ary, i);
-	oce = RB2OC(e);
-	r = CFRangeMake(i + 1, n - i - 1);	
-	while ((idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, 
-	    r, (const void *)oce)) != -1) {
-	    CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, idx);
-	    r.location = idx;
-	    r.length = --n - idx;
-	    changed = true;
+    if (IS_RARY(ary)) {
+	for (size_t i = 0; i < n; i++) {
+	    VALUE item = RARY(ary)->elements[i];
+	    size_t pos = i + 1;
+	    while (pos < n && (pos = rary_index_of_item(RARY(ary), pos, item))
+		    != NOT_FOUND) {
+		rary_erase(RARY(ary), pos, 1);
+		n--;
+		changed = true;
+	    }
 	}
     }
-    if (!changed)
+    else {
+	for (long i = 0; i < n; i++) {
+	    const void *ocval = RB2OC(RARRAY_AT(ary, i));
+	    CFRange r = CFRangeMake(i + 1, n - i - 1);
+	    long idx = 0;
+	    while ((idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, 
+			    r, ocval)) != -1) {
+		CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, idx);
+		r.location = idx;
+		r.length = --n - idx;
+		changed = true;
+	    }
+	}
+    }
+
+    if (!changed) {
 	return Qnil;
-
+    }
     return ary;
 }
 
@@ -2829,26 +3177,9 @@
 static VALUE
 rb_ary_compact_bang(VALUE ary, SEL sel)
 {
-    long i, n, k;
-    CFRange r;
-
-    rb_ary_modify(ary);
-    n = RARRAY_LEN(ary);
-    if (n == 0)
-	return Qnil;
-    k = 0;
-    r = CFRangeMake(0, n);
-    while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
-	r, (const void *)kCFNull)) != -1) {
-	CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
-	r.location = i;
-	r.length = --n - i;
-	k++;
-    }
-    if (k == 0)
-	return Qnil;
-
-    return ary;
+    const long n = RARRAY_LEN(ary);
+    rb_ary_delete(ary, Qnil);
+    return RARRAY_LEN(ary) == n ? Qnil : ary;
 }
 
 /*
@@ -2892,12 +3223,12 @@
     long n = 0;
  
     if (argc == 0) {
-	long i, count = RARRAY_LEN(ary);
+	long count = RARRAY_LEN(ary);
 
 	if (!rb_block_given_p())
 	    return LONG2NUM(count);
 
-	for (i = 0; i < count; i++) {
+	for (long i = 0; i < count; i++) {
 	    VALUE v = rb_yield(RARRAY_AT(ary, i)); 
 	    RETURN_IF_BROKEN();
 	    if (RTEST(v)) {
@@ -2907,13 +3238,27 @@
     }
     else {
 	VALUE obj;
-	long count = RARRAY_LEN(ary);
+	const long count = RARRAY_LEN(ary);
 
 	rb_scan_args(argc, argv, "1", &obj);
 	if (rb_block_given_p()) {
 	    rb_warn("given block not used");
 	}
-	n = CFArrayGetCountOfValue((CFArrayRef)ary, CFRangeMake(0, count), RB2OC(obj));
+
+	if (IS_RARY(ary)) {
+	    size_t pos = 0;
+	    while ((pos = rary_index_of_item(RARY(ary), pos, obj))
+		    != NOT_FOUND) {
+		++n;
+		if (++pos == count) {
+		    break;
+		}
+	    }
+	}
+	else {
+	    n = CFArrayGetCountOfValue((CFArrayRef)ary, CFRangeMake(0, count),
+		    RB2OC(obj));
+	}
     }
 
     return LONG2NUM(n);
@@ -3058,7 +3403,6 @@
  *  Shuffles elements in _self_ in place.
  */
 
-
 static VALUE
 rb_ary_shuffle_bang(VALUE ary, SEL sel)
 {
@@ -3066,13 +3410,14 @@
 
     rb_ary_modify(ary);
     while (i) {
-	long j = rb_genrand_real()*i;
-	CFArrayExchangeValuesAtIndices((CFMutableArrayRef)ary, --i, j);
+	const long j = rb_genrand_real() * i;
+	VALUE elem = rb_ary_elt(ary, --i);
+	rb_ary_store(ary, i, rb_ary_elt(ary, j));
+	rb_ary_store(ary, j, elem);
     }
     return ary;
 }
 
-
 /*
  *  call-seq:
  *     array.shuffle -> an_array
@@ -3091,7 +3436,6 @@
     return ary;
 }
 
-
 /*
  *  call-seq:
  *     array.sample        -> obj
@@ -3102,7 +3446,6 @@
  *  second form returns an empty array.
  */
 
-
 static VALUE
 rb_ary_sample(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
@@ -3156,7 +3499,7 @@
 	    return rb_ary_new3(3, RARRAY_AT(ary, i), RARRAY_AT(ary, j),
 		    RARRAY_AT(ary, k));
     }
-    if (n < sizeof(idx) / sizeof(idx[0])) {
+    if ((unsigned long)n < sizeof(idx) / sizeof(idx[0])) {
 	long sorted[sizeof(idx) / sizeof(idx[0])];
 	sorted[0] = idx[0] = rb_genrand_real()*len;
 	for (i = 1; i < n; i++) {
@@ -3189,7 +3532,6 @@
     return result;
 }
 
-
 /*
  *  call-seq:
  *     ary.cycle {|obj| block }
@@ -3209,22 +3551,24 @@
 static VALUE
 rb_ary_cycle(VALUE ary, SEL sel, int argc, VALUE *argv)
 {
-    long n, i;
     VALUE nv = Qnil;
-
     rb_scan_args(argc, argv, "01", &nv);
 
     RETURN_ENUMERATOR(ary, argc, argv);
+
+    long n;
     if (NIL_P(nv)) {
         n = -1;
     }
     else {
         n = NUM2LONG(nv);
-        if (n <= 0) return Qnil;
+        if (n <= 0) {
+	    return Qnil;
+	}
     }
 
     while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
-        for (i=0; i<RARRAY_LEN(ary); i++) {
+        for (long i = 0; i < RARRAY_LEN(ary); i++) {
             rb_yield(RARRAY_AT(ary, i));
 	    RETURN_IF_BROKEN();
         }
@@ -3506,7 +3850,7 @@
 static VALUE
 rb_ary_take(VALUE obj, SEL sel, VALUE n)
 {
-    long len = NUM2LONG(n);
+    const long len = NUM2LONG(n);
     if (len < 0) {
 	rb_raise(rb_eArgError, "attempt to take negative size");
     }
@@ -3528,10 +3872,9 @@
 static VALUE
 rb_ary_take_while(VALUE ary, SEL sel)
 {
-    long i;
-
     RETURN_ENUMERATOR(ary, 0, 0);
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
+    long i = 0;
+    for (; i < RARRAY_LEN(ary); i++) {
 	VALUE v = rb_yield(RARRAY_AT(ary, i));
 	RETURN_IF_BROKEN();
 	if (!RTEST(v)) {
@@ -3556,14 +3899,15 @@
 static VALUE
 rb_ary_drop(VALUE ary, SEL sel, VALUE n)
 {
-    VALUE result;
-    long pos = NUM2LONG(n);
+    const long pos = NUM2LONG(n);
     if (pos < 0) {
 	rb_raise(rb_eArgError, "attempt to drop negative size");
     }
 
-    result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
-    if (result == Qnil) result = rb_ary_new();
+    VALUE result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
+    if (result == Qnil) {
+	result = rb_ary_new();
+    }
     return result;
 }
 
@@ -3583,10 +3927,9 @@
 static VALUE
 rb_ary_drop_while(VALUE ary, SEL sel)
 {
-    long i;
-
     RETURN_ENUMERATOR(ary, 0, 0);
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
+    long i = 0;
+    for (; i < RARRAY_LEN(ary); i++) {
 	VALUE v = rb_yield(RARRAY_AT(ary, i));
 	RETURN_IF_BROKEN();
 	if (!RTEST(v)) {
@@ -3606,7 +3949,7 @@
 bool
 rb_objc_ary_is_pure(VALUE ary)
 {
-    return *(Class *)ary == (Class)rb_cCFArray;
+    return *(Class *)ary == (Class)rb_cRubyArray;
 }
 
 static CFIndex
@@ -3671,7 +4014,7 @@
     RESTORE_RCV(rcv);
 }
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+#if MAC_OS_X_VERSION_MAX_ALLOWED <1060
 static CFIndex
 imp_rb_array_cfindexOfObjectInRange(void *rcv, SEL sel, void *obj, 
     CFRange range)
@@ -3691,10 +4034,10 @@
     rb_objc_install_method2(klass, "objectAtIndex:",
 	    (IMP)imp_rb_array_objectAtIndex);
 
-    const bool mutable = class_getSuperclass(klass)
+    const bool is_mutable = class_getSuperclass(klass)
 	== (Class)rb_cNSMutableArray;
 
-    if (mutable) {
+    if (is_mutable) {
 	rb_objc_install_method2(klass, "insertObject:atIndex:",
 		(IMP)imp_rb_array_insertObjectAtIndex);
 	rb_objc_install_method2(klass, "removeObjectAtIndex:",
@@ -3723,6 +4066,44 @@
     rb_objc_define_method(*(VALUE *)klass, "alloc", ary_alloc, 0);
 }
 
+static CFIndex
+imp_rary_count(void *rcv, SEL sel)
+{
+    return RARY(rcv)->len;
+}
+
+static const void *
+imp_rary_objectAtIndex(void *rcv, SEL sel, CFIndex idx)
+{
+    assert(idx < RARY(rcv)->len);
+    return RB2OC(RARY(rcv)->elements[idx]);
+}
+
+static void
+imp_rary_insertObjectAtIndex(void *rcv, SEL sel, void *obj, CFIndex idx)
+{
+    rary_insert(RARY(rcv), idx, OC2RB(obj));
+}
+
+static void
+imp_rary_removeObjectAtIndex(void *rcv, SEL sel, CFIndex idx)
+{
+    rary_erase(RARY(rcv), idx, 1);
+}
+
+static void
+imp_rary_replaceObjectAtIndexWithObject(void *rcv, SEL sel, CFIndex idx, 
+	void *obj)
+{
+    rary_store(RARY(rcv), idx, OC2RB(obj));
+}
+
+static void
+imp_rary_addObject(void *rcv, SEL sel, void *obj)
+{
+    rary_append(RARY(rcv), OC2RB(obj));
+}
+
 /* 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 
@@ -3756,7 +4137,7 @@
     rb_objc_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
     rb_objc_define_method(rb_cArray, "frozen?",  rb_ary_frozen_imp, 0);
 
-    rb_objc_define_method(rb_cArray, "==", rb_ary_equal, 1);
+    rb_objc_define_method(rb_cArray, "==", rb_ary_equal_imp, 1);
     rb_objc_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
 
     rb_objc_define_method(rb_cArray, "[]", rb_ary_aref, -1);
@@ -3848,5 +4229,19 @@
     rb_objc_define_method(rb_cArray, "dup", rb_ary_dup_imp, 0);
     rb_objc_define_method(rb_cArray, "clone", rb_ary_clone, 0);
 
-    //Init_RubyArray();
+    rb_cRubyArray = rb_define_class("RubyArray", rb_cNSMutableArray);
+    rb_objc_define_method(*(VALUE *)rb_cRubyArray, "alloc", ary_alloc, 0);
+    rb_objc_install_method2((Class)rb_cRubyArray, "count", (IMP)imp_rary_count);
+    rb_objc_install_method2((Class)rb_cRubyArray, "objectAtIndex:",
+	    (IMP)imp_rary_objectAtIndex);
+
+    rb_objc_install_method2((Class)rb_cRubyArray, "insertObject:atIndex:",
+	    (IMP)imp_rary_insertObjectAtIndex);
+    rb_objc_install_method2((Class)rb_cRubyArray, "removeObjectAtIndex:",
+	    (IMP)imp_rary_removeObjectAtIndex);
+    rb_objc_install_method2((Class)rb_cRubyArray,
+	    "replaceObjectAtIndex:withObject:", 
+	    (IMP)imp_rary_replaceObjectAtIndexWithObject);
+    rb_objc_install_method2((Class)rb_cRubyArray, "addObject:",
+	    (IMP)imp_rary_addObject);
 }

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/class.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -30,6 +30,10 @@
 {
     if (rb_cArray != 0 && rb_cHash != 0 && rb_cString != 0 && rb_cSet != 0) {
 	do {
+	    if (ocsuper == (Class)rb_cRubyArray) {
+		RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);
+		return false;
+	    }
 	    if (ocsuper == (Class)rb_cArray) {
 		rb_objc_install_array_primitives(ocklass);
 		RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/compiler.cpp	2009-08-11 06:19:45 UTC (rev 2274)
@@ -8,18 +8,7 @@
 
 #define ROXOR_COMPILER_DEBUG 	0
 
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/Constants.h>
-#include <llvm/CallingConv.h>
-#include <llvm/Instructions.h>
-#include <llvm/ModuleProvider.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/ExecutionEngine/JIT.h>
-#include <llvm/PassManager.h>
-#include <llvm/Target/TargetData.h>
-using namespace llvm;
-
+#include "llvm.h"
 #include "ruby/ruby.h"
 #include "ruby/node.h"
 #include "id.h"
@@ -723,7 +712,10 @@
 	params.push_back(*i);
     }
 
-    compile_dispatch_call(params);
+    if (compile_optimized_dispatch_call(sel, argc, params) == NULL) {
+	compile_dispatch_call(params);
+    }
+    // The return value of these assignments is always the new value.
     return params.back();
 }
 
@@ -2358,6 +2350,12 @@
 	    return NULL;
 	}
 
+	if (params.size() - argc > 6) {
+	    // Looks like there is a splat argument there, we can't handle this
+	    // in the primitives.
+	    return NULL;
+	}
+
 	Function *opt_func = NULL;
 
 	if (sel == selLTLT) {
@@ -2382,13 +2380,7 @@
 	    new_params.push_back(params.back());	// other
 	}
 	else {
-	    // Damn I hate the STL.
-	    std::vector<Value *>::iterator iter = params.end();
-	    --iter;
-	    --iter;
-	    new_params.push_back(*iter);		// other1
-	    ++iter;
-	    new_params.push_back(*iter);		// other2
+	    new_params.insert(new_params.end(), params.end() - 2, params.end());
 	}
 	new_params.push_back(params[0]);		// cache
 

Modified: MacRuby/trunk/enum.c
===================================================================
--- MacRuby/trunk/enum.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/enum.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -702,20 +702,10 @@
 }
 
 static int
-sort_by_cmp(const void *ap, const void *bp, void *data)
+sort_by_cmp(void *data, const void *ap, const void *bp)
 {
-#if WITH_OBJC
-    VALUE a = ((NODE *)ap)->u1.value;
-    VALUE b = ((NODE *)bp)->u1.value;
-#else
     VALUE a = (*(NODE *const *)ap)->u1.value;
     VALUE b = (*(NODE *const *)bp)->u1.value;
-    VALUE ary = (VALUE)data;
-    
-    if (RBASIC(ary)->klass) {
-	rb_raise(rb_eRuntimeError, "sort_by reentered");
-    }
-#endif
     return rb_cmpint(rb_objs_cmp(a, b), a, b);
 }
 
@@ -791,11 +781,9 @@
 static VALUE
 enum_sort_by(VALUE obj, SEL sel)
 {
-    VALUE ary;
-    long i;
-
     RETURN_ENUMERATOR(obj, 0, 0);
 
+    VALUE ary;
     if (TYPE(obj) == T_ARRAY) {
 	ary  = rb_ary_new2(RARRAY_LEN(obj));
     }
@@ -804,11 +792,10 @@
     }
     rb_objc_block_call(obj, selEach, cacheEach, 0, 0, sort_by_i, ary);
     if (RARRAY_LEN(ary) > 1) {
-	CFArraySortValues((CFMutableArrayRef)ary, 
-	    CFRangeMake(0, RARRAY_LEN(ary)),
-	    (CFComparatorFunction)sort_by_cmp, (void *)ary);
+	qsort_r((VALUE *)RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE), NULL,
+		sort_by_cmp);
     }
-    for (i=0; i<RARRAY_LEN(ary); i++) {
+    for (long i = 0; i < RARRAY_LEN(ary); i++) {
 	rb_ary_store(ary, i, RNODE(RARRAY_AT(ary, i))->u2.value);
     }
     return ary;

Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/gc.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -31,13 +31,9 @@
 #endif
 
 #include <mach/mach.h>
-#if HAVE_AUTO_ZONE_H
-# include <auto_zone.h>
-#else
-# include "auto_zone.h"
-#endif
-static auto_zone_t *__auto_zone = NULL;
 
+auto_zone_t *__auto_zone = NULL;
+
 static VALUE nomem_error;
 
 static bool dont_gc = false;
@@ -248,18 +244,6 @@
     return auto_read_weak_reference(__auto_zone, referrer);
 }
 
-
-void
-rb_objc_wb(void *dst, void *newval)
-{
-    if (!SPECIAL_CONST_P(newval)) {
-	if (!auto_zone_set_write_barrier(__auto_zone, dst, newval)) {
-	    rb_bug("destination %p isn't in the auto zone", dst);
-	}
-    }
-    *(void **)dst = newval;
-}
-
 void *
 rb_gc_memmove(void *dst, const void *src, size_t len)
 {
@@ -267,43 +251,29 @@
 }
 
 void
-rb_objc_root(void *addr)
+rb_objc_set_associative_ref(void *obj, void *key, void *val)
 {
-    if (addr != NULL) {
-	auto_zone_add_root(__auto_zone, addr, *(void **)addr);
-    }
+    auto_zone_set_associative_ref(__auto_zone, obj, key, val);
 }
 
-const void *
-rb_objc_retain(const void *addr)
+void *
+rb_objc_get_associative_ref(void *obj, void *key)
 {
-    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
-	auto_zone_retain(__auto_zone, (void *)addr);
-    }
-    return addr;
+    return auto_zone_get_associative_ref(__auto_zone, obj, key);
 }
 
 const void *
-rb_objc_release(const void *addr)
+rb_objc_retain_ni(const void *addr)
 {
-    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
-	auto_zone_release(__auto_zone, (void *)addr);
-    }
-    return addr;
+    return rb_objc_retain(addr);
 }
 
-void
-rb_objc_set_associative_ref(void *obj, void *key, void *val)
+const void *
+rb_objc_release_ni(const void *addr)
 {
-    auto_zone_set_associative_ref(__auto_zone, obj, key, val);
+    return rb_objc_release(addr);
 }
 
-void *
-rb_objc_get_associative_ref(void *obj, void *key)
-{
-    return auto_zone_get_associative_ref(__auto_zone, obj, key);
-}
-
 void
 rb_gc_register_address(VALUE *addr)
 {
@@ -998,6 +968,7 @@
 static void
 rb_obj_imp_finalize(void *obj, SEL sel)
 {
+#if 0
 //    const bool need_protection = 
 //	GET_THREAD()->thread_id != pthread_self();
     bool call_finalize, free_ivar;
@@ -1029,6 +1000,7 @@
 //	    native_mutex_unlock(&GET_THREAD()->vm->global_interpreter_lock);
 //	}
     }
+#endif
 }
 
 static bool gc_disabled = false;

Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/hash.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -686,7 +686,7 @@
     return rb_hash_key(hash, 0, value);
 }
 
-static VALUE
+VALUE
 rb_hash_delete_key(VALUE hash, VALUE key)
 {
     VALUE val;

Modified: MacRuby/trunk/include/ruby/defines.h
===================================================================
--- MacRuby/trunk/include/ruby/defines.h	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/include/ruby/defines.h	2009-08-11 06:19:45 UTC (rev 2274)
@@ -280,35 +280,7 @@
 
 #define WITH_OBJC 1 /* TODO: this should be set by configure */
 
-#if WITH_OBJC
-# include <objc/objc.h>
-# include <objc/runtime.h>
-# include <objc/message.h>
-# include <objc/objc-auto.h>
-# include <assert.h>
-# include <CoreFoundation/CoreFoundation.h>
-# define ASSERT_NO_OBJC() (assert(1 == 0))
-void rb_objc_wb(void *dst, void *newval);
-void rb_objc_root(void *addr);
-# define GC_WB(dst, newval) \
-    do { \
-	void *nv = (void *)newval; \
-	if (SPECIAL_CONST_P(nv)) { \
-	    *(void **)dst = nv; \
-	} \
-	else { \
-	    rb_objc_wb((void *)dst, (void *)nv); \
-	} \
-    } \
-    while (0)
-# define GC_ROOT(dst) (rb_objc_root((void *)dst))
-# define GC_WEAK(dst) (rb_objc_weak((void *)dst))
-#else
-# define ASSERT_NO_OBJC
-# define GC_WB(dst, newval) do { *(void **)dst = (void *)newval; } while (0)
-# define GC_ROOT(dst)
-# define GC_WEAK(dst)
-#endif
+#define force_inline __attribute__((always_inline))
 
 #if defined(__cplusplus)
 #if 0

Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/include/ruby/intern.h	2009-08-11 06:19:45 UTC (rev 2274)
@@ -73,8 +73,11 @@
 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);
+VALUE rb_ary_equal(VALUE, VALUE);
 #if WITH_OBJC
+long rb_ary_len(VALUE);
 VALUE rb_ary_elt(VALUE, long);
+VALUE rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
 bool rb_objc_ary_is_pure(VALUE);
 #endif
 /* bignum.c */
@@ -366,6 +369,7 @@
 VALUE rb_hash_aset(VALUE, VALUE, VALUE);
 //VALUE rb_hash_delete_if(VALUE);
 VALUE rb_hash_delete(VALUE,VALUE);
+VALUE rb_hash_delete_key(VALUE,VALUE);
 VALUE rb_hash_has_key(VALUE hash, VALUE key);
 VALUE rb_hash_keys(VALUE hash);
 struct st_table *rb_hash_tbl(VALUE);

Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/include/ruby/ruby.h	2009-08-11 06:19:45 UTC (rev 2274)
@@ -77,6 +77,18 @@
 #include "defines.h"
 #endif
 
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <objc/message.h>
+#include <objc/objc-auto.h>
+#include <assert.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#if HAVE_AUTO_ZONE_H
+# include <auto_zone.h>
+#else
+# include "auto_zone.h"
+#endif
 #if defined(HAVE_ALLOCA_H)
 #include <alloca.h>
 #else
@@ -640,7 +652,8 @@
 # define RARRAY_PTR(a) RARRAY(a)->ptr
 # define RARRAY_AT(a,i) RARRAY_PTR(a)[i]
 #else
-# define RARRAY_LEN(a) (CFArrayGetCount((CFArrayRef)a))
+# define RARRAY_LEN(a) (rb_ary_len((VALUE)a))
+# define RARRAY_AT(a,i) (rb_ary_elt((VALUE)a, (long)i))
 /* IMPORTANT: try to avoid using RARRAY_PTR if necessary, because it's
  * a _much_ slower operation than RARRAY_AT. RARRAY_PTR is only provided for
  * compatibility but should _not_ be used intensively.
@@ -1095,6 +1108,7 @@
 #endif
 RUBY_EXTERN VALUE rb_cNSArray;
 RUBY_EXTERN VALUE rb_cNSMutableArray;
+RUBY_EXTERN VALUE rb_cRubyArray;
 RUBY_EXTERN VALUE rb_cCFHash;
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
 RUBY_EXTERN VALUE rb_cNSHash0; 
@@ -1246,35 +1260,34 @@
 }
 #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
+static force_inline VALUE
 rb_class_of(VALUE obj)
 {
     if (IMMEDIATE_P(obj)) {
-	if (FIXNUM_P(obj)) return rb_cFixnum;
-	if (FIXFLOAT_P(obj)) return rb_cFloat;
-	if (obj == Qtrue)  return rb_cTrueClass;
-#if !WITH_OBJC
-	if (SYMBOL_P(obj)) return rb_cSymbol;
-#endif
+	if (FIXNUM_P(obj)) {
+	    return rb_cFixnum;
+	}
+	if (FIXFLOAT_P(obj)) {
+	    return rb_cFloat;
+	}
+	if (obj == Qtrue) {
+	    return rb_cTrueClass;
+	}
     }
     else if (!RTEST(obj)) {
-	if (obj == Qnil)   return rb_cNilClass;
-	if (obj == Qfalse) return rb_cFalseClass;
+	if (obj == Qnil) {
+	    return rb_cNilClass;
+	}
+	if (obj == Qfalse) {
+	    return rb_cFalseClass;
+	}
     }
     return RBASIC(obj)->klass;
 }
 
-static inline int
+static force_inline int
 rb_type(VALUE obj)
 {
     Class k;
@@ -1307,19 +1320,13 @@
     }
 #if WITH_OBJC
     else if ((k = *(Class *)obj) != NULL) {
-	if (k == (Class)rb_cCFString
-	    || (RCLASS_VERSION(k) & RCLASS_IS_STRING_SUBCLASS) 
-		== RCLASS_IS_STRING_SUBCLASS) {
+	if (k == (Class)rb_cCFString) {
 	    return T_STRING;
 	}
-	if (k == (Class)rb_cCFArray
-	    || (RCLASS_VERSION(k) & RCLASS_IS_ARRAY_SUBCLASS) 
-		== RCLASS_IS_ARRAY_SUBCLASS) {
+	if (k == (Class)rb_cCFArray || k == (Class)rb_cRubyArray) {
 	    return T_ARRAY;
 	}
-	if (k == (Class)rb_cCFHash
-	    || (RCLASS_VERSION(k) & RCLASS_IS_HASH_SUBCLASS) 
-	        == RCLASS_IS_HASH_SUBCLASS) {
+	if (k == (Class)rb_cCFHash) {
 	    return T_HASH;
 	}
 	if (RCLASS_META(k)) {
@@ -1336,6 +1343,16 @@
 	if (k == (Class)rb_cFixnum) {
 	    return T_FIXNUM;
 	}
+	const long v = RCLASS_VERSION(k);
+	if ((v & RCLASS_IS_STRING_SUBCLASS) == RCLASS_IS_STRING_SUBCLASS) {
+	    return T_STRING;
+	}
+	if ((v & RCLASS_IS_ARRAY_SUBCLASS) == RCLASS_IS_ARRAY_SUBCLASS) {
+	    return T_ARRAY;
+	}
+	if ((v & RCLASS_IS_HASH_SUBCLASS) == RCLASS_IS_HASH_SUBCLASS) {
+	    return T_HASH;
+	}
 	if (NATIVE(obj)) {
 	    return T_NATIVE;
 	}
@@ -1344,6 +1361,13 @@
     return BUILTIN_TYPE(obj);
 }
 
+static inline void
+__ignore_stupid_gcc_warnings(void)
+{
+    TYPE(INT2FIX(0));
+    CLASS_OF(INT2FIX(0));
+}
+
 static inline int
 rb_special_const_p(VALUE obj)
 {
@@ -1351,6 +1375,49 @@
     return Qfalse;
 }
 
+extern auto_zone_t *__auto_zone;
+
+#define GC_WB(dst, newval) \
+    do { \
+	void *nv = (void *)newval; \
+	if (!SPECIAL_CONST_P(nv)) { \
+	    if (!auto_zone_set_write_barrier(__auto_zone, (const void *)dst, (const void *)nv)) { \
+		rb_bug("destination %p isn't in the auto zone", dst); \
+	    } \
+	} \
+	*(void **)dst = nv; \
+    } \
+    while (0)
+
+static inline void
+rb_objc_root(void *addr)
+{
+    if (addr != NULL) {
+	auto_zone_add_root(__auto_zone, addr, *(void **)addr);
+    }
+}
+#define GC_ROOT(addr) (rb_objc_root((void *)addr))
+
+static inline const void *
+rb_objc_retain(const void *addr)
+{
+    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
+        auto_zone_retain(__auto_zone, (void *)addr);
+    }
+    return addr;
+}
+#define GC_RETAIN(obj) (rb_objc_retain((const void *)obj))
+
+static inline const void *
+rb_objc_release(const void *addr)
+{
+    if (addr != NULL && !SPECIAL_CONST_P(addr)) {
+        auto_zone_release(__auto_zone, (void *)addr);
+    }
+    return addr;
+}
+#define GC_RELEASE(obj) (rb_objc_retain((const void *)obj))
+
 #if RUBY_INCLUDED_AS_FRAMEWORK
 #include <MacRuby/ruby/missing.h>
 #include <MacRuby/ruby/intern.h>

Added: MacRuby/trunk/llvm.h
===================================================================
--- MacRuby/trunk/llvm.h	                        (rev 0)
+++ MacRuby/trunk/llvm.h	2009-08-11 06:19:45 UTC (rev 2274)
@@ -0,0 +1,19 @@
+#ifndef __MR_LLVM_H_
+#define __MR_LLVM_H_
+
+// This file must be included at the very beginning of every C++ file in the
+// project, due to type collisions between LLVM and the MRI C API.
+
+#include <llvm/Module.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/CallingConv.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/PassManager.h>
+#include <llvm/Target/TargetData.h>
+using namespace llvm;
+
+#endif // __MR_LLVM_H_

Modified: MacRuby/trunk/numeric.c
===================================================================
--- MacRuby/trunk/numeric.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/numeric.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -1276,7 +1276,7 @@
 {
     double value = RFLOAT_VALUE(num);
 
-#if HAVE_FINITE
+#if 0//HAVE_FINITE
     if (!finite(value))
 	return Qfalse;
 #else

Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/object.c	2009-08-11 06:19:45 UTC (rev 2274)
@@ -150,21 +150,27 @@
 VALUE
 rb_class_real(VALUE cl)
 {
-    if (cl == 0)
+    if (cl == 0) {
         return 0;
-    if (RCLASS_META(cl))
+    }
+    if (RCLASS_META(cl)) {
 	return rb_cClass;
+    }
     while (RCLASS_SINGLETON(cl)) {
 	cl = RCLASS_SUPER(cl);
     }
-    if (cl == rb_cCFString)
+    if (cl == rb_cCFString) {
 	return rb_cNSMutableString;
-    if (cl == rb_cCFArray)
+    }
+    if (cl == rb_cCFArray || cl == rb_cRubyArray) {
 	return rb_cNSMutableArray;
-    if (cl == rb_cCFHash)
+    }
+    if (cl == rb_cCFHash) {
 	return rb_cNSMutableHash;
-    if (cl == rb_cCFSet)
+    }
+    if (cl == rb_cCFSet) {
 	return rb_cNSMutableSet;
+    }
     return cl;
 }
 
@@ -192,26 +198,9 @@
 init_copy(VALUE dest, VALUE obj)
 {
     if (NATIVE(obj)) {
-#ifdef __LP64__
-	switch (TYPE(obj)) {
-	    case T_STRING:
-	    case T_ARRAY:
-	    case T_HASH:
-		if (RCLASS_RC_FLAGS(obj) & FL_TAINT) {
-		    RCLASS_RC_FLAGS(dest) |= FL_TAINT;
-		}
-		/* fall through */
-	    default:
-		if (rb_objc_flag_check((const void *)obj, FL_TAINT)) {
-		    rb_objc_flag_set((const void *)dest, FL_TAINT, true);
-		}
-		break;
-	}
-#else
-	if (rb_objc_flag_check((const void *)obj, FL_TAINT)) {
-	    rb_objc_flag_set((const void *)dest, FL_TAINT, true);
-	}
-#endif
+	if (OBJ_TAINTED(obj)) {
+	    OBJ_TAINT(dest);
+	} 
 	goto call_init_copy;
     }
     if (OBJ_FROZEN(dest)) {
@@ -313,9 +302,9 @@
 	    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);
-#ifdef __LP64__
-	    RCLASS_RC_FLAGS(clone) = RCLASS_RC_FLAGS(obj);
-#endif
+//#ifdef __LP64__
+//	    RCLASS_RC_FLAGS(clone) = RCLASS_RC_FLAGS(obj);
+//#endif
 	    break;
     }
 
@@ -777,13 +766,17 @@
 {
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
+	    case T_ARRAY:
+		if (*(VALUE *)obj != rb_cCFArray) {
+		    return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
+		}
+		// fall through
 	    case T_STRING:
 		if (*(VALUE *)obj == rb_cByteString) {
 		    return rb_objc_flag_check((const void *)obj, FL_TAINT)
 			? Qtrue : Qfalse;
 		}
 		// fall through
-	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
 		return (RCLASS_RC_FLAGS(obj) & FL_TAINT) == FL_TAINT ? Qtrue : Qfalse;
@@ -813,13 +806,18 @@
     rb_secure(4);
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
+	    case T_ARRAY:
+		if (*(VALUE *)obj != rb_cCFArray) {
+		    RBASIC(obj)->flags |= FL_TAINT;
+		    break;
+		}
+		// fall through
 	    case T_STRING:
 		if (*(VALUE *)obj == rb_cByteString) {
 		    rb_objc_flag_set((const void *)obj, FL_TAINT, true);
 		    break;
 		}
 		// fall through
-	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
 		RCLASS_RC_FLAGS(obj) |= FL_TAINT;
@@ -853,13 +851,18 @@
     rb_secure(3);
     if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
 	switch (TYPE(obj)) {
+	    case T_ARRAY:
+		if (*(VALUE *)obj != rb_cCFArray) {
+		   RBASIC(obj)->flags &= ~FL_TAINT;
+		   break;
+		}	
+		// fall through
 	    case T_STRING:
 		if (*(VALUE *)obj == rb_cByteString) {
-		    // TODO
-		    return obj;
+		    rb_objc_flag_set((const void *)obj, FL_TAINT, false);
+		    break;
 		}
 		// fall through
-	    case T_ARRAY:
 	    case T_HASH:
 #ifdef __LP64__
 		RCLASS_RC_FLAGS(obj) &= ~FL_TAINT;
@@ -923,13 +926,18 @@
 	}
 	else if (NATIVE(obj)) {
 	    switch(TYPE(obj)) {
+		case T_ARRAY:
+		    if (*(VALUE *)obj != rb_cCFArray) {
+			RBASIC(obj)->flags |= FL_FREEZE;
+			break;
+		    }	
+		    // fall through
 		case T_STRING:
-		if (*(VALUE *)obj == rb_cByteString) {
-		    rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
-		    break;
-		}
-		// fall through
-		case T_ARRAY:
+		    if (*(VALUE *)obj == rb_cByteString) {
+			rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
+			break;
+		    }
+		    // fall through
 		case T_HASH:
 #ifdef __LP64__
 		    RCLASS_RC_FLAGS(obj) |= FL_FREEZE;
@@ -969,13 +977,17 @@
 	return Qfalse;
     }
     switch (TYPE(obj)) {
+	case T_ARRAY:
+	    if (*(VALUE *)obj != rb_cCFArray) {
+		return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
+	    }
+	    // fall through
 	case T_STRING:
 	    if (*(VALUE *)obj == rb_cByteString) {
 		return rb_objc_flag_check((const void *)obj, FL_FREEZE)
 		    ? Qtrue : Qfalse;
 	    }
 	    // fall through
-	case T_ARRAY:
 	case T_HASH:
 #ifdef __LP64__
 	    return (RCLASS_RC_FLAGS(obj) & FL_FREEZE) == FL_FREEZE ? Qtrue : Qfalse;
@@ -1691,6 +1703,10 @@
 {
     VALUE obj, init_obj, p;
 
+    if (klass == rb_cNSMutableArray) {
+	klass = rb_cRubyArray;
+    }
+
     obj = rb_obj_alloc0(klass);
 
     /* Because we cannot override +[NSObject initialize] */
@@ -2215,10 +2231,10 @@
 VALUE
 rb_convert_type(VALUE val, int type, const char *tname, const char *method)
 {
-    VALUE v;
-
-    if (TYPE(val) == type) return val;
-    v = convert_type(val, tname, method, Qtrue);
+    if (TYPE(val) == type) {
+	return val;
+    }
+    VALUE v = convert_type(val, tname, method, Qtrue);
     if (TYPE(v) != type) {
 	const char *cname = rb_obj_classname(val);
 	rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",

Modified: MacRuby/trunk/onig/regint.h
===================================================================
--- MacRuby/trunk/onig/regint.h	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/onig/regint.h	2009-08-11 06:19:45 UTC (rev 2274)
@@ -113,25 +113,25 @@
 
 /* Ruby-specific defines... */
 
-const void *rb_objc_retain(const void *addr);
-const void *rb_objc_release(const void *addr);
+const void *rb_objc_retain_ni(const void *addr);
+const void *rb_objc_release_ni(const void *addr);
 
 #define onig_st_init_table(t) \
-    ((st_table *)rb_objc_retain(st_init_table(t)))
+    ((st_table *)rb_objc_retain_ni(st_init_table(t)))
 #define onig_st_init_table_with_size(t, s) \
-    ((st_table *)rb_objc_retain(st_init_table_with_size(t, s)))
+    ((st_table *)rb_objc_retain_ni(st_init_table_with_size(t, s)))
 #define onig_st_init_numtable() \
-    ((st_table *)rb_objc_retain(st_init_numtable()))
+    ((st_table *)rb_objc_retain_ni(st_init_numtable()))
 #define onig_st_init_numtable_with_size(s) \
-    ((st_table *)rb_objc_retain(st_init_numtable_with_size(s)))
+    ((st_table *)rb_objc_retain_ni(st_init_numtable_with_size(s)))
 #define onig_st_init_strtable() \
-    ((st_table *)rb_objc_retain(st_init_strtable()))
+    ((st_table *)rb_objc_retain_ni(st_init_strtable()))
 #define onig_st_init_strtable_with_size(s) \
-    ((st_table *)rb_objc_retain(st_init_strtable_with_size(s)))
+    ((st_table *)rb_objc_retain_ni(st_init_strtable_with_size(s)))
 #define onig_st_copy(t) \
-    ((st_table *)rb_objc_retain(st_copy(t)))
+    ((st_table *)rb_objc_retain_ni(st_copy(t)))
 #define onig_st_free_table(t) \
-    (st_free_table((st_table *)rb_objc_release(t)))
+    (st_free_table((st_table *)rb_objc_release_ni(t)))
 #define onig_st_delete                      st_delete
 #define onig_st_delete_safe                 st_delete_safe
 #define onig_st_insert                      st_insert

Modified: MacRuby/trunk/rakelib/builder.rake
===================================================================
--- MacRuby/trunk/rakelib/builder.rake	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/rakelib/builder.rake	2009-08-11 06:19:45 UTC (rev 2274)
@@ -324,7 +324,7 @@
         if !File.exist?('Makefile') or File.mtime('extconf.rb') > File.mtime('Makefile')
           sh "#{srcdir}/miniruby -I#{srcdir} -I#{srcdir}/lib -r rbconfig -e \"RbConfig::CONFIG['libdir'] = '#{srcdir}'; require './extconf.rb'\""
         end
-        line = "/usr/bin/make top_srcdir=#{srcdir} ruby=\"#{srcdir}/miniruby -I#{srcdir} -I#{srcdir}/lib\" extout=#{srcdir}/.ext"
+        line = "/usr/bin/make top_srcdir=#{srcdir} ruby=\"#{srcdir}/miniruby -I#{srcdir} -I#{srcdir}/lib\" extout=#{srcdir}/.ext hdrdir=#{srcdir}/include arch_hdrdir=#{srcdir}/include"
         case target
           when :all
             line << " libdir=#{srcdir}"

Modified: MacRuby/trunk/rakelib/builder.rb
===================================================================
--- MacRuby/trunk/rakelib/builder.rb	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/rakelib/builder.rb	2009-08-11 06:19:45 UTC (rev 2274)
@@ -96,6 +96,7 @@
 LDFLAGS = `#{LLVM_CONFIG} --ldflags --libs #{LLVM_MODULES}`.strip.gsub(/\n/, '')
 LDFLAGS << " -lpthread -ldl -lxml2 -lobjc -lauto -framework Foundation"
 DLDFLAGS = "-dynamiclib -undefined suppress -flat_namespace -install_name #{INSTALL_NAME} -current_version #{MACRUBY_VERSION} -compatibility_version #{MACRUBY_VERSION}"
+CFLAGS << " -std=c99" # we add this one later to not conflict with ObjC/C++ flags
 
 # removed: marshal
 OBJS = %w{ 
@@ -136,6 +137,7 @@
             when '.c' then [CC, @cflags]
             when '.cpp' then [CXX, @cxxflags]
             when '.m' then [CC, @objc_cflags]
+            when '.mm' then [CXX, @cxxflags + ' ' + @objc_cflags]
           end
         sh("#{cc} #{flags} -c #{s} -o #{obj}.o")
       end
@@ -201,7 +203,7 @@
   def obj_source(obj)
     s = @obj_sources[obj]
     unless s
-      s = ['.c', '.cpp', '.m'].map { |e| obj + e }.find { |p| File.exist?(p) }
+      s = ['.c', '.cpp', '.m', '.mm'].map { |e| obj + e }.find { |p| File.exist?(p) }
       err "cannot locate source file for object `#{obj}'" if s.nil?
       @obj_sources[obj] = s
     end

Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/union_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/union_tags.txt	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/union_tags.txt	2009-08-11 06:19:45 UTC (rev 2274)
@@ -1,2 +1,3 @@
 fails:Array#| acts as if using an intermediate hash to collect values
 fails:Array#| tries to convert the passed argument to an Array using #to_ary
+fails:Array#| properly handles recursive arrays

Modified: MacRuby/trunk/sprintf.cpp
===================================================================
--- MacRuby/trunk/sprintf.cpp	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/sprintf.cpp	2009-08-11 06:19:45 UTC (rev 2274)
@@ -9,20 +9,9 @@
  * Copyright (C) 2000  Information-technology Promotion Agency, Japan
  */
 
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/Constants.h>
-#include <llvm/CallingConv.h>
-#include <llvm/Instructions.h>
-#include <llvm/ModuleProvider.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/ExecutionEngine/JIT.h>
-#include <llvm/PassManager.h>
-#include <llvm/Target/TargetData.h>
-using namespace llvm;
-
 #include <stdarg.h>
 
+#include "llvm.h"
 #include "ruby/ruby.h"
 #include "ruby/node.h"
 #include "ruby/encoding.h"

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-08-11 01:39:15 UTC (rev 2273)
+++ MacRuby/trunk/vm.cpp	2009-08-11 06:19:45 UTC (rev 2274)
@@ -51,8 +51,6 @@
 #include <iostream>
 #include <fstream>
 
-#define force_inline __attribute__((always_inline))
-
 RoxorCore *RoxorCore::shared = NULL;
 RoxorVM *RoxorVM::main = NULL;
 pthread_key_t RoxorVM::vm_thread_key;
@@ -1888,7 +1886,7 @@
 rb_vm_masgn_get_elem_before_splat(VALUE ary, int offset)
 {
     if (offset < RARRAY_LEN(ary)) {
-	return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
+	return RARRAY_AT(ary, offset);
     }
     return Qnil;
 }
@@ -1901,12 +1899,12 @@
     if (len < before_splat_count + after_splat_count) {
 	offset += before_splat_count;
 	if (offset < len) {
-	    return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
+	    return RARRAY_AT(ary, offset);
 	}
     }
     else {
 	offset += len - after_splat_count;
-	return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
+	return RARRAY_AT(ary, offset);
     }
     return Qnil;
 }
@@ -1929,7 +1927,7 @@
 {
     assert(argc >= arity.min);
     assert((arity.max == -1) || (argc <= arity.max));
-    int used_opt_args = argc - arity.min;
+    const int used_opt_args = argc - arity.min;
     int opt_args, rest_pos;
     if (arity.max == -1) {
 	opt_args = arity.real - arity.min - 1;
@@ -2635,6 +2633,9 @@
 		return RARRAY_IMMUTABLE(self)
 		    ? rb_cNSArray : rb_cNSMutableArray;
 	    }
+	    else if (klass == (Class)rb_cRubyArray) {
+		return rb_cNSMutableArray;
+	    }
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
 	    if (klass == (Class)rb_cCFHash || klass == (Class)rb_cNSHash0) {
 #else
@@ -2815,6 +2816,9 @@
 	    if (TYPE(comparedTo) != self_type) {
 		return Qfalse;
 	    }
+	    if (self_type == T_ARRAY) {
+		return rb_ary_equal(self, comparedTo);
+	    }
 	    return CFEqual((CFTypeRef)self, (CFTypeRef)comparedTo)
 		? Qtrue : Qfalse;
     }
@@ -2914,7 +2918,6 @@
 	if (TYPE(other) == T_FIXNUM) {
 	    return rb_ary_entry(obj, FIX2LONG(other));
 	}
-	extern VALUE rb_ary_aref(VALUE ary, SEL sel, int argc, VALUE *argv);
 	return rb_ary_aref(obj, 0, 1, &other);
     }
     return __rb_vm_dispatch(GET_VM(), cache, obj, NULL, selAREF, NULL, 0, 1,
@@ -2929,13 +2932,11 @@
     // TODO what about T_HASH?
     if (overriden == 0 && TYPE(obj) == T_ARRAY) {
 	if (TYPE(other1) == T_FIXNUM) {
-	    rb_ary_store(obj, FIX2INT(other1), other2);
+	    rb_ary_store(obj, FIX2LONG(other1), other2);
 	    return other2;
 	}
     }
-    VALUE args[2];
-    args[0] = other1;
-    args[1] = other2;
+    VALUE args[2] = { other1, other2 };
     return __rb_vm_dispatch(GET_VM(), cache, obj, NULL, selASET, NULL, 0, 2,
 	    args);
 }
@@ -3959,7 +3960,6 @@
 {
     RoxorReturnFromBlockException *exc = new RoxorReturnFromBlockException();
 
-    rb_objc_retain((void *)val);
     exc->val = val;
     exc->id = id;
 
@@ -3984,7 +3984,6 @@
 	RoxorReturnFromBlockException *exc = *pexc;
 	if (id == -1 || exc->id == id) {
 	    VALUE val = exc->val;
-	    rb_objc_release((void *)val);
 	    delete exc;
 	    return val;
 	}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090810/f762fdec/attachment-0001.html>


More information about the macruby-changes mailing list