diff options
Diffstat (limited to 'ractor.c')
-rw-r--r-- | ractor.c | 32 |
1 files changed, 25 insertions, 7 deletions
@@ -1357,8 +1357,25 @@ make_shareable_check_shareable(VALUE obj) } } - if (RB_TYPE_P(obj, T_IMEMO)) { + switch (TYPE(obj)) { + case T_IMEMO: return traverse_skip; + case T_OBJECT: + { + // If a T_OBJECT is shared and has no free capacity, we can't safely store the object_id inline, + // as it would require to move the object content into an external buffer. + // This is only a problem for T_OBJECT, given other types have external fields and can do RCU. + // To avoid this issue, we proactively create the object_id. + shape_id_t shape_id = RBASIC_SHAPE_ID(obj); + attr_index_t capacity = RSHAPE_CAPACITY(shape_id); + attr_index_t free_capacity = capacity - RSHAPE_LEN(shape_id); + if (!rb_shape_has_object_id(shape_id) && capacity && !free_capacity) { + rb_obj_id(obj); + } + } + break; + default: + break; } if (!RB_OBJ_FROZEN_RAW(obj)) { @@ -1639,9 +1656,9 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data) else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \ } while (0) - if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) { - struct gen_fields_tbl *fields_tbl; - rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl); + if (UNLIKELY(rb_obj_exivar_p(obj))) { + VALUE fields_obj; + rb_ivar_generic_fields_tbl_lookup(obj, &fields_obj); if (UNLIKELY(rb_shape_obj_too_complex_p(obj))) { struct obj_traverse_replace_callback_data d = { @@ -1650,7 +1667,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data) .src = obj, }; rb_st_foreach_with_replace( - fields_tbl->as.complex.table, + rb_imemo_fields_complex_tbl(fields_obj), obj_iv_hash_traverse_replace_foreach_i, obj_iv_hash_traverse_replace_i, (st_data_t)&d @@ -1659,8 +1676,9 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data) } else { uint32_t fields_count = RSHAPE_LEN(RBASIC_SHAPE_ID(obj)); + VALUE *fields = rb_imemo_fields_ptr(fields_obj); for (uint32_t i = 0; i < fields_count; i++) { - CHECK_AND_REPLACE(fields_tbl->as.shape.fields[i]); + CHECK_AND_REPLACE(fields[i]); } } } @@ -1868,7 +1886,7 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data) rb_gc_obj_id_moved(data->replacement); - if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) { + if (UNLIKELY(rb_obj_exivar_p(obj))) { rb_replace_generic_ivar(data->replacement, obj); } |