Skip to content

Commit

Permalink
fix shared array terminology.
Browse files Browse the repository at this point in the history
Shared arrays created by Array#dup and so on points
a shared_root object to manage lifetime of Array buffer.
However, sometimes shared_root is called only shared so
it is confusing. So I fixed these wording "shared" to "shared_root".

* RArray::heap::aux::shared -> RArray::heap::aux::shared_root
* ARY_SHARED() -> ARY_SHARED_ROOT()
* ARY_SHARED_NUM() -> ARY_SHARED_ROOT_REFCNT()

Also, add some debug_counters to count shared array objects.

* ary_shared_create: shared ary by Array#dup and so on.
* ary_shared: finished in shard.
* ary_shared_root_occupied: shared_root but has only 1 refcnt.
  The number (ary_shared - ary_shared_root_occupied) is meaningful.
  • Loading branch information
ko1 committed Jul 19, 2019
1 parent 547f574 commit 182ae14
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 57 deletions.
115 changes: 62 additions & 53 deletions array.c
Expand Up @@ -10,7 +10,6 @@
Copyright (C) 2000 Information-technology Promotion Agency, Japan
**********************************************************************/

#include "ruby/encoding.h"
#include "ruby/util.h"
#include "ruby/st.h"
Expand Down Expand Up @@ -116,21 +115,21 @@ VALUE rb_cArray;
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_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
#define ARY_SET_SHARED(ary, value) do { \
const VALUE _ary_ = (ary); \
const VALUE _value_ = (value); \
assert(!ARY_EMBED_P(_ary_)); \
assert(ARY_SHARED_P(_ary_)); \
assert(ARY_SHARED_ROOT_P(_value_)); \
RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \
RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
} while (0)
#define RARRAY_SHARED_ROOT_FLAG FL_USER5
#define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
#define ARY_SHARED_NUM(ary) \
#define ARY_SHARED_ROOT_REFCNT(ary) \
(assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
#define ARY_SHARED_OCCUPIED(ary) (ARY_SHARED_NUM(ary) == 1)
#define ARY_SET_SHARED_NUM(ary, value) do { \
#define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
assert(ARY_SHARED_ROOT_P(ary)); \
RARRAY(ary)->as.heap.aux.capa = (value); \
} while (0)
Expand Down Expand Up @@ -160,7 +159,7 @@ ary_verify_(VALUE ary, const char *file, int line)
assert(RB_TYPE_P(ary, T_ARRAY));

if (FL_TEST(ary, ELTS_SHARED)) {
VALUE root = RARRAY(ary)->as.heap.aux.shared;
VALUE root = RARRAY(ary)->as.heap.aux.shared_root;
const VALUE *ptr = ARY_HEAP_PTR(ary);
const VALUE *root_ptr = RARRAY_CONST_PTR_TRANSIENT(root);
long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
Expand Down Expand Up @@ -470,25 +469,25 @@ ary_double_capa(VALUE ary, long min)
}

static void
rb_ary_decrement_share(VALUE shared)
rb_ary_decrement_share(VALUE shared_root)
{
if (shared) {
long num = ARY_SHARED_NUM(shared) - 1;
if (shared_root) {
long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
if (num == 0) {
rb_ary_free(shared);
rb_gc_force_recycle(shared);
rb_ary_free(shared_root);
rb_gc_force_recycle(shared_root);
}
else if (num > 0) {
ARY_SET_SHARED_NUM(shared, num);
ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
}
}
}

static void
rb_ary_unshare(VALUE ary)
{
VALUE shared = RARRAY(ary)->as.heap.aux.shared;
rb_ary_decrement_share(shared);
VALUE shared_root = RARRAY(ary)->as.heap.aux.shared_root;
rb_ary_decrement_share(shared_root);
FL_UNSET_SHARED(ary);
}

Expand All @@ -501,21 +500,22 @@ rb_ary_unshare_safe(VALUE ary)
}

static VALUE
rb_ary_increment_share(VALUE shared)
rb_ary_increment_share(VALUE shared_root)
{
long num = ARY_SHARED_NUM(shared);
long num = ARY_SHARED_ROOT_REFCNT(shared_root);
if (num >= 0) {
ARY_SET_SHARED_NUM(shared, num + 1);
ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
}
return shared;
return shared_root;
}

static void
rb_ary_set_shared(VALUE ary, VALUE shared)
rb_ary_set_shared(VALUE ary, VALUE shared_root)
{
rb_ary_increment_share(shared);
rb_ary_increment_share(shared_root);
FL_SET_SHARED(ary);
ARY_SET_SHARED(ary, shared);
RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
ARY_SET_SHARED(ary, shared_root);
}

