From 6b0434c0f721a62d617b26986565985598c7b8c9 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 12 Mar 2024 14:27:34 -0400 Subject: [PATCH] Don't create per size pool shapes for non-T_OBJECT --- gc.c | 4 ---- object.c | 2 +- shape.c | 38 ++++++++++++++++++++------------------ shape.h | 2 +- test/ruby/test_shapes.rb | 7 +++---- variable.c | 2 +- 6 files changed, 26 insertions(+), 29 deletions(-) diff --git a/gc.c b/gc.c index 5b10fc7b95..0d35e6fe88 100644 --- a/gc.c +++ b/gc.c @@ -2918,10 +2918,6 @@ newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v size_t size_pool_idx = rb_gc_size_pool_id_for_size(alloc_size); - if (SHAPE_IN_BASIC_FLAGS || (flags & RUBY_T_MASK) == T_OBJECT) { - flags |= (VALUE)size_pool_idx << SHAPE_FLAG_SHIFT; - } - rb_ractor_newobj_cache_t *cache = &cr->newobj_cache; if (!UNLIKELY(during_gc || diff --git a/object.c b/object.c index 1156b69767..b420f49067 100644 --- a/object.c +++ b/object.c @@ -135,7 +135,7 @@ rb_class_allocate_instance(VALUE klass) RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT); // Set the shape to the specific T_OBJECT shape. - ROBJECT_SET_SHAPE_ID(obj, SIZE_POOL_COUNT + rb_gc_size_pool_id_for_size(size)); + ROBJECT_SET_SHAPE_ID(obj, (shape_id_t)(rb_gc_size_pool_id_for_size(size) + 1)); #if RUBY_DEBUG RUBY_ASSERT(!rb_shape_obj_too_complex(obj)); diff --git a/shape.c b/shape.c index 5854e4f94e..d3e68ef1dc 100644 --- a/shape.c +++ b/shape.c @@ -1256,43 +1256,45 @@ Init_default_shapes(void) GET_SHAPE_TREE()->root_shape = root; RUBY_ASSERT(rb_shape_id(GET_SHAPE_TREE()->root_shape) == ROOT_SHAPE_ID); - // Shapes by size pool - for (int i = 1; i < SIZE_POOL_COUNT; i++) { - rb_shape_t *new_shape = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID); - new_shape->type = SHAPE_ROOT; - new_shape->size_pool_index = i; - new_shape->ancestor_index = LEAF; - RUBY_ASSERT(rb_shape_id(new_shape) == (shape_id_t)i); - } - // Make shapes for T_OBJECT size_t *sizes = rb_gc_size_pool_sizes(); for (int i = 0; sizes[i] > 0; i++) { - rb_shape_t * shape = rb_shape_get_shape_by_id(i); - bool dont_care; rb_shape_t *t_object_shape = - get_next_shape_internal(shape, id_t_object, SHAPE_T_OBJECT, &dont_care, true); + rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID); + t_object_shape->type = SHAPE_T_OBJECT; t_object_shape->capacity = (uint32_t)((sizes[i] - offsetof(struct RObject, as.ary)) / sizeof(VALUE)); t_object_shape->edges = rb_id_table_create(0); t_object_shape->ancestor_index = LEAF; - RUBY_ASSERT(rb_shape_id(t_object_shape) == (shape_id_t)(i + SIZE_POOL_COUNT)); + RUBY_ASSERT(rb_shape_id(t_object_shape) == (shape_id_t)(i + 1)); } bool dont_care; // Special const shape #if RUBY_DEBUG - rb_shape_t * special_const_shape = + rb_shape_t *special_const_shape = #endif get_next_shape_internal(root, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true); RUBY_ASSERT(rb_shape_id(special_const_shape) == SPECIAL_CONST_SHAPE_ID); RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1)); RUBY_ASSERT(rb_shape_frozen_shape_p(special_const_shape)); - rb_shape_t * hash_fallback_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID); - hash_fallback_shape->type = SHAPE_OBJ_TOO_COMPLEX; - hash_fallback_shape->size_pool_index = 0; + rb_shape_t *too_complex_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID); + too_complex_shape->type = SHAPE_OBJ_TOO_COMPLEX; + too_complex_shape->size_pool_index = 0; RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1)); - RUBY_ASSERT(rb_shape_id(hash_fallback_shape) == OBJ_TOO_COMPLEX_SHAPE_ID); + RUBY_ASSERT(rb_shape_id(too_complex_shape) == OBJ_TOO_COMPLEX_SHAPE_ID); + + // Make shapes for T_OBJECT + size_t *sizes = rb_gc_size_pool_sizes(); + for (int i = 0; sizes[i] > 0; i++) { + rb_shape_t *t_object_shape = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID); + t_object_shape->type = SHAPE_T_OBJECT; + t_object_shape->size_pool_index = i; + t_object_shape->capacity = (uint32_t)((sizes[i] - offsetof(struct RObject, as.ary)) / sizeof(VALUE)); + t_object_shape->edges = rb_id_table_create(0); + t_object_shape->ancestor_index = LEAF; + RUBY_ASSERT(rb_shape_id(t_object_shape) == (shape_id_t)(i + FIRST_T_OBJECT_SHAPE_ID)); + } } void diff --git a/shape.h b/shape.h index 60e68dfe9b..2cb4a8715a 100644 --- a/shape.h +++ b/shape.h @@ -35,7 +35,7 @@ typedef uint32_t redblack_id_t; # define INVALID_SHAPE_ID SHAPE_MASK # define ROOT_SHAPE_ID 0x0 -# define SPECIAL_CONST_SHAPE_ID (SIZE_POOL_COUNT * 2) +# define SPECIAL_CONST_SHAPE_ID (SIZE_POOL_COUNT + 1) # define OBJ_TOO_COMPLEX_SHAPE_ID (SPECIAL_CONST_SHAPE_ID + 1) typedef struct redblack_node redblack_node_t; diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index ee99fbad6d..ed95d9538f 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -786,7 +786,7 @@ class TestShapes < Test::Unit::TestCase def test_remove_instance_variable_capacity_transition assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; - t_object_shape = RubyVM::Shape.find_by_id(GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT]) + t_object_shape = RubyVM::Shape.find_by_id(1) assert_equal(RubyVM::Shape::SHAPE_T_OBJECT, t_object_shape.type) initial_capacity = t_object_shape.capacity @@ -889,7 +889,7 @@ class TestShapes < Test::Unit::TestCase obj = TestObject.new shape = RubyVM::Shape.of(obj) assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type - assert_shape_equal(RubyVM::Shape.root_shape, shape.parent) + assert_nil shape.parent end def test_str_has_root_shape @@ -922,9 +922,8 @@ class TestShapes < Test::Unit::TestCase shape = shape.parent assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type + assert_nil shape.parent - shape = shape.parent - assert_equal(RubyVM::Shape.root_shape.id, shape.id) assert_equal(1, obj.instance_variable_get(:@a)) end diff --git a/variable.c b/variable.c index 99332d89a0..ca22572e73 100644 --- a/variable.c +++ b/variable.c @@ -1929,6 +1929,7 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu { switch ((enum shape_type)shape->type) { case SHAPE_ROOT: + case SHAPE_T_OBJECT: return false; case SHAPE_IVAR: ASSUME(callback); @@ -1962,7 +1963,6 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu } return false; case SHAPE_FROZEN: - case SHAPE_T_OBJECT: return iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data); case SHAPE_OBJ_TOO_COMPLEX: default: