Simplify rb_gc_rebuild_shape
Now that there no longer multiple shape roots, all we need to do when moving an object from one slot to the other is to update the `heap_index` part of the shape_id. Since this never need to create a shape transition, it will always work and never result in a complex shape.
This commit is contained in:
parent
191f6e3b87
commit
a640723d31
Notes:
git
2025-06-07 16:30:58 +00:00
14
gc.c
14
gc.c
@ -381,19 +381,9 @@ rb_gc_set_shape(VALUE obj, uint32_t shape_id)
|
||||
uint32_t
|
||||
rb_gc_rebuild_shape(VALUE obj, size_t heap_id)
|
||||
{
|
||||
shape_id_t orig_shape_id = rb_obj_shape_id(obj);
|
||||
if (rb_shape_too_complex_p(orig_shape_id)) {
|
||||
return (uint32_t)orig_shape_id;
|
||||
}
|
||||
RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
|
||||
|
||||
shape_id_t initial_shape_id = rb_shape_root(heap_id);
|
||||
shape_id_t new_shape_id = rb_shape_traverse_from_new_root(initial_shape_id, orig_shape_id);
|
||||
|
||||
if (new_shape_id == INVALID_SHAPE_ID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint32_t)new_shape_id;
|
||||
return (uint32_t)rb_shape_transition_heap(obj, heap_id);
|
||||
}
|
||||
|
||||
void rb_vm_update_references(void *ptr);
|
||||
|
63
shape.c
63
shape.c
@ -823,6 +823,12 @@ rb_shape_transition_complex(VALUE obj)
|
||||
return transition_complex(RBASIC_SHAPE_ID(obj));
|
||||
}
|
||||
|
||||
shape_id_t
|
||||
rb_shape_transition_heap(VALUE obj, size_t heap_index)
|
||||
{
|
||||
return (RBASIC_SHAPE_ID(obj) & (~SHAPE_ID_HEAP_INDEX_MASK)) | rb_shape_root(heap_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used for assertions where we don't want to increment
|
||||
* max_iv_count
|
||||
@ -1065,63 +1071,6 @@ rb_shape_id_offset(void)
|
||||
return sizeof(uintptr_t) - SHAPE_ID_NUM_BITS / sizeof(uintptr_t);
|
||||
}
|
||||
|
||||
static rb_shape_t *
|
||||
shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
|
||||
{
|
||||
RUBY_ASSERT(initial_shape->type == SHAPE_ROOT);
|
||||
rb_shape_t *next_shape = initial_shape;
|
||||
|
||||
if (dest_shape->type != initial_shape->type) {
|
||||
next_shape = shape_traverse_from_new_root(initial_shape, RSHAPE(dest_shape->parent_id));
|
||||
if (!next_shape) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch ((enum shape_type)dest_shape->type) {
|
||||
case SHAPE_IVAR:
|
||||
case SHAPE_OBJ_ID:
|
||||
if (!next_shape->edges) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VALUE lookup_result;
|
||||
if (SINGLE_CHILD_P(next_shape->edges)) {
|
||||
rb_shape_t *child = SINGLE_CHILD(next_shape->edges);
|
||||
if (child->edge_name == dest_shape->edge_name) {
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rb_managed_id_table_lookup(next_shape->edges, dest_shape->edge_name, &lookup_result)) {
|
||||
next_shape = (rb_shape_t *)lookup_result;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SHAPE_ROOT:
|
||||
break;
|
||||
}
|
||||
|
||||
return next_shape;
|
||||
}
|
||||
|
||||
shape_id_t
|
||||
rb_shape_traverse_from_new_root(shape_id_t initial_shape_id, shape_id_t dest_shape_id)
|
||||
{
|
||||
rb_shape_t *initial_shape = RSHAPE(initial_shape_id);
|
||||
rb_shape_t *dest_shape = RSHAPE(dest_shape_id);
|
||||
|
||||
// Keep all dest_shape_id flags except for the heap_index.
|
||||
shape_id_t dest_flags = (dest_shape_id & ~SHAPE_ID_HEAP_INDEX_MASK) | (initial_shape_id & SHAPE_ID_HEAP_INDEX_MASK);
|
||||
return shape_id(shape_traverse_from_new_root(initial_shape, dest_shape), dest_flags);
|
||||
}
|
||||
|
||||
// Rebuild a similar shape with the same ivars but starting from
|
||||
// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
|
||||
// such as SHAPE_OBJ_ID.
|
||||
|
3
shape.h
3
shape.h
@ -164,6 +164,7 @@ shape_id_t rb_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed
|
||||
shape_id_t rb_shape_transition_add_ivar(VALUE obj, ID id);
|
||||
shape_id_t rb_shape_transition_add_ivar_no_warnings(VALUE obj, ID id);
|
||||
shape_id_t rb_shape_transition_object_id(VALUE obj);
|
||||
shape_id_t rb_shape_transition_heap(VALUE obj, size_t heap_index);
|
||||
shape_id_t rb_shape_object_id(shape_id_t original_shape_id);
|
||||
|
||||
void rb_shape_free_all(void);
|
||||
@ -302,8 +303,6 @@ RBASIC_FIELDS_COUNT(VALUE obj)
|
||||
return RSHAPE(rb_obj_shape_id(obj))->next_field_index;
|
||||
}
|
||||
|
||||
shape_id_t rb_shape_traverse_from_new_root(shape_id_t initial_shape_id, shape_id_t orig_shape_id);
|
||||
|
||||
bool rb_obj_set_shape_id(VALUE obj, shape_id_t shape_id);
|
||||
|
||||
static inline bool
|
||||
|
Loading…
x
Reference in New Issue
Block a user