static inline void
Expand All @@ -531,28 +531,28 @@ rb_ary_modify(VALUE ary)
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
long shared_len, len = RARRAY_LEN(ary);
VALUE shared = ARY_SHARED(ary);
VALUE shared_root = ARY_SHARED_ROOT(ary);

ary_verify(shared);
ary_verify(shared_root);

if (len <= RARRAY_EMBED_LEN_MAX) {
const VALUE *ptr = ARY_HEAP_PTR(ary);
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
rb_ary_decrement_share(shared);
rb_ary_decrement_share(shared_root);
ARY_SET_EMBED_LEN(ary, len);
}
else if (ARY_SHARED_OCCUPIED(shared) && len > ((shared_len = RARRAY_LEN(shared))>>1)) {
long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared);
else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root);
FL_UNSET_SHARED(ary);
ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared));
ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared_root));
ARY_SET_CAPA(ary, shared_len);
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
MEMMOVE(ptr, ptr+shift, VALUE, len);
});
FL_SET_EMBED(shared);
rb_ary_decrement_share(shared);
FL_SET_EMBED(shared_root);
rb_ary_decrement_share(shared_root);
}
else {
VALUE *ptr = ary_heap_alloc(ary, len);
Expand All @@ -579,14 +579,14 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
}
if (ARY_SHARED_P(ary)) {
if (new_len > RARRAY_EMBED_LEN_MAX) {
VALUE shared = ARY_SHARED(ary);
if (ARY_SHARED_OCCUPIED(shared)) {
if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared) + new_len <= RARRAY_LEN(shared)) {
VALUE shared_root = ARY_SHARED_ROOT(ary);
if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
rb_ary_modify_check(ary);

ary_verify(ary);
ary_verify(shared);
return shared;
ary_verify(shared_root);
return shared_root;
}
else {
/* if array is shared, then it is likely it participate in push/shift pattern */
Expand Down Expand Up @@ -643,7 +643,7 @@ rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
{
if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
!ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
RARRAY(ary1)->as.heap.aux.shared_root == RARRAY(ary2)->as.heap.aux.shared_root &&
RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
return Qtrue;
}
Expand Down Expand Up @@ -778,6 +778,13 @@ rb_ary_free(VALUE ary)
else {
RB_DEBUG_COUNTER_INC(obj_ary_embed);
}

if (ARY_SHARED_P(ary)) {
RB_DEBUG_COUNTER_INC(obj_ary_shared);
}
if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
}
}

RUBY_FUNC_EXPORTED size_t
Expand Down Expand Up @@ -806,7 +813,7 @@ ary_make_shared(VALUE ary)
ary_verify(ary);

if (ARY_SHARED_P(ary)) {
return ARY_SHARED(ary);
return ARY_SHARED_ROOT(ary);
}
else if (ARY_SHARED_ROOT_P(ary)) {
return ary;
Expand All @@ -815,7 +822,7 @@ ary_make_shared(VALUE ary)
rb_ary_transient_heap_evacuate(ary, TRUE);
ary_shrink_capa(ary);
FL_SET_SHARED_ROOT(ary);
ARY_SET_SHARED_NUM(ary, 1);
ARY_SET_SHARED_ROOT_REFCNT(ary, 1);
return ary;
}
else {
Expand All @@ -831,13 +838,15 @@ ary_make_shared(VALUE ary)
ARY_SET_PTR((VALUE)shared, ptr);
ary_mem_clear((VALUE)shared, len, capa - len);
FL_SET_SHARED_ROOT(shared);
ARY_SET_SHARED_NUM((VALUE)shared, 1);
ARY_SET_SHARED_ROOT_REFCNT((VALUE)shared, 1);
FL_SET_SHARED(ary);
RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
ARY_SET_SHARED(ary, (VALUE)shared);
OBJ_FREEZE(shared);

ary_verify((VALUE)shared);
ary_verify(ary);

return (VALUE)shared;
}
}
Expand Down Expand Up @@ -1279,7 +1288,7 @@ rb_ary_shift(VALUE ary)
ARY_SET(ary, 0, Qnil);
ary_make_shared(ary);
}
else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
RARRAY_PTR_USE_TRANSIENT(ary, ptr, ptr[0] = Qnil);
}
ARY_INCREASE_PTR(ary, 1); /* shift ptr */
Expand Down Expand Up @@ -1338,7 +1347,7 @@ rb_ary_behead(VALUE ary, long n)

rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
setup_occupied_shared:
ary_mem_clear(ary, 0, n);
}
Expand Down Expand Up @@ -1374,12 +1383,12 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
}

