diff options
author | Jemma Issroff <jemmaissroff@gmail.com> | 2022-10-03 11:14:32 -0400 |
---|---|---|
committer | Aaron Patterson <tenderlove@ruby-lang.org> | 2022-10-11 08:40:56 -0700 |
commit | ad63b668e22e21c352b852f3119ae98a7acf99f1 (patch) | |
tree | cdaea65a9cae753a25f521c06d9d6a205085335f /object.c | |
parent | 5ffbb2be187681a37f2722ce1d7db4ec5c128464 (diff) | |
download | ruby-ad63b668e22e21c352b852f3119ae98a7acf99f1.tar.gz |
Revert "Revert "This commit implements the Object Shapes technique in CRuby.""
This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
Diffstat (limited to 'object.c')
-rw-r--r-- | object.c | 46 |
1 files changed, 44 insertions, 2 deletions
@@ -39,6 +39,7 @@ #include "ruby/util.h" #include "ruby/assert.h" #include "builtin.h" +#include "shape.h" /*! * \addtogroup object @@ -271,9 +272,33 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj) VALUE *src_buf = ROBJECT_IVPTR(obj); uint32_t dest_len = ROBJECT_NUMIV(dest); uint32_t src_len = ROBJECT_NUMIV(obj); - uint32_t len = dest_len < src_len ? dest_len : src_len; + uint32_t max_len = dest_len < src_len ? src_len : dest_len; - MEMCPY(dest_buf, src_buf, VALUE, len); + rb_ensure_iv_list_size(dest, dest_len, max_len); + + dest_len = ROBJECT_NUMIV(dest); + uint32_t min_len = dest_len > src_len ? src_len : dest_len; + + if (RBASIC(obj)->flags & ROBJECT_EMBED) { + src_buf = ROBJECT(obj)->as.ary; + + // embedded -> embedded + if (RBASIC(dest)->flags & ROBJECT_EMBED) { + dest_buf = ROBJECT(dest)->as.ary; + } + // embedded -> extended + else { + dest_buf = ROBJECT(dest)->as.heap.ivptr; + } + } + // extended -> extended + else { + RUBY_ASSERT(!(RBASIC(dest)->flags & ROBJECT_EMBED)); + dest_buf = ROBJECT(dest)->as.heap.ivptr; + src_buf = ROBJECT(obj)->as.heap.ivptr; + } + + MEMCPY(dest_buf, src_buf, VALUE, min_len); } static void @@ -283,10 +308,23 @@ init_copy(VALUE dest, VALUE obj) rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest)); } RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR); + // Copies the shape id from obj to dest RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR); rb_copy_wb_protected_attribute(dest, obj); rb_copy_generic_ivar(dest, obj); rb_gc_copy_finalizer(dest, obj); + + rb_shape_t *shape_to_set = rb_shape_get_shape(obj); + + // If the object is frozen, the "dup"'d object will *not* be frozen, + // so we need to copy the frozen shape's parent to the new object. + if (rb_shape_frozen_shape_p(shape_to_set)) { + shape_to_set = shape_to_set->parent; + } + + // shape ids are different + rb_shape_set_shape(dest, shape_to_set); + if (RB_TYPE_P(obj, T_OBJECT)) { rb_obj_copy_ivar(dest, obj); } @@ -392,6 +430,9 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze) case Qnil: 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); + } break; case Qtrue: { @@ -407,6 +448,7 @@ 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); break; } case Qfalse: |