shape.c: refactor frozen shape to no longer be final
This opens the door to store more informations in shapes, such as the `object_id` or object address in case it has been observed and the object has to be moved.
This commit is contained in:
parent
6c9b3ac232
commit
d34c150547
Notes:
git
2025-05-08 05:58:19 +00:00
2
object.c
2
object.c
@ -358,7 +358,7 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
|
||||
|
||||
rb_shape_t *initial_shape = rb_shape_get_shape(dest);
|
||||
|
||||
if (initial_shape->heap_index != src_shape->heap_index) {
|
||||
if (initial_shape->heap_index != src_shape->heap_index || !rb_shape_canonical_p(src_shape)) {
|
||||
RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
|
||||
|
||||
shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
|
||||
|
13
shape.c
13
shape.c
@ -50,6 +50,12 @@ static ID id_t_object;
|
||||
#define BLACK 0x0
|
||||
#define RED 0x1
|
||||
|
||||
enum shape_flags {
|
||||
SHAPE_FL_FROZEN = 1 << 0,
|
||||
|
||||
SHAPE_FL_NON_CANONICAL_MASK = SHAPE_FL_FROZEN,
|
||||
};
|
||||
|
||||
static redblack_node_t *
|
||||
redblack_left(redblack_node_t *node)
|
||||
{
|
||||
@ -418,6 +424,7 @@ rb_shape_alloc(ID edge_name, rb_shape_t *parent, enum shape_type type)
|
||||
{
|
||||
rb_shape_t *shape = rb_shape_alloc_with_parent_id(edge_name, rb_shape_id(parent));
|
||||
shape->type = (uint8_t)type;
|
||||
shape->flags = parent->flags;
|
||||
shape->heap_index = parent->heap_index;
|
||||
shape->capacity = parent->capacity;
|
||||
shape->edges = 0;
|
||||
@ -478,6 +485,7 @@ rb_shape_alloc_new_child(ID id, rb_shape_t *shape, enum shape_type shape_type)
|
||||
break;
|
||||
case SHAPE_FROZEN:
|
||||
new_shape->next_field_index = shape->next_field_index;
|
||||
new_shape->flags |= SHAPE_FL_FROZEN;
|
||||
break;
|
||||
case SHAPE_OBJ_TOO_COMPLEX:
|
||||
case SHAPE_ROOT:
|
||||
@ -576,7 +584,7 @@ get_next_shape_internal(rb_shape_t *shape, ID id, enum shape_type shape_type, bo
|
||||
bool
|
||||
rb_shape_frozen_shape_p(rb_shape_t *shape)
|
||||
{
|
||||
return SHAPE_FROZEN == (enum shape_type)shape->type;
|
||||
return SHAPE_FL_FROZEN & shape->flags;
|
||||
}
|
||||
|
||||
static rb_shape_t *
|
||||
@ -975,6 +983,9 @@ rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shap
|
||||
return next_shape;
|
||||
}
|
||||
|
||||
// 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_FROZEN.
|
||||
rb_shape_t *
|
||||
rb_shape_rebuild_shape(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
|
||||
{
|
||||
|
7
shape.h
7
shape.h
@ -48,6 +48,7 @@ struct rb_shape {
|
||||
attr_index_t capacity; // Total capacity of the object with this shape
|
||||
uint8_t type;
|
||||
uint8_t heap_index;
|
||||
uint8_t flags;
|
||||
shape_id_t parent_id;
|
||||
redblack_node_t *ancestor_index;
|
||||
};
|
||||
@ -171,6 +172,12 @@ rb_shape_t *rb_shape_get_next_no_warnings(rb_shape_t *shape, VALUE obj, ID id);
|
||||
|
||||
rb_shape_t *rb_shape_rebuild_shape(rb_shape_t *initial_shape, rb_shape_t *dest_shape);
|
||||
|
||||
static inline bool
|
||||
rb_shape_canonical_p(rb_shape_t *shape)
|
||||
{
|
||||
return !shape->flags;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_CAPACITY(VALUE obj)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user