Skip to content

Commit a640723

Browse files
committed
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.
1 parent 191f6e3 commit a640723

File tree

3 files changed

+9
-71
lines changed

3 files changed

+9
-71
lines changed

gc.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,19 +381,9 @@ rb_gc_set_shape(VALUE obj, uint32_t shape_id)
381381
uint32_t
382382
rb_gc_rebuild_shape(VALUE obj, size_t heap_id)
383383
{
384-
shape_id_t orig_shape_id = rb_obj_shape_id(obj);
385-
if (rb_shape_too_complex_p(orig_shape_id)) {
386-
return (uint32_t)orig_shape_id;
387-
}
388-
389-
shape_id_t initial_shape_id = rb_shape_root(heap_id);
390-
shape_id_t new_shape_id = rb_shape_traverse_from_new_root(initial_shape_id, orig_shape_id);
391-
392-
if (new_shape_id == INVALID_SHAPE_ID) {
393-
return 0;
394-
}
384+
RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
395385

396-
return (uint32_t)new_shape_id;
386+
return (uint32_t)rb_shape_transition_heap(obj, heap_id);
397387
}
398388

399389
void rb_vm_update_references(void *ptr);

shape.c

Lines changed: 6 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,12 @@ rb_shape_transition_complex(VALUE obj)
823823
return transition_complex(RBASIC_SHAPE_ID(obj));
824824
}
825825

826+
shape_id_t
827+
rb_shape_transition_heap(VALUE obj, size_t heap_index)
828+
{
829+
return (RBASIC_SHAPE_ID(obj) & (~SHAPE_ID_HEAP_INDEX_MASK)) | rb_shape_root(heap_index);
830+
}
831+
826832
/*
827833
* This function is used for assertions where we don't want to increment
828834
* max_iv_count
@@ -1065,63 +1071,6 @@ rb_shape_id_offset(void)
10651071
return sizeof(uintptr_t) - SHAPE_ID_NUM_BITS / sizeof(uintptr_t);
10661072
}
10671073

1068-
static rb_shape_t *
1069-
shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
1070-
{
1071-
RUBY_ASSERT(initial_shape->type == SHAPE_ROOT);
1072-
rb_shape_t *next_shape = initial_shape;
1073-
1074-
if (dest_shape->type != initial_shape->type) {
1075-
next_shape = shape_traverse_from_new_root(initial_shape, RSHAPE(dest_shape->parent_id));
1076-
if (!next_shape) {
1077-
return NULL;
1078-
}
1079-
}
1080-
1081-
switch ((enum shape_type)dest_shape->type) {
1082-
case SHAPE_IVAR:
1083-
case SHAPE_OBJ_ID:
1084-
if (!next_shape->edges) {
1085-
return NULL;
1086-
}
1087-
1088-
VALUE lookup_result;
1089-
if (SINGLE_CHILD_P(next_shape->edges)) {
1090-
rb_shape_t *child = SINGLE_CHILD(next_shape->edges);
1091-
if (child->edge_name == dest_shape->edge_name) {
1092-
return child;
1093-
}
1094-
else {
1095-
return NULL;
1096-
}
1097-
}
1098-
else {
1099-
if (rb_managed_id_table_lookup(next_shape->edges, dest_shape->edge_name, &lookup_result)) {
1100-
next_shape = (rb_shape_t *)lookup_result;
1101-
}
1102-
else {
1103-
return NULL;
1104-
}
1105-
}
1106-
break;
1107-
case SHAPE_ROOT:
1108-
break;
1109-
}
1110-
1111-
return next_shape;
1112-
}
1113-
1114-
shape_id_t
1115-
rb_shape_traverse_from_new_root(shape_id_t initial_shape_id, shape_id_t dest_shape_id)
1116-
{
1117-
rb_shape_t *initial_shape = RSHAPE(initial_shape_id);
1118-
rb_shape_t *dest_shape = RSHAPE(dest_shape_id);
1119-
1120-
// Keep all dest_shape_id flags except for the heap_index.
1121-
shape_id_t dest_flags = (dest_shape_id & ~SHAPE_ID_HEAP_INDEX_MASK) | (initial_shape_id & SHAPE_ID_HEAP_INDEX_MASK);
1122-
return shape_id(shape_traverse_from_new_root(initial_shape, dest_shape), dest_flags);
1123-
}
1124-
11251074
// Rebuild a similar shape with the same ivars but starting from
11261075
// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
11271076
// such as SHAPE_OBJ_ID.

shape.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ shape_id_t rb_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed
164164
shape_id_t rb_shape_transition_add_ivar(VALUE obj, ID id);
165165
shape_id_t rb_shape_transition_add_ivar_no_warnings(VALUE obj, ID id);
166166
shape_id_t rb_shape_transition_object_id(VALUE obj);
167+
shape_id_t rb_shape_transition_heap(VALUE obj, size_t heap_index);
167168
shape_id_t rb_shape_object_id(shape_id_t original_shape_id);
168169

169170
void rb_shape_free_all(void);
@@ -302,8 +303,6 @@ RBASIC_FIELDS_COUNT(VALUE obj)
302303
return RSHAPE(rb_obj_shape_id(obj))->next_field_index;
303304
}
304305

305-
shape_id_t rb_shape_traverse_from_new_root(shape_id_t initial_shape_id, shape_id_t orig_shape_id);
306-
307306
bool rb_obj_set_shape_id(VALUE obj, shape_id_t shape_id);
308307

309308
static inline bool

0 commit comments

Comments
 (0)