summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'array.c')
-rw-r--r--array.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/array.c b/array.c
index da32a8984e..7afc1301b5 100644
--- a/array.c
+++ b/array.c
@@ -459,7 +459,7 @@ rb_ary_pop(ary)
return RARRAY(ary)->ptr[--RARRAY(ary)->len];
}
-static void
+static VALUE
ary_make_shared(ary)
VALUE ary;
{
@@ -472,6 +472,11 @@ ary_make_shared(ary)
shared->aux.capa = RARRAY(ary)->aux.capa;
RARRAY(ary)->aux.shared = (VALUE)shared;
FL_SET(ary, ELTS_SHARED);
+ OBJ_FREEZE(shared);
+ return (VALUE)shared;
+ }
+ else {
+ return RARRAY(ary)->aux.shared;
}
}
@@ -591,7 +596,8 @@ rb_ary_subseq(ary, beg, len)
VALUE ary;
long beg, len;
{
- VALUE klass, ary2;
+ VALUE klass, ary2, shared;
+ VALUE *ptr;
if (beg > RARRAY(ary)->len) return Qnil;
if (beg < 0 || len < 0) return Qnil;
@@ -604,11 +610,12 @@ rb_ary_subseq(ary, beg, len)
klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0);
- ary_make_shared(ary);
+ shared = ary_make_shared(ary);
+ ptr = RARRAY(ary)->ptr;
ary2 = ary_alloc(klass);
- RARRAY(ary2)->ptr = RARRAY(ary)->ptr + beg;
+ RARRAY(ary2)->ptr = ptr + beg;
RARRAY(ary2)->len = len;
- RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared;
+ RARRAY(ary2)->aux.shared = shared;
FL_SET(ary2, ELTS_SHARED);
return ary2;
@@ -1562,9 +1569,10 @@ sort_1(a, b, data)
struct ary_sort_data *data;
{
VALUE retval = rb_yield_values(2, *a, *b);
+ int n;
- ary_sort_check(data);
- return rb_cmpint(retval, *a, *b);
+ n = rb_cmpint(retval, *a, *b);
+ return n;
}
static int
@@ -1573,11 +1581,12 @@ sort_2(ap, bp, data)
struct ary_sort_data *data;
{
VALUE retval;
- long a = (long)*ap, b = (long)*bp;
+ VALUE a = *ap, b = *bp;
+ int n;
if (FIXNUM_P(a) && FIXNUM_P(b)) {
- if (a > b) return 1;
- if (a < b) return -1;
+ if ((long)a > (long)b) return 1;
+ if ((long)a < (long)b) return -1;
return 0;
}
if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) {
@@ -1585,8 +1594,9 @@ sort_2(ap, bp, data)
}
retval = rb_funcall(a, id_cmp, 1, b);
- ary_sort_check(data);
- return rb_cmpint(retval, a, b);
+ n = rb_cmpint(retval, a, b);
+
+ return n;
}
static VALUE
@@ -2150,15 +2160,17 @@ static VALUE
rb_ary_replace(copy, orig)
VALUE copy, orig;
{
+ VALUE shared;
+
rb_ary_modify(copy);
orig = to_ary(orig);
if (copy == orig) return copy;
- ary_make_shared(orig);
+ shared = ary_make_shared(orig);
if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
free(RARRAY(copy)->ptr);
- RARRAY(copy)->ptr = RARRAY(orig)->ptr;
- RARRAY(copy)->len = RARRAY(orig)->len;
- RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared;
+ RARRAY(copy)->ptr = RARRAY(shared)->ptr;
+ RARRAY(copy)->len = RARRAY(shared)->len;
+ RARRAY(copy)->aux.shared = shared;
FL_SET(copy, ELTS_SHARED);
return copy;
@@ -2874,8 +2886,11 @@ flatten(ary, idx, ary2, memo)
rb_ary_push(memo, id);
rb_ary_update(ary, idx, 1, ary2);
while (i < lim) {
- if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) {
- n = flatten(ary, i, RARRAY(ary)->ptr[i], memo);
+ VALUE tmp;
+
+ tmp = rb_check_array_type(RARRAY(ary)->ptr[i]);
+ if (!NIL_P(tmp)) {
+ n = flatten(ary, i, tmp, memo);
i += n; lim += n;
}
i++;
@@ -2910,12 +2925,14 @@ rb_ary_flatten_bang(ary)
rb_ary_modify(ary);
while (i<RARRAY(ary)->len) {
VALUE ary2 = RARRAY(ary)->ptr[i];
+ VALUE tmp;
- if (TYPE(ary2) == T_ARRAY) {
+ tmp = rb_check_array_type(ary2);
+ if (!NIL_P(tmp)) {
if (NIL_P(memo)) {
memo = rb_ary_new();
}
- i += flatten(ary, i, ary2, memo);
+ i += flatten(ary, i, tmp, memo);
mod = 1;
}
i++;