* ruby.h (struct RArray): revert embedding ptr in RVALUE.

* array.c: ditto.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11256 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2006-11-01 14:42:39 +00:00
parent 11e562f34a
commit 15df557a4d
4 changed files with 113 additions and 206 deletions

View File

@ -1,3 +1,9 @@
Wed Nov 1 23:24:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* ruby.h (struct RArray): revert embedding ptr in RVALUE.
* array.c: ditto.
Wed Nov 1 23:01:55 2006 Yukihiro Matsumoto <matz@ruby-lang.org> Wed Nov 1 23:01:55 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (hash): use Bob Jenkins' hash algorithm. * string.c (hash): use Bob Jenkins' hash algorithm.

259
array.c
View File

@ -40,66 +40,37 @@ memfill(register VALUE *mem, register long size, register VALUE val)
} }
#define ARY_TMPLOCK FL_USER1 #define ARY_TMPLOCK FL_USER1
#define ARY_NOEMBED FL_USER3
#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED) #define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
#define ARY_SET_NOEMBED(ary) do {\
FL_SET(ary, ARY_NOEMBED);\
ARY_SET_EMBED_LEN(ary, 0);\
} while (0)
#define ARY_SET_EMBED(str) FL_UNSET(str, ARY_NOEMBED)
#define ARY_EMBED_P(ary) (!FL_TEST(ary, ARY_NOEMBED))
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n);\
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;\
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT;\
} while (0)
#define ARY_SET_LEN(ary, n) do { \ #define ARY_SET_LEN(ary, n) do { \
if (ARY_EMBED_P(ary)) {\ RARRAY(ary)->len = (n);\
ARY_SET_EMBED_LEN(ary, n);\
}\
else {\
RARRAY(ary)->as.heap.len = (n);\
}\
} while (0) } while (0)
#define ARY_LFREE FL_USER6 #define ARY_LFREE FL_USER6
#define ARY_LFREE_P(ary) FL_TEST(ary, ARY_LFREE) #define ARY_LFREE_P(ary) FL_TEST(ary, ARY_LFREE)
#define LFREE_SIZE(ary) RARRAY(ary)->as.heap.ptr[-1] #define LFREE_SIZE(ary) RARRAY(ary)->ptr[-1]
#define LFREE_CAPA(ary) (LFREE_SIZE(ary)+RARRAY(ary)->as.heap.aux.capa) #define LFREE_CAPA(ary) (LFREE_SIZE(ary)+RARRAY(ary)->aux.capa)
#define ARY_CAPA(ary) ((ARY_EMBED_P(ary)) ? RARRAY_EMBED_LEN_MAX : RARRAY(ary)->as.heap.aux.capa) #define ARY_CAPA(ary) RARRAY(ary)->aux.capa
#define RESIZE_CAPA(ary,capacity) do {\ #define RESIZE_CAPA(ary,capacity) do {\
if (ARY_EMBED_P(ary)) {\ if (ARY_LFREE_P(ary)) {\
if ((capacity) > RARRAY_EMBED_LEN_MAX) {\ VALUE *ptr = RARRAY(ary)->ptr - LFREE_SIZE(ary);\
VALUE *tmp = ALLOC_N(VALUE, capacity);\
long len = RARRAY_LEN(ary);\
MEMCPY(tmp, RARRAY_PTR(ary), VALUE, len);\
RARRAY(ary)->as.heap.ptr = tmp;\
RARRAY(ary)->as.heap.len = len;\
ARY_SET_NOEMBED(ary);\
RARRAY(ary)->as.heap.aux.capa = (capacity);\
}\
}\
else if (ARY_LFREE_P(ary)) {\
VALUE *ptr = RARRAY(ary)->as.heap.ptr - LFREE_SIZE(ary);\
if (LFREE_CAPA(ary) >= (capacity)) {\ if (LFREE_CAPA(ary) >= (capacity)) {\
RARRAY(ary)->as.heap.aux.capa = LFREE_CAPA(ary);\ RARRAY(ary)->aux.capa = LFREE_CAPA(ary);\
MEMMOVE(ptr, RARRAY(ary)->as.heap.ptr, VALUE, RARRAY_LEN(ary));\ MEMMOVE(ptr, RARRAY(ary)->ptr, VALUE, RARRAY_LEN(ary));\
FL_UNSET(ary, ARY_LFREE);\ FL_UNSET(ary, ARY_LFREE);\
RARRAY(ary)->as.heap.ptr = ptr;\ RARRAY(ary)->ptr = ptr;\
}\ }\
else {\ else {\
long offset = LFREE_SIZE(ary);\ long offset = LFREE_SIZE(ary);\
REALLOC_N(ptr, VALUE, offset+(capacity));\ REALLOC_N(ptr, VALUE, offset+(capacity));\
RARRAY(ary)->as.heap.aux.capa = (capacity);\ RARRAY(ary)->aux.capa = (capacity);\
RARRAY(ary)->as.heap.ptr = ptr + offset;\ RARRAY(ary)->ptr = ptr + offset;\
}\ }\
}\ }\
else {\ else {\
REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));\ REALLOC_N(RARRAY(ary)->ptr, VALUE, (capacity));\
RARRAY(ary)->as.heap.aux.capa = (capacity);\ RARRAY(ary)->aux.capa = (capacity);\
}\ }\
} while (0) } while (0)
@ -125,13 +96,12 @@ rb_ary_modify(VALUE ary)
VALUE *ptr; VALUE *ptr;
rb_ary_modify_check(ary); rb_ary_modify_check(ary);
if (ARY_EMBED_P(ary)) return;
if (ARY_SHARED_P(ary)) { if (ARY_SHARED_P(ary)) {
ptr = ALLOC_N(VALUE, RARRAY_LEN(ary)); ptr = ALLOC_N(VALUE, RARRAY_LEN(ary));
FL_UNSET(ary, ELTS_SHARED); FL_UNSET(ary, ELTS_SHARED);
RARRAY(ary)->as.heap.aux.capa = RARRAY_LEN(ary); RARRAY(ary)->aux.capa = RARRAY_LEN(ary);
MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary)); MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
RARRAY(ary)->as.heap.ptr = ptr; RARRAY(ary)->ptr = ptr;
} }
} }
@ -163,9 +133,9 @@ ary_alloc(VALUE klass)
NEWOBJ(ary, struct RArray); NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY); OBJSETUP(ary, klass, T_ARRAY);
ary->as.heap.len = 0; ary->len = 0;
ary->as.heap.ptr = 0; ary->ptr = 0;
ary->as.heap.aux.capa = 0; ary->aux.capa = 0;
return (VALUE)ary; return (VALUE)ary;
} }
@ -182,15 +152,9 @@ ary_new(VALUE klass, long len)
rb_raise(rb_eArgError, "array size too big"); rb_raise(rb_eArgError, "array size too big");
} }
ary = ary_alloc(klass); ary = ary_alloc(klass);
if (len <= RARRAY_EMBED_LEN_MAX) {
ARY_SET_EMBED_LEN(ary, 0);
}
else {
if (len == 0) len++; if (len == 0) len++;
ARY_SET_NOEMBED(ary); RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
RARRAY(ary)->as.heap.ptr = ALLOC_N(VALUE, len); RARRAY(ary)->aux.capa = len;
RARRAY(ary)->as.heap.aux.capa = len;
}
return ary; return ary;
} }
@ -225,7 +189,7 @@ rb_ary_new3(long n, ...)
} }
va_end(ar); va_end(ar);
ARY_SET_LEN(ary, n); RARRAY(ary)->len = n;
return ary; return ary;
} }
@ -237,7 +201,7 @@ rb_ary_new4(long n, const VALUE *elts)
ary = rb_ary_new2(n); ary = rb_ary_new2(n);
if (n > 0 && elts) { if (n > 0 && elts) {
MEMCPY(RARRAY_PTR(ary), elts, VALUE, n); MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
ARY_SET_LEN(ary, n); RARRAY(ary)->len = n;
} }
return ary; return ary;
@ -246,12 +210,12 @@ rb_ary_new4(long n, const VALUE *elts)
void void
rb_ary_free(VALUE ary) rb_ary_free(VALUE ary)
{ {
if (!ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) { if (!ARY_SHARED_P(ary)) {
if (ARY_LFREE_P(ary)) { if (ARY_LFREE_P(ary)) {
xfree(RARRAY(ary)->as.heap.ptr - LFREE_SIZE(ary)); xfree(RARRAY(ary)->ptr - LFREE_SIZE(ary));
} }
else { else {
xfree(RARRAY(ary)->as.heap.ptr); xfree(RARRAY(ary)->ptr);
} }
} }
} }
@ -259,23 +223,21 @@ rb_ary_free(VALUE ary)
static VALUE static VALUE
ary_make_shared(VALUE ary) ary_make_shared(VALUE ary)
{ {
if (ARY_EMBED_P(ary)) abort();
if (ARY_SHARED_P(ary)) { if (ARY_SHARED_P(ary)) {
return RARRAY(ary)->as.heap.aux.shared; return RARRAY(ary)->aux.shared;
} }
else { else {
NEWOBJ(shared, struct RArray); NEWOBJ(shared, struct RArray);
OBJSETUP(shared, 0, T_ARRAY); OBJSETUP(shared, 0, T_ARRAY);
ARY_SET_NOEMBED(shared); shared->len = RARRAY(ary)->len;
shared->as.heap.len = RARRAY(ary)->as.heap.len; shared->ptr = RARRAY(ary)->ptr;
shared->as.heap.ptr = RARRAY(ary)->as.heap.ptr; shared->aux.capa = RARRAY(ary)->aux.capa;
shared->as.heap.aux.capa = RARRAY(ary)->as.heap.aux.capa;
if (ARY_LFREE_P(ary)) { if (ARY_LFREE_P(ary)) {
FL_SET(shared,ARY_LFREE); FL_SET(shared,ARY_LFREE);
FL_UNSET(ary,ARY_LFREE); FL_UNSET(ary,ARY_LFREE);
} }
RARRAY(ary)->as.heap.aux.shared = (VALUE)shared; RARRAY(ary)->aux.shared = (VALUE)shared;
FL_SET(ary, ELTS_SHARED); FL_SET(ary, ELTS_SHARED);
OBJ_FREEZE(shared); OBJ_FREEZE(shared);
return (VALUE)shared; return (VALUE)shared;
@ -354,11 +316,10 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary); rb_ary_modify(ary);
if (rb_scan_args(argc, argv, "02", &size, &val) == 0) { if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
if (!ARY_EMBED_P(ary) && RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) { if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
free(RARRAY(ary)->as.heap.ptr); free(RARRAY(ary)->ptr);
} }
ARY_SET_EMBED(ary); RARRAY(ary)->len = 0;
ARY_SET_LEN(ary, 0);
if (rb_block_given_p()) { if (rb_block_given_p()) {
rb_warning("given block not used"); rb_warning("given block not used");
} }
@ -381,21 +342,7 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_raise(rb_eArgError, "array size too big"); rb_raise(rb_eArgError, "array size too big");
} }
rb_ary_modify(ary); rb_ary_modify(ary);
if (len <= RARRAY_EMBED_LEN_MAX) {
if (!ARY_EMBED_P(ary)) {
xfree(RARRAY(ary)->as.heap.ptr);
ARY_SET_EMBED(ary);
}
ARY_SET_EMBED_LEN(ary, len);
}
else {
if (ARY_EMBED_P(ary)) {
ARY_SET_NOEMBED(ary);
RARRAY(ary)->as.heap.len = 0;
RARRAY(ary)->as.heap.ptr = 0;
}
RESIZE_CAPA(ary, len); RESIZE_CAPA(ary, len);
}
if (rb_block_given_p()) { if (rb_block_given_p()) {
long i; long i;
@ -404,12 +351,12 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
} }
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
rb_ary_store(ary, i, rb_yield(LONG2NUM(i))); rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
ARY_SET_LEN(ary, i+1); RARRAY(ary)->len = i + 1;
} }
} }
else { else {
memfill(RARRAY_PTR(ary), len, val); memfill(RARRAY_PTR(ary), len, val);
ARY_SET_LEN(ary, len); RARRAY(ary)->len = len;
} }
return ary; return ary;
} }
@ -431,13 +378,10 @@ rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
if (argc < 0) { if (argc < 0) {
rb_raise(rb_eArgError, "negative array size"); rb_raise(rb_eArgError, "negative array size");
} }
if (argc > RARRAY_EMBED_LEN_MAX) { RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
ARY_SET_NOEMBED(ary); RARRAY(ary)->aux.capa = argc;
RARRAY(ary)->as.heap.ptr = ALLOC_N(VALUE, argc);
RARRAY(ary)->as.heap.aux.capa = argc;
}
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_SET_LEN(ary, argc); RARRAY(ary)->len = argc;
return ary; return ary;
} }
@ -475,7 +419,7 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
} }
if (idx >= RARRAY_LEN(ary)) { if (idx >= RARRAY_LEN(ary)) {
ARY_SET_LEN(ary, idx + 1); RARRAY(ary)->len = idx + 1;
} }
RARRAY_PTR(ary)[idx] = val; RARRAY_PTR(ary)[idx] = val;
} }
@ -486,10 +430,9 @@ ary_shared_array(VALUE klass, VALUE ary)
VALUE val = ary_alloc(klass); VALUE val = ary_alloc(klass);
ary_make_shared(ary); ary_make_shared(ary);
ARY_SET_NOEMBED(val); RARRAY(val)->ptr = RARRAY(ary)->ptr;
RARRAY(val)->as.heap.ptr = RARRAY(ary)->as.heap.ptr; RARRAY(val)->len = RARRAY(ary)->len;
RARRAY(val)->as.heap.len = RARRAY(ary)->as.heap.len; RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
RARRAY(val)->as.heap.aux.shared = RARRAY(ary)->as.heap.aux.shared;
FL_SET(val, ELTS_SHARED); FL_SET(val, ELTS_SHARED);
return val; return val;
} }
@ -512,14 +455,10 @@ ary_shared_first(int argc, VALUE *argv, VALUE ary, int last)
if (last) { if (last) {
offset = RARRAY_LEN(ary) - n; offset = RARRAY_LEN(ary) - n;
} }
if (ARY_EMBED_P(ary) || n <= RARRAY_EMBED_LEN_MAX) {
return rb_ary_new4(n, RARRAY_PTR(ary)+offset);
}
else {
result = ary_shared_array(rb_cArray, ary); result = ary_shared_array(rb_cArray, ary);
RARRAY(result)->as.heap.ptr += offset; RARRAY(result)->ptr += offset;
RARRAY(result)->as.heap.len = n; RARRAY(result)->len = n;
}
return result; return result;
} }
@ -578,7 +517,7 @@ rb_ary_pop(VALUE ary)
RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2); RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2);
} }
n = RARRAY_LEN(ary)-1; n = RARRAY_LEN(ary)-1;
ARY_SET_LEN(ary, n); RARRAY(ary)->len = n;
return RARRAY_PTR(ary)[n]; return RARRAY_PTR(ary)[n];
} }
@ -606,7 +545,7 @@ rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
rb_ary_modify_check(ary); rb_ary_modify_check(ary);
result = ary_shared_first(argc, argv, ary, Qtrue); result = ary_shared_first(argc, argv, ary, Qtrue);
ARY_SET_LEN(ary, RARRAY_LEN(ary) - RARRAY_LEN(result)); RARRAY(ary)->len -= RARRAY_LEN(result);
return result; return result;
} }
@ -618,23 +557,18 @@ rb_ary_shift(VALUE ary)
rb_ary_modify_check(ary); rb_ary_modify_check(ary);
if (RARRAY_LEN(ary) == 0) return Qnil; if (RARRAY_LEN(ary) == 0) return Qnil;
top = RARRAY_PTR(ary)[0]; top = RARRAY_PTR(ary)[0];
if (ARY_EMBED_P(ary)) {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
ARY_SET_EMBED_LEN(ary, RARRAY_LEN(ary)-1);
return top;
}
if (!ARY_SHARED_P(ary)) { if (!ARY_SHARED_P(ary)) {
if (ARY_LFREE_P(ary)) { if (ARY_LFREE_P(ary)) {
RARRAY(ary)->as.heap.ptr[0] = LFREE_SIZE(ary)+1; RARRAY(ary)->ptr[0] = LFREE_SIZE(ary)+1;
} }
else { else {
FL_SET(ary, ARY_LFREE); FL_SET(ary, ARY_LFREE);
RARRAY(ary)->as.heap.ptr[0] = 1; RARRAY(ary)->ptr[0] = 1;
} }
RARRAY(ary)->as.heap.aux.capa--; RARRAY(ary)->aux.capa--;
} }
RARRAY(ary)->as.heap.ptr++; /* shift ptr */ RARRAY(ary)->ptr++; /* shift ptr */
RARRAY(ary)->as.heap.len--; RARRAY(ary)->len--;
return top; return top;
} }
@ -670,12 +604,12 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
result = ary_shared_first(argc, argv, ary, Qfalse); result = ary_shared_first(argc, argv, ary, Qfalse);
n = RARRAY_LEN(result); n = RARRAY_LEN(result);
if (ARY_SHARED_P(ary)) { if (ARY_SHARED_P(ary)) {
RARRAY(ary)->as.heap.ptr += n; RARRAY(ary)->ptr += n;
RARRAY(ary)->as.heap.len -= n; RARRAY(ary)->len -= n;
} }
else { else {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n); MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
ARY_SET_LEN(ary, RARRAY_LEN(ary)-n); RARRAY(ary)->len -= n;
} }
return result; return result;
@ -708,12 +642,12 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
long free = shared ? RARRAY_LEN(ary) : ARY_CAPA(ary); long free = shared ? RARRAY_LEN(ary) : ARY_CAPA(ary);
VALUE *ptr; VALUE *ptr;
if (!ARY_EMBED_P(ary) && free > len + argc) { if (free > len + argc) {
free += lfree; free += lfree;
free2 = (free - len - argc) / 2 + argc; free2 = (free - len - argc) / 2 + argc;
ptr = RARRAY(ary)->as.heap.ptr-lfree+free2; ptr = RARRAY(ary)->ptr-lfree+free2;
MEMMOVE(ptr, RARRAY(ary)->as.heap.ptr, VALUE, MEMMOVE(ptr, RARRAY(ary)->ptr, VALUE,
RARRAY(ary)->as.heap.len); RARRAY(ary)->len);
} }
else { else {
free = (len+argc) * 1.5; free = (len+argc) * 1.5;
@ -726,23 +660,20 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
if (shared) { if (shared) {
FL_UNSET(ary, ELTS_SHARED); FL_UNSET(ary, ELTS_SHARED);
} }
else if (ARY_EMBED_P(ary)) {
ARY_SET_NOEMBED(ary);
}
else { else {
xfree(RARRAY(ary)->as.heap.ptr-lfree); xfree(RARRAY(ary)->ptr-lfree);
} }
} }
RARRAY(ary)->as.heap.ptr = ptr; RARRAY(ary)->ptr = ptr;
RARRAY(ary)->as.heap.len = len; RARRAY(ary)->len = len;
RARRAY(ary)->as.heap.aux.capa = free-free2; RARRAY(ary)->aux.capa = free-free2;
} }
RARRAY(ary)->as.heap.ptr -= argc; RARRAY(ary)->ptr -= argc;
RARRAY(ary)->as.heap.len += argc; RARRAY(ary)->len += argc;
RARRAY(ary)->as.heap.aux.capa += argc; RARRAY(ary)->aux.capa += argc;
free2 -= argc; free2 -= argc;
if (free2 > 0) { if (free2 > 0) {
RARRAY(ary)->as.heap.ptr[-1] = free2; RARRAY(ary)->ptr[-1] = free2;
FL_SET(ary, ARY_LFREE); FL_SET(ary, ARY_LFREE);
} else { } else {
FL_UNSET(ary, ARY_LFREE); FL_UNSET(ary, ARY_LFREE);
@ -795,20 +726,15 @@ rb_ary_subseq(VALUE ary, long beg, long len)
klass = rb_obj_class(ary); klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0); if (len == 0) return ary_new(klass, 0);
if (ARY_EMBED_P(ary) && len <= RARRAY_EMBED_LEN_MAX) {
return rb_ary_new4(len, RARRAY_PTR(ary)+beg);
}
else {
shared = ary_make_shared(ary); shared = ary_make_shared(ary);
ptr = RARRAY_PTR(ary); ptr = RARRAY_PTR(ary);
ary2 = ary_alloc(klass); ary2 = ary_alloc(klass);
ARY_SET_NOEMBED(ary2); RARRAY(ary2)->ptr = ptr + beg;
RARRAY(ary2)->as.heap.ptr = ptr + beg; RARRAY(ary2)->len = len;
RARRAY(ary2)->as.heap.len = len; RARRAY(ary2)->aux.shared = shared;
RARRAY(ary2)->as.heap.aux.shared = shared;
FL_SET(ary2, ELTS_SHARED); FL_SET(ary2, ELTS_SHARED);
return ary2; return ary2;
}
} }
/* /*
@ -1124,7 +1050,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
if (rlen > 0) { if (rlen > 0) {
MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
} }
ARY_SET_LEN(ary, len); RARRAY(ary)->len = len;
} }
else { else {
long alen; long alen;
@ -1141,7 +1067,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
if (len != rlen) { if (len != rlen) {
MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len, MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
VALUE, RARRAY_LEN(ary) - (beg + len)); VALUE, RARRAY_LEN(ary) - (beg + len));
ARY_SET_LEN(ary, alen); RARRAY(ary)->len = alen;
} }
if (rlen > 0) { if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
@ -1360,7 +1286,7 @@ rb_ary_dup(VALUE ary)
VALUE dup = rb_ary_new2(RARRAY_LEN(ary)); VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary)); MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
ARY_SET_LEN(dup, RARRAY_LEN(ary)); RARRAY(dup)->len = RARRAY_LEN(ary);
OBJ_INFECT(dup, ary); OBJ_INFECT(dup, ary);
return dup; return dup;
@ -1864,7 +1790,7 @@ rb_ary_delete(VALUE ary, VALUE item)
rb_ary_modify(ary); rb_ary_modify(ary);
if (RARRAY_LEN(ary) > i2) { if (RARRAY_LEN(ary) > i2) {
ARY_SET_LEN(ary, i2); RARRAY(ary)->len = i2;
if (i2 * 2 < ARY_CAPA(ary) && if (i2 * 2 < ARY_CAPA(ary) &&
ARY_CAPA(ary) > ARY_DEFAULT_SIZE) { ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
RESIZE_CAPA(ary, i2*2); RESIZE_CAPA(ary, i2*2);
@ -1890,7 +1816,7 @@ rb_ary_delete_at(VALUE ary, long pos)
del = RARRAY_PTR(ary)[pos]; del = RARRAY_PTR(ary)[pos];
MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE, MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
RARRAY_LEN(ary)-pos-1); RARRAY_LEN(ary)-pos-1);
ARY_SET_LEN(ary, RARRAY_LEN(ary)-1); RARRAY(ary)->len--;
return del; return del;
} }
@ -1992,7 +1918,7 @@ rb_ary_reject_bang(VALUE ary)
} }
if (RARRAY_LEN(ary) == i2) return Qnil; if (RARRAY_LEN(ary) == i2) return Qnil;
if (i2 < RARRAY_LEN(ary)) if (i2 < RARRAY_LEN(ary))
ARY_SET_LEN(ary, i2); RARRAY(ary)->len = i2;
return ary; return ary;
} }
@ -2145,29 +2071,20 @@ static VALUE
rb_ary_replace(VALUE copy, VALUE orig) rb_ary_replace(VALUE copy, VALUE orig)
{ {
VALUE shared; VALUE shared;
VALUE *ptr;
rb_ary_modify(copy); rb_ary_modify(copy);
orig = to_ary(orig); orig = to_ary(orig);
if (copy == orig) return copy; if (copy == orig) return copy;
if (ARY_EMBED_P(orig)) {
MEMCPY(RARRAY_PTR(copy), RARRAY_PTR(orig), VALUE, RARRAY_LEN(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
return copy;
}
shared = ary_make_shared(orig); shared = ary_make_shared(orig);
if (ARY_EMBED_P(copy)) { ptr = RARRAY(copy)->ptr;
ARY_SET_NOEMBED(copy);
}
else {
VALUE *ptr = RARRAY(copy)->as.heap.ptr;
if (ARY_LFREE_P(copy)) { if (ARY_LFREE_P(copy)) {
ptr -= LFREE_SIZE(copy); ptr -= LFREE_SIZE(copy);
} }
xfree(ptr); xfree(ptr);
} RARRAY(copy)->ptr = RARRAY(shared)->ptr;
RARRAY(copy)->as.heap.ptr = RARRAY(shared)->as.heap.ptr; RARRAY(copy)->len = RARRAY(shared)->len;
RARRAY(copy)->as.heap.len = RARRAY(shared)->as.heap.len; RARRAY(copy)->aux.shared = shared;
RARRAY(copy)->as.heap.aux.shared = shared;
FL_SET(copy, ELTS_SHARED); FL_SET(copy, ELTS_SHARED);
return copy; return copy;
@ -2187,7 +2104,7 @@ VALUE
rb_ary_clear(VALUE ary) rb_ary_clear(VALUE ary)
{ {
rb_ary_modify(ary); rb_ary_modify(ary);
ARY_SET_LEN(ary, 0); RARRAY(ary)->len = 0;
if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) { if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2); RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
} }
@ -2260,7 +2177,7 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
RESIZE_CAPA(ary, end); RESIZE_CAPA(ary, end);
} }
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary)); rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
ARY_SET_LEN(ary, end); RARRAY(ary)->len = end;
} }
if (block_p) { if (block_p) {
@ -2304,7 +2221,7 @@ rb_ary_plus(VALUE x, VALUE y)
z = rb_ary_new2(len); z = rb_ary_new2(len);
MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x)); MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y)); MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
ARY_SET_LEN(z, len); RARRAY(z)->len = len;
return z; return z;
} }
@ -2366,7 +2283,7 @@ rb_ary_times(VALUE ary, VALUE times)
len *= RARRAY_LEN(ary); len *= RARRAY_LEN(ary);
ary2 = ary_new(rb_obj_class(ary), len); ary2 = ary_new(rb_obj_class(ary), len);
ARY_SET_LEN(ary2, len); RARRAY(ary2)->len = len;
for (i=0; i<len; i+=RARRAY_LEN(ary)) { for (i=0; i<len; i+=RARRAY_LEN(ary)) {
MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary)); MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
@ -2746,7 +2663,7 @@ rb_ary_uniq_bang(VALUE ary)
rb_ary_store(ary, j++, v); rb_ary_store(ary, j++, v);
} }
} }
ARY_SET_LEN(ary, j); RARRAY(ary)->len = j;
return ary; return ary;
} }
@ -2799,7 +2716,7 @@ rb_ary_compact_bang(VALUE ary)
} }
n = p - RARRAY_PTR(ary); n = p - RARRAY_PTR(ary);
RESIZE_CAPA(ary, n); RESIZE_CAPA(ary, n);
ARY_SET_LEN(ary, n); RARRAY(ary)->len = n;
return ary; return ary;
} }

2
gc.c
View File

@ -926,7 +926,7 @@ gc_mark_children(VALUE ptr, int lev)
case T_ARRAY: case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) { if (FL_TEST(obj, ELTS_SHARED)) {
ptr = obj->as.array.as.heap.aux.shared; ptr = obj->as.array.aux.shared;
goto again; goto again;
} }
else { else {

20
ruby.h
View File

@ -391,33 +391,17 @@ struct RString {
RSTRING(str)->as.ary : \ RSTRING(str)->as.ary : \
RSTRING(str)->as.heap.ptr) RSTRING(str)->as.heap.ptr)
#define RARRAY_EMBED_LEN_MAX 3
struct RArray { struct RArray {
struct RBasic basic; struct RBasic basic;
union {
struct {
long len; long len;
union { union {
long capa; long capa;
VALUE shared; VALUE shared;
} aux; } aux;
VALUE *ptr; VALUE *ptr;
} heap;
VALUE ary[RARRAY_EMBED_LEN_MAX];
} as;
}; };
#define RARRAY_NOEMBED FL_USER3 #define RARRAY_LEN(a) RARRAY(a)->len
#define RARRAY_EMBED_LEN_MASK (FL_USER4|FL_USER5) #define RARRAY_PTR(a) RARRAY(a)->ptr
#define RARRAY_EMBED_LEN_SHIFT (FL_USHIFT+4)
#define RARRAY_LEN(a) \
(!(RBASIC(a)->flags & RARRAY_NOEMBED) ? \
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
(RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)) : \
RARRAY(a)->as.heap.len)
#define RARRAY_PTR(a) \
(!(RBASIC(a)->flags & RARRAY_NOEMBED) ? \
RARRAY(a)->as.ary : \
RARRAY(a)->as.heap.ptr)
struct RRegexp { struct RRegexp {
struct RBasic basic; struct RBasic basic;