* include/ruby/ruby.h: embeds the elements of an array into its

struct RArray for # of elements <= 3.

	* array.c: ditto.

	* gc.c (gc_mark_children): following the change of struct RArray.

	* ext/tk/tcltklib.c (ip_ruby_cmp): ditto.

	* parse.y (coverage): ditto.

	* proc.c (curry): ditto.

	* .gdbinit: ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19723 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
yugui 2008-10-09 05:47:04 +00:00
Родитель 517a1c3406
Коммит c86ce094e2
8 изменённых файлов: 365 добавлений и 154 удалений

Просмотреть файл

@ -104,9 +104,34 @@ define rp
print (struct RRegexp *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY
printf "T_ARRAY: len=%ld ", ((struct RArray*)$arg0)->len
if ($flags & RUBY_FL_USER1)
set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
printf "T_ARRAY: len=%ld ", $len
printf "(embed) "
if ($len == 0)
printf "{(empty)} "
else
output/x *((VALUE*)((struct RArray*)$arg0)->as.ary) @ $len
printf " "
end
else
set $len = ((struct RArray*)$arg0)->as.heap.len
printf "T_ARRAY: len=%ld ", $len
if ($flags & RUBY_FL_USER2)
printf "(shared) shared="
output/x ((struct RArray*)$arg0)->as.heap.aux.shared
printf " "
else
printf "(ownership) capa=%ld ", ((struct RArray*)$arg0)->as.heap.aux.capa
end
if ($len == 0)
printf "{(empty)} "
else
output/x *((VALUE*)((struct RArray*)$arg0)->as.heap.ptr) @ $len
printf " "
end
end
print (struct RArray *)$arg0
x/xw ((struct RArray*)$arg0)->ptr
else
if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM
printf "T_FIXNUM: "

Просмотреть файл

@ -1,3 +1,20 @@
Thu Oct 9 14:37:59 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
* include/ruby/ruby.h: embeds the elements of an array into its
struct RArray for # of elements <= 3.
* array.c: ditto.
* gc.c (gc_mark_children): following the change of struct RArray.
* ext/tk/tcltklib.c (ip_ruby_cmp): ditto.
* parse.y (coverage): ditto.
* proc.c (curry): ditto.
* .gdbinit: ditto.
Thu Oct 9 11:29:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
* encoding.c (Init_Encoding): new instance method Encoding#names,

421
array.c
Просмотреть файл

@ -14,6 +14,7 @@
#include "ruby/ruby.h"
#include "ruby/util.h"
#include "ruby/st.h"
#include <assert.h>
VALUE rb_cArray;
@ -38,17 +39,119 @@ memfill(register VALUE *mem, register long size, register VALUE val)
}
}
#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
# define ARY_SHARED_P(ary) \
(assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
FL_TEST(ary,ELTS_SHARED))
# define ARY_EMBED_P(ary) \
(assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
FL_TEST(ary, RARRAY_EMBED_FLAG))
#define ARY_SET_LEN(ary, n) do { \
RARRAY(ary)->len = (n);\
} while (0)
#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
#define ARY_EMBED_LEN(a) \
(assert(ARY_EMBED_P(a)), \
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
(RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
#define ARY_CAPA(ary) RARRAY(ary)->aux.capa
#define RESIZE_CAPA(ary,capacity) do {\
REALLOC_N(RARRAY(ary)->ptr, VALUE, (capacity));\
RARRAY(ary)->aux.capa = (capacity);\
#define ARY_OWNS_HEAP_P(a) (!FL_TEST(a, ELTS_SHARED|RARRAY_EMBED_FLAG))
#define FL_SET_EMBED(a) do { \
assert(!ARY_SHARED_P(a)); \
assert(!OBJ_FROZEN(a)); \
FL_SET(a, RARRAY_EMBED_FLAG); \
} while (0)
#define FL_UNSET_EMBED(ary) FL_UNSET(ary, RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
#define FL_SET_SHARED(ary) do { \
assert(!ARY_EMBED_P(ary)); \
FL_SET(ary, ELTS_SHARED); \
} while (0)
#define FL_UNSET_SHARED(ary) FL_UNSET(ary, ELTS_SHARED)
#define ARY_SET_PTR(ary, p) do { \
assert(!ARY_EMBED_P(ary)); \
assert(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.ptr = (p); \
} while (0)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = n; \
assert(ARY_EMBED_P(ary)); \
assert(!OBJ_FROZEN(ary)); \
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
} while (0)
#define ARY_SET_HEAP_LEN(ary, n) do { \
assert(!ARY_EMBED_P(ary)); \
RARRAY(ary)->as.heap.len = n; \
} while (0)
#define ARY_SET_LEN(ary, n) do { \
if (ARY_EMBED_P(ary)) { \
ARY_SET_EMBED_LEN(ary, n); \
} \
else { \
ARY_SET_HEAP_LEN(ary, n); \
} \
assert(RARRAY_LEN(ary) == n); \
} while (0)
#define ARY_INCREASE_PTR(ary, n) do { \
assert(!ARY_EMBED_P(ary)); \
assert(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.ptr += n; \
} while (0)
#define ARY_INCREASE_LEN(ary, n) do { \
assert(!OBJ_FROZEN(ary)); \
if (ARY_EMBED_P(ary)) { \
ARY_SET_EMBED_LEN(ary, RARRAY_LEN(ary)+n); \
} \
else { \
RARRAY(ary)->as.heap.len += n; \
} \
} while (0)
#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : RARRAY(ary)->as.heap.aux.capa)
#define ARY_SET_CAPA(ary, n) do { \
assert(!ARY_EMBED_P(ary)); \
assert(!ARY_SHARED_P(ary)); \
assert(!OBJ_FROZEN(ary)); \
RARRAY(ary)->as.heap.aux.capa = (n); \
} while (0)
#define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
#define ARY_SET_SHARED(ary, value) do { \
assert(!ARY_EMBED_P(ary)); \
assert(ARY_SHARED_P(ary)); \
RARRAY(ary)->as.heap.aux.shared = (value); \
} while (0)
static void
RESIZE_CAPA(VALUE ary, long capacity)
{
assert(!OBJ_FROZEN(ary));
assert(!ARY_SHARED_P(ary));
if (capacity > RARRAY_EMBED_LEN_MAX) {
if (ARY_EMBED_P(ary)) {
long len = ARY_EMBED_LEN(ary);
VALUE *ptr = ALLOC_N(VALUE, (capacity));
MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
FL_UNSET_EMBED(ary);
ARY_SET_PTR(ary, ptr);
ARY_SET_HEAP_LEN(ary, len);
}
else {
REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));
}
ARY_SET_CAPA(ary, (capacity));
}
else {
if (!ARY_EMBED_P(ary)) {
long len = RARRAY_LEN(ary);
VALUE *ptr = RARRAY_PTR(ary);
MEMCPY(RARRAY(ary)->as.ary, ptr, VALUE, len);
FL_SET_EMBED(ary);
ARY_SET_LEN(ary, len);
xfree(ptr);
}
}
}
static inline void
rb_ary_modify_check(VALUE ary)
@ -61,15 +164,23 @@ rb_ary_modify_check(VALUE ary)
static void
rb_ary_modify(VALUE ary)
{
VALUE *ptr;
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
ptr = ALLOC_N(VALUE, RARRAY_LEN(ary));
FL_UNSET(ary, ELTS_SHARED);
RARRAY(ary)->aux.capa = RARRAY_LEN(ary);
MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
RARRAY(ary)->ptr = ptr;
long len = RARRAY_LEN(ary);
if (len <= RARRAY_EMBED_LEN_MAX) {
VALUE *ptr = ARY_HEAP_PTR(ary);
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
ARY_SET_EMBED_LEN(ary, len);
}
else {
VALUE *ptr = ALLOC_N(VALUE, len);
FL_UNSET_SHARED(ary);
ARY_SET_CAPA(ary, len);
MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
ARY_SET_PTR(ary, ptr);
}
}
}
@ -99,10 +210,8 @@ ary_alloc(VALUE klass)
{
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY);
ary->len = 0;
ary->ptr = 0;
ary->aux.capa = 0;
FL_SET_EMBED((VALUE)ary);
ARY_SET_EMBED_LEN((VALUE)ary, 0);
return (VALUE)ary;
}
@ -119,9 +228,12 @@ ary_new(VALUE klass, long len)
rb_raise(rb_eArgError, "array size too big");
}
ary = ary_alloc(klass);
if (len == 0) len++;
RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
RARRAY(ary)->aux.capa = len;
if (len > RARRAY_EMBED_LEN_MAX) {
FL_UNSET_EMBED(ary);
ARY_SET_PTR(ary, ALLOC_N(VALUE, len));
ARY_SET_CAPA(ary, len);
ARY_SET_HEAP_LEN(ary, 0);
}
return ary;
}
@ -136,7 +248,7 @@ rb_ary_new2(long len)
VALUE
rb_ary_new(void)
{
return rb_ary_new2(ARY_DEFAULT_SIZE);
return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
}
#include <stdarg.h>
@ -156,7 +268,7 @@ rb_ary_new3(long n, ...)
}
va_end(ar);
RARRAY(ary)->len = n;
ARY_SET_LEN(ary, n);
return ary;
}
@ -168,7 +280,7 @@ rb_ary_new4(long n, const VALUE *elts)
ary = rb_ary_new2(n);
if (n > 0 && elts) {
MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
RARRAY(ary)->len = n;
ARY_SET_LEN(ary, n);
}
return ary;
@ -183,31 +295,48 @@ rb_ary_tmp_new(long len)
void
rb_ary_free(VALUE ary)
{
if (!ARY_SHARED_P(ary)) {
xfree(RARRAY(ary)->ptr);
if (ARY_OWNS_HEAP_P(ary)) {
xfree(RARRAY_PTR(ary));
}
}
static VALUE
ary_make_shared(VALUE ary)
{
assert(!ARY_EMBED_P(ary));
if (ARY_SHARED_P(ary)) {
return RARRAY(ary)->aux.shared;
return ARY_SHARED(ary);
}
else {
NEWOBJ(shared, struct RArray);
OBJSETUP(shared, 0, T_ARRAY);
FL_UNSET_EMBED(shared);
shared->len = RARRAY(ary)->len;
shared->ptr = RARRAY(ary)->ptr;
shared->aux.capa = RARRAY(ary)->aux.capa;
RARRAY(ary)->aux.shared = (VALUE)shared;
FL_SET(ary, ELTS_SHARED);
ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary));
ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
ARY_SET_CAPA((VALUE)shared, ARY_CAPA(ary));
FL_SET_SHARED(ary);
ARY_SET_SHARED(ary, (VALUE)shared);
OBJ_FREEZE(shared);
return (VALUE)shared;
}
}
static VALUE
ary_make_substitution(VALUE ary)
{
if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
return subst;
}
else {
return ary_make_shared(ary);
}
}
VALUE
rb_assoc_new(VALUE car, VALUE cdr)
{
@ -298,10 +427,12 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
xfree(RARRAY(ary)->ptr);
if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
xfree(RARRAY_PTR(ary));
}
RARRAY(ary)->len = 0;
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
ARY_SET_EMBED_LEN(ary, 0);
if (rb_block_given_p()) {
rb_warning("given block not used");
}
@ -333,12 +464,12 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
}
for (i=0; i<len; i++) {
rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
RARRAY(ary)->len = i + 1;
ARY_SET_LEN(ary, i + 1);
}
}
else {
memfill(RARRAY_PTR(ary), len, val);
RARRAY(ary)->len = len;
ARY_SET_LEN(ary, len);
}
return ary;
}
@ -355,15 +486,11 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
static VALUE
rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
{
VALUE ary = ary_alloc(klass);
if (argc < 0) {
rb_raise(rb_eArgError, "negative array size");
VALUE ary = ary_new(klass, argc);
if (argc > 0 && argv) {
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_SET_LEN(ary, argc);
}
RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
RARRAY(ary)->aux.capa = argc;
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
RARRAY(ary)->len = argc;
return ary;
}
@ -401,28 +528,41 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
}
if (idx >= RARRAY_LEN(ary)) {
RARRAY(ary)->len = idx + 1;
ARY_SET_LEN(ary, idx + 1);
}
RARRAY_PTR(ary)[idx] = val;
}
static VALUE
ary_shared_array(VALUE klass, VALUE ary)
ary_make_partial0(VALUE ary, long offset, long len)
{
VALUE val = ary_alloc(klass);
assert(offset >= 0);
assert(len >= 0);
assert(offset+len <= RARRAY_LEN(ary));
ary_make_shared(ary);
RARRAY(val)->ptr = RARRAY(ary)->ptr;
RARRAY(val)->len = RARRAY(ary)->len;
RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
FL_SET(val, ELTS_SHARED);
return val;
if (len <= RARRAY_EMBED_LEN_MAX) {
return rb_ary_new4(len, RARRAY_PTR(ary) + offset);
}
else {
VALUE shared, result = ary_alloc(rb_obj_class(ary));
FL_UNSET_EMBED(result);
shared = ary_make_shared(ary);
ARY_SET_PTR(result, RARRAY_PTR(ary));
ARY_SET_LEN(result, RARRAY_LEN(ary));
FL_SET_SHARED(result);
ARY_SET_SHARED(result, shared);
ARY_INCREASE_PTR(result, offset);
ARY_SET_LEN(result, len);
return result;
}
}
static VALUE
ary_shared_first(int argc, VALUE *argv, VALUE ary, int last)
ary_make_partial(int argc, VALUE *argv, VALUE ary, int last)
{
VALUE nv, result;
VALUE nv;
long n;
long offset = 0;
@ -437,11 +577,7 @@ ary_shared_first(int argc, VALUE *argv, VALUE ary, int last)
if (last) {
offset = RARRAY_LEN(ary) - n;
}
result = ary_shared_array(rb_cArray, ary);
RARRAY(result)->ptr += offset;
RARRAY(result)->len = n;
return result;
return ary_make_partial0(ary, offset, n);
}
/*
@ -492,14 +628,14 @@ rb_ary_pop(VALUE ary)
long n;
rb_ary_modify_check(ary);
if (RARRAY_LEN(ary) == 0) return Qnil;
if (!ARY_SHARED_P(ary) &&
if (ARY_OWNS_HEAP_P(ary) &&
RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
{
RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2);
}
n = RARRAY_LEN(ary)-1;
RARRAY(ary)->len = n;
ARY_SET_LEN(ary, n);
return RARRAY_PTR(ary)[n];
}
@ -530,8 +666,8 @@ rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
}
rb_ary_modify_check(ary);
result = ary_shared_first(argc, argv, ary, Qtrue);
RARRAY(ary)->len -= RARRAY_LEN(result);
result = ary_make_partial(argc, argv, ary, Qtrue);
ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
return result;
}
@ -546,14 +682,16 @@ rb_ary_shift(VALUE ary)
if (!ARY_SHARED_P(ary)) {
if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
RARRAY(ary)->len--;
ARY_INCREASE_LEN(ary, -1);
return top;
}
assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
RARRAY_PTR(ary)[0] = Qnil;
ary_make_shared(ary);
}
RARRAY(ary)->ptr++; /* shift ptr */
RARRAY(ary)->len--;
ARY_INCREASE_PTR(ary, 1); /* shift ptr */
ARY_INCREASE_LEN(ary, -1);
return top;
}
@ -590,16 +728,15 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
}
rb_ary_modify_check(ary);
result = ary_shared_first(argc, argv, ary, Qfalse);
result = ary_make_partial(argc, argv, ary, Qfalse);
n = RARRAY_LEN(result);
if (ARY_SHARED_P(ary)) {
RARRAY(ary)->ptr += n;
RARRAY(ary)->len -= n;
}
ARY_INCREASE_PTR(ary, n);
}
else {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
RARRAY(ary)->len -= n;
}
ARY_INCREASE_LEN(ary, -n);
return result;
}
@ -623,14 +760,14 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
if (argc == 0) return ary;
rb_ary_modify(ary);
if (RARRAY(ary)->aux.capa <= (len = RARRAY(ary)->len) + argc) {
if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) {
RESIZE_CAPA(ary, len + argc + ARY_DEFAULT_SIZE);
}
/* sliding items */
MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
RARRAY(ary)->len += argc;
MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_INCREASE_LEN(ary, argc);
return ary;
}
@ -664,8 +801,7 @@ rb_ary_entry(VALUE ary, long offset)
VALUE
rb_ary_subseq(VALUE ary, long beg, long len)
{
VALUE klass, ary2, shared;
VALUE *ptr;
VALUE klass;
if (beg > RARRAY_LEN(ary)) return Qnil;
if (beg < 0 || len < 0) return Qnil;
@ -676,15 +812,7 @@ rb_ary_subseq(VALUE ary, long beg, long len)
klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0);
shared = ary_make_shared(ary);
ptr = RARRAY_PTR(ary);
ary2 = ary_alloc(klass);
RARRAY(ary2)->ptr = ptr + beg;
RARRAY(ary2)->len = len;
RARRAY(ary2)->aux.shared = shared;
FL_SET(ary2, ELTS_SHARED);
return ary2;
return ary_make_partial0(ary, beg, len);
}
/*
@ -794,7 +922,7 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
return RARRAY_PTR(ary)[0];
}
else {
return ary_shared_first(argc, argv, ary, Qfalse);
return ary_make_partial(argc, argv, ary, Qfalse);
}
}
@ -819,7 +947,7 @@ rb_ary_last(int argc, VALUE *argv, VALUE ary)
return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
}
else {
return ary_shared_first(argc, argv, ary, Qtrue);
return ary_make_partial(argc, argv, ary, Qtrue);
}
}
@ -1003,7 +1131,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
if (rlen > 0) {
MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
}
RARRAY(ary)->len = len;
ARY_SET_LEN(ary, len);
}
else {
long alen;
@ -1020,7 +1148,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
if (len != rlen) {
MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
VALUE, RARRAY_LEN(ary) - (beg + len));
RARRAY(ary)->len = alen;
ARY_SET_LEN(ary, alen);
}
if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
@ -1238,10 +1366,11 @@ VALUE
rb_ary_dup(VALUE ary)
{
VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
int is_embed = ARY_EMBED_P(dup);
DUPSETUP(dup, ary);
if (is_embed) FL_SET_EMBED(dup);
MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
RARRAY(dup)->len = RARRAY_LEN(ary);
ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
}
@ -1548,8 +1677,9 @@ VALUE
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
assert(!ARY_SHARED_P(ary));
if (RARRAY_LEN(ary) > 1) {
VALUE tmp = ary_make_shared(ary);
VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
struct ary_sort_data data;
RBASIC(tmp)->klass = 0;
@ -1558,18 +1688,39 @@ rb_ary_sort_bang(VALUE ary)
data.opt_inited = 0;
ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2, &data);
if (RARRAY(ary)->ptr != RARRAY(tmp)->ptr) {
if (!ARY_SHARED_P(ary)) xfree(RARRAY(ary)->ptr);
RARRAY(ary)->ptr = RARRAY(tmp)->ptr;
RARRAY(ary)->len = RARRAY(tmp)->len;
RARRAY(ary)->aux.capa = RARRAY(tmp)->aux.capa;
FL_SET(ary, ELTS_SHARED);
};
FL_UNSET(ary, ELTS_SHARED);
RARRAY(tmp)->ptr = 0;
RARRAY(tmp)->len = 0;
RARRAY(tmp)->aux.capa = 0;
RBASIC(tmp)->klass = rb_cArray;
if (ARY_EMBED_P(ary) || ARY_EMBED_P(tmp)) {
assert(ARY_EMBED_P(tmp));
MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
}
else {
assert(!ARY_EMBED_P(ary));
assert(!ARY_EMBED_P(tmp));
if (RARRAY_PTR(ary) != RARRAY_PTR(tmp)) {
assert(!ARY_SHARED_P(tmp));
if (ARY_SHARED_P(ary)) {
FL_UNSET_SHARED(ary);
}
else {
xfree(ARY_HEAP_PTR(ary));
}
ARY_SET_PTR(ary, RARRAY_PTR(tmp));
ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp));
ARY_SET_CAPA(ary, ARY_CAPA(tmp));
}
else {
FL_UNSET_SHARED(ary);
ARY_SET_CAPA(ary, ARY_CAPA(tmp));
}
/* tmp was lost ownership for the ptr */
FL_UNSET(tmp, FL_FREEZE);
FL_SET_EMBED(tmp);
ARY_SET_EMBED_LEN(tmp, 0);
FL_SET(tmp, FL_FREEZE);
}
/* tmp will be GC'ed. */
RBASIC(tmp)->klass = rb_cArray;
}
return ary;
}
@ -1778,7 +1929,7 @@ rb_ary_delete(VALUE ary, VALUE item)
rb_ary_modify(ary);
if (RARRAY_LEN(ary) > i2) {
RARRAY(ary)->len = i2;
ARY_SET_LEN(ary, i2);
if (i2 * 2 < ARY_CAPA(ary) &&
ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
RESIZE_CAPA(ary, i2*2);
@ -1804,7 +1955,7 @@ rb_ary_delete_at(VALUE ary, long pos)
del = RARRAY_PTR(ary)[pos];
MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
RARRAY_LEN(ary)-pos-1);
RARRAY(ary)->len--;
ARY_INCREASE_LEN(ary, -1);
return del;
}
@ -1921,7 +2072,7 @@ rb_ary_reject_bang(VALUE ary)
if (RARRAY_LEN(ary) == i2) return Qnil;
if (i2 < RARRAY_LEN(ary))
RARRAY(ary)->len = i2;
ARY_SET_LEN(ary, i2);
return ary;
}
@ -2089,22 +2240,30 @@ rb_ary_transpose(VALUE ary)
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
VALUE shared;
VALUE *ptr;
orig = to_ary(orig);
rb_ary_modify_check(copy);
if (copy == orig) return copy;
shared = ary_make_shared(orig);
if (!ARY_SHARED_P(copy)) {
ptr = RARRAY(copy)->ptr;
xfree(ptr);
}
RARRAY(copy)->ptr = RARRAY(orig)->ptr;
RARRAY(copy)->len = RARRAY(orig)->len;
RARRAY(copy)->aux.shared = shared;
FL_SET(copy, ELTS_SHARED);
if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
VALUE *ptr;
if (ARY_OWNS_HEAP_P(copy)) xfree(RARRAY_PTR(copy));
FL_UNSET_SHARED(copy);
FL_SET_EMBED(copy);
ptr = RARRAY_PTR(orig);
MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
}
else {
VALUE shared = ary_make_shared(orig);
if (ARY_OWNS_HEAP_P(copy)) {
xfree(RARRAY_PTR(copy));
}
FL_UNSET_EMBED(copy);
FL_SET_SHARED(copy);
ARY_SET_PTR(copy, RARRAY_PTR(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
ARY_SET_SHARED(copy, shared);
}
return copy;
}
@ -2122,7 +2281,7 @@ VALUE
rb_ary_clear(VALUE ary)
{
rb_ary_modify(ary);
RARRAY(ary)->len = 0;
ARY_SET_LEN(ary, 0);
if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
}
@ -2201,7 +2360,7 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
RESIZE_CAPA(ary, end);
}
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
RARRAY(ary)->len = end;
ARY_SET_LEN(ary, end);
}
if (block_p) {
@ -2245,7 +2404,7 @@ rb_ary_plus(VALUE x, VALUE y)
z = rb_ary_new2(len);
MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
RARRAY(z)->len = len;
ARY_SET_LEN(z, len);
return z;
}
@ -2307,7 +2466,7 @@ rb_ary_times(VALUE ary, VALUE times)
len *= RARRAY_LEN(ary);
ary2 = ary_new(rb_obj_class(ary), len);
RARRAY(ary2)->len = len;
ARY_SET_LEN(ary2, len);
for (i=0; i<len; i+=RARRAY_LEN(ary)) {
MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
@ -2716,7 +2875,7 @@ rb_ary_uniq_bang(VALUE ary)
rb_ary_store(ary, j++, v);
}
}
RARRAY(ary)->len = j;
ARY_SET_LEN(ary, j);
return ary;
}
@ -2771,7 +2930,7 @@ rb_ary_compact_bang(VALUE ary)
if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
RESIZE_CAPA(ary, n * 2);
}
RARRAY(ary)->len = n;
ARY_SET_LEN(ary, n);
return ary;
}
@ -3168,7 +3327,7 @@ permute0(long n, long r, long *p, long index, int *used, VALUE values)
const VALUE *values_array = RARRAY_PTR(values);
for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
RARRAY(result)->len = r;
ARY_SET_LEN(result, r);
rb_yield(result);
}
}
@ -3228,7 +3387,7 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
long *p = (long*)RSTRING_PTR(t0);
volatile VALUE t1 = tmpbuf(n,sizeof(int));
int *used = (int*)RSTRING_PTR(t1);
VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
VALUE ary0 = ary_make_substitution(ary); /* private defensive copy of ary */
for (i = 0; i < n; i++) used[i] = 0; /* initialize array */

