Don't create per size pool shapes for non-T_OBJECT
This commit is contained in:
parent
6ad347a105
commit
6b0434c0f7
4
gc.c
4
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);
|
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;
|
rb_ractor_newobj_cache_t *cache = &cr->newobj_cache;
|
||||||
|
|
||||||
if (!UNLIKELY(during_gc ||
|
if (!UNLIKELY(during_gc ||
|
||||||
|
2
object.c
2
object.c
@ -135,7 +135,7 @@ rb_class_allocate_instance(VALUE klass)
|
|||||||
RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT);
|
RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT);
|
||||||
|
|
||||||
// Set the shape to the specific T_OBJECT shape.
|
// 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
|
#if RUBY_DEBUG
|
||||||
RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
|
RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
|
||||||
|
36
shape.c
36
shape.c
@ -1256,26 +1256,16 @@ Init_default_shapes(void)
|
|||||||
GET_SHAPE_TREE()->root_shape = root;
|
GET_SHAPE_TREE()->root_shape = root;
|
||||||
RUBY_ASSERT(rb_shape_id(GET_SHAPE_TREE()->root_shape) == ROOT_SHAPE_ID);
|
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
|
// Make shapes for T_OBJECT
|
||||||
size_t *sizes = rb_gc_size_pool_sizes();
|
size_t *sizes = rb_gc_size_pool_sizes();
|
||||||
for (int i = 0; sizes[i] > 0; i++) {
|
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 =
|
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->capacity = (uint32_t)((sizes[i] - offsetof(struct RObject, as.ary)) / sizeof(VALUE));
|
||||||
t_object_shape->edges = rb_id_table_create(0);
|
t_object_shape->edges = rb_id_table_create(0);
|
||||||
t_object_shape->ancestor_index = LEAF;
|
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;
|
bool dont_care;
|
||||||
@ -1288,11 +1278,23 @@ Init_default_shapes(void)
|
|||||||
RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
|
RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
|
||||||
RUBY_ASSERT(rb_shape_frozen_shape_p(special_const_shape));
|
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);
|
rb_shape_t *too_complex_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID);
|
||||||
hash_fallback_shape->type = SHAPE_OBJ_TOO_COMPLEX;
|
too_complex_shape->type = SHAPE_OBJ_TOO_COMPLEX;
|
||||||
hash_fallback_shape->size_pool_index = 0;
|
too_complex_shape->size_pool_index = 0;
|
||||||
RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
|
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
|
void
|
||||||
|
2
shape.h
2
shape.h
@ -35,7 +35,7 @@ typedef uint32_t redblack_id_t;
|
|||||||
# define INVALID_SHAPE_ID SHAPE_MASK
|
# define INVALID_SHAPE_ID SHAPE_MASK
|
||||||
# define ROOT_SHAPE_ID 0x0
|
# 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)
|
# define OBJ_TOO_COMPLEX_SHAPE_ID (SPECIAL_CONST_SHAPE_ID + 1)
|
||||||
|
|
||||||
typedef struct redblack_node redblack_node_t;
|
typedef struct redblack_node redblack_node_t;
|
||||||
|
@ -786,7 +786,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
def test_remove_instance_variable_capacity_transition
|
def test_remove_instance_variable_capacity_transition
|
||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
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)
|
assert_equal(RubyVM::Shape::SHAPE_T_OBJECT, t_object_shape.type)
|
||||||
|
|
||||||
initial_capacity = t_object_shape.capacity
|
initial_capacity = t_object_shape.capacity
|
||||||
@ -889,7 +889,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
obj = TestObject.new
|
obj = TestObject.new
|
||||||
shape = RubyVM::Shape.of(obj)
|
shape = RubyVM::Shape.of(obj)
|
||||||
assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
|
assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
|
||||||
assert_shape_equal(RubyVM::Shape.root_shape, shape.parent)
|
assert_nil shape.parent
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_str_has_root_shape
|
def test_str_has_root_shape
|
||||||
@ -922,9 +922,8 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
|
|
||||||
shape = shape.parent
|
shape = shape.parent
|
||||||
assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
|
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))
|
assert_equal(1, obj.instance_variable_get(:@a))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1929,6 +1929,7 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu
|
|||||||
{
|
{
|
||||||
switch ((enum shape_type)shape->type) {
|
switch ((enum shape_type)shape->type) {
|
||||||
case SHAPE_ROOT:
|
case SHAPE_ROOT:
|
||||||
|
case SHAPE_T_OBJECT:
|
||||||
return false;
|
return false;
|
||||||
case SHAPE_IVAR:
|
case SHAPE_IVAR:
|
||||||
ASSUME(callback);
|
ASSUME(callback);
|
||||||
@ -1962,7 +1963,6 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case SHAPE_FROZEN:
|
case SHAPE_FROZEN:
|
||||||
case SHAPE_T_OBJECT:
|
|
||||||
return iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
|
return iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
|
||||||
case SHAPE_OBJ_TOO_COMPLEX:
|
case SHAPE_OBJ_TOO_COMPLEX:
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user