diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2023-10-19 16:01:35 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2023-10-24 10:52:06 -0700 |
commit | a3f66e09f6596259677f00255a9b6231a2739774 (patch) | |
tree | addc47766e34c520307baab7952343855af872e0 /object.c | |
parent | caf6a72348431e0e6b61be84919cd06c7a745189 (diff) |
geniv objects can become too complex
Diffstat (limited to 'object.c')
-rw-r--r-- | object.c | 18 |
1 files changed, 16 insertions, 2 deletions
@@ -463,7 +463,13 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze) rb_funcall(clone, id_init_clone, 1, obj); RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE; if (RB_OBJ_FROZEN(obj)) { - rb_shape_transition_shape_frozen(clone); + 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)); + } + else { + rb_shape_set_shape(clone, next_shape); + } } break; case Qtrue: { @@ -479,7 +485,15 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze) argv[1] = freeze_true_hash; rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS); RBASIC(clone)->flags |= FL_FREEZE; - rb_shape_transition_shape_frozen(clone); + rb_shape_t * next_shape = rb_shape_transition_shape_frozen(clone); + // 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)); + } + else { + rb_shape_set_shape(clone, next_shape); + } break; } case Qfalse: { |