diff options
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 215 |
1 files changed, 72 insertions, 143 deletions
@@ -2895,7 +2895,8 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected) GC_ASSERT((flags & RUBY_T_MASK) == T_OBJECT); GC_ASSERT(flags & ROBJECT_EMBED); - uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count; + st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass); + uint32_t index_tbl_num_entries = index_tbl == NULL ? 0 : (uint32_t)index_tbl->num_entries; size_t size; bool embed = true; @@ -2930,7 +2931,7 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected) #endif } else { - rb_ensure_iv_list_size(obj, 0, index_tbl_num_entries); + rb_init_iv_list(obj); } return obj; @@ -2971,7 +2972,6 @@ rb_imemo_name(enum imemo_type type) IMEMO_NAME(callinfo); IMEMO_NAME(callcache); IMEMO_NAME(constcache); - IMEMO_NAME(shape); #undef IMEMO_NAME } return "unknown"; @@ -3018,14 +3018,6 @@ imemo_memsize(VALUE obj) case imemo_iseq: size += rb_iseq_memsize((rb_iseq_t *)obj); break; - case imemo_shape: - { - struct rb_id_table* edges = ((rb_shape_t *) obj)->edges; - if (edges) { - size += rb_id_table_memsize(edges); - } - break; - } case imemo_env: size += RANY(obj)->as.imemo.env.env_size * sizeof(VALUE); break; @@ -3214,6 +3206,20 @@ rb_free_const_table(struct rb_id_table *tbl) rb_id_table_free(tbl); } +static int +free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data) +{ + xfree((void *)value); + return ST_CONTINUE; +} + +static void +iv_index_tbl_free(struct st_table *tbl) +{ + st_foreach(tbl, free_iv_index_tbl_free_i, 0); + st_free_table(tbl); +} + // alive: if false, target pointers can be freed already. // To check it, we need objspace parameter. static void @@ -3381,22 +3387,6 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj) } } -static enum rb_id_table_iterator_result -remove_child_shapes_parent(VALUE value, void *ref) -{ - rb_shape_t * shape = (rb_shape_t *) value; - GC_ASSERT(IMEMO_TYPE_P(shape, imemo_shape)); - - // If both objects live on the same page and we're currently - // sweeping that page, then we need to assert that neither are marked - if (GET_HEAP_PAGE(shape) == GET_HEAP_PAGE(shape->parent)) { - GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(shape), shape)); - } - - shape->parent = NULL; - return ID_TABLE_CONTINUE; -} - static int obj_free(rb_objspace_t *objspace, VALUE obj) { @@ -3445,19 +3435,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) RB_DEBUG_COUNTER_INC(obj_obj_transient); } else { - // A shape can be collected before an object is collected (if both - // happened to be garbage at the same time), so when we look up the shape, _do not_ - // assert that the shape is an IMEMO because it could be null - rb_shape_t *shape = rb_shape_get_shape_by_id_without_assertion(ROBJECT_SHAPE_ID(obj)); - if (shape) { - VALUE klass = RBASIC_CLASS(obj); - - // Increment max_iv_count if applicable, used to determine size pool allocation - uint32_t num_of_ivs = shape->iv_count; - if (RCLASS_EXT(klass)->max_iv_count < num_of_ivs) { - RCLASS_EXT(klass)->max_iv_count = num_of_ivs; - } - } xfree(RANY(obj)->as.object.as.heap.ivptr); RB_DEBUG_COUNTER_INC(obj_obj_ptr); } @@ -3472,6 +3449,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) if (RCLASS_CONST_TBL(obj)) { rb_free_const_table(RCLASS_CONST_TBL(obj)); } + if (RCLASS_IV_INDEX_TBL(obj)) { + iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj)); + } if (RCLASS_CVC_TBL(obj)) { rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL); rb_id_table_free(RCLASS_CVC_TBL(obj)); @@ -3748,37 +3728,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case imemo_constcache: RB_DEBUG_COUNTER_INC(obj_imemo_constcache); break; - case imemo_shape: - { - rb_shape_t *shape = (rb_shape_t *)obj; - rb_shape_t *parent = shape->parent; - - if (parent) { - RUBY_ASSERT(IMEMO_TYPE_P(parent, imemo_shape)); - RUBY_ASSERT(parent->edges); - VALUE res; // Only used to temporarily store lookup value - if (rb_id_table_lookup(parent->edges, shape->edge_name, &res)) { - if ((rb_shape_t *)res == shape) { - rb_id_table_delete(parent->edges, shape->edge_name); - } - } - else { - rb_bug("Edge %s should exist", rb_id2name(shape->edge_name)); - } - } - if (shape->edges) { - rb_id_table_foreach_values(shape->edges, remove_child_shapes_parent, NULL); - rb_id_table_free(shape->edges); - shape->edges = NULL; - } - - shape->parent = NULL; - - rb_shape_set_shape_by_id(SHAPE_ID(shape), NULL); - - RB_DEBUG_COUNTER_INC(obj_imemo_shape); - break; - } } return TRUE; @@ -4924,6 +4873,10 @@ obj_memsize_of(VALUE obj, int use_all_types) if (RCLASS_CVC_TBL(obj)) { size += rb_id_table_memsize(RCLASS_CVC_TBL(obj)); } + if (RCLASS_IV_INDEX_TBL(obj)) { + // TODO: more correct value + size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); + } if (RCLASS_EXT(obj)->iv_tbl) { size += st_memsize(RCLASS_EXT(obj)->iv_tbl); } @@ -7201,21 +7154,6 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) const struct rb_callcache *cc = (const struct rb_callcache *)obj; // should not mark klass here gc_mark(objspace, (VALUE)vm_cc_cme(cc)); - - // Check it's an attr_(reader|writer) - if (cc->cme_ && (cc->cme_->def->type == VM_METHOD_TYPE_ATTRSET || - cc->cme_->def->type == VM_METHOD_TYPE_IVAR)) { - shape_id_t source_shape_id = vm_cc_attr_index_source_shape_id(cc); - shape_id_t dest_shape_id = vm_cc_attr_index_dest_shape_id(cc); - if (source_shape_id != INVALID_SHAPE_ID) { - rb_shape_t *shape = rb_shape_get_shape_by_id(source_shape_id); - rb_gc_mark((VALUE)shape); - } - if (dest_shape_id != INVALID_SHAPE_ID) { - rb_shape_t *shape = rb_shape_get_shape_by_id(dest_shape_id); - rb_gc_mark((VALUE)shape); - } - } } return; case imemo_constcache: @@ -7224,14 +7162,6 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) gc_mark(objspace, ice->value); } return; - case imemo_shape: - { - rb_shape_t *shape = (rb_shape_t *)obj; - if (shape->edges) { - mark_m_tbl(objspace, shape->edges); - } - } - return; #if VM_CHECK_MODE > 0 default: VM_UNREACHABLE(gc_mark_imemo); @@ -9835,10 +9765,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) GC_ASSERT(!SPECIAL_CONST_P(obj)); switch (BUILTIN_TYPE(obj)) { - case T_IMEMO: - if (IMEMO_TYPE_P(obj, imemo_shape)) { - return FALSE; - } case T_NONE: case T_NIL: case T_MOVED: @@ -9852,6 +9778,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) case T_STRING: case T_OBJECT: case T_FLOAT: + case T_IMEMO: case T_ARRAY: case T_BIGNUM: case T_ICLASS: @@ -10251,38 +10178,6 @@ gc_update_values(rb_objspace_t *objspace, long n, VALUE *values) } } -static enum rb_id_table_iterator_result -check_id_table_move(VALUE value, void *data) -{ - rb_objspace_t *objspace = (rb_objspace_t *)data; - - if (gc_object_moved_p(objspace, (VALUE)value)) { - return ID_TABLE_REPLACE; - } - - return ID_TABLE_CONTINUE; -} - -static enum rb_id_table_iterator_result -update_id_table(VALUE *value, void *data, int existing) -{ - rb_objspace_t *objspace = (rb_objspace_t *)data; - - if (gc_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_location((VALUE)*value); - } - - return ID_TABLE_CONTINUE; -} - -static void -update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) -{ - if (tbl) { - rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace); - } -} - static void gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) { @@ -10355,23 +10250,24 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_tmpbuf: case imemo_callinfo: break; - case imemo_shape: - { - rb_shape_t * shape = (rb_shape_t *)obj; - if(shape->edges) { - update_m_tbl(objspace, shape->edges); - } - if (shape->parent) { - shape->parent = (rb_shape_t *)rb_gc_location((VALUE)shape->parent); - } - } - break; default: rb_bug("not reachable %d", imemo_type(obj)); break; } } +static enum rb_id_table_iterator_result +check_id_table_move(VALUE value, void *data) +{ + rb_objspace_t *objspace = (rb_objspace_t *)data; + + if (gc_object_moved_p(objspace, (VALUE)value)) { + return ID_TABLE_REPLACE; + } + + return ID_TABLE_CONTINUE; +} + /* Returns the new location of an object, if it moved. Otherwise returns * the existing location. */ VALUE @@ -10405,6 +10301,26 @@ rb_gc_location(VALUE value) } static enum rb_id_table_iterator_result +update_id_table(VALUE *value, void *data, int existing) +{ + rb_objspace_t *objspace = (rb_objspace_t *)data; + + if (gc_object_moved_p(objspace, (VALUE)*value)) { + *value = rb_gc_location((VALUE)*value); + } + + return ID_TABLE_CONTINUE; +} + +static void +update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) +{ + if (tbl) { + rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace); + } +} + +static enum rb_id_table_iterator_result update_cc_tbl_i(VALUE ccs_ptr, void *data) { rb_objspace_t *objspace = (rb_objspace_t *)data; @@ -10491,6 +10407,15 @@ update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry) } } +static int +update_iv_index_tbl_i(st_data_t key, st_data_t value, st_data_t arg) +{ + rb_objspace_t *objspace = (rb_objspace_t *)arg; + struct rb_iv_index_tbl_entry *ent = (struct rb_iv_index_tbl_entry *)value; + UPDATE_IF_MOVED(objspace, ent->class_value); + return ST_CONTINUE; +} + static void update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext) { @@ -10498,6 +10423,11 @@ update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext) UPDATE_IF_MOVED(objspace, ext->includer); UPDATE_IF_MOVED(objspace, ext->refined_class); update_subclass_entries(objspace, ext->subclasses); + + // ext->iv_index_tbl + if (ext->iv_index_tbl) { + st_foreach(ext->iv_index_tbl, update_iv_index_tbl_i, (st_data_t)objspace); + } } static void @@ -10739,8 +10669,6 @@ gc_update_references(rb_objspace_t *objspace) struct heap_page *page = NULL; - rb_vm_update_references(vm); - for (int i = 0; i < SIZE_POOL_COUNT; i++) { bool should_set_mark_bits = TRUE; rb_size_pool_t *size_pool = &size_pools[i]; @@ -10759,6 +10687,7 @@ gc_update_references(rb_objspace_t *objspace) } } } + rb_vm_update_references(vm); rb_transient_heap_update_references(); rb_gc_update_global_tbl(); global_symbols.ids = rb_gc_location(global_symbols.ids); |