зеркало из https://github.com/github/ruby.git
Refactor VM root modules
This `st_table` is used to both mark and pin classes defined from the C API. But `vm->mark_object_ary` already does both much more efficiently. Currently a Ruby process starts with 252 rooted classes, which uses `7224B` in an `st_table` or `2016B` in an `RArray`. So a baseline of 5kB saved, but since `mark_object_ary` is preallocated with `1024` slots but only use `405` of them, it's a net `7kB` save. `vm->mark_object_ary` is also being refactored. Prior to this changes, `mark_object_ary` was a regular `RArray`, but since this allows for references to be moved, it was marked a second time from `rb_vm_mark()` to pin these objects. This has the detrimental effect of marking these references on every minors even though it's a mostly append only list. But using a custom TypedData we can save from having to mark all the references on minor GC runs. Addtionally, immediate values are now ignored and not appended to `vm->mark_object_ary` as it's just wasted space.
This commit is contained in:
Родитель
16ec54ec41
Коммит
d4f3dcf4df
2
bignum.c
2
bignum.c
|
@ -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];
|
||||
|
|
24
class.c
24
class.c
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
18
gc.c
18
gc.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
2
io.c
2
io.c
|
@ -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);
|
||||
|
|
2
load.c
2
load.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__");
|
||||
|
|
|
@ -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);
|
||||
|
|
10
object.c
10
object.c
|
@ -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);
|
||||
|
|
2
proc.c
2
proc.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
2
random.c
2
random.c
|
@ -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 */
|
||||
|
|
4
ruby.c
4
ruby.c
|
@ -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);
|
||||
|
|
4
struct.c
4
struct.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
4
symbol.c
4
symbol.c
|
@ -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();
|
||||
|
|
6
time.c
6
time.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
155
vm.c
155
vm.c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
2
yjit.c
2
yjit.c
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче