8000 shape.c: refactor frozen shape to no longer be final · ruby/ruby@6577ef7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6577ef7

Browse files
committed
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.
1 parent d2d7476 commit 6577ef7

File tree

3 files changed

+20
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
358358

359359
rb_shape_t *initial_shape = rb_shape_get_shape(dest);
360360

361-
if (initial_shape->heap_index != src_shape->heap_index) {
361+
if (initial_shape->heap_index != src_shape->heap_index || !rb_shape_canonical_p(src_shape)) {
362362
RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
363363

364364
shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ static ID id_t_object;
5050
#define BLACK 0x0
5151
#define RED 0x1
5252

53+
enum shape_flags {
54+
SHAPE_FL_FROZEN = 1 << 0,
55+
56+
SHAPE_FL_NON_CANONICAL_MASK = SHAPE_FL_FROZEN,
57+
};
58+
5359
static redblack_node_t *
5460
redblack_left(redblack_node_t *node)
5561
{
@@ -418,6 +424,7 @@ rb_shape_alloc(ID edge_name, rb_shape_t *parent, enum shape_type type)
418424
{
419425
rb_shape_t *shape = rb_shape_alloc_with_parent_id(edge_name, rb_shape_id(parent));
420426
shape->type = (uint8_t)type;
427+
shape->flags = parent->flags;
421428
shape->heap_index = parent->heap_index;
422429
shape->capacity = parent->capacity;
423430
shape->edges = 0;
@@ -478,6 +485,7 @@ rb_shape_alloc_new_child(ID id, rb_shape_t *shape, enum shape_type shape_type)
478485
break;
479486
case SHAPE_FROZEN:
480487
new_shape->next_field_index = shape->next_field_index;
488+
new_shape->flags |= SHAPE_FL_FROZEN;
481489
break;
482490
case SHAPE_OBJ_TOO_COMPLEX:
483491
case SHAPE_ROOT:
@@ -576,7 +584,7 @@ get_next_shape_internal(rb_shape_t *shape, ID id, enum shape_type shape_type, bo
576584
bool
577585
rb_shape_frozen_shape_p(rb_shape_t *shape)
578586
{
579-
return SHAPE_FROZEN == (enum shape_type)shape->type;
587+
return SHAPE_FL_FROZEN & shape->flags;
580588
}
581589

582590
static rb_shape_t *
@@ -975,6 +983,9 @@ rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shap
975983
return next_shape;
976984
}
977985

986< E57B span class="diff-text-marker">+
// Rebuild a similar shape with the same ivars but starting from
987+
// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
988+
// such as SHAPE_FROZEN.
978989
rb_shape_t *
979990
rb_shape_rebuild_shape(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
980991
{
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct rb_shape {
4848
attr_index_t capacity; // Total capacity of the object with this shape
4949
uint8_t type;
5050
uint8_t heap_index;
51+
uint8_t flags;
5152
shape_id_t parent_id;
5253
redblack_node_t *ancestor_index;
5354
};
@@ -171,6 +172,12 @@ rb_shape_t *rb_shape_get_next_no_warnings(rb_shape_t *shape, VALUE obj, ID id);
171172

172173
rb_shape_t *rb_shape_rebuild_shape(rb_shape_t *initial_shape, rb_shape_t *dest_shape);
173174

175+
static inline bool
176+
rb_shape_canonical_p(rb_shape_t *shape)
177+
{
178+
return !shape->flags;
179+
}
180+
174181
static inline uint32_t
175182
ROBJECT_FIELDS_CAPACITY(VALUE obj)
176183
{