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
|
uint32_t
|
||||||
rb_gc_rebuild_shape(VALUE obj, size_t heap_id)
|
rb_gc_rebuild_shape(VALUE obj, size_t heap_id)
|
||||||
{
|
{
|
||||||
shape_id_t orig_shape_id = rb_obj_shape_id(obj);
|
RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
|
||||||
if (rb_shape_too_complex_p(orig_shape_id)) {
|
|
||||||
return (uint32_t)orig_shape_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
shape_id_t initial_shape_id = rb_shape_root(heap_id);
|
return (uint32_t)rb_shape_transition_heap(obj, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rb_vm_update_references(void *ptr);
|
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));
|
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
|
* This function is used for assertions where we don't want to increment
|
||||||
* max_iv_count
|
* max_iv_count
|
||||||
@ -1065,63 +1071,6 @@ rb_shape_id_offset(void)
|
|||||||
return sizeof(uintptr_t) - SHAPE_ID_NUM_BITS / sizeof(uintptr_t);
|
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
|
// Rebuild a similar shape with the same ivars but starting from
|
||||||
// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
|
// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
|
||||||
// such as SHAPE_OBJ_ID.
|
// 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(VALUE obj, ID id);
|
||||||
shape_id_t rb_shape_transition_add_ivar_no_warnings(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_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);
|
shape_id_t rb_shape_object_id(shape_id_t original_shape_id);
|
||||||
|
|
||||||
void rb_shape_free_all(void);
|
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;
|
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);
|
bool rb_obj_set_shape_id(VALUE obj, shape_id_t shape_id);
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
|
Loading…
x
Reference in New Issue
Block a user