diff options
author | Jean Boussier <byroot@ruby-lang.org> | 2023-10-30 12:29:59 +0100 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2023-10-31 12:07:54 -0400 |
commit | 4aacc559d99988f395eced3534c7a6938bd356c8 (patch) | |
tree | a33af6b2ae7ae803053dad304687b321cdd73e93 /object.c | |
parent | 85ad1025328989bb4e10436aed121b9136b0c8bf (diff) | |
download | ruby-4aacc559d99988f395eced3534c7a6938bd356c8.tar.gz |
Handle running out of shapes in `Object#dup`
There is a handful of call sites where we may transition to
OBJ_TOO_COMPLEX_SHAPE if we just ran out of shapes, but that
weren't handling it properly.
Diffstat (limited to 'object.c')
-rw-r--r-- | object.c | 11 |
1 files changed, 10 insertions, 1 deletions
@@ -326,9 +326,18 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj) RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT); shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape); + if (UNLIKELY(rb_shape_id(shape_to_set_on_dest) == OBJ_TOO_COMPLEX_SHAPE_ID)) { + st_table * table = rb_st_init_numtable_with_size(src_num_ivs); + + rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table); + rb_shape_set_too_complex(dest); + ROBJECT(dest)->as.heap.ivptr = (VALUE *)table; + + return; + } } - RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity); + RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity || rb_shape_id(shape_to_set_on_dest) == OBJ_TOO_COMPLEX_SHAPE_ID); if (initial_shape->capacity < shape_to_set_on_dest->capacity) { rb_ensure_iv_list_size(dest, initial_shape->capacity, shape_to_set_on_dest->capacity); dest_buf = ROBJECT_IVPTR(dest); |