Fix Ractor sharing for too complex generic ivars
This commit is contained in:
parent
4938390177
commit
6eb5a9cf8f
44
ractor.c
44
ractor.c
@ -2739,6 +2739,19 @@ obj_traverse_rec(struct obj_traverse_data *data)
|
|||||||
return data->rec;
|
return data->rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
obj_traverse_ivar_foreach_i(ID key, VALUE val, st_data_t ptr)
|
||||||
|
{
|
||||||
|
struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr;
|
||||||
|
|
||||||
|
if (obj_traverse_i(val, d->data)) {
|
||||||
|
d->stop = true;
|
||||||
|
return ST_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
|
obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
|
||||||
{
|
{
|
||||||
@ -2755,14 +2768,12 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
|
struct obj_traverse_callback_data d = {
|
||||||
struct gen_ivtbl *ivtbl;
|
.stop = false,
|
||||||
rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
|
.data = data,
|
||||||
for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
|
};
|
||||||
VALUE val = ivtbl->as.shape.ivptr[i];
|
rb_ivar_foreach(obj, obj_traverse_ivar_foreach_i, (st_data_t)&d);
|
||||||
if (!UNDEF_P(val) && obj_traverse_i(val, data)) return 1;
|
if (d.stop) return 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (BUILTIN_TYPE(obj)) {
|
switch (BUILTIN_TYPE(obj)) {
|
||||||
// no child node
|
// no child node
|
||||||
@ -3229,12 +3240,29 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
|
|||||||
if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
|
if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
|
||||||
struct gen_ivtbl *ivtbl;
|
struct gen_ivtbl *ivtbl;
|
||||||
rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
|
rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
|
||||||
|
|
||||||
|
if (UNLIKELY(rb_shape_obj_too_complex(obj))) {
|
||||||
|
struct obj_traverse_replace_callback_data d = {
|
||||||
|
.stop = false,
|
||||||
|
.data = data,
|
||||||
|
.src = obj,
|
||||||
|
};
|
||||||
|
rb_st_foreach_with_replace(
|
||||||
|
ivtbl->as.complex.table,
|
||||||
|
obj_iv_hash_traverse_replace_foreach_i,
|
||||||
|
obj_iv_hash_traverse_replace_i,
|
||||||
|
(st_data_t)&d
|
||||||
|
);
|
||||||
|
if (d.stop) return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
|
for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
|
||||||
if (!UNDEF_P(ivtbl->as.shape.ivptr[i])) {
|
if (!UNDEF_P(ivtbl->as.shape.ivptr[i])) {
|
||||||
CHECK_AND_REPLACE(ivtbl->as.shape.ivptr[i]);
|
CHECK_AND_REPLACE(ivtbl->as.shape.ivptr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (BUILTIN_TYPE(obj)) {
|
switch (BUILTIN_TYPE(obj)) {
|
||||||
// no child node
|
// no child node
|
||||||
|
@ -621,6 +621,24 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_too_complex_generic_ivar_ractor_share
|
||||||
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
|
begin;
|
||||||
|
$VERBOSE = nil
|
||||||
|
|
||||||
|
RubyVM::Shape.exhaust_shapes
|
||||||
|
|
||||||
|
r = Ractor.new do
|
||||||
|
o = []
|
||||||
|
o.instance_variable_set(:@a, "hello")
|
||||||
|
Ractor.yield(o)
|
||||||
|
end
|
||||||
|
|
||||||
|
o = r.take
|
||||||
|
assert_equal "hello", o.instance_variable_get(:@a)
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
def test_read_iv_after_complex
|
def test_read_iv_after_complex
|
||||||
ensure_complex
|
ensure_complex
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user