summaryrefslogtreecommitdiff
path: root/object.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2023-10-19 16:01:35 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2023-10-24 10:52:06 -0700
commita3f66e09f6596259677f00255a9b6231a2739774 (patch)
treeaddc47766e34c520307baab7952343855af872e0 /object.c
parentcaf6a72348431e0e6b61be84919cd06c7a745189 (diff)
geniv objects can become too complex
Diffstat (limited to 'object.c')
-rw-r--r--object.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/object.c b/object.c
index c32cb82dd9..4c589b2655 100644
--- a/object.c
+++ b/object.c
@@ -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: {