diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index 80732d0282..f90ad89b5a 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -801,7 +801,7 @@ shape_id_i(shape_id_t shape_id, void *data) if (RSHAPE_TYPE(shape_id) != SHAPE_ROOT) { dump_append(dc, ", \"parent_id\":"); - dump_append_lu(dc, RSHAPE_PARENT(shape_id)); + dump_append_lu(dc, RSHAPE_PARENT_RAW_ID(shape_id)); } dump_append(dc, ", \"depth\":"); diff --git a/shape.h b/shape.h index a418dc7821..2d13c9b762 100644 --- a/shape.h +++ b/shape.h @@ -271,11 +271,18 @@ rb_shape_root(size_t heap_id) } static inline shape_id_t -RSHAPE_PARENT(shape_id_t shape_id) +RSHAPE_PARENT_RAW_ID(shape_id_t shape_id) { return RSHAPE(shape_id)->parent_id; } +static inline bool +RSHAPE_DIRECT_CHILD_P(shape_id_t parent_id, shape_id_t child_id) +{ + return (parent_id & SHAPE_ID_FLAGS_MASK) == (child_id & SHAPE_ID_FLAGS_MASK) && + RSHAPE(child_id)->parent_id == (parent_id & SHAPE_ID_OFFSET_MASK); +} + static inline enum shape_type RSHAPE_TYPE(shape_id_t shape_id) { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index d5eb84e691..0fef0e0976 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1473,7 +1473,7 @@ vm_setivar_default(VALUE obj, ID id, VALUE val, shape_id_t dest_shape_id, attr_i RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID); } else if (dest_shape_id != INVALID_SHAPE_ID) { - if (shape_id == RSHAPE_PARENT(dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) == id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) { + if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) == id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) { RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id)); } else { @@ -1514,14 +1514,11 @@ vm_setivar(VALUE obj, ID id, VALUE val, shape_id_t dest_shape_id, attr_index_t i VM_ASSERT(!rb_ractor_shareable_p(obj)); } else if (dest_shape_id != INVALID_SHAPE_ID) { - shape_id_t source_shape_id = RSHAPE_PARENT(dest_shape_id); - - if (shape_id == source_shape_id && RSHAPE_EDGE_NAME(dest_shape_id) == id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) { + if (RSHAPE_DIRECT_CHILD_P(shape_id, dest_shape_id) && RSHAPE_EDGE_NAME(dest_shape_id) == id && RSHAPE_CAPACITY(shape_id) == RSHAPE_CAPACITY(dest_shape_id)) { RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID); RBASIC_SET_SHAPE_ID(obj, dest_shape_id); - RUBY_ASSERT(rb_shape_get_next_iv_shape(source_shape_id, id) == dest_shape_id); RUBY_ASSERT(index < RSHAPE_CAPACITY(dest_shape_id)); } else {