Skip to content

Commit be60058

Browse files
committed
WIP
1 parent a67156d commit be60058

1 file changed

Lines changed: 50 additions & 18 deletions

File tree

object.c

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -322,61 +322,93 @@ rb_obj_singleton_class(VALUE obj)
322322
return rb_singleton_class(obj);
323323
}
324324

325+
struct ivar_copy_value_args = {
326+
VALUE dest;
327+
VALUE src;
328+
};
329+
330+
static int
331+
ivar_copy_value_i(ID key, VALUE _empty_val, st_data_t data)
332+
{
333+
struct ivar_copy_value_args args = (struct ivar_copy_value_args*)data;
334+
335+
rb_ivar_set(args->dest, key, rb_ivar_get(args->src, key));
336+
return ST_CONTINUE;
337+
}
338+
325339
/*! \private */
326340
void
327341
rb_obj_copy_ivar(VALUE dest, VALUE obj)
328342
{
329343
RUBY_ASSERT(!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE));
330344

331345
RUBY_ASSERT(BUILTIN_TYPE(dest) == BUILTIN_TYPE(obj));
346+
347+
unsigned long src_num_ivs = rb_ivar_count(obj);
348+
if (!src_num_ivs) {
349+
return;
350+
}
351+
332352
rb_shape_t *src_shape = rb_shape_get_shape(obj);
333353

334-
if (rb_shape_obj_too_complex(obj)) {
354+
if (rb_shape_too_complex_p(src_shape)) {
335355
// obj is TOO_COMPLEX so we can copy its iv_hash
336356
st_table *table = st_copy(ROBJECT_IV_HASH(obj));
357+
if (rb_shape_has_object_id(src_shape)) {
358+
st_data_t id = (st_data_t)internal_object_id;
359+
st_delete(table, &id, NULL);
360+
}
337361
rb_obj_init_too_complex(dest, table);
338362

339363
return;
340364
}
341365

342-
uint32_t src_num_ivs = RBASIC_FIELDS_COUNT(obj);
343366
rb_shape_t *shape_to_set_on_dest = src_shape;
344-
VALUE * src_buf;
345-
VALUE * dest_buf;
346-
347-
if (!src_num_ivs) {
348-
return;
349-
}
350-
351-
src_buf = ROBJECT_IVPTR(obj);
352-
dest_buf = ROBJECT_IVPTR(dest);
353-
354367
rb_shape_t *initial_shape = rb_shape_get_shape(dest);
355368

356369
if (initial_shape->heap_index != src_shape->heap_index || !rb_shape_canonical_p(src_shape)) {
357370
RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
358371

359372
shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
360373
if (UNLIKELY(rb_shape_too_complex_p(shape_to_set_on_dest))) {
361-
st_table * table = rb_st_init_numtable_with_size(src_num_ivs);
374+
st_table *table = rb_st_init_numtable_with_size(src_num_ivs);
362375
rb_obj_copy_ivs_to_hash_table(obj, table);
363376
rb_obj_init_too_complex(dest, table);
364377

365378
return;
366379
}
367380
}
368381

369-
RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity || rb_shape_too_complex_p(shape_to_set_on_dest));
382+
VALUE *src_buf = ROBJECT_IVPTR(obj);
383+
VALUE *dest_buf = ROBJECT_IVPTR(dest);
384+
385+
RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity);
370386
if (initial_shape->capacity < shape_to_set_on_dest->capacity) {
371387
rb_ensure_iv_list_size(dest, initial_shape->capacity, shape_to_set_on_dest->capacity);
372388
dest_buf = ROBJECT_IVPTR(dest);
373389
}
374390

375-
MEMCPY(dest_buf, src_buf, VALUE, src_num_ivs);
391+
if (src_shape->next_field_index == shape_to_set_on_dest->next_field_index) {
392+
// Happy path, we can just memcpy the ivptr content
393+
MEMCPY(dest_buf, src_buf, VALUE, src_num_ivs);
376394

377-
// Fire write barriers
378-
for (uint32_t i = 0; i < src_num_ivs; i++) {
379-
RB_OBJ_WRITTEN(dest, Qundef, dest_buf[i]);
395+
// Fire write barriers
396+
for (uint32_t i = 0; i < src_num_ivs; i++) {
397+
RB_OBJ_WRITTEN(dest, Qundef, dest_buf[i]);
398+
}
399+
}
400+
else {
401+
itr_data = {
402+
.dest = dest,
403+
.src_obj = obj,
404+
}
405+
VALUE args[2] = {dest, obj};
406+
iterate_over_shapes_with_callback(shape_to_set_on_dest, ivar_copy_value, &itr_data);
407+
// FIXME: this is a stub
408+
409+
rb_ivar_foreach(obj, ivar_copy_i, (st_data_t)dest);
410+
// The shape was rebuilt, we have to copy ivars one by one.
411+
// rb_bug("Not implemented");
380412
}
381413

382414
rb_shape_set_shape(dest, shape_to_set_on_dest);

0 commit comments

Comments
 (0)