@@ -37,6 +37,8 @@ static ID id_frozen;
3737static ID id_t_object ;
3838ID ruby_internal_object_id ; // extern
3939
40+ static const attr_index_t * shape_capacities = NULL ;
41+
4042#define LEAF 0
4143#define BLACK 0x0
4244#define RED 0x1
@@ -496,6 +498,23 @@ redblack_cache_ancestors(rb_shape_t *shape)
496498}
497499#endif
498500
501+ static attr_index_t
502+ shape_grow_capa (attr_index_t current_capa )
503+ {
504+ const attr_index_t * capacities = shape_capacities ;
505+
506+ // First try to use the next size that will be embeddable in a larger object slot.
507+ attr_index_t capa ;
508+ while ((capa = * capacities )) {
509+ if (capa > current_capa ) {
510+ return capa ;
511+ }
512+ capacities ++ ;
513+ }
514+
515+ return (attr_index_t )rb_malloc_grow_capa (current_capa , sizeof (VALUE ));
516+ }
517+
499518static rb_shape_t *
500519rb_shape_alloc_new_child (ID id , rb_shape_t * shape , enum shape_type shape_type )
501520{
@@ -506,7 +525,7 @@ rb_shape_alloc_new_child(ID id, rb_shape_t *shape, enum shape_type shape_type)
506525 case SHAPE_IVAR :
507526 if (UNLIKELY (shape -> next_field_index >= shape -> capacity )) {
508527 RUBY_ASSERT (shape -> next_field_index == shape -> capacity );
509- new_shape -> capacity = ( uint32_t ) rb_malloc_grow_capa ( shape -> capacity , sizeof ( VALUE ) );
528+ new_shape -> capacity = shape_grow_capa ( shape -> capacity );
510529 }
511530 RUBY_ASSERT (new_shape -> capacity > shape -> next_field_index );
512531 new_shape -> next_field_index = shape -> next_field_index + 1 ;
@@ -1431,6 +1450,19 @@ Init_default_shapes(void)
14311450{
14321451 rb_shape_tree_ptr = xcalloc (1 , sizeof (rb_shape_tree_t ));
14331452
1453+ size_t * heap_sizes = rb_gc_heap_sizes ();
1454+ size_t heaps_count = 0 ;
1455+ while (heap_sizes [heaps_count ]) {
1456+ heaps_count ++ ;
1457+ }
1458+ attr_index_t * capacities = ALLOC_N (attr_index_t , heaps_count + 1 );
1459+ capacities [heaps_count ] = 0 ;
1460+ size_t index ;
1461+ for (index = 0 ; index < heaps_count ; index ++ ) {
1462+ capacities [index ] = (heap_sizes [index ] - sizeof (struct RBasic )) / sizeof (VALUE );
1463+ }
1464+ shape_capacities = capacities ;
1465+
14341466#ifdef HAVE_MMAP
14351467 size_t shape_list_mmap_size = rb_size_mul_or_raise (SHAPE_BUFFER_SIZE , sizeof (rb_shape_t ), rb_eRuntimeError );
14361468 rb_shape_tree_ptr -> shape_list = (rb_shape_t * )mmap (NULL , shape_list_mmap_size ,
@@ -1505,6 +1537,8 @@ Init_default_shapes(void)
15051537void
15061538rb_shape_free_all (void )
15071539{
1540+ xfree ((void * )shape_capacities );
1541+ shape_capacities = NULL ;
15081542 xfree (GET_SHAPE_TREE ());
15091543}
15101544
0 commit comments