diff --git a/shape.c b/shape.c index 9fe30e3851bd02..5b5e2ce4ec5c77 100644 --- a/shape.c +++ b/shape.c @@ -374,28 +374,20 @@ static const rb_data_type_t shape_tree_type = { */ static inline shape_id_t -shape_offset(rb_shape_t *shape) +SHAPE_OFFSET(rb_shape_t *shape) { RUBY_ASSERT(shape); return (shape_id_t)(shape - rb_shape_tree.shape_list); } static inline shape_id_t -shape_id(rb_shape_t *shape, shape_id_t previous_shape_id) +SHAPE_ID(rb_shape_t *shape, shape_id_t previous_shape_id) { RUBY_ASSERT(shape); - shape_id_t raw_id = (shape_id_t)(shape - rb_shape_tree.shape_list); - return raw_id | RSHAPE_FLAGS(previous_shape_id); + shape_id_t offset = (shape_id_t)(shape - rb_shape_tree.shape_list); + return offset | RSHAPE_FLAGS(previous_shape_id); } -#if RUBY_DEBUG -static inline bool -shape_frozen_p(shape_id_t shape_id) -{ - return shape_id & SHAPE_ID_FL_FROZEN; -} -#endif - void rb_shape_each_shape_id(each_shape_callback callback, void *data) { @@ -431,9 +423,9 @@ rb_shape_depth(shape_id_t shape_id) size_t depth = 1; rb_shape_t *shape = RSHAPE(shape_id); - while (shape->parent_id != INVALID_SHAPE_ID) { + while (shape->parent_offset != INVALID_SHAPE_ID) { depth++; - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); } return depth; @@ -456,14 +448,14 @@ shape_alloc(void) } static rb_shape_t * -rb_shape_alloc_with_parent_id(ID edge_name, shape_id_t parent_id) +rb_shape_alloc_with_parent_offset(ID edge_name, shape_id_t parent_offset) { rb_shape_t *shape = shape_alloc(); if (!shape) return NULL; shape->edge_name = edge_name; shape->next_field_index = 0; - shape->parent_id = parent_id; + shape->parent_offset = parent_offset; shape->edges = 0; return shape; @@ -472,7 +464,7 @@ rb_shape_alloc_with_parent_id(ID edge_name, shape_id_t parent_id) static rb_shape_t * 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, shape_offset(parent)); + rb_shape_t *shape = rb_shape_alloc_with_parent_offset(edge_name, SHAPE_OFFSET(parent)); if (!shape) return NULL; shape->type = (uint8_t)type; @@ -485,8 +477,8 @@ rb_shape_alloc(ID edge_name, rb_shape_t *parent, enum shape_type type) static redblack_node_t * redblack_cache_ancestors(rb_shape_t *shape) { - if (!(shape->ancestor_index || shape->parent_id == INVALID_SHAPE_ID)) { - redblack_node_t *parent_index_node = redblack_cache_ancestors(RSHAPE(shape->parent_id)); + if (!(shape->ancestor_index || shape->parent_offset == INVALID_SHAPE_ID)) { + redblack_node_t *parent_index_node = redblack_cache_ancestors(RSHAPE(shape->parent_offset)); if (shape->type == SHAPE_IVAR) { shape->ancestor_index = redblack_insert(parent_index_node, shape->edge_name, shape); @@ -709,7 +701,7 @@ rb_shape_transition_object_id(shape_id_t original_shape_id) } RUBY_ASSERT(shape); - return shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID; + return SHAPE_ID(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID; } shape_id_t @@ -719,13 +711,13 @@ rb_shape_object_id(shape_id_t original_shape_id) rb_shape_t *shape = RSHAPE(original_shape_id); while (shape->type != SHAPE_OBJ_ID) { - if (UNLIKELY(shape->parent_id == INVALID_SHAPE_ID)) { + if (UNLIKELY(shape->parent_offset == INVALID_SHAPE_ID)) { rb_bug("Missing object_id in shape tree"); } - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); } - return shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID; + return SHAPE_ID(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID; } /* @@ -748,13 +740,13 @@ rb_shape_get_next_iv_shape(shape_id_t shape_id, ID id) if (!next_shape) { return INVALID_SHAPE_ID; } - return shape_offset(next_shape); + return SHAPE_OFFSET(next_shape); } static bool shape_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value) { - while (shape->parent_id != INVALID_SHAPE_ID) { + while (shape->parent_offset != INVALID_SHAPE_ID) { if (shape->edge_name == id) { enum shape_type shape_type; shape_type = (enum shape_type)shape->type; @@ -771,7 +763,7 @@ shape_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value) } } - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); } return false; @@ -847,7 +839,7 @@ obj_get_owner_class(VALUE obj) static rb_shape_t * remove_shape_recursive(VALUE obj, rb_shape_t *shape, ID id, rb_shape_t **removed_shape) { - if (shape->parent_id == INVALID_SHAPE_ID) { + if (shape->parent_offset == INVALID_SHAPE_ID) { // We've hit the top of the shape tree and couldn't find the // IV we wanted to remove, so return NULL *removed_shape = NULL; @@ -857,11 +849,11 @@ remove_shape_recursive(VALUE obj, rb_shape_t *shape, ID id, rb_shape_t **removed if (shape->type == SHAPE_IVAR && shape->edge_name == id) { *removed_shape = shape; - return RSHAPE(shape->parent_id); + return RSHAPE(shape->parent_offset); } else { // This isn't the IV we want to remove, keep walking up. - rb_shape_t *new_parent = remove_shape_recursive(obj, RSHAPE(shape->parent_id), id, removed_shape); + rb_shape_t *new_parent = remove_shape_recursive(obj, RSHAPE(shape->parent_offset), id, removed_shape); // We found a new parent. Create a child of the new parent that // has the same attributes as this shape. @@ -884,7 +876,7 @@ shape_id_t rb_obj_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed_shape_id) { shape_id_t original_shape_id = RBASIC_SHAPE_ID(obj); - RUBY_ASSERT(!shape_frozen_p(original_shape_id)); + RUBY_ASSERT(!rb_shape_frozen_p(original_shape_id)); if (rb_shape_too_complex_p(original_shape_id)) { return original_shape_id; @@ -894,11 +886,11 @@ rb_obj_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed_shape_ rb_shape_t *new_shape = remove_shape_recursive(obj, RSHAPE(original_shape_id), id, &removed_shape); if (removed_shape) { - *removed_shape_id = shape_offset(removed_shape); + *removed_shape_id = SHAPE_OFFSET(removed_shape); } if (new_shape) { - return shape_id(new_shape, original_shape_id); + return SHAPE_ID(new_shape, original_shape_id); } else if (removed_shape) { // We found the shape to remove, but couldn't create a new variation. @@ -914,12 +906,12 @@ shape_id_t rb_obj_shape_transition_add_ivar(VALUE obj, ID id) { shape_id_t original_shape_id = RBASIC_SHAPE_ID(obj); - RUBY_ASSERT(!shape_frozen_p(original_shape_id)); + RUBY_ASSERT(!rb_shape_frozen_p(original_shape_id)); VALUE klass = obj_get_owner_class(obj); rb_shape_t *next_shape = shape_get_next(RSHAPE(original_shape_id), SHAPE_IVAR, klass, id, true); if (next_shape) { - return shape_id(next_shape, original_shape_id); + return SHAPE_ID(next_shape, original_shape_id); } else { return rb_shape_transition_complex(original_shape_id); @@ -929,11 +921,11 @@ rb_obj_shape_transition_add_ivar(VALUE obj, ID id) shape_id_t rb_shape_transition_add_ivar_no_warnings(shape_id_t original_shape_id, ID id, VALUE klass) { - RUBY_ASSERT(!shape_frozen_p(original_shape_id)); + RUBY_ASSERT(!rb_shape_frozen_p(original_shape_id)); rb_shape_t *next_shape = shape_get_next(RSHAPE(original_shape_id), SHAPE_IVAR, klass, id, false); if (next_shape) { - return shape_id(next_shape, original_shape_id); + return SHAPE_ID(next_shape, original_shape_id); } else { return rb_shape_transition_complex(original_shape_id); @@ -967,23 +959,23 @@ rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t *value, while (depth > 0 && shape->next_field_index > index_hint) { while (shape_hint->next_field_index > shape->next_field_index) { - shape_hint = RSHAPE(shape_hint->parent_id); + shape_hint = RSHAPE(shape_hint->parent_offset); } if (shape_hint == shape) { // We've found a common ancestor so use the index hint *value = index_hint; - *shape_id_hint = shape_offset(shape); + *shape_id_hint = SHAPE_OFFSET(shape); return true; } if (shape->edge_name == id) { // We found the matching id before a common ancestor *value = shape->next_field_index - 1; - *shape_id_hint = shape_offset(shape); + *shape_id_hint = SHAPE_OFFSET(shape); return true; } - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); depth--; } @@ -1014,14 +1006,14 @@ shape_cache_find_ivar(rb_shape_t *shape, ID id, rb_shape_t **ivar_shape) static bool shape_find_ivar(rb_shape_t *shape, ID id, rb_shape_t **ivar_shape) { - while (shape->parent_id != INVALID_SHAPE_ID) { + while (shape->parent_offset != INVALID_SHAPE_ID) { if (shape->edge_name == id) { RUBY_ASSERT(shape->type == SHAPE_IVAR); *ivar_shape = shape; return true; } - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); } return false; @@ -1047,7 +1039,7 @@ rb_shape_find_ivar(shape_id_t current_shape_id, ID id, shape_id_t *ivar_shape_id } } - *ivar_shape_id = shape_id(ivar_shape, current_shape_id); + *ivar_shape_id = SHAPE_ID(ivar_shape, current_shape_id); return true; } @@ -1083,7 +1075,7 @@ shape_rebuild(rb_shape_t *initial_shape, rb_shape_t *dest_shape) RUBY_ASSERT(initial_shape->type == SHAPE_ROOT); if (dest_shape->type != initial_shape->type) { - midway_shape = shape_rebuild(initial_shape, RSHAPE(dest_shape->parent_id)); + midway_shape = shape_rebuild(initial_shape, RSHAPE(dest_shape->parent_offset)); if (UNLIKELY(!midway_shape)) { return NULL; } @@ -1117,7 +1109,7 @@ rb_shape_rebuild(shape_id_t initial_shape_id, shape_id_t dest_shape_id) if (dest_shape_id & SHAPE_ID_FL_HAS_OBJECT_ID) { rb_shape_t *next_shape = shape_rebuild(RSHAPE(initial_shape_id), RSHAPE(dest_shape_id)); if (next_shape) { - next_shape_id = shape_id(next_shape, initial_shape_id & ~SHAPE_ID_FL_NON_CANONICAL_MASK); + next_shape_id = SHAPE_ID(next_shape, initial_shape_id & ~SHAPE_ID_FL_NON_CANONICAL_MASK); } else { return rb_shape_transition_complex(initial_shape_id | (dest_shape_id & ~SHAPE_ID_FL_NON_CANONICAL_MASK)); @@ -1146,18 +1138,18 @@ rb_shape_copy_fields(VALUE dest, VALUE *dest_buf, shape_id_t dest_shape_id, VALU } } else { - while (src_shape->parent_id != INVALID_SHAPE_ID) { + while (src_shape->parent_offset != INVALID_SHAPE_ID) { if (src_shape->type == SHAPE_IVAR) { while (dest_shape->edge_name != src_shape->edge_name) { - if (UNLIKELY(dest_shape->parent_id == INVALID_SHAPE_ID)) { + if (UNLIKELY(dest_shape->parent_offset == INVALID_SHAPE_ID)) { rb_bug("Lost field %s", rb_id2name(src_shape->edge_name)); } - dest_shape = RSHAPE(dest_shape->parent_id); + dest_shape = RSHAPE(dest_shape->parent_offset); } RB_OBJ_WRITE(dest, &dest_buf[dest_shape->next_field_index - 1], src_buf[src_shape->next_field_index - 1]); } - src_shape = RSHAPE(src_shape->parent_id); + src_shape = RSHAPE(src_shape->parent_offset); } } } @@ -1212,9 +1204,9 @@ rb_shape_foreach_field(shape_id_t initial_shape_id, rb_shape_foreach_transition_ return true; } - shape_id_t parent_id = shape_id(RSHAPE(shape->parent_id), initial_shape_id); - if (rb_shape_foreach_field(parent_id, func, data)) { - switch (func(shape_id(shape, initial_shape_id), data)) { + shape_id_t parent_offset = SHAPE_ID(RSHAPE(shape->parent_offset), initial_shape_id); + if (rb_shape_foreach_field(parent_offset, func, data)) { + switch (func(SHAPE_ID(shape, initial_shape_id), data)) { case ST_STOP: return false; case ST_CHECK: @@ -1242,12 +1234,12 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id) rb_shape_t *shape = RSHAPE(shape_id); bool has_object_id = false; - while (shape->parent_id != INVALID_SHAPE_ID) { + while (shape->parent_offset != INVALID_SHAPE_ID) { if (shape->type == SHAPE_OBJ_ID) { has_object_id = true; break; } - shape = RSHAPE(shape->parent_id); + shape = RSHAPE(shape->parent_offset); } if (rb_shape_has_object_id(shape_id)) { @@ -1352,7 +1344,7 @@ shape_id_t_to_rb_cShape(shape_id_t shape_id) VALUE obj = rb_struct_new(rb_cShape, INT2NUM(shape_id), INT2NUM(RSHAPE_OFFSET(shape_id)), - INT2NUM(shape->parent_id), + INT2NUM(shape->parent_offset), rb_shape_edge_name(shape), INT2NUM(shape->next_field_index), INT2NUM(rb_shape_heap_index(shape_id)), @@ -1365,7 +1357,7 @@ shape_id_t_to_rb_cShape(shape_id_t shape_id) static enum rb_id_table_iterator_result rb_edges_to_hash(ID key, VALUE value, void *ref) { - rb_hash_aset(*(VALUE *)ref, parse_key(key), shape_id_t_to_rb_cShape(shape_offset((rb_shape_t *)value))); + rb_hash_aset(*(VALUE *)ref, parse_key(key), shape_id_t_to_rb_cShape(SHAPE_OFFSET((rb_shape_t *)value))); return ID_TABLE_CONTINUE; } @@ -1415,8 +1407,8 @@ rb_shape_parent(VALUE self) { rb_shape_t *shape; shape = RSHAPE(NUM2INT(rb_struct_getmember(self, rb_intern("id")))); - if (shape->parent_id != INVALID_SHAPE_ID) { - return shape_id_t_to_rb_cShape(shape->parent_id); + if (shape->parent_offset != INVALID_SHAPE_ID) { + return shape_id_t_to_rb_cShape(shape->parent_offset); } else { return Qnil; @@ -1487,14 +1479,14 @@ shape_to_h(rb_shape_t *shape) { VALUE rb_shape = rb_hash_new(); - rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(shape_offset(shape))); + rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(SHAPE_OFFSET(shape))); rb_hash_aset(rb_shape, ID2SYM(rb_intern("edges")), edges(shape->edges)); if (shape == rb_shape_get_root_shape()) { - rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(ROOT_SHAPE_ID)); + rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_offset")), INT2NUM(ROOT_SHAPE_ID)); } else { - rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(shape->parent_id)); + rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_offset")), INT2NUM(shape->parent_offset)); } rb_hash_aset(rb_shape, ID2SYM(rb_intern("edge_name")), rb_id2str(shape->edge_name)); @@ -1588,20 +1580,20 @@ Init_default_shapes(void) shape_tree_obj = TypedData_Wrap_Struct(0, &shape_tree_type, (void *)1); // Root shape - rb_shape_t *root = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID); + rb_shape_t *root = rb_shape_alloc_with_parent_offset(0, INVALID_SHAPE_ID); root->capacity = 0; root->type = SHAPE_ROOT; - RUBY_ASSERT(shape_offset(root) == ROOT_SHAPE_ID); - RUBY_ASSERT(!(shape_offset(root) & SHAPE_ID_HAS_IVAR_MASK)); + RUBY_ASSERT(SHAPE_OFFSET(root) == ROOT_SHAPE_ID); + RUBY_ASSERT(!(SHAPE_OFFSET(root) & SHAPE_ID_HAS_IVAR_MASK)); bool dontcare; rb_shape_t *root_with_obj_id = get_next_shape_internal(root, id_object_id, SHAPE_OBJ_ID, &dontcare, true); RUBY_ASSERT(root_with_obj_id); - RUBY_ASSERT(shape_offset(root_with_obj_id) == ROOT_SHAPE_WITH_OBJ_ID); + RUBY_ASSERT(SHAPE_OFFSET(root_with_obj_id) == ROOT_SHAPE_WITH_OBJ_ID); RUBY_ASSERT(root_with_obj_id->type == SHAPE_OBJ_ID); RUBY_ASSERT(root_with_obj_id->edge_name == id_object_id); RUBY_ASSERT(root_with_obj_id->next_field_index == 1); - RUBY_ASSERT(!(shape_offset(root_with_obj_id) & SHAPE_ID_HAS_IVAR_MASK)); + RUBY_ASSERT(!(SHAPE_OFFSET(root_with_obj_id) & SHAPE_ID_HAS_IVAR_MASK)); (void)root_with_obj_id; } @@ -1613,8 +1605,8 @@ Init_shape(void) * :nodoc: */ VALUE rb_cShape = rb_struct_define_under(rb_cRubyVM, "Shape", "id", - "raw_id", - "parent_id", + "offset", + "parent_offset", "edge_name", "next_field_index", "heap_index", diff --git a/shape.h b/shape.h index e41efde797e348..c284cfb3a89945 100644 --- a/shape.h +++ b/shape.h @@ -88,7 +88,7 @@ struct rb_shape { VALUE edges; // id_table from ID (ivar) to next shape ID edge_name; // ID (ivar) for transition from parent to rb_shape redblack_id_t ancestor_index; - shape_id_t parent_id; + shape_id_t parent_offset; attr_index_t next_field_index; // Fields are either ivars or internal properties like `object_id` attr_index_t capacity; // Total capacity of the object with this shape enum shape_type type : 8; @@ -260,14 +260,14 @@ rb_shape_root(size_t heap_id) static inline shape_id_t RSHAPE_PARENT_OFFSET(shape_id_t shape_id) { - return RSHAPE(shape_id)->parent_id; + return RSHAPE(shape_id)->parent_offset; } static inline bool -RSHAPE_DIRECT_CHILD_P(shape_id_t parent_id, shape_id_t child_id) +RSHAPE_DIRECT_CHILD_P(shape_id_t parent_offset, shape_id_t child_id) { - return (RSHAPE_FLAGS(parent_id) == RSHAPE_FLAGS(child_id) && - RSHAPE_PARENT_OFFSET(child_id) == RSHAPE_OFFSET(parent_id)); + return (RSHAPE_FLAGS(parent_offset) == RSHAPE_FLAGS(child_id) && + RSHAPE_PARENT_OFFSET(child_id) == RSHAPE_OFFSET(parent_offset)); } static inline enum shape_type diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index 717ef48a1ff6e8..d50b59c1d8914a 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -95,15 +95,15 @@ def write_iv # shapes def assert_shape_equal(e, a) assert_equal( - {id: e.id, parent_id: e.parent_id, depth: e.depth, type: e.type}, - {id: a.id, parent_id: a.parent_id, depth: a.depth, type: a.type}, + {id: e.id, parent_offset: e.parent_offset, depth: e.depth, type: e.type}, + {id: a.id, parent_offset: a.parent_offset, depth: a.depth, type: a.type}, ) end def refute_shape_equal(e, a) refute_equal( - {id: e.id, parent_id: e.parent_id, depth: e.depth, type: e.type}, - {id: a.id, parent_id: a.parent_id, depth: a.depth, type: a.type}, + {id: e.id, parent_offset: e.parent_offset, depth: e.depth, type: e.type}, + {id: a.id, parent_offset: a.parent_offset, depth: a.depth, type: a.type}, ) end @@ -1032,7 +1032,7 @@ def test_iv_index example.add_foo # makes a transition add_foo_shape = RubyVM::Shape.of(example) assert_equal([:@foo], example.instance_variables) - assert_equal(initial_shape.raw_id, add_foo_shape.parent.raw_id) + assert_equal(initial_shape.offset, add_foo_shape.parent.offset) assert_equal(1, add_foo_shape.next_field_index) example.remove_foo # makes a transition @@ -1043,7 +1043,7 @@ def test_iv_index example.add_bar # makes a transition bar_shape = RubyVM::Shape.of(example) assert_equal([:@bar], example.instance_variables) - assert_equal(initial_shape.raw_id, bar_shape.parent_id) + assert_equal(initial_shape.offset, bar_shape.parent_offset) assert_equal(1, bar_shape.next_field_index) end @@ -1097,7 +1097,7 @@ def test_raise_on_special_consts def test_root_shape_frozen frozen_root_shape = RubyVM::Shape.of([].freeze) assert_predicate(frozen_root_shape, :frozen?) - assert_equal(RubyVM::Shape.root_shape.id, frozen_root_shape.raw_id) + assert_equal(RubyVM::Shape.root_shape.id, frozen_root_shape.offset) end def test_basic_shape_transition diff --git a/vm_callinfo.h b/vm_callinfo.h index 9f147522815d50..aad0d5f5849bf8 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -459,7 +459,7 @@ vm_unpack_shape_and_index(const uint64_t cache_value, shape_id_t *shape_id, attr .pack = cache_value, }; *shape_id = cache.unpack.shape_id; - *index = cache.unpack.index - 1; + *index = cache.unpack.index; } static inline void @@ -514,7 +514,7 @@ vm_pack_shape_and_index(shape_id_t shape_id, attr_index_t index) union rb_attr_index_cache cache = { .unpack = { .shape_id = shape_id, - .index = index + 1, + .index = index, } }; return cache.pack;