if (ARY_SHARED_P(ary)) {
VALUE shared = ARY_SHARED(ary);
capa = RARRAY_LEN(shared);
if (ARY_SHARED_OCCUPIED(shared) && capa > new_len) {
VALUE shared_root = ARY_SHARED_ROOT(ary);
capa = RARRAY_LEN(shared_root);
if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && capa > new_len) {
rb_ary_modify_check(ary);
head = RARRAY_CONST_PTR_TRANSIENT(ary);
sharedp = RARRAY_CONST_PTR_TRANSIENT(shared);
sharedp = RARRAY_CONST_PTR_TRANSIENT(shared_root);
goto makeroom_if_need;
}
}
Expand Down Expand Up @@ -1410,10 +1419,10 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
head = sharedp + argc + room;
}
ARY_SET_PTR(ary, head - argc);
assert(ARY_SHARED_OCCUPIED(ARY_SHARED(ary)));
assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));

ary_verify(ary);
return ARY_SHARED(ary);
return ARY_SHARED_ROOT(ary);
}
else {
/* sliding items */
Expand Down Expand Up @@ -3784,24 +3793,24 @@ rb_ary_replace(VALUE copy, VALUE orig)
if (copy == orig) return copy;

if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
VALUE shared = 0;
VALUE shared_root = 0;

if (ARY_OWNS_HEAP_P(copy)) {
ary_heap_free(copy);
}
else if (ARY_SHARED_P(copy)) {
shared = ARY_SHARED(copy);
shared_root = ARY_SHARED_ROOT(copy);
FL_UNSET_SHARED(copy);
}
FL_SET_EMBED(copy);
ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
if (shared) {
rb_ary_decrement_share(shared);
if (shared_root) {
rb_ary_decrement_share(shared_root);
}
ARY_SET_LEN(copy, RARRAY_LEN(orig));
}
else {
VALUE shared = ary_make_shared(orig);
VALUE shared_root = ary_make_shared(orig);
if (ARY_OWNS_HEAP_P(copy)) {
ary_heap_free(copy);
}
Expand All @@ -3811,7 +3820,7 @@ rb_ary_replace(VALUE copy, VALUE orig)
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
rb_ary_set_shared(copy, shared);
rb_ary_set_shared(copy, shared_root);
}
ary_verify(copy);
return copy;
Expand Down
9 changes: 9 additions & 0 deletions debug_counter.h
Expand Up @@ -206,6 +206,15 @@ RB_DEBUG_COUNTER(obj_str_fstr)
RB_DEBUG_COUNTER(obj_ary_embed)
RB_DEBUG_COUNTER(obj_ary_transient)
RB_DEBUG_COUNTER(obj_ary_ptr)
/*
ary_shared_create: shared ary by Array#dup and so on.
ary_shared: finished in shard.
ary_shared_root_occupied: shared_root but has only 1 refcnt.
The number (ary_shared - ary_shared_root_occupied) is meaningful.
*/
RB_DEBUG_COUNTER(obj_ary_shared_create)
RB_DEBUG_COUNTER(obj_ary_shared)
RB_DEBUG_COUNTER(obj_ary_shared_root_occupied)

RB_DEBUG_COUNTER(obj_hash_empty)
RB_DEBUG_COUNTER(obj_hash_under4)
Expand Down
6 changes: 3 additions & 3 deletions gc.c
Expand Up @@ -5083,7 +5083,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)

case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) {
VALUE root = any->as.array.as.heap.aux.shared;
VALUE root = any->as.array.as.heap.aux.shared_root;
gc_mark(objspace, root);
}
else {
Expand Down Expand Up @@ -8007,7 +8007,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)

case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) {
UPDATE_IF_MOVED(objspace, any->as.array.as.heap.aux.shared);
UPDATE_IF_MOVED(objspace, any->as.array.as.heap.aux.shared_root);
}
else {
gc_ref_update_array(objspace, obj);
Expand Down Expand Up @@ -11219,7 +11219,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) {
APPENDF((BUFF_ARGS, "shared -> %s",
rb_obj_info(RARRAY(obj)->as.heap.aux.shared)));
rb_obj_info(RARRAY(obj)->as.heap.aux.shared_root)));
}
else if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
APPENDF((BUFF_ARGS, "[%s%s] len: %d (embed)",
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/ruby.h
Expand Up @@ -1054,7 +1054,7 @@ struct RArray {
long len;
union {
long capa;
VALUE shared;
VALUE shared_root;
} aux;
const VALUE *ptr;
} heap;
Expand Down

0 comments on commit 182ae14

Please sign in to comment.