make `RARRAY_PTR_USE` more conservertive.

* include/ruby/ruby.h: de-transient at
  `RARRAY_PTR_USE` and `RARRAY_PTR_USE_START`.
  Introduce `RARRAY_PTR_USE_TRANSIENT` and
  `RARRAY_PTR_USE_START_TRANSIENT` if you don't want to
  de-transient an array. Generally, it is difficult
  so C-extension writers should not use them.

* array.c: use `RARRAY_PTR_USE_TRANSIENT` if possible.

* hash.c: ditto.

* enum.c (enum_sort_by): remove `rb_ary_transient_heap_evacuate()`
  because `RARRAY_PTR_USE` do de-transient.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66165 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2018-12-03 12:36:39 +00:00
Родитель 60989daa1b
Коммит 5e11de6585
5 изменённых файлов: 82 добавлений и 55 удалений

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

@ -223,7 +223,7 @@ rb_mem_clear(register VALUE *mem, register long size)
static void static void
ary_mem_clear(VALUE ary, long beg, long size) ary_mem_clear(VALUE ary, long beg, long size)
{ {
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
rb_mem_clear(ptr + beg, size); rb_mem_clear(ptr + beg, size);
}); });
} }
@ -239,7 +239,7 @@ memfill(register VALUE *mem, register long size, register VALUE val)
static void static void
ary_memfill(VALUE ary, long beg, long size, VALUE val) ary_memfill(VALUE ary, long beg, long size, VALUE val)
{ {
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
memfill(ptr + beg, size, val); memfill(ptr + beg, size, val);
RB_OBJ_WRITTEN(ary, Qundef, val); RB_OBJ_WRITTEN(ary, Qundef, val);
}); });
@ -252,13 +252,13 @@ ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_
if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) { if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
rb_gc_writebarrier_remember(buff_owner_ary); rb_gc_writebarrier_remember(buff_owner_ary);
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMCPY(ptr+beg, argv, VALUE, argc); MEMCPY(ptr+beg, argv, VALUE, argc);
}); });
} }
else { else {
int i; int i;
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
for (i=0; i<argc; i++) { for (i=0; i<argc; i++) {
RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]); RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
} }
@ -539,7 +539,7 @@ rb_ary_modify(VALUE ary)
FL_UNSET_SHARED(ary); FL_UNSET_SHARED(ary);
ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared)); ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared));
ARY_SET_CAPA(ary, shared_len); ARY_SET_CAPA(ary, shared_len);
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr, ptr+shift, VALUE, len); MEMMOVE(ptr, ptr+shift, VALUE, len);
}); });
FL_SET_EMBED(shared); FL_SET_EMBED(shared);
@ -1149,7 +1149,7 @@ rb_ary_push(VALUE ary, VALUE item)
{ {
long idx = RARRAY_LEN((ary_verify(ary), ary)); long idx = RARRAY_LEN((ary_verify(ary), ary));
VALUE target_ary = ary_ensure_room_for_push(ary, 1); VALUE target_ary = ary_ensure_room_for_push(ary, 1);
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
RB_OBJ_WRITE(target_ary, &ptr[idx], item); RB_OBJ_WRITE(target_ary, &ptr[idx], item);
}); });
ARY_SET_LEN(ary, idx + 1); ARY_SET_LEN(ary, idx + 1);
@ -1254,7 +1254,7 @@ rb_ary_shift(VALUE ary)
top = RARRAY_AREF(ary, 0); top = RARRAY_AREF(ary, 0);
if (!ARY_SHARED_P(ary)) { if (!ARY_SHARED_P(ary)) {
if (len < ARY_DEFAULT_SIZE) { if (len < ARY_DEFAULT_SIZE) {
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr, ptr+1, VALUE, len-1); MEMMOVE(ptr, ptr+1, VALUE, len-1);
}); /* WB: no new reference */ }); /* WB: no new reference */
ARY_INCREASE_LEN(ary, -1); ARY_INCREASE_LEN(ary, -1);
@ -1267,7 +1267,7 @@ rb_ary_shift(VALUE ary)
ary_make_shared(ary); ary_make_shared(ary);
} }
else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) { else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
RARRAY_PTR_USE(ary, ptr, ptr[0] = Qnil); RARRAY_PTR_USE_TRANSIENT(ary, ptr, ptr[0] = Qnil);
} }
ARY_INCREASE_PTR(ary, 1); /* shift ptr */ ARY_INCREASE_PTR(ary, 1); /* shift ptr */
ARY_INCREASE_LEN(ary, -1); ARY_INCREASE_LEN(ary, -1);
@ -1333,7 +1333,7 @@ rb_ary_behead(VALUE ary, long n)
} }
else { else {
if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) { if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n); MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
}); /* WB: no new reference */ }); /* WB: no new reference */
} }
@ -1403,7 +1403,7 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
} }
else { else {
/* sliding items */ /* sliding items */
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr + argc, ptr, VALUE, len); MEMMOVE(ptr + argc, ptr, VALUE, len);
}); });
@ -1856,7 +1856,7 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
} }
if (len != rlen) { if (len != rlen) {
RARRAY_PTR_USE(ary, ptr, RARRAY_PTR_USE_TRANSIENT(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len, MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len))); VALUE, olen - (beg + len)));
ARY_SET_LEN(ary, alen); ARY_SET_LEN(ary, alen);
@ -2490,7 +2490,7 @@ rb_ary_reverse(VALUE ary)
rb_ary_modify(ary); rb_ary_modify(ary);
if (len > 1) { if (len > 1) {
RARRAY_PTR_USE(ary, p1, { RARRAY_PTR_USE_TRANSIENT(ary, p1, {
p2 = p1 + len - 1; /* points last item */ p2 = p1 + len - 1; /* points last item */
ary_reverse(p1, p2); ary_reverse(p1, p2);
}); /* WB: no new reference */ }); /* WB: no new reference */
@ -2563,7 +2563,7 @@ rb_ary_rotate(VALUE ary, long cnt)
if (cnt != 0) { if (cnt != 0) {
long len = RARRAY_LEN(ary); long len = RARRAY_LEN(ary);
if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) { if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt)); RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
return ary; return ary;
} }
} }
@ -3208,7 +3208,7 @@ select_bang_ensure(VALUE a)
long tail = 0; long tail = 0;
if (i1 < len) { if (i1 < len) {
tail = len - i1; tail = len - i1;
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr + i2, ptr + i1, VALUE, tail); MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
}); });
} }
@ -3377,7 +3377,7 @@ rb_ary_delete_at(VALUE ary, long pos)
rb_ary_modify(ary); rb_ary_modify(ary);
del = RARRAY_AREF(ary, pos); del = RARRAY_AREF(ary, pos);
RARRAY_PTR_USE(ary, ptr, { RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1); MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
}); });
ARY_INCREASE_LEN(ary, -1); ARY_INCREASE_LEN(ary, -1);
@ -5367,7 +5367,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
sorted[j] = idx[i] = k; sorted[j] = idx[i] = k;
} }
result = rb_ary_new_capa(n); result = rb_ary_new_capa(n);
RARRAY_PTR_USE(result, ptr_result, { RARRAY_PTR_USE_TRANSIENT(result, ptr_result, {
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
ptr_result[i] = RARRAY_AREF(ary, idx[i]); ptr_result[i] = RARRAY_AREF(ary, idx[i]);
} }
@ -5390,7 +5390,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
len = RARRAY_LEN(ary); len = RARRAY_LEN(ary);
if (len <= max_idx) n = 0; if (len <= max_idx) n = 0;
else if (n > len) n = len; else if (n > len) n = len;
RARRAY_PTR_USE(ary, ptr_ary, { RARRAY_PTR_USE_TRANSIENT(ary, ptr_ary, {
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
long j2 = j = ptr_result[i]; long j2 = j = ptr_result[i];
long i2 = i; long i2 = i;

1
enum.c
Просмотреть файл

@ -1172,7 +1172,6 @@ enum_sort_by(VALUE obj)
rb_ary_concat(ary, buf); rb_ary_concat(ary, buf);
} }
if (RARRAY_LEN(ary) > 2) { if (RARRAY_LEN(ary) > 2) {
rb_ary_transient_heap_evacuate(ary, TRUE); /* should be malloc heap */
RARRAY_PTR_USE(ary, ptr, RARRAY_PTR_USE(ary, ptr,
ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE), ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
sort_by_cmp, (void *)ary)); sort_by_cmp, (void *)ary));

20
hash.c
Просмотреть файл

@ -3113,27 +3113,22 @@ keys_i(VALUE key, VALUE value, VALUE ary)
MJIT_FUNC_EXPORTED VALUE MJIT_FUNC_EXPORTED VALUE
rb_hash_keys(VALUE hash) rb_hash_keys(VALUE hash)
{ {
VALUE keys;
st_index_t size = RHASH_SIZE(hash); st_index_t size = RHASH_SIZE(hash);
VALUE keys = rb_ary_new_capa(size);
keys = rb_ary_new_capa(size);
if (size == 0) return keys; if (size == 0) return keys;
if (ST_DATA_COMPATIBLE_P(VALUE)) { if (ST_DATA_COMPATIBLE_P(VALUE)) {
RARRAY_PTR_USE_TRANSIENT(keys, ptr, {
if (RHASH_ARRAY_P(hash)) { if (RHASH_ARRAY_P(hash)) {
rb_gc_writebarrier_remember(keys);
RARRAY_PTR_USE(keys, ptr, {
size = linear_keys(hash, ptr, size); size = linear_keys(hash, ptr, size);
});
} }
else if (RHASH_TABLE_P(hash)) { else {
st_table *table = RHASH_ST_TABLE(hash); st_table *table = RHASH_ST_TABLE(hash);
rb_gc_writebarrier_remember(keys);
RARRAY_PTR_USE(keys, ptr, {
size = st_keys(table, ptr, size); size = st_keys(table, ptr, size);
});
} }
});
rb_gc_writebarrier_remember(keys);
rb_ary_set_len(keys, size); rb_ary_set_len(keys, size);
} }
else { else {
@ -3174,15 +3169,14 @@ rb_hash_values(VALUE hash)
if (ST_DATA_COMPATIBLE_P(VALUE)) { if (ST_DATA_COMPATIBLE_P(VALUE)) {
if (RHASH_ARRAY_P(hash)) { if (RHASH_ARRAY_P(hash)) {
rb_gc_writebarrier_remember(values); rb_gc_writebarrier_remember(values);
RARRAY_PTR_USE(values, ptr, { RARRAY_PTR_USE_TRANSIENT(values, ptr, {
size = linear_values(hash, ptr, size); size = linear_values(hash, ptr, size);
}); });
} }
else if (RHASH_TABLE_P(hash)) { else if (RHASH_TABLE_P(hash)) {
st_table *table = RHASH_ST_TABLE(hash); st_table *table = RHASH_ST_TABLE(hash);
rb_gc_writebarrier_remember(values); rb_gc_writebarrier_remember(values);
RARRAY_PTR_USE(values, ptr, { RARRAY_PTR_USE_TRANSIENT(values, ptr, {
size = st_values(table, ptr, size); size = st_values(table, ptr, size);
}); });
} }

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

@ -1066,11 +1066,18 @@ struct RArray {
#define RARRAY_TRANSIENT_P(ary) 0 #define RARRAY_TRANSIENT_P(ary) 0
#endif #endif
VALUE *rb_ary_ptr_use_start(VALUE ary); #define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1)
void rb_ary_ptr_use_end(VALUE ary); #define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1)
#define RARRAY_PTR_USE_START(a) rb_ary_ptr_use_start(a) #define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) do { \
#define RARRAY_PTR_USE_END(a) rb_ary_ptr_use_end(a) const VALUE _ary = (ary); \
VALUE *ptr_name = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \
expr; \
RARRAY_PTR_USE_END_TRANSIENT(_ary); \
} while (0)
#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0)
#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
#define RARRAY_PTR_USE(ary, ptr_name, expr) do { \ #define RARRAY_PTR_USE(ary, ptr_name, expr) do { \
const VALUE _ary = (ary); \ const VALUE _ary = (ary); \
@ -1083,9 +1090,9 @@ void rb_ary_ptr_use_end(VALUE ary);
#define RARRAY_ASET(a, i, v) do { \ #define RARRAY_ASET(a, i, v) do { \
const VALUE _ary = (a); \ const VALUE _ary = (a); \
const VALUE _v = (v); \ const VALUE _v = (v); \
VALUE *ptr = (VALUE *)RARRAY_PTR_USE_START(_ary); \ VALUE *ptr = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \
RB_OBJ_WRITE(_ary, &ptr[i], _v); \ RB_OBJ_WRITE(_ary, &ptr[i], _v); \
RARRAY_PTR_USE_END(_ary); \ RARRAY_PTR_USE_END_TRANSIENT(_ary); \
} while (0) } while (0)
#define RARRAY_PTR(a) ((VALUE *)RARRAY_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(ARRAY, a))) #define RARRAY_PTR(a) ((VALUE *)RARRAY_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(ARRAY, a)))
@ -2134,6 +2141,7 @@ rb_array_len(VALUE a)
# define FIX_CONST_VALUE_PTR(x) (x) # define FIX_CONST_VALUE_PTR(x) (x)
#endif #endif
/* internal function. do not use this function */
static inline const VALUE * static inline const VALUE *
rb_array_const_ptr_transient(VALUE a) rb_array_const_ptr_transient(VALUE a)
{ {
@ -2141,6 +2149,7 @@ rb_array_const_ptr_transient(VALUE a)
RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr); RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr);
} }
/* internal function. do not use this function */
static inline const VALUE * static inline const VALUE *
rb_array_const_ptr(VALUE a) rb_array_const_ptr(VALUE a)
{ {
@ -2154,6 +2163,32 @@ rb_array_const_ptr(VALUE a)
return rb_array_const_ptr_transient(a); return rb_array_const_ptr_transient(a);
} }
/* internal function. do not use this function */
static inline VALUE *
rb_array_ptr_use_start(VALUE a, int allow_transient)
{
VALUE *rb_ary_ptr_use_start(VALUE ary);
#if USE_TRANSIENT_HEAP
if (!allow_transient) {
if (RARRAY_TRANSIENT_P(a)) {
void rb_ary_detransient(VALUE a);
rb_ary_detransient(a);
}
}
#endif
return rb_ary_ptr_use_start(a);
}
/* internal function. do not use this function */
static inline void
rb_array_ptr_use_end(VALUE a, int allow_transient)
{
void rb_ary_ptr_use_end(VALUE a);
rb_ary_ptr_use_end(a);
}
#if defined(EXTLIB) && defined(USE_DLN_A_OUT) #if defined(EXTLIB) && defined(USE_DLN_A_OUT)
/* hook for external modules */ /* hook for external modules */
static char *dln_libs_to_be_linked[] = { EXTLIB, 0 }; static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };

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

@ -1262,14 +1262,13 @@ VALUE rb_gvar_defined(struct rb_global_entry *);
#ifdef ARRAY_DEBUG #ifdef ARRAY_DEBUG
#define RARRAY_PTR_IN_USE_FLAG FL_USER14 #define RARRAY_PTR_IN_USE_FLAG FL_USER14
#define ARY_PTR_USING_P(ary) FL_TEST_RAW((ary), RARRAY_PTR_IN_USE_FLAG) #define ARY_PTR_USING_P(ary) FL_TEST_RAW((ary), RARRAY_PTR_IN_USE_FLAG)
#else #else
/* disable debug function */ /* disable debug function */
#undef RARRAY_PTR_USE_START #undef RARRAY_PTR_USE_START_TRANSIENT
#undef RARRAY_PTR_USE_END #undef RARRAY_PTR_USE_END_TRANSIENT
#define RARRAY_PTR_USE_START(a) ((VALUE *)RARRAY_CONST_PTR_TRANSIENT(a)) #define RARRAY_PTR_USE_START_TRANSIENT(a) ((VALUE *)RARRAY_CONST_PTR_TRANSIENT(a))
#define RARRAY_PTR_USE_END(a) #define RARRAY_PTR_USE_END_TRANSIENT(a)
#define ARY_PTR_USING_P(ary) 0 #define ARY_PTR_USING_P(ary) 0
#endif #endif