@@ -322,36 +322,28 @@ void
322322rb_obj_copy_ivar (VALUE dest , VALUE obj )
323323{
324324 RUBY_ASSERT (!RB_TYPE_P (obj , T_CLASS ) && !RB_TYPE_P (obj , T_MODULE ));
325-
326325 RUBY_ASSERT (BUILTIN_TYPE (dest ) == BUILTIN_TYPE (obj ));
327326
328327 unsigned long src_num_ivs = rb_ivar_count (obj );
329328 if (!src_num_ivs ) {
330329 return ;
331330 }
332331
333- rb_shape_t * src_shape = rb_obj_shape (obj );
334-
335- if (rb_shape_too_complex_p (src_shape )) {
336- // obj is TOO_COMPLEX so we can copy its iv_hash
337- st_table * table = st_copy (ROBJECT_FIELDS_HASH (obj ));
338- if (rb_shape_has_object_id (src_shape )) {
339- st_data_t id = (st_data_t )ruby_internal_object_id ;
340- st_delete (table , & id , NULL );
341- }
342- rb_obj_init_too_complex (dest , table );
332+ shape_id_t src_shape_id = RBASIC_SHAPE_ID (obj );
343333
334+ if (rb_shape_id_too_complex_p (src_shape_id )) {
335+ rb_shape_copy_complex_ivars (dest , obj , src_shape_id , ROBJECT_FIELDS_HASH (obj ));
344336 return ;
345337 }
346338
347- rb_shape_t * shape_to_set_on_dest = src_shape ;
348- rb_shape_t * initial_shape = rb_obj_shape (dest );
339+ shape_id_t dest_shape_id = src_shape_id ;
340+ shape_id_t initial_shape_id = RBASIC_SHAPE_ID (dest );
349341
350- if (initial_shape -> heap_index != src_shape -> heap_index || !rb_shape_canonical_p ( src_shape )) {
351- RUBY_ASSERT (initial_shape -> type == SHAPE_T_OBJECT );
342+ if (RSHAPE ( initial_shape_id ) -> heap_index != RSHAPE ( src_shape_id ) -> heap_index || !rb_shape_id_canonical_p ( src_shape_id )) {
343+ RUBY_ASSERT (RSHAPE ( initial_shape_id ) -> type == SHAPE_T_OBJECT );
352344
353- shape_to_set_on_dest = rb_shape_rebuild_shape ( initial_shape , src_shape );
354- if (UNLIKELY (rb_shape_too_complex_p ( shape_to_set_on_dest ))) {
345+ dest_shape_id = rb_shape_rebuild ( initial_shape_id , src_shape_id );
346+ if (UNLIKELY (rb_shape_id_too_complex_p ( dest_shape_id ))) {
355347 st_table * table = rb_st_init_numtable_with_size (src_num_ivs );
356348 rb_obj_copy_ivs_to_hash_table (obj , table );
357349 rb_obj_init_too_complex (dest , table );
@@ -363,36 +355,14 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
363355 VALUE * src_buf = ROBJECT_FIELDS (obj );
364356 VALUE * dest_buf = ROBJECT_FIELDS (dest );
365357
366- RUBY_ASSERT (src_num_ivs <= shape_to_set_on_dest -> capacity );
367- if (initial_shape -> capacity < shape_to_set_on_dest -> capacity ) {
368- rb_ensure_iv_list_size (dest , initial_shape -> capacity , shape_to_set_on_dest -> capacity );
358+ RUBY_ASSERT (src_num_ivs <= RSHAPE ( dest_shape_id ) -> capacity );
359+ if (RSHAPE ( initial_shape_id ) -> capacity < RSHAPE ( dest_shape_id ) -> capacity ) {
360+ rb_ensure_iv_list_size (dest , RSHAPE ( initial_shape_id ) -> capacity , RSHAPE ( dest_shape_id ) -> capacity );
369361 dest_buf = ROBJECT_FIELDS (dest );
370362 }
371363
372- if (src_shape -> next_field_index == shape_to_set_on_dest -> next_field_index ) {
373- // Happy path, we can just memcpy the fields content
374- MEMCPY (dest_buf , src_buf , VALUE , src_num_ivs );
375-
376- // Fire write barriers
377- for (uint32_t i = 0 ; i < src_num_ivs ; i ++ ) {
378- RB_OBJ_WRITTEN (dest , Qundef , dest_buf [i ]);
379- }
380- }
381- else {
382- rb_shape_t * dest_shape = shape_to_set_on_dest ;
383- while (src_shape -> parent_id != INVALID_SHAPE_ID ) {
384- if (src_shape -> type == SHAPE_IVAR ) {
385- while (dest_shape -> edge_name != src_shape -> edge_name ) {
386- dest_shape = RSHAPE (dest_shape -> parent_id );
387- }
388-
389- RB_OBJ_WRITE (dest , & dest_buf [dest_shape -> next_field_index - 1 ], src_buf [src_shape -> next_field_index - 1 ]);
390- }
391- src_shape = RSHAPE (src_shape -> parent_id );
392- }
393- }
394-
395- rb_shape_set_shape (dest , shape_to_set_on_dest );
364+ rb_shape_copy_fields (dest , dest_buf , dest_shape_id , obj , src_buf , src_shape_id );
365+ rb_shape_set_shape_id (dest , dest_shape_id );
396366}
397367
398368static void
@@ -404,11 +374,20 @@ init_copy(VALUE dest, VALUE obj)
404374 RBASIC (dest )-> flags &= ~(T_MASK |FL_EXIVAR );
405375 // Copies the shape id from obj to dest
406376 RBASIC (dest )-> flags |= RBASIC (obj )-> flags & (T_MASK |FL_EXIVAR );
407- if (RB_TYPE_P (obj , T_OBJECT )) {
408- rb_obj_copy_ivar (dest , obj );
409- }
410- else {
411- rb_copy_generic_ivar (dest , obj );
377+ switch (BUILTIN_TYPE (obj )) {
378+ case T_IMEMO :
379+ rb_bug ("Unreacheable" );
380+ break ;
381+ case T_CLASS :
382+ case T_MODULE :
383+ // noop: handled in class.c: rb_mod_init_copy
384+ break ;
385+ case T_OBJECT :
386+ rb_obj_copy_ivar (dest , obj );
387+ break ;
388+ default :
389+ rb_copy_generic_ivar (dest , obj );
390+ break ;
412391 }
413392 rb_gc_copy_attributes (dest , obj );
414393}
0 commit comments