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);
|
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);
|
RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
|
||||||
|
|
||||||
shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
|
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 BLACK 0x0
|
||||||
#define RED 0x1
|
#define RED 0x1
|
||||||
|
|
||||||
|
enum shape_flags {
|
||||||
|
SHAPE_FL_FROZEN = 1 << 0,
|
||||||
|
|
||||||
|
SHAPE_FL_NON_CANONICAL_MASK = SHAPE_FL_FROZEN,
|
||||||
|
};
|
||||||
|
|
||||||
static redblack_node_t *
|
static redblack_node_t *
|
||||||
redblack_left(redblack_node_t *node)
|
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));
|
rb_shape_t *shape = rb_shape_alloc_with_parent_id(edge_name, rb_shape_id(parent));
|
||||||
shape->type = (uint8_t)type;
|
shape->type = (uint8_t)type;
|
||||||
|
shape->flags = parent->flags;
|
||||||
shape->heap_index = parent->heap_index;
|
shape->heap_index = parent->heap_index;
|
||||||
shape->capacity = parent->capacity;
|
shape->capacity = parent->capacity;
|
||||||
shape->edges = 0;
|
shape->edges = 0;
|
||||||
@ -478,6 +485,7 @@ rb_shape_alloc_new_child(ID id, rb_shape_t *shape, enum shape_type shape_type)
|
|||||||
break;
|
break;
|
||||||
case SHAPE_FROZEN:
|
case SHAPE_FROZEN:
|
||||||
new_shape->next_field_index = shape->next_field_index;
|
new_shape->next_field_index = shape->next_field_index;
|
||||||
|
new_shape->flags |= SHAPE_FL_FROZEN;
|
||||||
break;
|
break;
|
||||||
case SHAPE_OBJ_TOO_COMPLEX:
|
case SHAPE_OBJ_TOO_COMPLEX:
|
||||||
case SHAPE_ROOT:
|
case SHAPE_ROOT:
|
||||||
@ -576,7 +584,7 @@ get_next_shape_internal(rb_shape_t *shape, ID id, enum shape_type shape_type, bo
|
|||||||
bool
|
bool
|
||||||
rb_shape_frozen_shape_p(rb_shape_t *shape)
|
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 *
|
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;
|
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_t *
|
||||||
rb_shape_rebuild_shape(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
|
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
|
attr_index_t capacity; // Total capacity of the object with this shape
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t heap_index;
|
uint8_t heap_index;
|
||||||
|
uint8_t flags;
|
||||||
shape_id_t parent_id;
|
shape_id_t parent_id;
|
||||||
redblack_node_t *ancestor_index;
|
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);
|
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
|
static inline uint32_t
|
||||||
ROBJECT_FIELDS_CAPACITY(VALUE obj)
|
ROBJECT_FIELDS_CAPACITY(VALUE obj)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user