Get rid of flatten_memo_data_type
We can use an hidden Hash instead, it's simpler, triggers write barriers, handle compaction, etc.
This commit is contained in:
parent
6968b289e7
commit
9691532428
35
array.c
35
array.c
@ -6295,16 +6295,9 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary)
|
|||||||
static VALUE
|
static VALUE
|
||||||
flatten(VALUE ary, int level)
|
flatten(VALUE ary, int level)
|
||||||
{
|
{
|
||||||
static const rb_data_type_t flatten_memo_data_type = {
|
|
||||||
.wrap_struct_name = "array_flatten_memo_data_type",
|
|
||||||
.function = { NULL, (RUBY_DATA_FUNC)st_free_table },
|
|
||||||
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
|
|
||||||
};
|
|
||||||
|
|
||||||
long i;
|
long i;
|
||||||
VALUE stack, result, tmp = 0, elt, vmemo;
|
VALUE stack, result, tmp = 0, elt;
|
||||||
st_table *memo = 0;
|
VALUE memo = Qfalse;
|
||||||
st_data_t id;
|
|
||||||
|
|
||||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||||
elt = RARRAY_AREF(ary, i);
|
elt = RARRAY_AREF(ary, i);
|
||||||
@ -6326,10 +6319,9 @@ flatten(VALUE ary, int level)
|
|||||||
rb_ary_push(stack, LONG2NUM(i + 1));
|
rb_ary_push(stack, LONG2NUM(i + 1));
|
||||||
|
|
||||||
if (level < 0) {
|
if (level < 0) {
|
||||||
memo = st_init_numtable();
|
memo = rb_obj_hide(rb_ident_hash_new());
|
||||||
vmemo = TypedData_Wrap_Struct(0, &flatten_memo_data_type, memo);
|
rb_hash_aset(memo, ary, Qtrue);
|
||||||
st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
|
rb_hash_aset(memo, tmp, Qtrue);
|
||||||
st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ary = tmp;
|
ary = tmp;
|
||||||
@ -6344,9 +6336,8 @@ flatten(VALUE ary, int level)
|
|||||||
}
|
}
|
||||||
tmp = rb_check_array_type(elt);
|
tmp = rb_check_array_type(elt);
|
||||||
if (RBASIC(result)->klass) {
|
if (RBASIC(result)->klass) {
|
||||||
if (memo) {
|
if (RTEST(memo)) {
|
||||||
RB_GC_GUARD(vmemo);
|
rb_hash_clear(memo);
|
||||||
st_clear(memo);
|
|
||||||
}
|
}
|
||||||
rb_raise(rb_eRuntimeError, "flatten reentered");
|
rb_raise(rb_eRuntimeError, "flatten reentered");
|
||||||
}
|
}
|
||||||
@ -6355,12 +6346,11 @@ flatten(VALUE ary, int level)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (memo) {
|
if (memo) {
|
||||||
id = (st_data_t)tmp;
|
if (rb_hash_aref(memo, tmp) == Qtrue) {
|
||||||
if (st_is_member(memo, id)) {
|
rb_hash_clear(memo);
|
||||||
st_clear(memo);
|
|
||||||
rb_raise(rb_eArgError, "tried to flatten recursive array");
|
rb_raise(rb_eArgError, "tried to flatten recursive array");
|
||||||
}
|
}
|
||||||
st_insert(memo, id, (st_data_t)Qtrue);
|
rb_hash_aset(memo, tmp, Qtrue);
|
||||||
}
|
}
|
||||||
rb_ary_push(stack, ary);
|
rb_ary_push(stack, ary);
|
||||||
rb_ary_push(stack, LONG2NUM(i));
|
rb_ary_push(stack, LONG2NUM(i));
|
||||||
@ -6372,8 +6362,7 @@ flatten(VALUE ary, int level)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (memo) {
|
if (memo) {
|
||||||
id = (st_data_t)ary;
|
rb_hash_delete(memo, ary);
|
||||||
st_delete(memo, &id, 0);
|
|
||||||
}
|
}
|
||||||
tmp = rb_ary_pop(stack);
|
tmp = rb_ary_pop(stack);
|
||||||
i = NUM2LONG(tmp);
|
i = NUM2LONG(tmp);
|
||||||
@ -6381,7 +6370,7 @@ flatten(VALUE ary, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (memo) {
|
if (memo) {
|
||||||
st_clear(memo);
|
rb_hash_clear(memo);
|
||||||
}
|
}
|
||||||
|
|
||||||
RBASIC_SET_CLASS(result, rb_cArray);
|
RBASIC_SET_CLASS(result, rb_cArray);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user