[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