Get rid of RSHAPE_PARENT in favor of RSHAPE_DIRECT_CHILD_P

`RSHAPE_PARENT` is error prone because it returns a raw untagged
shape_id.

To check if a shape is a direct parent of another, tags should be
discarded. So providing a comparison function is better than exposing
untagged ids.
This commit is contained in:
Jean Boussier 2025-07-31 14:25:41 +02:00
parent 84ee71df45
commit f0c31c5e64
3 changed files with 11 additions and 7 deletions

View file

@ -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\":");

View file

@ -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)
{

View file

@ -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 {