diff options
-rw-r--r-- | bignum.c | 2 | ||||
-rw-r--r-- | class.c | 24 | ||||
-rw-r--r-- | complex.c | 2 | ||||
-rw-r--r-- | encoding.c | 2 | ||||
-rw-r--r-- | enumerator.c | 2 | ||||
-rw-r--r-- | gc.c | 18 | ||||
-rw-r--r-- | internal/class.h | 1 | ||||
-rw-r--r-- | internal/vm.h | 2 | ||||
-rw-r--r-- | io.c | 2 | ||||
-rw-r--r-- | load.c | 2 | ||||
-rw-r--r-- | marshal.c | 2 | ||||
-rw-r--r-- | memory_view.c | 2 | ||||
-rw-r--r-- | mini_builtin.c | 2 | ||||
-rw-r--r-- | numeric.c | 2 | ||||
-rw-r--r-- | object.c | 10 | ||||
-rw-r--r-- | proc.c | 2 | ||||
-rw-r--r-- | random.c | 2 | ||||
-rw-r--r-- | ruby.c | 4 | ||||
-rw-r--r-- | struct.c | 4 | ||||
-rw-r--r-- | symbol.c | 4 | ||||
-rw-r--r-- | time.c | 6 | ||||
-rw-r--r-- | variable.c | 8 | ||||
-rw-r--r-- | vm.c | 155 | ||||
-rw-r--r-- | vm_backtrace.c | 2 | ||||
-rw-r--r-- | vm_core.h | 2 | ||||
-rw-r--r-- | vm_eval.c | 2 | ||||
-rw-r--r-- | yjit.c | 2 |
27 files changed, 167 insertions, 101 deletions
@@ -4728,7 +4728,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret) rb_obj_hide(power); base36_power_cache[base - 2][power_level] = power; base36_numdigits_cache[base - 2][power_level] = numdigits; - rb_gc_register_mark_object(power); + rb_vm_register_global_object(power); } if (numdigits_ret) *numdigits_ret = base36_numdigits_cache[base - 2][power_level]; @@ -32,6 +32,9 @@ /* Flags of T_CLASS * + * 0: RCLASS_IS_ROOT + * The class has been added to the VM roots. Will always be marked and pinned. + * This is done for classes defined from C to allow storing them in global variables. * 1: RUBY_FL_SINGLETON * This class is a singleton class. * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF @@ -56,6 +59,9 @@ /* Flags of T_MODULE * + * 0: RCLASS_IS_ROOT + * The class has been added to the VM roots. Will always be marked and pinned. + * This is done for classes defined from C to allow storing them in global variables. * 1: RMODULE_ALLOCATED_BUT_NOT_INITIALIZED * Module has not been initialized. * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF @@ -812,7 +818,7 @@ boot_defclass(const char *name, VALUE super) ID id = rb_intern(name); rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - rb_vm_add_root_module(obj); + rb_vm_register_global_object(obj); return obj; } @@ -894,7 +900,7 @@ Init_class_hierarchy(void) { rb_cBasicObject = boot_defclass("BasicObject", 0); rb_cObject = boot_defclass("Object", rb_cBasicObject); - rb_gc_register_mark_object(rb_cObject); + rb_vm_register_global_object(rb_cObject); /* resolve class name ASAP for order-independence */ rb_set_class_path_string(rb_cObject, rb_cObject, rb_fstring_lit("Object")); @@ -988,14 +994,14 @@ rb_define_class(const char *name, VALUE super) } /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); return klass; } if (!super) { rb_raise(rb_eArgError, "no super class for '%s'", name); } klass = rb_define_class_id(id, super); - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); @@ -1045,7 +1051,7 @@ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super) { VALUE klass = rb_define_class_id_under_no_pin(outer, id, super); - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); return klass; } @@ -1099,11 +1105,11 @@ rb_define_module(const char *name) name, rb_obj_class(module)); } /* Module may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(module); + rb_vm_register_global_object(module); return module; } module = rb_module_new(); - rb_vm_add_root_module(module); + rb_vm_register_global_object(module); rb_const_set(rb_cObject, id, module); return module; @@ -1128,13 +1134,13 @@ rb_define_module_id_under(VALUE outer, ID id) outer, rb_id2str(id), rb_obj_class(module)); } /* Module may have been defined in Ruby and not pin-rooted */ - rb_gc_register_mark_object(module); + rb_vm_register_global_object(module); return module; } module = rb_module_new(); rb_const_set(outer, id, module); rb_set_class_path_string(module, outer, rb_id2str(id)); - rb_gc_register_mark_object(module); + rb_vm_register_global_object(module); return module; } @@ -2723,7 +2723,7 @@ Init_Complex(void) f_complex_new_bang2(rb_cComplex, ZERO, ONE)); #if !USE_FLONUM - rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0)); + rb_vm_register_global_object(RFLOAT_0 = DBL2NUM(0.0)); #endif rb_provide("complex.so"); /* for backward compatibility */ diff --git a/encoding.c b/encoding.c index a0be931c97..df17f63bb1 100644 --- a/encoding.c +++ b/encoding.c @@ -1927,7 +1927,7 @@ Init_Encoding(void) list = rb_encoding_list = rb_ary_new2(ENCODING_LIST_CAPA); RBASIC_CLEAR_CLASS(list); - rb_gc_register_mark_object(list); + rb_vm_register_global_object(list); for (i = 0; i < enc_table->count; ++i) { rb_ary_push(list, enc_new(enc_table->list[i].enc)); diff --git a/enumerator.c b/enumerator.c index d2819e4049..989fdb3426 100644 --- a/enumerator.c +++ b/enumerator.c @@ -4562,7 +4562,7 @@ InitVM_Enumerator(void) rb_hash_aset(lazy_use_super_method, sym("uniq"), sym("_enumerable_uniq")); rb_hash_aset(lazy_use_super_method, sym("with_index"), sym("_enumerable_with_index")); rb_obj_freeze(lazy_use_super_method); - rb_gc_register_mark_object(lazy_use_super_method); + rb_vm_register_global_object(lazy_use_super_method); #if 0 /* for RDoc */ rb_define_method(rb_cLazy, "to_a", lazy_to_a, 0); @@ -8767,29 +8767,13 @@ rb_gc_force_recycle(VALUE obj) /* no-op */ } -#ifndef MARK_OBJECT_ARY_BUCKET_SIZE -#define MARK_OBJECT_ARY_BUCKET_SIZE 1024 -#endif - void rb_gc_register_mark_object(VALUE obj) { if (!is_pointer_to_heap(&rb_objspace, (void *)obj)) return; - RB_VM_LOCK_ENTER(); - { - VALUE ary_ary = GET_VM()->mark_object_ary; - VALUE ary = rb_ary_last(0, 0, ary_ary); - - if (NIL_P(ary) || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) { - ary = rb_ary_hidden_new(MARK_OBJECT_ARY_BUCKET_SIZE); - rb_ary_push(ary_ary, ary); - } - - rb_ary_push(ary, obj); - } - RB_VM_LOCK_LEAVE(); + rb_vm_register_global_object(obj); } void diff --git a/internal/class.h b/internal/class.h index 7f700c675c..8a6c956233 100644 --- a/internal/class.h +++ b/internal/class.h @@ -108,6 +108,7 @@ struct RClass_and_rb_classext_t { #define RCLASS_SUPERCLASSES(c) (RCLASS_EXT(c)->superclasses) #define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT(c)->as.singleton_class.attached_object) +#define RCLASS_IS_ROOT FL_USER0 #define RICLASS_IS_ORIGIN FL_USER0 #define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2 #define RICLASS_ORIGIN_SHARED_MTBL FL_USER3 diff --git a/internal/vm.h b/internal/vm.h index a32a14e045..1adce8a390 100644 --- a/internal/vm.h +++ b/internal/vm.h @@ -45,13 +45,13 @@ VALUE rb_vm_push_frame_fname(struct rb_execution_context_struct *ec, VALUE fname /* vm.c */ VALUE rb_obj_is_thread(VALUE obj); void rb_vm_mark(void *ptr); +void rb_vm_register_global_object(VALUE obj); void rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx); PUREFUNC(VALUE rb_vm_top_self(void)); const void **rb_vm_get_insns_address_table(void); VALUE rb_source_location(int *pline); const char *rb_source_location_cstr(int *pline); void rb_vm_pop_cfunc_frame(void); -int rb_vm_add_root_module(VALUE module); void rb_vm_check_redefinition_by_prepend(VALUE klass); int rb_vm_check_optimizable_mid(VALUE mid); VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements); @@ -15629,7 +15629,7 @@ Init_IO(void) rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter); rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */ - rb_gc_register_mark_object(rb_default_rs); + rb_vm_register_global_object(rb_default_rs); rb_rs = rb_default_rs; rb_output_rs = Qnil; rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter); @@ -1615,5 +1615,5 @@ Init_load(void) rb_define_global_function("autoload?", rb_f_autoload_p, -1); ruby_dln_libmap = rb_hash_new_with_size(0); - rb_gc_register_mark_object(ruby_dln_libmap); + rb_vm_register_global_object(ruby_dln_libmap); } @@ -2538,7 +2538,7 @@ compat_allocator_table(void) #define RUBY_UNTYPED_DATA_WARNING 0 compat_allocator_tbl_wrapper = Data_Wrap_Struct(0, mark_marshal_compat_t, free_compat_allocator_table, compat_allocator_tbl); - rb_gc_register_mark_object(compat_allocator_tbl_wrapper); + rb_vm_register_global_object(compat_allocator_tbl_wrapper); return compat_allocator_tbl; } diff --git a/memory_view.c b/memory_view.c index df7be91e76..519aad2ca1 100644 --- a/memory_view.c +++ b/memory_view.c @@ -863,7 +863,7 @@ Init_MemoryView(void) VALUE obj = TypedData_Wrap_Struct( 0, &rb_memory_view_exported_object_registry_data_type, exported_object_table); - rb_gc_register_mark_object(obj); + rb_vm_register_global_object(obj); rb_memory_view_exported_object_registry = obj; id_memory_view = rb_intern_const("__memory_view__"); diff --git a/mini_builtin.c b/mini_builtin.c index 8371073f28..a93a5ebddb 100644 --- a/mini_builtin.c +++ b/mini_builtin.c @@ -51,7 +51,7 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta #ifndef INCLUDED_BY_BUILTIN_C st_insert(loaded_builtin_table, (st_data_t)feature_name, (st_data_t)iseq); - rb_gc_register_mark_object((VALUE)iseq); + rb_vm_register_global_object((VALUE)iseq); #endif return iseq; @@ -6262,7 +6262,7 @@ Init_Numeric(void) rb_fix_to_s_static[8] = rb_fstring_literal("8"); rb_fix_to_s_static[9] = rb_fstring_literal("9"); for(int i = 0; i < 10; i++) { - rb_gc_register_mark_object(rb_fix_to_s_static[i]); + rb_vm_register_global_object(rb_fix_to_s_static[i]); } rb_cFloat = rb_define_class("Float", rb_cNumeric); @@ -517,7 +517,7 @@ rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze) static VALUE freeze_true_hash; if (!freeze_true_hash) { freeze_true_hash = rb_hash_new(); - rb_gc_register_mark_object(freeze_true_hash); + rb_vm_register_global_object(freeze_true_hash); rb_hash_aset(freeze_true_hash, ID2SYM(idFreeze), Qtrue); rb_obj_freeze(freeze_true_hash); } @@ -541,7 +541,7 @@ rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze) static VALUE freeze_false_hash; if (!freeze_false_hash) { freeze_false_hash = rb_hash_new(); - rb_gc_register_mark_object(freeze_false_hash); + rb_vm_register_global_object(freeze_false_hash); rb_hash_aset(freeze_false_hash, ID2SYM(idFreeze), Qfalse); rb_obj_freeze(freeze_false_hash); } @@ -4450,7 +4450,7 @@ InitVM_Object(void) rb_cNilClass = rb_define_class("NilClass", rb_cObject); rb_cNilClass_to_s = rb_fstring_enc_lit("", rb_usascii_encoding()); - rb_gc_register_mark_object(rb_cNilClass_to_s); + rb_vm_register_global_object(rb_cNilClass_to_s); rb_define_method(rb_cNilClass, "to_s", rb_nil_to_s, 0); rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0); rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0); @@ -4536,7 +4536,7 @@ InitVM_Object(void) rb_cTrueClass = rb_define_class("TrueClass", rb_cObject); rb_cTrueClass_to_s = rb_fstring_enc_lit("true", rb_usascii_encoding()); - rb_gc_register_mark_object(rb_cTrueClass_to_s); + rb_vm_register_global_object(rb_cTrueClass_to_s); rb_define_method(rb_cTrueClass, "to_s", rb_true_to_s, 0); rb_define_alias(rb_cTrueClass, "inspect", "to_s"); rb_define_method(rb_cTrueClass, "&", true_and, 1); @@ -4548,7 +4548,7 @@ InitVM_Object(void) rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding()); - rb_gc_register_mark_object(rb_cFalseClass_to_s); + rb_vm_register_global_object(rb_cFalseClass_to_s); rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, 0); rb_define_alias(rb_cFalseClass, "inspect", "to_s"); rb_define_method(rb_cFalseClass, "&", false_and, 1); @@ -1462,7 +1462,7 @@ rb_sym_to_proc(VALUE sym) if (!sym_proc_cache) { sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE * 2); - rb_gc_register_mark_object(sym_proc_cache); + rb_vm_register_global_object(sym_proc_cache); rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil); } @@ -596,7 +596,7 @@ fill_random_bytes_crypt(void *seed, size_t size) if (prov != INVALID_HCRYPTPROV) { #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 - rb_gc_register_mark_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov)); + rb_vm_register_global_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov)); } } else { /* another thread acquired */ @@ -2202,7 +2202,7 @@ process_options_global_setup(const ruby_cmdline_options_t *opt, const rb_iseq_t if ((rb_e_script = opt->e_script) != 0) { rb_str_freeze(rb_e_script); - rb_gc_register_mark_object(opt->e_script); + rb_vm_register_global_object(opt->e_script); } rb_execution_context_t *ec = GET_EC(); @@ -3070,7 +3070,7 @@ ruby_process_options(int argc, char **argv) } set_progname(external_str_new_cstr(script_name)); /* for the time being */ rb_argv0 = rb_str_new4(rb_progname); - rb_gc_register_mark_object(rb_argv0); + rb_vm_register_global_object(rb_argv0); #ifndef HAVE_SETPROCTITLE ruby_init_setproctitle(argc, argv); @@ -496,7 +496,7 @@ rb_struct_define(const char *name, ...) } else { st = new_struct(rb_str_new2(name), rb_cStruct); - rb_vm_add_root_module(st); + rb_vm_register_global_object(st); } return setup_struct(st, ary); } @@ -1705,7 +1705,7 @@ rb_data_define(VALUE super, ...) va_end(ar); if (!super) super = rb_cData; VALUE klass = setup_data(anonymous_struct(super), ary); - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); return klass; } @@ -95,12 +95,12 @@ Init_sym(void) VALUE dsym_fstrs = rb_ident_hash_new(); symbols->dsymbol_fstr_hash = dsym_fstrs; - rb_gc_register_mark_object(dsym_fstrs); + rb_vm_register_global_object(dsym_fstrs); rb_obj_hide(dsym_fstrs); symbols->str_sym = st_init_table_with_size(&symhash, 1000); symbols->ids = rb_ary_hidden_new(0); - rb_gc_register_mark_object(symbols->ids); + rb_vm_register_global_object(symbols->ids); Init_op_tbl(); Init_id(); @@ -1501,7 +1501,7 @@ guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, VALUE *zone_ret) localtime_with_gmtoff_zone(&now, &tm, &now_gmtoff, &zone); now_isdst = tm.tm_isdst; zone = rb_fstring(zone); - rb_gc_register_mark_object(zone); + rb_vm_register_global_object(zone); now_zone = zone; } if (isdst_ret) @@ -5773,9 +5773,9 @@ Init_Time(void) sym_zone = ID2SYM(rb_intern_const("zone")); str_utc = rb_fstring_lit("UTC"); - rb_gc_register_mark_object(str_utc); + rb_vm_register_global_object(str_utc); str_empty = rb_fstring_lit(""); - rb_gc_register_mark_object(str_empty); + rb_vm_register_global_object(str_empty); rb_cTime = rb_define_class("Time", rb_cObject); VALUE scTime = rb_singleton_class(rb_cTime); diff --git a/variable.c b/variable.c index eaedbc2d48..b484d65d19 100644 --- a/variable.c +++ b/variable.c @@ -72,11 +72,11 @@ Init_var_tables(void) autoload_mutex = rb_mutex_new(); rb_obj_hide(autoload_mutex); - rb_gc_register_mark_object(autoload_mutex); + rb_vm_register_global_object(autoload_mutex); autoload_features = rb_ident_hash_new(); rb_obj_hide(autoload_features); - rb_gc_register_mark_object(autoload_features); + rb_vm_register_global_object(autoload_features); } static inline bool @@ -3701,7 +3701,9 @@ rb_define_const(VALUE klass, const char *name, VALUE val) if (!rb_is_const_id(id)) { rb_warn("rb_define_const: invalid name '%s' for constant", name); } - rb_gc_register_mark_object(val); + if (!RB_SPECIAL_CONST_P(val)) { + rb_vm_register_global_object(val); + } rb_const_set(klass, id, val); } @@ -2951,8 +2951,7 @@ rb_vm_mark(void *ptr) if (ptr) { rb_vm_t *vm = ptr; rb_ractor_t *r = 0; - long i, len; - const VALUE *obj_ary; + long i; ccan_list_for_each(&vm->ractor.set, r, vmlr_node) { // ractor.set only contains blocking or running ractors @@ -2962,22 +2961,6 @@ rb_vm_mark(void *ptr) } rb_gc_mark_movable(vm->mark_object_ary); - - len = RARRAY_LEN(vm->mark_object_ary); - obj_ary = RARRAY_CONST_PTR(vm->mark_object_ary); - for (i=0; i < len; i++) { - const VALUE *ptr; - long j, jlen; - - rb_gc_mark(*obj_ary); - jlen = RARRAY_LEN(*obj_ary); - ptr = RARRAY_CONST_PTR(*obj_ary); - for (j=0; j < jlen; j++) { - rb_gc_mark(*ptr++); - } - obj_ary++; - } - rb_gc_mark_movable(vm->load_path); rb_gc_mark_movable(vm->load_path_snapshot); RUBY_MARK_MOVABLE_UNLESS_NULL(vm->load_path_check_cache); @@ -2990,8 +2973,6 @@ rb_vm_mark(void *ptr) rb_gc_mark_movable(vm->orig_progname); RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages); RUBY_MARK_MOVABLE_UNLESS_NULL(vm->me2counter); - /* Prevent classes from moving */ - rb_mark_tbl(vm->defined_module_hash); if (vm->loading_table) { rb_mark_tbl(vm->loading_table); @@ -3029,17 +3010,7 @@ rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls, VALUE exc = rb_exc_new3(cls, rb_obj_freeze(mesg)); OBJ_FREEZE(exc); ((VALUE *)vm->special_exceptions)[sp] = exc; - rb_gc_register_mark_object(exc); -} - -int -rb_vm_add_root_module(VALUE module) -{ - rb_vm_t *vm = GET_VM(); - - st_insert(vm->defined_module_hash, (st_data_t)module, (st_data_t)module); - - return TRUE; + rb_vm_register_global_object(exc); } static int @@ -3093,7 +3064,6 @@ ruby_vm_destruct(rb_vm_t *vm) st_free_table(vm->ensure_rollback_table); rb_vm_postponed_job_free(); - st_free_table(vm->defined_module_hash); rb_id_table_free(vm->constant_cache); @@ -3214,7 +3184,6 @@ vm_memsize(const void *ptr) rb_st_memsize(vm->ensure_rollback_table) + rb_vm_memsize_postponed_job_queue() + rb_vm_memsize_workqueue(&vm->workqueue) + - rb_st_memsize(vm->defined_module_hash) + vm_memsize_at_exit_list(vm->at_exit) + rb_st_memsize(vm->ci_table) + rb_st_memsize(vm->frozen_strings) + @@ -3945,8 +3914,8 @@ Init_VM(void) rb_obj_freeze(fcore); RBASIC_CLEAR_CLASS(klass); rb_obj_freeze(klass); - rb_gc_register_mark_object(fcore); - rb_gc_register_mark_object(rb_class_path_cached(fcore)); + rb_vm_register_global_object(fcore); + rb_vm_register_global_object(rb_class_path_cached(fcore)); rb_mRubyVMFrozenCore = fcore; /* @@ -4204,7 +4173,7 @@ Init_VM(void) th->top_wrapper = 0; th->top_self = rb_vm_top_self(); - rb_gc_register_mark_object((VALUE)iseq); + rb_vm_register_global_object((VALUE)iseq); th->ec->cfp->iseq = iseq; th->ec->cfp->pc = ISEQ_BODY(iseq)->iseq_encoded; th->ec->cfp->self = th->top_self; @@ -4225,7 +4194,7 @@ Init_VM(void) rb_add_method_optimized(rb_singleton_class(rb_block_param_proxy), idCall, OPTIMIZED_METHOD_TYPE_BLOCK_CALL, 0, METHOD_VISI_PUBLIC); rb_obj_freeze(rb_block_param_proxy); - rb_gc_register_mark_object(rb_block_param_proxy); + rb_vm_register_global_object(rb_block_param_proxy); /* vm_backtrace.c */ Init_vm_backtrace(); @@ -4301,15 +4270,121 @@ ruby_init_stack(void *addr) #include <sys/mman.h> #endif + +#ifndef MARK_OBJECT_ARY_BUCKET_SIZE +#define MARK_OBJECT_ARY_BUCKET_SIZE 1024 +#endif + +struct pin_array_list { + VALUE next; + long len; + VALUE *array; +}; + +static void +pin_array_list_mark(void *data) +{ + struct pin_array_list *array = (struct pin_array_list *)data; + rb_gc_mark_movable(array->next); + + rb_gc_mark_vm_stack_values(array->len, array->array); +} + +static void +pin_array_list_free(void *data) +{ + struct pin_array_list *array = (struct pin_array_list *)data; + xfree(array->array); +} + +static size_t +pin_array_list_memsize(const void *data) +{ + return sizeof(struct pin_array_list) + (MARK_OBJECT_ARY_BUCKET_SIZE * sizeof(VALUE)); +} + +static void +pin_array_list_update_references(void *data) +{ + struct pin_array_list *array = (struct pin_array_list *)data; + array->next = rb_gc_location(array->next); +} + +static const rb_data_type_t pin_array_list_type = { + .wrap_struct_name = "VM/pin_array_list", + .function = { + .dmark = pin_array_list_mark, + .dfree = pin_array_list_free, + .dsize = pin_array_list_memsize, + .dcompact = pin_array_list_update_references, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE, +}; + +static VALUE +pin_array_list_new(VALUE next) +{ + struct pin_array_list *array_list; + VALUE obj = TypedData_Make_Struct(0, struct pin_array_list, &pin_array_list_type, array_list); + RB_OBJ_WRITE(obj, &array_list->next, next); + array_list->array = ALLOC_N(VALUE, MARK_OBJECT_ARY_BUCKET_SIZE); + return obj; +} + +static VALUE +pin_array_list_append(VALUE obj, VALUE item) +{ + struct pin_array_list *array_list; + TypedData_Get_Struct(obj, struct pin_array_list, &pin_array_list_type, array_list); + + if (array_list->len >= MARK_OBJECT_ARY_BUCKET_SIZE) { + obj = pin_array_list_new(obj); + TypedData_Get_Struct(obj, struct pin_array_list, &pin_array_list_type, array_list); + } + + RB_OBJ_WRITE(obj, &array_list->array[array_list->len], item); + array_list->len++; + return obj; +} + +void +rb_vm_register_global_object(VALUE obj) +{ + RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj)); + if (RB_SPECIAL_CONST_P(obj)) { + return; + } + + switch (RB_BUILTIN_TYPE(obj)) { + case T_CLASS: + case T_MODULE: + if (FL_TEST(obj, RCLASS_IS_ROOT)) { + return; + } + FL_SET(obj, RCLASS_IS_ROOT); + break; + default: + break; + } + RB_VM_LOCK_ENTER(); + { + VALUE list = GET_VM()->mark_object_ary; + VALUE head = pin_array_list_append(list, obj); + if (head != list) { + GET_VM()->mark_object_ary = head; + } + RB_GC_GUARD(obj); + } + RB_VM_LOCK_LEAVE(); +} + void Init_vm_objects(void) { rb_vm_t *vm = GET_VM(); - vm->defined_module_hash = st_init_numtable(); - /* initialize mark object array, hash */ - vm->mark_object_ary = rb_ary_hidden_new(128); + vm->mark_object_ary = pin_array_list_new(Qnil); vm->loading_table = st_init_strtable(); vm->ci_table = st_init_table(&vm_ci_hashtype); vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 10000); diff --git a/vm_backtrace.c b/vm_backtrace.c index 279bf88d38..e36347b406 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -1731,7 +1731,7 @@ rb_profile_frame_absolute_path(VALUE frame) static VALUE cfunc_str = Qfalse; if (!cfunc_str) { cfunc_str = rb_str_new_literal("<cfunc>"); - rb_gc_register_mark_object(cfunc_str); + rb_vm_register_global_object(cfunc_str); } return cfunc_str; } @@ -744,8 +744,6 @@ typedef struct rb_vm_struct { VALUE coverages, me2counter; int coverage_mode; - st_table * defined_module_hash; - struct rb_objspace *objspace; rb_at_exit_list *at_exit; @@ -1637,7 +1637,7 @@ get_eval_default_path(void) if (!eval_default_path) { eval_default_path = rb_fstring_lit("(eval)"); - rb_gc_register_mark_object(eval_default_path); + rb_vm_register_global_object(eval_default_path); } return eval_default_path; } @@ -1264,5 +1264,5 @@ rb_yjit_init_gc_hooks(void) { struct yjit_root_struct *root; VALUE yjit_root = TypedData_Make_Struct(0, struct yjit_root_struct, &yjit_root_type, root); - rb_gc_register_mark_object(yjit_root); + rb_vm_register_global_object(yjit_root); } |