diff --git a/NEWS.md b/NEWS.md index 49eec73f4b492c..4c9a3e8eaee538 100644 --- a/NEWS.md +++ b/NEWS.md @@ -58,12 +58,13 @@ releases. * test-unit 3.7.7 * rss 0.3.2 * net-imap 0.6.2 -* rbs 3.10.2 +* rbs 3.10.3 * typeprof 0.31.1 * debug 1.11.1 * mutex_m 0.3.0 * resolv-replace 0.2.0 * syslog 0.4.0 +* repl_type_completor 0.1.13 * rdoc 7.1.0 ### RubyGems and Bundler diff --git a/bignum.c b/bignum.c index ee2fa1ed30a2a6..c39f74576a2c31 100644 --- a/bignum.c +++ b/bignum.c @@ -3036,20 +3036,21 @@ rb_big_realloc(VALUE big, size_t len) else { if (len <= embed_capa) { ds = RBIGNUM(big)->as.heap.digits; + size_t old_len = RBIGNUM(big)->as.heap.len; FL_SET_RAW(big, BIGNUM_EMBED_FLAG); BIGNUM_SET_LEN(big, len); (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, embed_capa * sizeof(BDIGIT)); if (ds) { MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len); - xfree(ds); + SIZED_FREE_N(ds, old_len); } } else { if (BIGNUM_LEN(big) == 0) { RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len); } - else if (BIGNUM_LEN(big) < len) { - REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len); + else if (BIGNUM_LEN(big) != len) { + SIZED_REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len, BIGNUM_LEN(big)); } } } diff --git a/class.c b/class.c index 9c1bd86dc3e405..bd017b51a58445 100644 --- a/class.c +++ b/class.c @@ -83,7 +83,8 @@ static enum rb_id_table_iterator_result cvar_table_free_i(VALUE value, void *ctx) { - xfree((void *)value); + struct rb_cvar_class_tbl_entry *entry = (struct rb_cvar_class_tbl_entry *)value; + SIZED_FREE(entry); return ID_TABLE_CONTINUE; } @@ -118,11 +119,15 @@ rb_class_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime) if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) { RUBY_ASSERT(is_prime); // superclasses should only be used on prime - xfree(RCLASSEXT_SUPERCLASSES(ext)); + size_t depth = RCLASSEXT_SUPERCLASS_DEPTH(ext); + if (depth != RCLASS_MAX_SUPERCLASS_DEPTH) { + depth++; + } + SIZED_FREE_N(RCLASSEXT_SUPERCLASSES(ext), depth); } if (!is_prime) { // the prime classext will be freed with RClass - xfree(ext); + SIZED_FREE(ext); } } @@ -141,7 +146,7 @@ rb_iclass_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime) rb_class_classext_free_subclasses(ext, klass, false); if (!is_prime) { // the prime classext will be freed with RClass - xfree(ext); + SIZED_FREE(ext); } } @@ -159,7 +164,7 @@ iclass_free_orphan_classext(VALUE klass, rb_classext_t *ext) rb_class_classext_free_subclasses(ext, klass, true); // replacing this classext with a newer one - xfree(ext); + SIZED_FREE(ext); } struct rb_class_set_box_classext_args { @@ -655,7 +660,7 @@ remove_class_from_subclasses(struct st_table *tbl, VALUE box_id, VALUE klass) } } - xfree(entry); + SIZED_FREE(entry); break; } @@ -688,7 +693,7 @@ rb_class_classext_free_subclasses(rb_classext_t *ext, VALUE klass, bool replacin while (entry) { next = entry->next; - xfree(entry); + SIZED_FREE(entry); entry = next; } VM_ASSERT( @@ -696,7 +701,7 @@ rb_class_classext_free_subclasses(rb_classext_t *ext, VALUE klass, bool replacin "box_subclasses refcount (%p) %ld", anchor->box_subclasses, rb_box_subclasses_ref_count(anchor->box_subclasses)); st_delete(tbl, &box_id, NULL); rb_box_subclasses_ref_dec(anchor->box_subclasses); - xfree(anchor); + SIZED_FREE(anchor); if (RCLASSEXT_BOX_SUPER_SUBCLASSES(ext)) { rb_box_subclasses_t *box_sub = RCLASSEXT_BOX_SUPER_SUBCLASSES(ext); diff --git a/compile.c b/compile.c index b7d6b07090ba90..a5a0ab46e9b8bc 100644 --- a/compile.c +++ b/compile.c @@ -1692,7 +1692,7 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) debugs("[compile step 6.1 (remove unused catch tables)] \n"); RUBY_ASSERT(ISEQ_COMPILE_DATA(iseq)); if (!ISEQ_COMPILE_DATA(iseq)->catch_except_p && ISEQ_BODY(iseq)->catch_table) { - xfree(ISEQ_BODY(iseq)->catch_table); + ruby_sized_xfree(ISEQ_BODY(iseq)->catch_table, iseq_catch_table_bytes(ISEQ_BODY(iseq)->catch_table->size)); ISEQ_BODY(iseq)->catch_table = NULL; } @@ -2398,8 +2398,8 @@ get_cvar_ic_value(rb_iseq_t *iseq,ID id) dump_disasm_list_with_cursor(FIRST_ELEMENT(anchor), list, dest) #define BADINSN_ERROR \ - (xfree(generated_iseq), \ - xfree(insns_info), \ + (SIZED_FREE_N(generated_iseq, generated_iseq_size), \ + SIZED_FREE_N(insns_info, insns_info_size), \ BADINSN_DUMP(anchor, list, NULL), \ COMPILE_ERROR) @@ -2665,8 +2665,13 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) } /* make instruction sequence */ + const int generated_iseq_size = code_index; generated_iseq = ALLOC_N(VALUE, code_index); + + const int insns_info_size = insn_num; insns_info = ALLOC_N(struct iseq_insn_info_entry, insn_num); + + const int positions_size = insn_num; positions = ALLOC_N(unsigned int, insn_num); if (ISEQ_IS_SIZE(body)) { body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(body)); @@ -2693,12 +2698,13 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) bool needs_bitmap = false; - if (ISEQ_MBITS_BUFLEN(code_index) == 1) { + const size_t mark_offset_bits_size = ISEQ_MBITS_BUFLEN(code_index); + if (mark_offset_bits_size == 1) { mark_offset_bits = &ISEQ_COMPILE_DATA(iseq)->mark_bits.single; ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = true; } else { - mark_offset_bits = ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index)); + mark_offset_bits = ZALLOC_N(iseq_bits_t, mark_offset_bits_size); ISEQ_COMPILE_DATA(iseq)->mark_bits.list = mark_offset_bits; ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = false; } @@ -2891,11 +2897,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) } else if (diff < 0) { int label_no = adjust->label ? adjust->label->label_no : -1; - xfree(generated_iseq); - xfree(insns_info); - xfree(positions); + SIZED_FREE_N(generated_iseq, generated_iseq_size); + SIZED_FREE_N(insns_info, insns_info_size); + SIZED_FREE_N(positions, positions_size); if (ISEQ_MBITS_BUFLEN(code_size) > 1) { - xfree(mark_offset_bits); + SIZED_FREE_N(mark_offset_bits, ISEQ_MBITS_BUFLEN(code_index)); } debug_list(anchor, list); COMPILE_ERROR(iseq, adjust->line_no, @@ -2927,7 +2933,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) else { body->mark_bits.list = NULL; ISEQ_COMPILE_DATA(iseq)->mark_bits.list = NULL; - ruby_xfree(mark_offset_bits); + SIZED_FREE_N(mark_offset_bits, mark_offset_bits_size); } } @@ -2935,9 +2941,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) body->insns_info.body = insns_info; body->insns_info.positions = positions; - REALLOC_N(insns_info, struct iseq_insn_info_entry, insns_info_index); + SIZED_REALLOC_N(insns_info, struct iseq_insn_info_entry, insns_info_index, insns_info_size); body->insns_info.body = insns_info; - REALLOC_N(positions, unsigned int, insns_info_index); + SIZED_REALLOC_N(positions, unsigned int, insns_info_index, positions_size); body->insns_info.positions = positions; body->insns_info.size = insns_info_index; @@ -13127,7 +13133,7 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod } else { load_body->mark_bits.list = 0; - ruby_xfree(mark_offset_bits); + SIZED_FREE_N(mark_offset_bits, ISEQ_MBITS_BUFLEN(iseq_size)); } } @@ -13312,7 +13318,7 @@ ibf_load_local_table(const struct ibf_load *load, ibf_offset_t local_table_offse } if (size == 1 && table[0] == idERROR_INFO) { - xfree(table); + ruby_sized_xfree(table, sizeof(ID) * size); return rb_iseq_shared_exc_local_tbl; } else { @@ -13616,7 +13622,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) positions = rb_iseq_insns_info_decode_positions(ISEQ_BODY(iseq)); const ibf_offset_t insns_info_positions_offset = ibf_dump_insns_info_positions(dump, positions, body->insns_info.size); - ruby_xfree(positions); + SIZED_FREE_N(positions, ISEQ_BODY(iseq)->insns_info.size); const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq); const ibf_offset_t lvar_states_offset = ibf_dump_lvar_states(dump, iseq); @@ -14944,7 +14950,7 @@ static void ibf_loader_free(void *ptr) { struct ibf_load *load = (struct ibf_load *)ptr; - ruby_xfree(load); + SIZED_FREE(load); } static size_t diff --git a/concurrent_set.c b/concurrent_set.c index 234b6408b6b938..c8b0c73881a85d 100644 --- a/concurrent_set.c +++ b/concurrent_set.c @@ -61,7 +61,7 @@ static void concurrent_set_free(void *ptr) { struct concurrent_set *set = ptr; - xfree(set->entries); + SIZED_FREE_N(set->entries, set->capacity); } static size_t diff --git a/cont.c b/cont.c index 8af093a3163479..4582466faca335 100644 --- a/cont.c +++ b/cont.c @@ -215,6 +215,7 @@ typedef struct rb_context_struct { enum context_type type; int argc; int kw_splat; + bool root; VALUE self; VALUE value; @@ -1102,7 +1103,12 @@ cont_free(void *ptr) VM_ASSERT(cont->jit_cont != NULL); jit_cont_free(cont->jit_cont); /* free rb_cont_t or rb_fiber_t */ - ruby_xfree(ptr); + if (cont->root) { + ruby_mimfree(ptr); + } + else { + ruby_xfree(ptr); + } RUBY_FREE_LEAVE("cont"); } @@ -2574,6 +2580,7 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th) } fiber->cont.type = FIBER_CONTEXT; + fiber->cont.root = true; fiber->cont.saved_ec.fiber_ptr = fiber; fiber->cont.saved_ec.serial = next_ec_serial(th->ractor); fiber->cont.saved_ec.thread_ptr = th; diff --git a/gc.c b/gc.c index 407541b309abb8..53a65d6acb8aab 100644 --- a/gc.c +++ b/gc.c @@ -1455,7 +1455,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) st_free_table(ROBJECT_FIELDS_HASH(obj)); } else { - xfree(ROBJECT(obj)->as.heap.fields); + SIZED_FREE_N(ROBJECT(obj)->as.heap.fields, ROBJECT_FIELDS_CAPACITY(obj)); RB_DEBUG_COUNTER_INC(obj_obj_ptr); } } @@ -1550,7 +1550,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) } #endif onig_region_free(&rm->regs, 0); - xfree(rm->char_offset); + SIZED_FREE_N(rm->char_offset, rm->char_offset_num_allocated); RB_DEBUG_COUNTER_INC(obj_match_ptr); } @@ -1587,7 +1587,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) case T_BIGNUM: if (!BIGNUM_EMBED_P(obj) && BIGNUM_DIGITS(obj)) { - xfree(BIGNUM_DIGITS(obj)); + SIZED_FREE_N(BIGNUM_DIGITS(obj), BIGNUM_LEN(obj)); RB_DEBUG_COUNTER_INC(obj_bignum_ptr); } else { @@ -1605,7 +1605,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) RB_DEBUG_COUNTER_INC(obj_struct_embed); } else { - xfree((void *)RSTRUCT(obj)->as.heap.ptr); + SIZED_FREE_N(RSTRUCT(obj)->as.heap.ptr, RSTRUCT(obj)->as.heap.len); RB_DEBUG_COUNTER_INC(obj_struct_ptr); } break; @@ -3657,7 +3657,7 @@ rb_gc_unregister_address(VALUE *addr) if (tmp->varptr == addr) { vm->global_object_list = tmp->next; - xfree(tmp); + SIZED_FREE(tmp); return; } while (tmp->next) { @@ -3665,7 +3665,7 @@ rb_gc_unregister_address(VALUE *addr) struct global_object_list *t = tmp->next; tmp->next = tmp->next->next; - xfree(t); + SIZED_FREE(t); break; } tmp = tmp->next; @@ -3780,8 +3780,8 @@ gc_ref_update_object(void *objspace, VALUE v) if (slot_size >= embed_size) { // Object can be re-embedded memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * ROBJECT_FIELDS_COUNT(v)); + SIZED_FREE_N(ptr, ROBJECT_FIELDS_CAPACITY(v)); FL_UNSET_RAW(v, ROBJECT_HEAP); - xfree(ptr); ptr = ROBJECT(v)->as.ary; } } diff --git a/gc/default/default.c b/gc/default/default.c index 90232c76184a55..bfddb08ea5c23d 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -8279,6 +8279,10 @@ rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size) #if CALC_EXACT_MALLOC_SIZE struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1; #if VERIFY_FREE_SIZE + if (!info->size) { + rb_bug("buffer %p has no recorded size. Was it allocated with ruby_mimalloc? If so it should be freed with ruby_mimfree", ptr); + } + if (old_size && (old_size + sizeof(struct malloc_obj_info)) != info->size) { rb_bug("buffer %p freed with old_size=%lu, but was allocated with size=%lu", ptr, old_size, info->size - sizeof(struct malloc_obj_info)); } diff --git a/gems/bundled_gems b/gems/bundled_gems index e85061bc0f842e..91c5387067c1cc 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -18,7 +18,7 @@ net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.5.1 https://github.com/ruby/net-smtp matrix 0.4.3 https://github.com/ruby/matrix prime 0.1.4 https://github.com/ruby/prime -rbs 3.10.2 https://github.com/ruby/rbs +rbs 3.10.3 https://github.com/ruby/rbs typeprof 0.31.1 https://github.com/ruby/typeprof debug 1.11.1 https://github.com/ruby/debug racc 1.8.1 https://github.com/ruby/racc @@ -34,7 +34,7 @@ drb 2.2.3 https://github.com/ruby/drb nkf 0.2.0 https://github.com/ruby/nkf syslog 0.4.0 https://github.com/ruby/syslog csv 3.3.5 https://github.com/ruby/csv -repl_type_completor 0.1.12 https://github.com/ruby/repl_type_completor 26b8e964557690c0b539cff8940bcfb1591f1fe6 +repl_type_completor 0.1.13 https://github.com/ruby/repl_type_completor ostruct 0.6.3 https://github.com/ruby/ostruct pstore 0.2.0 https://github.com/ruby/pstore benchmark 0.5.0 https://github.com/ruby/benchmark diff --git a/internal/gc.h b/internal/gc.h index 427b2f4553afc0..b28fd25bced6b2 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -313,6 +313,9 @@ ruby_sized_xfree_inlined(void *ptr, size_t size) # define SIZED_REALLOC_N(v, T, m, n) \ ((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n))) +# define SIZED_FREE(v) ruby_sized_xfree((void *)(v), sizeof(*(v))) +# define SIZED_FREE_N(v, n) ruby_sized_xfree((void *)(v), sizeof(*(v)) * n) + static inline void * ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t old_count) { diff --git a/jit.c b/jit.c index 9399cb4026c6e8..c0b8f901ad8903 100644 --- a/jit.c +++ b/jit.c @@ -192,7 +192,7 @@ rb_jit_get_proc_ptr(VALUE procv) } VALUE -rb_optimized_call(VALUE *recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler) +rb_optimized_call(VALUE recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler) { rb_proc_t *proc; GetProcPtr(recv, proc); diff --git a/proc.c b/proc.c index 5f23e5fed6a6df..298497401dfe88 100644 --- a/proc.c +++ b/proc.c @@ -98,7 +98,7 @@ proc_memsize(const void *ptr) return sizeof(rb_proc_t); } -static const rb_data_type_t proc_data_type = { +const rb_data_type_t ruby_proc_data_type = { "proc", { proc_mark_and_move, @@ -109,6 +109,8 @@ static const rb_data_type_t proc_data_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; +#define proc_data_type ruby_proc_data_type + VALUE rb_proc_alloc(VALUE klass) { diff --git a/ractor.c b/ractor.c index 2dcbbd10a054bc..da1db8d803ce06 100644 --- a/ractor.c +++ b/ractor.c @@ -298,7 +298,12 @@ ractor_free(void *ptr) } ractor_sync_free(r); - ruby_xfree(r); + if (r->main_ractor) { + ruby_mimfree(r); + } + else { + ruby_xfree(r); + } } static size_t @@ -478,6 +483,7 @@ rb_ractor_main_alloc(void) r->pub.self = Qnil; r->newobj_cache = rb_gc_ractor_cache_alloc(r); r->next_ec_serial = 1; + r->main_ractor = true; ruby_single_main_ractor = r; return r; diff --git a/ractor_core.h b/ractor_core.h index d112ff87244944..d795136b707e3c 100644 --- a/ractor_core.h +++ b/ractor_core.h @@ -104,6 +104,7 @@ struct rb_ractor_struct { VALUE debug; bool malloc_gc_disabled; + bool main_ractor; void *newobj_cache; }; // rb_ractor_t is defined in vm_core.h diff --git a/variable.c b/variable.c index ff8d24d78aef6c..ce1873560fcb26 100644 --- a/variable.c +++ b/variable.c @@ -550,10 +550,10 @@ free_global_variable(struct rb_global_variable *var) struct trace_var *trace = var->trace; while (trace) { struct trace_var *next = trace->next; - xfree(trace); + SIZED_FREE(trace); trace = next; } - xfree(var); + SIZED_FREE(var); } static enum rb_id_table_iterator_result @@ -564,7 +564,7 @@ free_global_entry_i(VALUE val, void *arg) if (entry->var->counter == 0) { free_global_variable(entry->var); } - ruby_xfree(entry); + SIZED_FREE(entry); return ID_TABLE_DELETE; } @@ -902,7 +902,7 @@ remove_trace(struct rb_global_variable *var) next = trace->next; if (next->removed) { trace->next = next->next; - xfree(next); + SIZED_FREE(next); } else { trace = next; @@ -1565,8 +1565,10 @@ obj_transition_too_complex(VALUE obj, st_table *table) case T_OBJECT: { VALUE *old_fields = NULL; + uint32_t old_fields_len = 0; if (FL_TEST_RAW(obj, ROBJECT_HEAP)) { old_fields = ROBJECT_FIELDS(obj); + old_fields_len = ROBJECT_FIELDS_CAPACITY(obj); } else { FL_SET_RAW(obj, ROBJECT_HEAP); @@ -1574,7 +1576,7 @@ obj_transition_too_complex(VALUE obj, st_table *table) RBASIC_SET_SHAPE_ID(obj, shape_id); ROBJECT_SET_FIELDS_HASH(obj, table); if (old_fields) { - xfree(old_fields); + SIZED_FREE_N(old_fields, old_fields_len); } } break; @@ -1697,13 +1699,18 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef) MEMMOVE(&fields[removed_index], &fields[removed_index + 1], VALUE, trailing_fields); RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id); - if (FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP) && rb_obj_embedded_size(new_fields_count) <= rb_gc_obj_slot_size(fields_obj)) { - // Re-embed objects when instances become small enough - // This is necessary because YJIT assumes that objects with the same shape - // have the same embeddedness for efficiency (avoid extra checks) - FL_UNSET_RAW(fields_obj, ROBJECT_HEAP); - MEMCPY(rb_imemo_fields_ptr(fields_obj), fields, VALUE, new_fields_count); - xfree(fields); + if (FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP)) { + if (rb_obj_embedded_size(new_fields_count) <= rb_gc_obj_slot_size(fields_obj)) { + // Re-embed objects when instances become small enough + // This is necessary because YJIT assumes that objects with the same shape + // have the same embeddedness for efficiency (avoid extra checks) + FL_UNSET_RAW(fields_obj, ROBJECT_HEAP); + MEMCPY(rb_imemo_fields_ptr(fields_obj), fields, VALUE, new_fields_count); + SIZED_FREE_N(fields, RSHAPE_CAPACITY(old_shape_id)); + } + else if (RSHAPE_CAPACITY(old_shape_id) != RSHAPE_CAPACITY(next_shape_id)) { + IMEMO_OBJ_FIELDS(fields_obj)->as.external.ptr = ruby_sized_xrealloc(fields, RSHAPE_CAPACITY(next_shape_id) * sizeof(VALUE), RSHAPE_CAPACITY(old_shape_id) * sizeof(VALUE)); + } } } else { @@ -2693,7 +2700,7 @@ autoload_data_free(void *ptr) ccan_list_del_init(&autoload_const->cnode); } - ruby_xfree(p); + SIZED_FREE(p); } static size_t @@ -2732,7 +2739,7 @@ autoload_const_free(void *ptr) struct autoload_const *autoload_const = ptr; ccan_list_del(&autoload_const->cnode); - ruby_xfree(ptr); + SIZED_FREE(autoload_const); } static const rb_data_type_t autoload_const_type = { @@ -3584,7 +3591,7 @@ rb_const_remove(VALUE mod, ID id) if (rb_id_table_lookup(RCLASS_WRITABLE_CONST_TBL(mod), id, &writable_ce)) { rb_id_table_delete(RCLASS_WRITABLE_CONST_TBL(mod), id); if ((rb_const_entry_t *)writable_ce != ce) { - xfree((rb_const_entry_t *)writable_ce); + SIZED_FREE((rb_const_entry_t *)writable_ce); } } @@ -3599,7 +3606,7 @@ rb_const_remove(VALUE mod, ID id) } if (ce != const_lookup(RCLASS_PRIME_CONST_TBL(mod), id)) { - ruby_xfree(ce); + SIZED_FREE(ce); } // else - skip free'ing the ce because it still exists in the prime classext diff --git a/vm.c b/vm.c index 2cae6779d9cbc1..05d2025a12a178 100644 --- a/vm.c +++ b/vm.c @@ -3525,12 +3525,13 @@ vm_memsize(const void *ptr) // struct rb_objspace *objspace; } -static const rb_data_type_t vm_data_type = { +const rb_data_type_t ruby_vm_data_type = { "VM", {0, 0, vm_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; +#define vm_data_type ruby_vm_data_type static VALUE vm_default_params(void) @@ -3821,7 +3822,12 @@ thread_free(void *ptr) else { // ruby_xfree(th->nt); // TODO: MN system collect nt, but without MN system it should be freed here. - ruby_xfree(th); + if (th->main_thread) { + ruby_mimfree(th); + } + else { + ruby_xfree(th); + } } RUBY_FREE_LEAVE("thread"); @@ -4594,6 +4600,7 @@ Init_BareVM(void) vm->global_hooks.type = hook_list_type_global; // setup main thread + th->main_thread = 1; th->nt = ZALLOC(struct rb_native_thread); th->vm = vm; th->ractor = vm->ractor.main_ractor = rb_ractor_main_alloc(); diff --git a/vm_core.h b/vm_core.h index 68adc5eac16f32..8240a3b4f54c42 100644 --- a/vm_core.h +++ b/vm_core.h @@ -323,12 +323,18 @@ struct rb_calling_info { struct rb_execution_context_struct; -#if 1 -#define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj) +#ifndef RUBY_CORE_DATA_TYPE_CHECK +# if RUBY_DEBUG +# define RUBY_CORE_DATA_TYPE_CHECK 1 +# else +# define RUBY_CORE_DATA_TYPE_CHECK 0 +# endif +#endif +#if !RUBY_CORE_DATA_TYPE_CHECK +#define GetCoreDataFromValue(obj, type, data_type, ptr) ((ptr) = (type*)RTYPEDDATA_GET_DATA(obj)) #else -#define CoreDataFromValue(obj, type) (type*)rb_data_object_get(obj) +#define GetCoreDataFromValue(obj, type, data_type, ptr) TypedData_Get_Struct(obj, type, data_type, ptr) #endif -#define GetCoreDataFromValue(obj, type, ptr) ((ptr) = CoreDataFromValue((obj), type)) typedef struct rb_iseq_location_struct { VALUE pathobj; /* String (path) or Array [path, realpath]. Frozen. */ @@ -635,8 +641,10 @@ enum ruby_special_exceptions { ruby_special_error_count }; +extern const rb_data_type_t ruby_vm_data_type; + #define GetVMPtr(obj, ptr) \ - GetCoreDataFromValue((obj), rb_vm_t, (ptr)) + GetCoreDataFromValue((obj), rb_vm_t, &ruby_vm_data_type, (ptr)) struct rb_vm_struct; typedef void rb_vm_at_exit_func(struct rb_vm_struct*); @@ -1152,6 +1160,7 @@ typedef struct rb_thread_struct { BITFIELD(enum rb_thread_status, status, 2); /* bit flags */ + unsigned int main_thread : 1; unsigned int has_dedicated_nt : 1; unsigned int to_kill : 1; unsigned int abort_on_exception: 1; @@ -1281,8 +1290,10 @@ RUBY_EXTERN VALUE rb_mRubyVMFrozenCore; RUBY_EXTERN VALUE rb_block_param_proxy; RUBY_SYMBOL_EXPORT_END +extern const rb_data_type_t ruby_proc_data_type; + #define GetProcPtr(obj, ptr) \ - GetCoreDataFromValue((obj), rb_proc_t, (ptr)) + GetCoreDataFromValue((obj), rb_proc_t, &ruby_proc_data_type, (ptr)) typedef struct { const struct rb_block block; @@ -1308,7 +1319,7 @@ typedef struct { extern const rb_data_type_t ruby_binding_data_type; #define GetBindingPtr(obj, ptr) \ - GetCoreDataFromValue((obj), rb_binding_t, (ptr)) + GetCoreDataFromValue((obj), rb_binding_t, &ruby_binding_data_type, (ptr)) typedef struct { const struct rb_block block; diff --git a/vm_trace.c b/vm_trace.c index 00905412758bce..11cf7f55b5e18e 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1901,7 +1901,7 @@ void rb_vm_postponed_job_free(void) { rb_vm_t *vm = GET_VM(); - ruby_xfree(vm->postponed_job_queue); + ruby_mimfree(vm->postponed_job_queue); vm->postponed_job_queue = NULL; } diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 9216802a3c1919..57824f49118358 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1234,7 +1234,7 @@ extern "C" { pub fn rb_get_def_bmethod_proc(def: *mut rb_method_definition_t) -> VALUE; pub fn rb_jit_get_proc_ptr(procv: VALUE) -> *mut rb_proc_t; pub fn rb_optimized_call( - recv: *mut VALUE, + recv: VALUE, ec: *mut rb_execution_context_t, argc: ::std::os::raw::c_int, argv: *mut VALUE, diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index 969c5a4c693a73..0cd312abf9264c 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -2117,7 +2117,7 @@ unsafe extern "C" { pub fn rb_get_def_bmethod_proc(def: *mut rb_method_definition_t) -> VALUE; pub fn rb_jit_get_proc_ptr(procv: VALUE) -> *mut rb_proc_t; pub fn rb_optimized_call( - recv: *mut VALUE, + recv: VALUE, ec: *mut rb_execution_context_t, argc: ::std::os::raw::c_int, argv: *mut VALUE,