Просмотреть файл

@ -3089,9 +3089,6 @@ ip_ruby_cmd(clientData, interp, argc, argv)
/* get args */
args = rb_ary_new2(argc - 2);
#ifdef HAVE_STRUCT_RARRAY_LEN
RARRAY(args)->len = 0;
#endif
for(i = 3; i < argc; i++) {
#if TCL_MAJOR_VERSION >= 8
str = Tcl_GetStringFromObj(argv[i], &len);
@ -3099,14 +3096,14 @@ ip_ruby_cmd(clientData, interp, argc, argv)
#ifndef HAVE_STRUCT_RARRAY_LEN
rb_ary_push(args, rb_tainted_str_new(str, len));
#else
RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new(str, len);
RARRAY(args)->as.heap.ptr[RARRAY(args)->as.heap.len++] = rb_tainted_str_new(str, len);
#endif
#else /* TCL_MAJOR_VERSION < 8 */
DUMP2("arg:%s",argv[i]);
#ifndef HAVE_STRUCT_RARRAY_LEN
rb_ary_push(args, rb_tainted_str_new2(argv[i]));
#else
RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new2(argv[i]);
RARRAY(args)->as.heap.ptr[RARRAY(args)->as.heap.len++] = rb_tainted_str_new2(argv[i]);
#endif
#endif
}
@ -8298,7 +8295,7 @@ ip_invoke_with_position(argc, argv, obj, position)
DUMP2("back from handler (current thread:%lx)", current);
/* get result & free allocated memory */
ret = RARRAY(result)->ptr[0];
ret = RARRAY(result)->as.heap.ptr[0];
#if 0 /* use Tcl_EventuallyFree */
Tcl_EventuallyFree((ClientData)alloc_done, TCL_DYNAMIC); /* XXXXXXXX */
#else

