From 81b35fe7297957d78715a812f6edecec23c6e3b2 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 16 Nov 2023 16:28:12 +0100 Subject: [PATCH] rb_evict_ivars_to_hash: get rid of the sahpe paramater It's only used to allocate the table with the right size, but in some case we were passing `rb_shape_get_shape_by_id(SHAPE_OBJ_TOO_COMPLEX)` which `next_iv_index` is a bit undefined. So overall we're better to just allocate a table the size of the existing object, it should be close enough in the vast majority of cases, and that's already a de-optimizaton path anyway. --- internal/variable.h | 2 +- object.c | 4 ++-- variable.c | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/variable.h b/internal/variable.h index e7e24d2a15..021e7cc6a8 100644 --- a/internal/variable.h +++ b/internal/variable.h @@ -48,7 +48,7 @@ VALUE rb_mod_set_temporary_name(VALUE, VALUE); struct gen_ivtbl; int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl); int rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg); -void rb_evict_ivars_to_hash(VALUE obj, rb_shape_t * shape); +void rb_evict_ivars_to_hash(VALUE obj); RUBY_SYMBOL_EXPORT_BEGIN /* variable.c (export) */ diff --git a/object.c b/object.c index 73fbe78edc..f442a562ea 100644 --- a/object.c +++ b/object.c @@ -474,7 +474,7 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze) if (RB_OBJ_FROZEN(obj)) { rb_shape_t * next_shape = rb_shape_transition_shape_frozen(clone); if (!rb_shape_obj_too_complex(clone) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { - rb_evict_ivars_to_hash(clone, rb_shape_get_shape(clone)); + rb_evict_ivars_to_hash(clone); } else { rb_shape_set_shape(clone, next_shape); @@ -498,7 +498,7 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze) // If we're out of shapes, but we want to freeze, then we need to // evacuate this clone to a hash if (!rb_shape_obj_too_complex(clone) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { - rb_evict_ivars_to_hash(clone, rb_shape_get_shape(clone)); + rb_evict_ivars_to_hash(clone); } else { rb_shape_set_shape(clone, next_shape); diff --git a/variable.c b/variable.c index 4d46022509..d5c425472b 100644 --- a/variable.c +++ b/variable.c @@ -1331,7 +1331,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef) if (!rb_shape_transition_shape_remove_ivar(obj, id, shape, &val)) { if (!rb_shape_obj_too_complex(obj)) { - rb_evict_ivars_to_hash(obj, shape); + rb_evict_ivars_to_hash(obj); } st_table *table = NULL; @@ -1371,11 +1371,11 @@ rb_attr_delete(VALUE obj, ID id) } void -rb_evict_ivars_to_hash(VALUE obj, rb_shape_t * shape) +rb_evict_ivars_to_hash(VALUE obj) { RUBY_ASSERT(!rb_shape_obj_too_complex(obj)); - st_table *table = st_init_numtable_with_size(shape->next_iv_index); + st_table *table = st_init_numtable_with_size(rb_ivar_count(obj)); // Evacuate all previous values from shape into id_table rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table); @@ -1570,7 +1570,7 @@ generic_ivar_set_set_shape(VALUE obj, rb_shape_t *shape, void *data) static void generic_ivar_set_transition_too_complex(VALUE obj, void *_data) { - rb_evict_ivars_to_hash(obj, rb_shape_get_shape_by_id(SHAPE_OBJ_TOO_COMPLEX)); + rb_evict_ivars_to_hash(obj); FL_SET_RAW(obj, FL_EXIVAR); } @@ -1666,7 +1666,7 @@ obj_ivar_set_set_shape(VALUE obj, rb_shape_t *shape, void *_data) static void obj_ivar_set_transition_too_complex(VALUE obj, void *_data) { - rb_evict_ivars_to_hash(obj, rb_shape_get_shape_by_id(SHAPE_OBJ_TOO_COMPLEX)); + rb_evict_ivars_to_hash(obj); } static st_table * @@ -1756,7 +1756,7 @@ void rb_obj_freeze_inline(VALUE x) // If we're transitioning from "not complex" to "too complex" // then evict ivars. This can happen if we run out of shapes if (!rb_shape_obj_too_complex(x) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { - rb_evict_ivars_to_hash(x, rb_shape_get_shape(x)); + rb_evict_ivars_to_hash(x); } rb_shape_set_shape(x, next_shape); @@ -4185,7 +4185,7 @@ class_ivar_set_set_shape(VALUE obj, rb_shape_t *shape, void *_data) static void class_ivar_set_transition_too_complex(VALUE obj, void *_data) { - rb_evict_ivars_to_hash(obj, rb_shape_get_shape_by_id(SHAPE_OBJ_TOO_COMPLEX)); + rb_evict_ivars_to_hash(obj); } static st_table *