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.
This commit is contained in:
Jean Boussier 2023-11-16 16:28:12 +01:00 committed by Jean Boussier
parent b92a92a3ff
commit 81b35fe729
3 changed files with 10 additions and 10 deletions

View File

@ -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) */

View File

@ -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);

View File

@ -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 *