2
gc.c
Просмотреть файл

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

Просмотреть файл

@ -504,7 +504,7 @@ VALUE rb_newobj(void);
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\
} while (0)
#define DUPSETUP(dup,obj) do {\
OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED));\
OBJSETUP(dup,rb_obj_class(obj), (RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED)); \
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)dup,(VALUE)obj);\
} while (0)
@ -596,17 +596,34 @@ struct RString {
RSTRING(str)->as.heap.ptr)
#define RSTRING_END(str) (RSTRING_PTR(str)+RSTRING_LEN(str))
#define RARRAY_EMBED_LEN_MAX 3
struct RArray {
struct RBasic basic;
long len;
union {
long capa;
VALUE shared;
} aux;
VALUE *ptr;
struct {
long len;
union {
long capa;
VALUE shared;
} aux;
VALUE *ptr;
} heap;
VALUE ary[RARRAY_EMBED_LEN_MAX];
} as;
};
#define RARRAY_LEN(a) RARRAY(a)->len
#define RARRAY_PTR(a) RARRAY(a)->ptr
#define RARRAY_EMBED_FLAG FL_USER1
/* FL_USER2 is for ELTS_SHARED */
#define RARRAY_EMBED_LEN_MASK (FL_USER4|FL_USER3)
#define RARRAY_EMBED_LEN_SHIFT (FL_USHIFT+3)
#define RARRAY_LEN(a) \
((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
(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_EMBED_FLAG) ? \
RARRAY(a)->as.ary : \
RARRAY(a)->as.heap.ptr)
struct RRegexp {
struct RBasic basic;

Просмотреть файл

@ -4945,7 +4945,7 @@ coverage(const char *f, int n)
int i;
RBASIC(lines)->klass = 0;
for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
RARRAY(lines)->len = n;
RARRAY(lines)->as.heap.len = n;
rb_hash_aset(coverages, fname, lines);
return lines;
}

6
proc.c
Просмотреть файл

@ -1674,11 +1674,7 @@ static VALUE curry(VALUE dummy, VALUE args, int argc, VALUE *argv, VALUE passed_
static VALUE
make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
{
VALUE args = rb_ary_new2(3);
RARRAY_PTR(args)[0] = proc;
RARRAY_PTR(args)[1] = passed;
RARRAY_PTR(args)[2] = arity;
RARRAY_LEN(args) = 3;
VALUE args = rb_ary_new3(3, proc, passed, arity);
rb_ary_freeze(passed);
rb_ary_freeze(args);
return rb_proc_new(curry, args);