diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | array.c | 2 | ||||
-rw-r--r-- | class.c | 8 | ||||
-rw-r--r-- | compile.c | 6 | ||||
-rw-r--r-- | constant.h | 4 | ||||
-rw-r--r-- | defs/id.def | 1 | ||||
-rw-r--r-- | ext/json/generator/generator.c | 2 | ||||
-rw-r--r-- | ext/json/parser/parser.c | 2 | ||||
-rw-r--r-- | ext/openssl/ossl_bn.c | 7 | ||||
-rw-r--r-- | gc.c | 1308 | ||||
-rw-r--r-- | gc.h | 4 | ||||
-rw-r--r-- | hash.c | 40 | ||||
-rw-r--r-- | id_table.c | 22 | ||||
-rw-r--r-- | id_table.h | 3 | ||||
-rw-r--r-- | include/ruby/intern.h | 5 | ||||
-rw-r--r-- | include/ruby/ruby.h | 10 | ||||
-rw-r--r-- | include/ruby/st.h | 3 | ||||
-rw-r--r-- | internal.h | 42 | ||||
-rw-r--r-- | io.c | 3 | ||||
-rw-r--r-- | iseq.c | 102 | ||||
-rw-r--r-- | iseq.h | 2 | ||||
-rw-r--r-- | lib/net/imap.rb | 1 | ||||
-rw-r--r-- | method.h | 24 | ||||
-rw-r--r-- | mjit_worker.c | 3 | ||||
-rw-r--r-- | parse.y | 8 | ||||
-rw-r--r-- | st.c | 23 | ||||
-rw-r--r-- | symbol.c | 7 | ||||
-rw-r--r-- | symbol.h | 7 | ||||
-rw-r--r-- | test/openssl/test_bn.rb | 5 | ||||
-rw-r--r-- | test/ruby/test_gc.rb | 1 | ||||
-rw-r--r-- | test/ruby/test_gc_compact.rb | 103 | ||||
-rw-r--r-- | timev.h | 3 | ||||
-rw-r--r-- | transient_heap.c | 50 | ||||
-rw-r--r-- | transient_heap.h | 2 | ||||
-rw-r--r-- | variable.c | 32 | ||||
-rw-r--r-- | version.h | 2 | ||||
-rw-r--r-- | vm.c | 31 | ||||
-rw-r--r-- | vm_args.c | 2 | ||||
-rw-r--r-- | vm_core.h | 8 | ||||
-rw-r--r-- | vm_eval.c | 1 | ||||
-rw-r--r-- | vm_method.c | 7 |
41 files changed, 152 insertions, 1753 deletions
@@ -98,15 +98,6 @@ JIT:: * Default value of +--jit-min-calls+ is changed from 5 to 10,000 -GC:: - - * New `GC.compact` method for compacting the heap. - This function compacts live objects in the heap so that fewer pages may - be used, and the heap may be more CoW friendly. [Feature #15626] - - Details on the algorithm and caveats can be found here: - https://bugs.ruby-lang.org/issues/15626 - === Miscellaneous changes * Require compilers to support C99 [Misc #15347] @@ -1326,7 +1326,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) MJIT_FUNC_EXPORTED VALUE rb_ary_behead(VALUE ary, long n) { - if (n<=0) return ary; + if(n<=0) return ary; rb_ary_modify_check(ary); if (ARY_SHARED_P(ary)) { @@ -539,7 +539,6 @@ boot_defclass(const char *name, VALUE super) rb_name_class(obj, id); rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - rb_vm_add_root_module(id, obj); return obj; } @@ -731,9 +730,6 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) " (%"PRIsVALUE" is given but was %"PRIsVALUE")", outer, rb_id2str(id), RCLASS_SUPER(klass), super); } - /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(id, klass); - return klass; } if (!super) { @@ -744,7 +740,6 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) rb_set_class_path_string(klass, outer, rb_id2str(id)); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); - rb_vm_add_root_module(id, klass); rb_gc_register_mark_object(klass); return klass; @@ -782,13 +777,10 @@ rb_define_module(const char *name) rb_raise(rb_eTypeError, "%s is not a module (%"PRIsVALUE")", name, rb_obj_class(module)); } - /* Module may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(id, module); return module; } module = rb_define_module_id(id); rb_vm_add_root_module(id, module); - rb_gc_register_mark_object(module); rb_const_set(rb_cObject, id, module); return module; @@ -574,7 +574,6 @@ static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) { if (!SPECIAL_CONST_P(v)) { - rb_gc_writebarrier((VALUE)iseq, v); rb_ary_push(ISEQ_COMPILE_DATA(iseq)->mark_ary, v); } return COMPILE_OK; @@ -584,7 +583,6 @@ static inline VALUE freeze_literal(rb_iseq_t *iseq, VALUE lit) { lit = rb_fstring(lit); - rb_gc_writebarrier((VALUE)iseq, lit); rb_ary_push(ISEQ_COMPILE_DATA(iseq)->mark_ary, lit); return lit; } @@ -1366,10 +1364,12 @@ iseq_set_exception_local_table(rb_iseq_t *iseq) /* TODO: every id table is same -> share it. * Current problem is iseq_free(). */ + ID id_dollar_bang; ID *ids = (ID *)ALLOC_N(ID, 1); + CONST_ID(id_dollar_bang, "#$!"); iseq->body->local_table_size = 1; - ids[0] = idERROR_INFO; + ids[0] = id_dollar_bang; iseq->body->local_table = ids; return COMPILE_OK; } diff --git a/constant.h b/constant.h index 6c8cda08db..fcccf07384 100644 --- a/constant.h +++ b/constant.h @@ -31,8 +31,8 @@ typedef enum { typedef struct rb_const_entry_struct { rb_const_flag_t flag; int line; - VALUE value; /* should be mark */ - VALUE file; /* should be mark */ + const VALUE value; /* should be mark */ + const VALUE file; /* should be mark */ } rb_const_entry_t; VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj); diff --git a/defs/id.def b/defs/id.def index 24ca5d3f9f..91a9768ad6 100644 --- a/defs/id.def +++ b/defs/id.def @@ -70,7 +70,6 @@ firstline, predefined = __LINE__+1, %[\ $_ LASTLINE $~ BACKREF - $! ERROR_INFO ] # VM ID OP Parser Token diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index e59a120008..6b3cdd7e58 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1344,8 +1344,6 @@ void Init_generator(void) eGeneratorError = rb_path2class("JSON::GeneratorError"); eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eGeneratorError); - rb_gc_register_mark_object(eNestingError); cState = rb_define_class_under(mGenerator, "State", rb_cObject); rb_define_alloc_func(cState, cState_s_allocate); diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 0bd328ca42..f68676879b 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -2091,8 +2091,6 @@ void Init_parser(void) cParser = rb_define_class_under(mExt, "Parser", rb_cObject); eParserError = rb_path2class("JSON::ParserError"); eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eParserError); - rb_gc_register_mark_object(eNestingError); rb_define_alloc_func(cParser, cJSON_parser_s_allocate); rb_define_method(cParser, "initialize", cParser_initialize, -1); rb_define_method(cParser, "parse", cParser_parse, 0); diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 6f0064e966..4666ce6c2f 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -187,7 +187,6 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) BIGNUM *bn; VALUE str, bs; int base = 10; - char *ptr; if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) { base = NUM2INT(bs); @@ -214,14 +213,12 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) GetBN(self, bn); switch (base) { case 0: - ptr = StringValuePtr(str); - if (!BN_mpi2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) { + if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) { ossl_raise(eBNError, NULL); } break; case 2: - ptr = StringValuePtr(str); - if (!BN_bin2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) { + if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) { ossl_raise(eBNError, NULL); } break; @@ -29,7 +29,6 @@ #include "ruby_atomic.h" #include "probes.h" #include "id_table.h" -#include "symbol.h" #include <stdio.h> #include <stdarg.h> #include <setjmp.h> @@ -195,9 +194,6 @@ static ruby_gc_params_t gc_params = { FALSE, }; -static st_table *id_to_obj_tbl; -static st_table *obj_to_id_tbl; - /* GC_DEBUG: * enable to embed GC debugging information. */ @@ -408,7 +404,6 @@ typedef struct RVALUE { VALUE flags; /* always 0 for freed obj */ struct RVALUE *next; } free; - struct RMoved moved; struct RBasic basic; struct RObject object; struct RClass klass; @@ -586,7 +581,6 @@ typedef struct rb_objspace { #if USE_RGENGC size_t minor_gc_count; size_t major_gc_count; - size_t object_id_collisions; #if RGENGC_PROFILE > 0 size_t total_generated_normal_object_count; size_t total_generated_shady_object_count; @@ -641,12 +635,6 @@ typedef struct rb_objspace { size_t error_count; #endif } rgengc; - - struct { - size_t considered_count_table[T_MASK]; - size_t moved_count_table[T_MASK]; - } rcompactor; - #if GC_ENABLE_INCREMENTAL_MARK struct { size_t pooled_slots; @@ -694,8 +682,6 @@ struct heap_page { #if USE_RGENGC bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT]; #endif - /* If set, the object is not movable */ - bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT]; /* the following three bitmaps are cleared at the beginning of full GC */ bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT]; #if USE_RGENGC @@ -720,7 +706,6 @@ struct heap_page { /* getting bitmap */ #define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0]) -#define GET_HEAP_PINNED_BITS(x) (&GET_HEAP_PAGE(x)->pinned_bits[0]) #if USE_RGENGC #define GET_HEAP_UNCOLLECTIBLE_BITS(x) (&GET_HEAP_PAGE(x)->uncollectible_bits[0]) #define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0]) @@ -841,9 +826,7 @@ VALUE rb_mGC; int ruby_disable_gc = 0; void rb_iseq_mark(const rb_iseq_t *iseq); -void rb_iseq_update_references(rb_iseq_t *iseq); void rb_iseq_free(const rb_iseq_t *iseq); -void rb_vm_update_references(void *ptr); void rb_gcdebug_print_obj_condition(VALUE obj); @@ -878,11 +861,8 @@ static void gc_sweep_rest(rb_objspace_t *objspace); static void gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap); static inline void gc_mark(rb_objspace_t *objspace, VALUE ptr); -static inline void gc_pin(rb_objspace_t *objspace, VALUE ptr); -static inline void gc_mark_and_pin(rb_objspace_t *objspace, VALUE ptr); static void gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr); NO_SANITIZE("memory", static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr)); -static void gc_mark_and_pin_maybe(rb_objspace_t *objspace, VALUE ptr); static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr); static int gc_mark_stacked_objects_incremental(rb_objspace_t *, size_t count); @@ -915,14 +895,6 @@ static inline void gc_prof_sweep_timer_stop(rb_objspace_t *); static inline void gc_prof_set_malloc_info(rb_objspace_t *); static inline void gc_prof_set_heap_info(rb_objspace_t *); -#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \ - if (gc_object_moved_p(_objspace, (VALUE)_thing)) { \ - (_thing) = (_type)RMOVED((_thing))->destination; \ - } \ -} while (0) - -#define UPDATE_IF_MOVED(_objspace, _thing) TYPED_UPDATE_IF_MOVED(_objspace, VALUE, _thing) - #define gc_prof_record(objspace) (objspace)->profile.current_record #define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record) @@ -1048,7 +1020,6 @@ tick(void) #define FL_UNSET2(x,f) FL_CHECK2("FL_UNSET2", x, RBASIC(x)->flags &= ~(f)) #define RVALUE_MARK_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), (obj)) -#define RVALUE_PIN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), (obj)) #define RVALUE_PAGE_MARKED(page, obj) MARKED_IN_BITMAP((page)->mark_bits, (obj)) #if USE_RGENGC @@ -1143,39 +1114,12 @@ check_rvalue_consistency(const VALUE obj) #endif static inline int -gc_object_moved_p(rb_objspace_t * objspace, VALUE obj) -{ - if (RB_SPECIAL_CONST_P(obj)) { - return FALSE; - } - else { - void *poisoned = poisoned_object_p(obj); - unpoison_object(obj, false); - - int ret = BUILTIN_TYPE(obj) == T_MOVED; - /* Re-poison slot if it's not the one we want */ - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); - poison_object(obj); - } - return ret; - } -} - -static inline int RVALUE_MARKED(VALUE obj) { check_rvalue_consistency(obj); return RVALUE_MARK_BITMAP(obj) != 0; } -static inline int -RVALUE_PINNED(VALUE obj) -{ - check_rvalue_consistency(obj); - return RVALUE_PIN_BITMAP(obj) != 0; -} - #if USE_RGENGC static inline int RVALUE_WB_UNPROTECTED(VALUE obj) @@ -2263,18 +2207,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) FL_UNSET(obj, FL_EXIVAR); } - if (FL_TEST(obj, FL_FINALIZE)) { - VALUE id; - - FL_UNSET(obj, FL_FINALIZE); - - if (st_lookup(obj_to_id_tbl, (st_data_t)obj, &id)) { - gc_report(4, objspace, "Collecting %p -> %p\n", (void *)obj, (void *)obj_id_to_ref(id)); - st_delete(obj_to_id_tbl, (st_data_t *)&obj, 0); - st_delete(id_to_obj_tbl, (st_data_t *)&id, 0); - } - } - #if USE_RGENGC if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); @@ -2442,7 +2374,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_RATIONAL: case T_COMPLEX: - case T_MOVED: break; case T_ICLASS: /* Basically , T_ICLASS shares table with the module */ @@ -2552,10 +2483,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) } if (FL_TEST(obj, FL_FINALIZE)) { - /* "object_id" objects will not have a block to call */ - if (st_lookup(finalizer_table, obj, 0)) { - make_zombie(objspace, obj, 0, 0); - } + make_zombie(objspace, obj, 0, 0); return 1; } else { @@ -2711,7 +2639,6 @@ internal_object_p(VALUE obj) UNEXPECTED_NODE(internal_object_p); break; case T_NONE: - case T_MOVED: case T_IMEMO: case T_ICLASS: case T_ZOMBIE: @@ -3299,10 +3226,6 @@ id2ref(VALUE obj, VALUE objid) if (FLONUM_P(ptr)) return (VALUE)ptr; ptr = obj_id_to_ref(objid); - if (st_lookup(id_to_obj_tbl, objid, &ptr)) { - return ptr; - } - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { ID symid = ptr / sizeof(RVALUE); if (rb_id2str(symid) == 0) @@ -3391,32 +3314,6 @@ rb_obj_id(VALUE obj) else if (SPECIAL_CONST_P(obj)) { return LONG2NUM((SIGNED_VALUE)obj); } - VALUE id; - - if (st_lookup(obj_to_id_tbl, (st_data_t)obj, &id)) { - gc_report(4, &rb_objspace, "Second time object_id was called on this object: %p\n", (void*)obj); - return id; - } - else { - id = nonspecial_obj_id(obj); - - while (1) { - /* id is the object id */ - if (st_lookup(id_to_obj_tbl, (st_data_t)id, 0)) { - gc_report(4, &rb_objspace, "object_id called on %p, but there was a collision at %d\n", (void*)obj, NUM2INT(id)); - rb_objspace_t *objspace = &rb_objspace; - objspace->profile.object_id_collisions++; - id += 40; - } - else { - gc_report(4, &rb_objspace, "Initial insert: %p id: %d\n", (void*)obj, NUM2INT(id)); - st_insert(obj_to_id_tbl, (st_data_t)obj, id); - st_insert(id_to_obj_tbl, (st_data_t)id, obj); - FL_SET(obj, FL_FINALIZE); - return id; - } - } - } return nonspecial_obj_id(obj); } @@ -3540,7 +3437,6 @@ obj_memsize_of(VALUE obj, int use_all_types) break; case T_ZOMBIE: - case T_MOVED: break; default: @@ -3597,7 +3493,6 @@ type_sym(size_t type) COUNT_TYPE(T_NODE); COUNT_TYPE(T_ICLASS); COUNT_TYPE(T_ZOMBIE); - COUNT_TYPE(T_MOVED); #undef COUNT_TYPE default: return INT2NUM(type); break; } @@ -4309,7 +4204,7 @@ mark_locations_array(rb_objspace_t *objspace, register const VALUE *x, register VALUE v; while (n--) { v = *x; - gc_mark_and_pin_maybe(objspace, v); + gc_mark_maybe(objspace, v); x++; } } @@ -4331,12 +4226,12 @@ rb_gc_mark_locations(const VALUE *start, const VALUE *end) } static void -gc_mark_and_pin_values(rb_objspace_t *objspace, long n, const VALUE *values) +gc_mark_values(rb_objspace_t *objspace, long n, const VALUE *values) { long i; for (i=0; i<n; i++) { - gc_mark_and_pin(objspace, values[i]); + gc_mark(objspace, values[i]); } } @@ -4344,53 +4239,18 @@ void rb_gc_mark_values(long n, const VALUE *values) { rb_objspace_t *objspace = &rb_objspace; - gc_mark_and_pin_values(objspace, n, values); -} - -static void -gc_mark_and_pin_stack_values(rb_objspace_t *objspace, long n, const VALUE *values) -{ - long i; - - for (i=0; i<n; i++) { - /* skip MOVED objects that are on the stack */ - if (is_markable_object(objspace, values[i]) && T_MOVED != BUILTIN_TYPE(values[i])) { - gc_mark_and_pin(objspace, values[i]); - } - } -} - -void -rb_gc_mark_stack_values(long n, const VALUE *values) -{ - rb_objspace_t *objspace = &rb_objspace; - gc_mark_and_pin_stack_values(objspace, n, values); -} - -static int -mark_entry_no_pin(st_data_t key, st_data_t value, st_data_t data) -{ - rb_objspace_t *objspace = (rb_objspace_t *)data; - gc_mark(objspace, (VALUE)value); - return ST_CONTINUE; + gc_mark_values(objspace, n, values); } static int mark_entry(st_data_t key, st_data_t value, st_data_t data) { rb_objspace_t *objspace = (rb_objspace_t *)data; - gc_mark_and_pin(objspace, (VALUE)value); + gc_mark(objspace, (VALUE)value); return ST_CONTINUE; } static void -mark_tbl_no_pin(rb_objspace_t *objspace, st_table *tbl) -{ - if (!tbl || tbl->num_entries == 0) return; - st_foreach(tbl, mark_entry_no_pin, (st_data_t)objspace); -} - -static void mark_tbl(rb_objspace_t *objspace, st_table *tbl) { if (!tbl || tbl->num_entries == 0) return; @@ -4423,12 +4283,7 @@ mark_keyvalue(st_data_t key, st_data_t value, st_data_t data) { rb_objspace_t *objspace = (rb_objspace_t *)data; - if (SPECIAL_CONST_P((VALUE)key) || BUILTIN_TYPE((VALUE)key) == T_STRING) { - gc_mark(objspace, (VALUE)key); - } - else { - gc_mark_and_pin(objspace, (VALUE)key); - } + gc_mark(objspace, (VALUE)key); gc_mark(objspace, (VALUE)value); return ST_CONTINUE; } @@ -4608,14 +4463,8 @@ rb_mark_tbl(st_table *tbl) mark_tbl(&rb_objspace, tbl); } -void -rb_mark_tbl_no_pin(st_table *tbl) -{ - mark_tbl_no_pin(&rb_objspace, tbl); -} - static void -gc_mark_maybe_(rb_objspace_t *objspace, VALUE obj, int pin) +gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) { (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj)); if (is_pointer_to_heap(objspace, (void *)obj)) { @@ -4624,35 +4473,19 @@ gc_mark_maybe_(rb_objspace_t *objspace, VALUE obj, int pin) unpoison_object(obj, false); type = BUILTIN_TYPE(obj); - /* Garbage can live on the stack, so do not mark or pin */ - if (type != T_MOVED && type != T_ZOMBIE && type != T_NONE) { - if (pin) { - gc_pin(objspace, obj); - } + if (type != T_ZOMBIE && type != T_NONE) { gc_mark_ptr(objspace, obj); } if (ptr) { - GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE); poison_object(obj); } } } -static void -gc_mark_and_pin_maybe(rb_objspace_t *objspace, VALUE obj) -{ - gc_mark_maybe_(objspace, obj, TRUE); -} - -static void -gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) -{ - gc_mark_maybe_(objspace, obj, FALSE); -} void rb_gc_mark_maybe(VALUE obj) { - gc_mark_and_pin_maybe(&rb_objspace, obj); + gc_mark_maybe(&rb_objspace, obj); } static inline int @@ -4788,21 +4621,6 @@ gc_mark_ptr(rb_objspace_t *objspace, VALUE obj) } static inline void -gc_mark_and_pin(rb_objspace_t *objspace, VALUE obj) -{ - if (!is_markable_object(objspace, obj)) return; - MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj); - gc_mark_ptr(objspace, obj); -} - -static inline void -gc_pin(rb_objspace_t *objspace, VALUE obj) -{ - if (!is_markable_object(objspace, obj)) return; - MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj); -} - -static inline void gc_mark(rb_objspace_t *objspace, VALUE obj) { if (!is_markable_object(objspace, obj)) return; @@ -4810,15 +4628,9 @@ gc_mark(rb_objspace_t *objspace, VALUE obj) } void -rb_gc_mark_no_pin(VALUE ptr) -{ - gc_mark(&rb_objspace, ptr); -} - -void rb_gc_mark(VALUE ptr) { - gc_mark_and_pin(&rb_objspace, ptr); + gc_mark(&rb_objspace, ptr); } /* CAUTION: THIS FUNCTION ENABLE *ONLY BEFORE* SWEEPING. @@ -4831,12 +4643,6 @@ rb_objspace_marked_object_p(VALUE obj) return RVALUE_MARKED(obj) ? TRUE : FALSE; } -int -rb_objspace_pinned_object_p(VALUE obj) -{ - return RVALUE_PINNED(obj) ? TRUE : FALSE; -} - static inline void gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) { @@ -4858,9 +4664,9 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) { const rb_env_t *env = (const rb_env_t *)obj; GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); - gc_mark_and_pin_values(objspace, (long)env->env_size, env->env); + gc_mark_values(objspace, (long)env->env_size, env->env); VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); - gc_mark_and_pin(objspace, (VALUE)rb_vm_env_prev_env(env)); + gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); gc_mark(objspace, (VALUE)env->iseq); } return; @@ -4952,7 +4758,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) case T_MODULE: mark_m_tbl(objspace, RCLASS_M_TBL(obj)); if (!RCLASS_EXT(obj)) break; - mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj)); + mark_tbl(objspace, RCLASS_IV_TBL(obj)); mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); gc_mark(objspace, RCLASS_SUPER((VALUE)obj)); break; @@ -5080,7 +4886,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) #if GC_DEBUG rb_gcdebug_print_obj_condition((VALUE)obj); #endif - if (BUILTIN_TYPE(obj) == T_MOVED) rb_bug("rb_gc_mark(): %p is T_MOVED", (void *)obj); if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj); if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj); rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s", @@ -5560,12 +5365,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v /* count objects */ data->live_object_count++; - /* Normally, we don't expect T_MOVED objects to be in the heap. - * But they can stay alive on the stack, */ - if (!gc_object_moved_p(objspace, obj)) { - /* moved slots don't have children */ - rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data); - } + rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data); #if USE_RGENGC /* check health of children */ @@ -5679,7 +5479,7 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head) list_for_each(head, page, page_node) { unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); RVALUE *p = page->freelist; - while (p) { + while(p) { RVALUE *prev = p; unpoison_object((VALUE)p, false); if (BUILTIN_TYPE(p) != T_NONE) { @@ -6315,7 +6115,6 @@ rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap) list_for_each(&heap->pages, page, page_node) { memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); - memset(&page->pinned_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); memset(&page->marking_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); page->flags.has_uncollectible_shady_objects = FALSE; @@ -6570,7 +6369,7 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) size_t n = 0; static ID ID_marked; #if USE_RGENGC - static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible, ID_pinned; + static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible; #endif if (!ID_marked) { @@ -6581,7 +6380,6 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) I(old); I(marking); I(uncollectible); - I(pinned); #endif #undef I } @@ -6593,7 +6391,6 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj) && n<max) flags[n++] = ID_marking; #endif if (MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) && n<max) flags[n++] = ID_marked; - if (MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj) && n<max) flags[n++] = ID_pinned; return n; } @@ -7167,955 +6964,6 @@ gc_start_internal(int argc, VALUE *argv, VALUE self) return Qnil; } -static int -gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) -{ - if (SPECIAL_CONST_P(obj)) { - return FALSE; - } - - switch(BUILTIN_TYPE(obj)) { - case T_NONE: - case T_NIL: - case T_MOVED: - case T_ZOMBIE: - return FALSE; - break; - case T_STRING: - case T_OBJECT: - case T_FLOAT: - case T_IMEMO: - case T_ARRAY: - case T_BIGNUM: - case T_ICLASS: - case T_MODULE: - case T_REGEXP: - case T_DATA: - case T_SYMBOL: - case T_MATCH: - case T_STRUCT: - case T_HASH: - case T_FILE: - case T_COMPLEX: - case T_RATIONAL: - case T_NODE: - case T_CLASS: - if (FL_TEST(obj, FL_FINALIZE)) { - if (st_lookup(finalizer_table, obj, 0)) { - return FALSE; - } - } - return !rb_objspace_pinned_object_p(obj); - break; - - default: - rb_bug("gc_is_moveable_obj: unreachable (%d)", (int)BUILTIN_TYPE(obj)); - break; - } - - return FALSE; -} - -static int -update_id_to_obj(st_data_t *key, st_data_t *value, st_data_t arg, int exists) -{ - if (exists) { - *value = arg; - return ST_CONTINUE; - } - else { - return ST_STOP; - } -} - -static void -gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free) -{ - int marked; - int wb_unprotected; - int uncollectible; - int marking; - RVALUE *dest = (RVALUE *)free; - RVALUE *src = (RVALUE *)scan; - - gc_report(4, objspace, "Moving object: %s -> %p\n", obj_info(scan), (void *)free); - - GC_ASSERT(BUILTIN_TYPE(scan) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(free) == T_NONE); - - /* Save off bits for current object. */ - marked = rb_objspace_marked_object_p((VALUE)src); - wb_unprotected = RVALUE_WB_UNPROTECTED((VALUE)src); - uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src); - marking = RVALUE_MARKING((VALUE)src); - - objspace->total_allocated_objects++; - - /* Clear bits for eventual T_MOVED */ - CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)src), (VALUE)src); - CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)src), (VALUE)src); - CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)src), (VALUE)src); - CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)src), (VALUE)src); - - if (FL_TEST(src, FL_EXIVAR)) { - rb_mv_generic_ivar((VALUE)src, (VALUE)dest); - } - - VALUE id; - - /* If the source object's object_id has been seen, we need to update - * the object to object id mapping. */ - if (st_lookup(obj_to_id_tbl, (VALUE)src, &id)) { - gc_report(4, objspace, "Moving object with seen id: %p -> %p\n", (void *)src, (void *)dest); - st_delete(obj_to_id_tbl, (st_data_t *)&src, 0); - st_insert(obj_to_id_tbl, (VALUE)dest, id); - st_update(id_to_obj_tbl, (st_data_t)id, update_id_to_obj, (st_data_t)dest); - } - - /* Move the object */ - memcpy(dest, src, sizeof(RVALUE)); - memset(src, 0, sizeof(RVALUE)); - - /* Set bits for object in new location */ - if (marking) { - MARK_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)dest), (VALUE)dest); - } - else { - CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)dest), (VALUE)dest); - } - - if (marked) { - MARK_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)dest), (VALUE)dest); - } - else { - CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)dest), (VALUE)dest); - } - - if (wb_unprotected) { - MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)dest), (VALUE)dest); - } - else { - CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)dest), (VALUE)dest); - } - - if (uncollectible) { - MARK_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)dest), (VALUE)dest); - } - else { - CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)dest), (VALUE)dest); - } - - /* Assign forwarding address */ - src->as.moved.flags = T_MOVED; - src->as.moved.destination = (VALUE)dest; - GC_ASSERT(BUILTIN_TYPE((VALUE)dest) != T_NONE); -} - -struct heap_cursor { - RVALUE *slot; - size_t index; - struct heap_page *page; - rb_objspace_t * objspace; -}; - -static void -advance_cursor(struct heap_cursor *free, struct heap_page **page_list) -{ - if (free->slot == free->page->start + free->page->total_slots - 1) { - free->index++; - free->page = page_list[free->index]; - free->slot = free->page->start; - } - else { - free->slot++; - } -} - -static void -retreat_cursor(struct heap_cursor *scan, struct heap_page **page_list) -{ - if (scan->slot == scan->page->start) { - scan->index--; - scan->page = page_list[scan->index]; - scan->slot = scan->page->start + scan->page->total_slots - 1; - } - else { - scan->slot--; - } -} - -static int -not_met(struct heap_cursor *free, struct heap_cursor *scan) -{ - if (free->index < scan->index) - return 1; - - if (free->index > scan->index) - return 0; - - return free->slot < scan->slot; -} - -static void -init_cursors(rb_objspace_t *objspace, struct heap_cursor *free, struct heap_cursor *scan, struct heap_page **page_list) -{ - struct heap_page *page; - page = page_list[0]; - - free->index = 0; - free->page = page; - free->slot = page->start; - free->objspace = objspace; - - page = page_list[heap_allocated_pages - 1]; - scan->index = heap_allocated_pages - 1; - scan->page = page; - scan->slot = page->start + page->total_slots - 1; - scan->objspace = objspace; -} - -int count_pinned(struct heap_page *page) -{ - RVALUE *pstart = page->start; - RVALUE *pend = pstart + page->total_slots; - int pinned = 0; - - VALUE v = (VALUE)pstart; - for (; v != (VALUE)pend; v += sizeof(RVALUE)) { - void *poisoned = poisoned_object_p(v); - unpoison_object(v, false); - - if (RBASIC(v)->flags && RVALUE_PINNED(v)) { - pinned++; - } - - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); - poison_object(v); - } - } - - return pinned; -} - -int compare_pinned(const void *left, const void *right, void *dummy) -{ - int left_count = count_pinned(*(struct heap_page * const *)left); - int right_count = count_pinned(*(struct heap_page * const *)right); - return right_count - left_count; -} - -static void -gc_compact_heap(rb_objspace_t *objspace) -{ - struct heap_cursor free_cursor; - struct heap_cursor scan_cursor; - struct heap_page **page_list; - - memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t)); - memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t)); - - page_list = calloc(heap_allocated_pages, sizeof(struct heap_page *)); - memcpy(page_list, heap_pages_sorted, heap_allocated_pages * sizeof(struct heap_page *)); - ruby_qsort(page_list, heap_allocated_pages, sizeof(struct heap_page *), compare_pinned, NULL); - - init_cursors(objspace, &free_cursor, &scan_cursor, page_list); - - /* Two finger algorithm */ - while (not_met(&free_cursor, &scan_cursor)) { - /* Free cursor movement */ - - /* Unpoison free_cursor slot */ - void *free_slot_poison = poisoned_object_p((VALUE)free_cursor.slot); - unpoison_object((VALUE)free_cursor.slot, false); - - while (BUILTIN_TYPE(free_cursor.slot) != T_NONE && not_met(&free_cursor, &scan_cursor)) { - /* Re-poison slot if it's not the one we want */ - if (free_slot_poison) { - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE); - poison_object((VALUE)free_cursor.slot); - } - - advance_cursor(&free_cursor, page_list); - - /* Unpoison free_cursor slot */ - free_slot_poison = poisoned_object_p((VALUE)free_cursor.slot); - unpoison_object((VALUE)free_cursor.slot, false); - } - - /* Unpoison scan_cursor slot */ - void *scan_slot_poison = poisoned_object_p((VALUE)scan_cursor.slot); - unpoison_object((VALUE)scan_cursor.slot, false); - - /* Scan cursor movement */ - objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; - - while (!gc_is_moveable_obj(objspace, (VALUE)scan_cursor.slot) && not_met(&free_cursor, &scan_cursor)) { - - /* Re-poison slot if it's not the one we want */ - if (scan_slot_poison) { - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_NONE); - poison_object((VALUE)scan_cursor.slot); - } - - retreat_cursor(&scan_cursor, page_list); - - /* Unpoison scan_cursor slot */ - scan_slot_poison = poisoned_object_p((VALUE)scan_cursor.slot); - unpoison_object((VALUE)scan_cursor.slot, false); - - objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; - } - - if (not_met(&free_cursor, &scan_cursor)) { - objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++; - - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_MOVED); - - gc_move(objspace, (VALUE)scan_cursor.slot, (VALUE)free_cursor.slot); - - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_MOVED); - GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_NONE); - GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_MOVED); - - advance_cursor(&free_cursor, page_list); - retreat_cursor(&scan_cursor, page_list); - } - } - free(page_list); -} - -static void -gc_ref_update_array(rb_objspace_t * objspace, VALUE v) -{ - long i, len; - - if (FL_TEST(v, ELTS_SHARED)) - return; - - len = RARRAY_LEN(v); - if (len > 0) { - VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(v); - for (i = 0; i < len; i++) { - UPDATE_IF_MOVED(objspace, ptr[i]); - } - } -} - -static void -gc_ref_update_object(rb_objspace_t * objspace, VALUE v) -{ - VALUE *ptr = ROBJECT_IVPTR(v); - - if (ptr) { - uint32_t i, len = ROBJECT_NUMIV(v); - for (i = 0; i < len; i++) { - UPDATE_IF_MOVED(objspace, ptr[i]); - } - } -} - -static int -hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - rb_objspace_t *objspace = (rb_objspace_t *)argp; - - if (gc_object_moved_p(objspace, (VALUE)*key)) { - *key = rb_gc_new_location((VALUE)*key); - } - - if (gc_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_new_location((VALUE)*value); - } - - return ST_CONTINUE; -} - -static int -hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error) -{ - rb_objspace_t *objspace; - - objspace = (rb_objspace_t *)argp; - - if (gc_object_moved_p(objspace, (VALUE)key)) { - return ST_REPLACE; - } - - if (gc_object_moved_p(objspace, (VALUE)value)) { - return ST_REPLACE; - } - return ST_CONTINUE; -} - -static void -gc_update_table_refs(rb_objspace_t * objspace, st_table *ht) -{ - if (st_foreach_with_replace(ht, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } -} - -/* Update MOVED references in an st_table */ -void -rb_gc_update_tbl_refs(st_table *ptr) -{ - rb_objspace_t *objspace = &rb_objspace; - gc_update_table_refs(objspace, ptr); -} - -static void -gc_ref_update_hash(rb_objspace_t * objspace, VALUE v) -{ - rb_hash_stlike_foreach_with_replace(v, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace); -} - -void rb_update_st_references(struct st_table *ht) -{ - rb_objspace_t *objspace = &rb_objspace; - gc_update_table_refs(objspace, ht); -} - -static void -gc_ref_update_method_entry(rb_objspace_t *objspace, rb_method_entry_t *me) -{ - rb_method_definition_t *def = me->def; - - UPDATE_IF_MOVED(objspace, me->owner); - UPDATE_IF_MOVED(objspace, me->defined_class); - - if (def) { - switch (def->type) { - case VM_METHOD_TYPE_ISEQ: - if (def->body.iseq.iseqptr) { - TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, def->body.iseq.iseqptr); - } - TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, def->body.iseq.cref); - break; - case VM_METHOD_TYPE_ATTRSET: - case VM_METHOD_TYPE_IVAR: - UPDATE_IF_MOVED(objspace, def->body.attr.location); - break; - case VM_METHOD_TYPE_BMETHOD: - UPDATE_IF_MOVED(objspace, def->body.bmethod.proc); - break; - case VM_METHOD_TYPE_ALIAS: - TYPED_UPDATE_IF_MOVED(objspace, struct rb_method_entry_struct *, def->body.alias.original_me); - return; - case VM_METHOD_TYPE_REFINED: - TYPED_UPDATE_IF_MOVED(objspace, struct rb_method_entry_struct *, def->body.refined.orig_me); - UPDATE_IF_MOVED(objspace, def->body.refined.owner); - break; - case VM_METHOD_TYPE_CFUNC: - case VM_METHOD_TYPE_ZSUPER: - case VM_METHOD_TYPE_MISSING: - case VM_METHOD_TYPE_OPTIMIZED: - case VM_METHOD_TYPE_UNDEF: - case VM_METHOD_TYPE_NOTIMPLEMENTED: - break; - } - } -} - -static void -gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) -{ - switch(imemo_type(obj)) { - case imemo_env: - { - rb_env_t *env = (rb_env_t *)obj; - TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, env->iseq); - } - break; - break; - case imemo_cref: - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.klass); - TYPED_UPDATE_IF_MOVED(objspace, struct rb_cref_struct *, RANY(obj)->as.imemo.cref.next); - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.cref.refinements); - break; - case imemo_svar: - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.cref_or_me); - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.lastline); - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.backref); - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.svar.others); - break; - case imemo_throw_data: - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.throw_data.throw_obj); - break; - case imemo_ifunc: - if (is_pointer_to_heap(objspace, RANY(obj)->as.imemo.ifunc.data)) { - TYPED_UPDATE_IF_MOVED(objspace, void *, RANY(obj)->as.imemo.ifunc.data); - } - break; - case imemo_memo: - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.memo.v1); - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.memo.v2); - if (is_pointer_to_heap(objspace, (void *)RANY(obj)->as.imemo.memo.u3.value)) { - UPDATE_IF_MOVED(objspace, RANY(obj)->as.imemo.memo.u3.value); - } - break; - case imemo_ment: - gc_ref_update_method_entry(objspace, &RANY(obj)->as.imemo.ment); - break; - case imemo_iseq: - rb_iseq_update_references((rb_iseq_t *)obj); - break; - case imemo_ast: - case imemo_parser_strterm: - case imemo_tmpbuf: - break; - default: - rb_bug("not reachable %d", imemo_type(obj)); - break; - } -} - -static enum rb_id_table_iterator_result -check_id_table_move(ID id, 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 -rb_gc_new_location(VALUE value) -{ - - VALUE destination; - - if (!SPECIAL_CONST_P((void *)value)) { - void *poisoned = poisoned_object_p(value); - unpoison_object(value, false); - - if (BUILTIN_TYPE(value) == T_MOVED) { - destination = (VALUE)RMOVED(value)->destination; - assert(BUILTIN_TYPE(destination) != T_NONE); - } - else { - destination = value; - } - - /* Re-poison slot if it's not the one we want */ - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(value) == T_NONE); - poison_object(value); - } - } - else { - destination = value; - } - - return destination; -} - -static enum rb_id_table_iterator_result -update_id_table(ID *key, 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_new_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_with_replace(tbl, check_id_table_move, update_id_table, objspace); - } -} - -static enum rb_id_table_iterator_result -update_const_table(VALUE value, void *data) -{ - rb_const_entry_t *ce = (rb_const_entry_t *)value; - rb_objspace_t * objspace = (rb_objspace_t *)data; - - if (gc_object_moved_p(objspace, ce->value)) { - ce->value = rb_gc_new_location(ce->value); - } - - if (gc_object_moved_p(objspace, ce->file)) { - ce->file = rb_gc_new_location(ce->file); - } - - return ID_TABLE_CONTINUE; -} - -static void -update_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) -{ - if (!tbl) return; - rb_id_table_foreach_values(tbl, update_const_table, objspace); -} - -static void -update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry) -{ - while (entry) { - UPDATE_IF_MOVED(objspace, entry->klass); - entry = entry->next; - } -} - -static void -update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext) -{ - UPDATE_IF_MOVED(objspace, ext->origin_); - UPDATE_IF_MOVED(objspace, ext->refined_class); - update_subclass_entries(objspace, ext->subclasses); -} - -static void -gc_update_object_references(rb_objspace_t *objspace, VALUE obj) -{ - RVALUE *any = RANY(obj); - - gc_report(4, objspace, "update-refs: %s ->", obj_info(obj)); - - switch(BUILTIN_TYPE(obj)) { - case T_CLASS: - case T_MODULE: - update_m_tbl(objspace, RCLASS_M_TBL(obj)); - if (!RCLASS_EXT(obj)) break; - if (RCLASS_IV_TBL(obj)) { - gc_update_table_refs(objspace, RCLASS_IV_TBL(obj)); - } - update_class_ext(objspace, RCLASS_EXT(obj)); - update_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - UPDATE_IF_MOVED(objspace, RCLASS(obj)->super); - break; - - case T_ICLASS: - if (FL_TEST(obj, RICLASS_IS_ORIGIN)) { - update_m_tbl(objspace, RCLASS_M_TBL(obj)); - } - if (!RCLASS_EXT(obj)) break; - if (RCLASS_IV_TBL(obj)) { - gc_update_table_refs(objspace, RCLASS_IV_TBL(obj)); - } - update_class_ext(objspace, RCLASS_EXT(obj)); - update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj)); - UPDATE_IF_MOVED(objspace, RCLASS(obj)->super); - break; - - case T_IMEMO: - gc_ref_update_imemo(objspace, obj); - break; - - case T_NIL: - case T_FIXNUM: - case T_NODE: - case T_MOVED: - case T_NONE: - /* These can't move */ - return; - - case T_ARRAY: - if (FL_TEST(obj, ELTS_SHARED)) { - UPDATE_IF_MOVED(objspace, any->as.array.as.heap.aux.shared); - } - else { - gc_ref_update_array(objspace, obj); - } - break; - - case T_HASH: - gc_ref_update_hash(objspace, obj); - UPDATE_IF_MOVED(objspace, any->as.hash.ifnone); - break; - - case T_STRING: - if (STR_SHARED_P(obj)) { - UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared); - } - break; - - case T_DATA: - /* Call the compaction callback, if it exists */ - { - void *const ptr = DATA_PTR(obj); - if (ptr) { - if (RTYPEDDATA_P(obj)) { - RUBY_DATA_FUNC compact_func = any->as.typeddata.type->function.dcompact; - if (compact_func) (*compact_func)(ptr); - } - } - } - break; - - case T_OBJECT: - gc_ref_update_object(objspace, obj); - break; - - case T_FILE: - if (any->as.file.fptr) { - UPDATE_IF_MOVED(objspace, any->as.file.fptr->pathv); - UPDATE_IF_MOVED(objspace, any->as.file.fptr->tied_io_for_writing); - UPDATE_IF_MOVED(objspace, any->as.file.fptr->writeconv_asciicompat); - UPDATE_IF_MOVED(objspace, any->as.file.fptr->writeconv_pre_ecopts); - UPDATE_IF_MOVED(objspace, any->as.file.fptr->encs.ecopts); - UPDATE_IF_MOVED(objspace, any->as.file.fptr->write_lock); - } - break; - case T_REGEXP: - UPDATE_IF_MOVED(objspace, any->as.regexp.src); - break; - - case T_SYMBOL: - if (DYNAMIC_SYM_P((VALUE)any)) { - UPDATE_IF_MOVED(objspace, RSYMBOL(any)->fstr); - } - break; - - case T_FLOAT: - case T_BIGNUM: - break; - - case T_MATCH: - UPDATE_IF_MOVED(objspace, any->as.match.regexp); - - if (any->as.match.str) { - UPDATE_IF_MOVED(objspace, any->as.match.str); - } - break; - - case T_RATIONAL: - UPDATE_IF_MOVED(objspace, any->as.rational.num); - UPDATE_IF_MOVED(objspace, any->as.rational.den); - break; - - case T_COMPLEX: - UPDATE_IF_MOVED(objspace, any->as.complex.real); - UPDATE_IF_MOVED(objspace, any->as.complex.imag); - - break; - - case T_STRUCT: - { - long i, len = RSTRUCT_LEN(obj); - VALUE *ptr = (VALUE *)RSTRUCT_CONST_PTR(obj); - - for (i = 0; i < len; i++) { - UPDATE_IF_MOVED(objspace, ptr[i]); - } - } - break; - default: -#if GC_DEBUG - rb_gcdebug_print_obj_condition((VALUE)obj); - rb_obj_info_dump(obj); - rb_bug("unreachable"); -#endif - break; - - } - - UPDATE_IF_MOVED(objspace, RBASIC(obj)->klass); - - gc_report(4, objspace, "update-refs: %s <-", obj_info(obj)); -} -static int -gc_ref_update(void *vstart, void *vend, size_t stride, void * data) -{ - rb_objspace_t * objspace; - struct heap_page *page; - short free_slots = 0; - - VALUE v = (VALUE)vstart; - objspace = (rb_objspace_t *)data; - page = GET_HEAP_PAGE(v); - unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); - page->freelist = NULL; - poison_memory_region(&page->freelist, sizeof(RVALUE*)); - page->flags.has_uncollectible_shady_objects = FALSE; - - /* For each object on the page */ - for (; v != (VALUE)vend; v += stride) { - if (!SPECIAL_CONST_P(v)) { - unpoison_object(v, false); - - if (BUILTIN_TYPE(v) == T_NONE) { - heap_page_add_freeobj(objspace, page, v); - free_slots++; - } - else { - if (RVALUE_WB_UNPROTECTED(v)) { - page->flags.has_uncollectible_shady_objects = TRUE; - } - gc_update_object_references(objspace, v); - } - } - } - - page->free_slots = free_slots; - return 0; -} - -extern rb_symbols_t global_symbols; - -static void -gc_update_references(rb_objspace_t * objspace) -{ - rb_execution_context_t *ec = GET_EC(); - rb_vm_t *vm = rb_ec_vm_ptr(ec); - - rb_objspace_each_objects_without_setup(gc_ref_update, objspace); - rb_vm_update_references(vm); - rb_transient_heap_update_references(); - gc_update_table_refs(objspace, global_symbols.str_sym); -} - -static VALUE type_sym(size_t type); - -static VALUE -rb_gc_compact_stats(VALUE mod) -{ - size_t i; - - rb_objspace_t *objspace = &rb_objspace; - VALUE h = rb_hash_new(); - VALUE considered = rb_hash_new(); - VALUE moved = rb_hash_new(); - - for (i=0; i<T_MASK; i++) { - rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i])); - } - - for (i=0; i<T_MASK; i++) { - rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i])); - } - - rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered); - rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved); - - return h; -} - -static VALUE -rb_gc_compact(VALUE mod) -{ - rb_objspace_t *objspace = &rb_objspace; - - /* Ensure objects are pinned */ - rb_gc(); - - /* Drain interrupts so that THEAP has a chance to evacuate before - * any possible compaction. */ - rb_thread_execute_interrupts(rb_thread_current()); - - gc_compact_heap(objspace); - - heap_eden->freelist = NULL; - gc_update_references(objspace); - - rb_clear_method_cache_by_class(rb_cObject); - rb_clear_constant_cache(); - heap_eden->free_pages = NULL; - heap_eden->using_page = NULL; - - /* GC after compaction to eliminate T_MOVED */ - rb_gc(); - - return rb_gc_compact_stats(mod); -} - -static void -root_obj_check_moved_i(const char *category, VALUE obj, void *data) -{ - if (gc_object_moved_p(&rb_objspace, obj)) { - rb_bug("ROOT %s points to MOVED: %p -> %s\n", category, (void *)obj, obj_info(rb_gc_new_location(obj))); - } -} - -static void -reachable_object_check_moved_i(VALUE ref, void *data) -{ - VALUE parent = (VALUE)data; - if (gc_object_moved_p(&rb_objspace, ref)) { - rb_bug("Object %s points to MOVED: %p -> %s\n", obj_info(parent), (void *)ref, obj_info(rb_gc_new_location(ref))); - } -} - -static int -heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data) -{ - VALUE v = (VALUE)vstart; - for (; v != (VALUE)vend; v += stride) { - if (gc_object_moved_p(&rb_objspace, v)) { - /* Moved object still on the heap, something may have a reference. */ - } - else { - void *poisoned = poisoned_object_p(v); - unpoison_object(v, false); - - if (BUILTIN_TYPE(v) != T_NONE) { - rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v); - } - - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); - poison_object(v); - } - } - } - - return 0; -} - -static VALUE -gc_check_references_for_moved(VALUE dummy) -{ - rb_objspace_reachable_objects_from_root(root_obj_check_moved_i, NULL); - rb_objspace_each_objects(heap_check_moved_i, NULL); - return Qnil; -} - -/* - * call-seq: - * GC.verify_compaction_references -> nil - * - * Verify compaction reference consistency. - * - * This method is implementation specific. During compaction, objects that - * were moved are replaced with T_MOVED objects. No object should have a - * reference to a T_MOVED object after compaction. - * - * This function doubles the heap to ensure room to move all objects, - * compacts the heap to make sure everything moves, updates all references, - * then performs a full GC. If any object contains a reference to a T_MOVED - * object, that object should be pushed on the mark stack, and will - * make a SEGV. - */ -static VALUE -gc_verify_compaction_references(VALUE dummy) -{ - VALUE stats; - rb_objspace_t *objspace = &rb_objspace; - - /* Double heap size */ - heap_add_pages(objspace, heap_eden, heap_allocated_pages); - - stats = rb_gc_compact(dummy); - - gc_check_references_for_moved(dummy); - gc_verify_internal_consistency(dummy); - - return stats; -} - VALUE rb_gc_start(void) { @@ -8150,8 +6998,8 @@ gc_count_add_each_types(VALUE hash, const char *name, const size_t *types) VALUE result = rb_hash_new_with_size(T_MASK); int i; for (i=0; i<T_MASK; i++) { - const char *type = type_name(i, 0); - rb_hash_aset(result, ID2SYM(rb_intern(type)), SIZET2NUM(types[i])); + const char *type = type_name(i, 0); + rb_hash_aset(result, ID2SYM(rb_intern(type)), SIZET2NUM(types[i])); } rb_hash_aset(hash, ID2SYM(rb_intern(name)), result); } @@ -8194,47 +7042,47 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ VALUE flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info; if (SYMBOL_P(hash_or_key)) { - key = hash_or_key; + key = hash_or_key; } else if (RB_TYPE_P(hash_or_key, T_HASH)) { - hash = hash_or_key; + hash = hash_or_key; } else { - rb_raise(rb_eTypeError, "non-hash or symbol given"); + rb_raise(rb_eTypeError, "non-hash or symbol given"); } if (sym_major_by == Qnil) { #define S(s) sym_##s = ID2SYM(rb_intern_const(#s)) - S(major_by); - S(gc_by); - S(immediate_sweep); - S(have_finalizer); - S(state); - - S(stress); - S(nofree); - S(oldgen); - S(shady); - S(force); + S(major_by); + S(gc_by); + S(immediate_sweep); + S(have_finalizer); + S(state); + + S(stress); + S(nofree); + S(oldgen); + S(shady); + S(force); #if RGENGC_ESTIMATE_OLDMALLOC - S(oldmalloc); + S(oldmalloc); #endif - S(newobj); - S(malloc); - S(method); - S(capi); + S(newobj); + S(malloc); + S(method); + S(capi); - S(none); - S(marking); - S(sweeping); + S(none); + S(marking); + S(sweeping); #undef S } #define SET(name, attr) \ if (key == sym_##name) \ - return (attr); \ + return (attr); \ else if (hash != Qnil) \ - rb_hash_aset(hash, sym_##name, (attr)); + rb_hash_aset(hash, sym_##name, (attr)); major_by = (flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree : @@ -8248,25 +7096,25 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const int orig_ SET(major_by, major_by); SET(gc_by, - (flags & GPR_FLAG_NEWOBJ) ? sym_newobj : - (flags & GPR_FLAG_MALLOC) ? sym_malloc : - (flags & GPR_FLAG_METHOD) ? sym_method : - (flags & GPR_FLAG_CAPI) ? sym_capi : - (flags & GPR_FLAG_STRESS) ? sym_stress : - Qnil - ); + (flags & GPR_FLAG_NEWOBJ) ? sym_newobj : + (flags & GPR_FLAG_MALLOC) ? sym_malloc : + (flags & GPR_FLAG_METHOD) ? sym_method : + (flags & GPR_FLAG_CAPI) ? sym_capi : + (flags & GPR_FLAG_STRESS) ? sym_stress : + Qnil + ); SET(have_finalizer, (flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse); SET(immediate_sweep, (flags & GPR_FLAG_IMMEDIATE_SWEEP) ? Qtrue : Qfalse); if (orig_flags == 0) { - SET(state, gc_mode(objspace) == gc_mode_none ? sym_none : - gc_mode(objspace) == gc_mode_marking ? sym_marking : sym_sweeping); + SET(state, gc_mode(objspace) == gc_mode_none ? sym_none : + gc_mode(objspace) == gc_mode_marking ? sym_marking : sym_sweeping); } #undef SET if (!NIL_P(key)) {/* matched key should return above */ - rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key)); + rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key)); } return hash; @@ -8296,12 +7144,12 @@ gc_latest_gc_info(int argc, VALUE *argv, VALUE self) if (rb_check_arity(argc, 0, 1) == 1) { arg = argv[0]; - if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) { - rb_raise(rb_eTypeError, "non-hash or symbol given"); - } + if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) { + rb_raise(rb_eTypeError, "non-hash or symbol given"); + } } else { - arg = rb_hash_new(); + arg = rb_hash_new(); } return gc_info_decode(objspace, arg, 0); @@ -8328,7 +7176,6 @@ enum gc_stat_sym { #if USE_RGENGC gc_stat_sym_minor_gc_count, gc_stat_sym_major_gc_count, - gc_stat_sym_object_id_collisions, gc_stat_sym_remembered_wb_unprotected_objects, gc_stat_sym_remembered_wb_unprotected_objects_limit, gc_stat_sym_old_objects, @@ -8404,7 +7251,6 @@ setup_gc_stat_symbols(void) S(malloc_increase_bytes_limit); #if USE_RGENGC S(minor_gc_count); - S(object_id_collisions); S(major_gc_count); S(remembered_wb_unprotected_objects); S(remembered_wb_unprotected_objects_limit); @@ -8577,7 +7423,6 @@ gc_stat_internal(VALUE hash_or_sym) SET(malloc_increase_bytes_limit, malloc_limit); #if USE_RGENGC SET(minor_gc_count, objspace->profile.minor_gc_count); - SET(object_id_collisions, objspace->profile.object_id_collisions); SET(major_gc_count, objspace->profile.major_gc_count); SET(remembered_wb_unprotected_objects, objspace->rgengc.uncollectible_wb_unprotected_objects); SET(remembered_wb_unprotected_objects_limit, objspace->rgengc.uncollectible_wb_unprotected_objects_limit); @@ -9783,25 +8628,10 @@ wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg) } #endif -static int -wmap_pin_obj(st_data_t key, st_data_t val, st_data_t arg) -{ - rb_objspace_t *objspace = (rb_objspace_t *)arg; - VALUE obj = (VALUE)val; - if (obj && is_live_object(objspace, obj)) { - gc_pin(objspace, obj); - } - else { - return ST_DELETE; - } - return ST_CONTINUE; -} - static void wmap_mark(void *ptr) { struct weakmap *w = ptr; - if (w->wmap2obj) st_foreach(w->wmap2obj, wmap_pin_obj, (st_data_t)&rb_objspace); #if WMAP_DELETE_DEAD_OBJECT_IN_MARK if (w->obj2wmap) st_foreach(w->obj2wmap, wmap_mark_map, (st_data_t)&rb_objspace); #endif @@ -10801,7 +9631,6 @@ type_name(int type, VALUE obj) TYPE_NAME(T_UNDEF); TYPE_NAME(T_IMEMO); TYPE_NAME(T_ICLASS); - TYPE_NAME(T_MOVED); TYPE_NAME(T_ZOMBIE); case T_DATA: if (obj && rb_objspace_data_type_name(obj)) { @@ -10850,7 +9679,7 @@ method_type_name(rb_method_type_t type) static void rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq) { - if (iseq->body && iseq->body->location.label && !RB_TYPE_P(iseq->body->location.pathobj, T_MOVED)) { + if (iseq->body && iseq->body->location.label) { VALUE path = rb_iseq_path(iseq); VALUE n = iseq->body->location.first_lineno; snprintf(buff, buff_size, "%s %s@%s:%d", buff, @@ -10881,11 +9710,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags); if (is_pointer_to_heap(&rb_objspace, (void *)obj)) { - snprintf(buff, buff_size, "%p [%d%s%s%s%s%s] %s", + snprintf(buff, buff_size, "%p [%d%s%s%s%s] %s", (void *)obj, age, C(RVALUE_UNCOLLECTIBLE_BITMAP(obj), "L"), C(RVALUE_MARK_BITMAP(obj), "M"), - C(RVALUE_PIN_BITMAP(obj), "P"), C(RVALUE_MARKING_BITMAP(obj), "R"), C(RVALUE_WB_UNPROTECTED_BITMAP(obj), "U"), obj_type_name(obj)); @@ -10910,12 +9738,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) snprintf(buff, buff_size, "%s (temporary internal)", buff); } else { - if (RTEST(RBASIC(obj)->klass)) { VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass); if (!NIL_P(class_path)) { snprintf(buff, buff_size, "%s (%s)", buff, RSTRING_PTR(class_path)); } - } } #if GC_DEBUG @@ -10951,10 +9777,6 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) snprintf(buff, buff_size, "%s %s", buff, RSTRING_PTR(obj)); break; } - case T_MOVED: { - snprintf(buff, buff_size, "-> %p", (void*)rb_gc_new_location(obj)); - break; - } case T_HASH: { snprintf(buff, buff_size, "%s [%c%c] %d", buff, RHASH_AR_TABLE_P(obj) ? 'A' : 'S', @@ -11116,12 +9938,6 @@ rb_gcdebug_print_obj_condition(VALUE obj) fprintf(stderr, "created at: %s:%d\n", RANY(obj)->file, RANY(obj)->line); - if (BUILTIN_TYPE(obj) == T_MOVED) { - fprintf(stderr, "moved?: true\n"); - } - else { - fprintf(stderr, "moved?: false\n"); - } if (is_pointer_to_heap(objspace, (void *)obj)) { fprintf(stderr, "pointer to heap?: true\n"); } @@ -11131,7 +9947,6 @@ rb_gcdebug_print_obj_condition(VALUE obj) } fprintf(stderr, "marked? : %s\n", MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) ? "true" : "false"); - fprintf(stderr, "pinned? : %s\n", MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj) ? "true" : "false"); #if USE_RGENGC fprintf(stderr, "age? : %d\n", RVALUE_AGE(obj)); fprintf(stderr, "old? : %s\n", RVALUE_OLD_P(obj) ? "true" : "false"); @@ -11281,9 +10096,6 @@ Init_GC(void) VALUE rb_mProfiler; VALUE gc_constants; - id_to_obj_tbl = st_init_numtable(); - obj_to_id_tbl = rb_init_identtable(); - rb_mGC = rb_define_module("GC"); rb_define_singleton_method(rb_mGC, "start", gc_start_internal, -1); rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0); @@ -11293,7 +10105,6 @@ Init_GC(void) rb_define_singleton_method(rb_mGC, "count", gc_count, 0); rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); rb_define_singleton_method(rb_mGC, "latest_gc_info", gc_latest_gc_info, -1); - rb_define_singleton_method(rb_mGC, "compact", rb_gc_compact, 0); rb_define_method(rb_mGC, "garbage_collect", gc_start_internal, -1); gc_constants = rb_hash_new(); @@ -11354,7 +10165,6 @@ Init_GC(void) /* internal methods */ rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency, 0); - rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, 0); rb_define_singleton_method(rb_mGC, "verify_transient_heap_internal_consistency", gc_verify_transient_heap_internal_consistency, 0); #if MALLOC_ALLOCATED_SIZE rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0); @@ -57,10 +57,6 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) #define RUBY_GC_INFO if(0)printf #endif -#define RUBY_MARK_NO_PIN_UNLESS_NULL(ptr) do { \ - VALUE markobj = (ptr); \ - if (RTEST(markobj)) {rb_gc_mark_no_pin(markobj);} \ -} while (0) #define RUBY_MARK_UNLESS_NULL(ptr) do { \ VALUE markobj = (ptr); \ if (RTEST(markobj)) {rb_gc_mark(markobj);} \ @@ -781,7 +781,7 @@ ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash } static int -ar_general_foreach(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg) +ar_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) { if (RHASH_AR_TABLE_SIZE(hash) > 0) { unsigned i, bound = RHASH_AR_TABLE_BOUND(hash); @@ -799,20 +799,6 @@ ar_general_foreach(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *re case ST_CHECK: case ST_STOP: return 0; - case ST_REPLACE: - if (replace) { - VALUE key; - VALUE value; - - key = cur_entry->key; - value = cur_entry->record; - retval = (*replace)(&key, &value, arg, TRUE); - - ar_table_entry *entry = RHASH_AR_TABLE_REF(hash, i); - entry->key = key; - entry->record = value; - } - break; case ST_DELETE: ar_clear_entry(RHASH_AR_TABLE_REF(hash, i)); RHASH_AR_TABLE_SIZE_DEC(hash); @@ -824,18 +810,6 @@ ar_general_foreach(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *re } static int -ar_foreach_with_replace(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg) -{ - return ar_general_foreach(hash, func, replace, arg); -} - -static int -ar_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) -{ - return ar_general_foreach(hash, func, NULL, arg); -} - -static int ar_foreach_check(VALUE hash, int (*func)(ANYARGS), st_data_t arg, st_data_t never) { @@ -871,7 +845,6 @@ ar_foreach_check(VALUE hash, int (*func)(ANYARGS), st_data_t arg, case ST_CONTINUE: break; case ST_STOP: - case ST_REPLACE: return 0; case ST_DELETE: { if (!ar_empty_entry(cur_entry)) { @@ -1284,17 +1257,6 @@ rb_hash_stlike_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) } } -int -rb_hash_stlike_foreach_with_replace(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg) -{ - if (RHASH_AR_TABLE_P(hash)) { - return ar_foreach_with_replace(hash, func, replace, arg); - } - else { - return st_foreach_with_replace(RHASH_ST_TABLE(hash), func, replace, arg); - } -} - static VALUE hash_foreach_call(VALUE arg) { diff --git a/id_table.c b/id_table.c index f566582479..74c9e756a0 100644 --- a/id_table.c +++ b/id_table.c @@ -267,28 +267,6 @@ rb_id_table_delete(struct rb_id_table *tbl, ID id) } void -rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, rb_id_table_update_callback_func_t *replace, void *data) -{ - int i, capa = tbl->capa; - - for (i=0; i<capa; i++) { - if (ITEM_KEY_ISSET(tbl, i)) { - const id_key_t key = ITEM_GET_KEY(tbl, i); - enum rb_id_table_iterator_result ret = (*func)(Qundef, tbl->items[i].val, data); - assert(key != 0); - - if (ret == ID_TABLE_REPLACE) { - VALUE val = tbl->items[i].val; - ret = (*replace)(NULL, &val, data, TRUE); - tbl->items[i].val = val; - } - else if (ret == ID_TABLE_STOP) - return; - } - } -} - -void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data) { int i, capa = tbl->capa; diff --git a/id_table.h b/id_table.h index abd9eb5f38..b10b4ac164 100644 --- a/id_table.h +++ b/id_table.h @@ -9,7 +9,6 @@ enum rb_id_table_iterator_result { ID_TABLE_CONTINUE = ST_CONTINUE, ID_TABLE_STOP = ST_STOP, ID_TABLE_DELETE = ST_DELETE, - ID_TABLE_REPLACE = ST_REPLACE, ID_TABLE_ITERATOR_RESULT_END }; @@ -24,11 +23,9 @@ int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val); int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp); int rb_id_table_delete(struct rb_id_table *tbl, ID id); -typedef enum rb_id_table_iterator_result rb_id_table_update_callback_func_t(ID *id, VALUE *val, void *data, int existing); typedef enum rb_id_table_iterator_result rb_id_table_foreach_func_t(ID id, VALUE val, void *data); typedef enum rb_id_table_iterator_result rb_id_table_foreach_values_func_t(VALUE val, void *data); void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data); -void rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, rb_id_table_update_callback_func_t *replace, void *data); void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data); #endif /* RUBY_ID_TABLE_H */ diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 192347c8d5..17aafd7f8e 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -507,15 +507,10 @@ COLDFUNC NORETURN(void rb_memerror(void)); PUREFUNC(int rb_during_gc(void)); void rb_gc_mark_locations(const VALUE*, const VALUE*); void rb_mark_tbl(struct st_table*); -void rb_mark_tbl_no_pin(struct st_table*); -void rb_gc_update_tbl_refs(st_table *ptr); void rb_mark_set(struct st_table*); void rb_mark_hash(struct st_table*); -void rb_update_st_references(struct st_table *ht); void rb_gc_mark_maybe(VALUE); void rb_gc_mark(VALUE); -void rb_gc_mark_no_pin(VALUE); -VALUE rb_gc_new_location(VALUE); void rb_gc_force_recycle(VALUE); void rb_gc(void); void rb_gc_copy_finalizer(VALUE,VALUE); diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index b5757a79ad..11387b540a 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -512,7 +512,6 @@ enum ruby_value_type { RUBY_T_NODE = 0x1b, RUBY_T_ICLASS = 0x1c, RUBY_T_ZOMBIE = 0x1d, - RUBY_T_MOVED = 0x1e, RUBY_T_MASK = 0x1f }; @@ -543,7 +542,6 @@ enum ruby_value_type { #define T_UNDEF RUBY_T_UNDEF #define T_NODE RUBY_T_NODE #define T_ZOMBIE RUBY_T_ZOMBIE -#define T_MOVED RUBY_T_MOVED #define T_MASK RUBY_T_MASK #define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK) @@ -885,7 +883,7 @@ enum ruby_fl_type { struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { VALUE flags; - VALUE klass; + const VALUE klass; }; VALUE rb_obj_hide(VALUE obj); @@ -1107,7 +1105,7 @@ struct RArray { struct RRegexp { struct RBasic basic; struct re_pattern_buffer *ptr; - VALUE src; + const VALUE src; unsigned long usecnt; }; #define RREGEXP_PTR(r) (RREGEXP(r)->ptr) @@ -1146,8 +1144,7 @@ struct rb_data_type_struct { void (*dmark)(void*); void (*dfree)(void*); size_t (*dsize)(const void *); - void (*dcompact)(void*); - void *reserved[1]; /* For future extension. + void *reserved[2]; /* For future extension. This array *must* be filled with ZERO. */ } function; const rb_data_type_t *parent; @@ -1258,7 +1255,6 @@ int rb_big_sign(VALUE); #define RBIGNUM_NEGATIVE_P(b) (RBIGNUM_SIGN(b)==0) #define R_CAST(st) (struct st*) -#define RMOVED(obj) (R_CAST(RMoved)(obj)) #define RBASIC(obj) (R_CAST(RBasic)(obj)) #define ROBJECT(obj) (R_CAST(RObject)(obj)) #define RCLASS(obj) (R_CAST(RClass)(obj)) diff --git a/include/ruby/st.h b/include/ruby/st.h index a7eb0c6d7c..149e0ebaef 100644 --- a/include/ruby/st.h +++ b/include/ruby/st.h @@ -96,7 +96,7 @@ struct st_table { #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK, ST_REPLACE}; +enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; st_table *st_init_table(const struct st_hash_type *); st_table *st_init_table_with_size(const struct st_hash_type *, st_index_t); @@ -118,7 +118,6 @@ typedef int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t * results of hash() are same and compare() returns 0, otherwise the * behavior is undefined */ int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg); -int st_foreach_with_replace(st_table *tab, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg); int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); st_index_t st_keys(st_table *table, st_data_t *keys, st_index_t size); diff --git a/internal.h b/internal.h index 46a25ff77f..a9b4cfb4d5 100644 --- a/internal.h +++ b/internal.h @@ -731,8 +731,8 @@ struct RBignum { struct RRational { struct RBasic basic; - VALUE num; - VALUE den; + const VALUE num; + const VALUE den; }; #define RRATIONAL(obj) (R_CAST(RRational)(obj)) @@ -748,8 +748,8 @@ struct RFloat { struct RComplex { struct RBasic basic; - VALUE real; - VALUE imag; + const VALUE real; + const VALUE imag; }; #define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) @@ -816,8 +816,8 @@ struct RHash { st_table *st; struct ar_table_struct *ar; /* possibly 0 */ } as; - int iter_lev; - VALUE ifnone; + const int iter_lev; + const VALUE ifnone; }; #ifdef RHASH_ITER_LEV @@ -830,11 +830,6 @@ struct RHash { # define RHASH_SIZE(h) (RHASH_AR_TABLE_P(h) ? RHASH_AR_TABLE_SIZE_RAW(h) : RHASH_ST_SIZE(h)) #endif /* #ifdef RHASH_ITER_LEV */ -struct RMoved { - VALUE flags; - VALUE destination; -}; - /* missing/setproctitle.c */ #ifndef HAVE_SETPROCTITLE extern void ruby_init_setproctitle(int argc, char *argv[]); @@ -952,7 +947,7 @@ struct rb_classext_struct { */ rb_subclass_entry_t **module_subclasses; rb_serial_t class_serial; - VALUE origin_; + const VALUE origin_; VALUE refined_class; rb_alloc_func_t allocator; }; @@ -1070,10 +1065,10 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type) /*! SVAR (Special VARiable) */ struct vm_svar { VALUE flags; - VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ - VALUE lastline; - VALUE backref; - VALUE others; + const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ + const VALUE lastline; + const VALUE backref; + const VALUE others; }; @@ -1083,7 +1078,7 @@ struct vm_svar { struct vm_throw_data { VALUE flags; VALUE reserved; - VALUE throw_obj; + const VALUE throw_obj; const struct rb_control_frame_struct *catch_frame; VALUE throw_state; }; @@ -1106,7 +1101,7 @@ struct vm_ifunc { VALUE flags; VALUE reserved; VALUE (*func)(ANYARGS); - void *data; + const void *data; struct vm_ifunc_argc argc; }; @@ -1163,12 +1158,12 @@ void rb_strterm_mark(VALUE obj); struct MEMO { VALUE flags; VALUE reserved; - VALUE v1; - VALUE v2; + const VALUE v1; + const VALUE v2; union { long cnt; long state; - VALUE value; + const VALUE value; VALUE (*func)(ANYARGS); } u3; }; @@ -1571,7 +1566,6 @@ void rb_hash_bulk_insert(long, const VALUE *, VALUE); int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval); int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval); int rb_hash_stlike_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg); -int rb_hash_stlike_foreach_with_replace(VALUE hash, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg); int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg); /* inits.c */ @@ -2336,7 +2330,6 @@ extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, si /* variable.c (export) */ void rb_mark_generic_ivar(VALUE); -void rb_mv_generic_ivar(VALUE src, VALUE dst); VALUE rb_const_missing(VALUE klass, VALUE name); int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); st_table *rb_st_copy(VALUE obj, struct st_table *orig_tbl); @@ -2348,10 +2341,9 @@ VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE); size_t rb_obj_memsize_of(VALUE); void rb_gc_verify_internal_consistency(void); -#define RB_OBJ_GC_FLAGS_MAX 6 +#define RB_OBJ_GC_FLAGS_MAX 5 size_t rb_obj_gc_flags(VALUE, ID[], size_t); void rb_gc_mark_values(long n, const VALUE *values); -void rb_gc_mark_stack_values(long n, const VALUE *values); #if IMEMO_DEBUG VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line); @@ -10996,8 +10996,7 @@ nogvl_fcopyfile(struct copy_stream_struct *stp) return 1; } } - } - else { + } else { switch (errno) { case ENOTSUP: case EPERM: @@ -136,11 +136,11 @@ rb_vm_insn_null_translator(const void *addr) return (VALUE)addr; } -typedef VALUE iseq_value_itr_t(void *ctx, VALUE obj); +typedef void iseq_value_itr_t(void *ctx, VALUE obj); typedef VALUE rb_vm_insns_translator_t(const void *addr); static int -iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) +iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) { VALUE insn = translator((void *)code[pos]); int len = insn_len(insn); @@ -156,10 +156,7 @@ iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data { VALUE op = code[pos + op_no + 1]; if (!SPECIAL_CONST_P(op)) { - VALUE newop = func(data, op); - if (newop != op) { - code[pos + op_no + 1] = newop; - } + func(data, op); } break; } @@ -167,10 +164,7 @@ iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data { union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; if (is->once.value) { - VALUE nv = func(data, is->once.value); - if (is->once.value != nv) { - is->once.value = nv; - } + func(data, is->once.value); } break; } @@ -186,7 +180,7 @@ static void rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) { unsigned int size; - VALUE *code; + const VALUE *code; size_t n; rb_vm_insns_translator_t * translator; const struct rb_iseq_constant_body *const body = iseq->body; @@ -210,65 +204,10 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) } } -static VALUE -update_each_insn_value(void *ctx, VALUE obj) -{ - return rb_gc_new_location(obj); -} - -void -rb_iseq_update_references(rb_iseq_t *iseq) -{ - if (iseq->body) { - struct rb_iseq_constant_body *body = iseq->body; - - body->variable.coverage = rb_gc_new_location(body->variable.coverage); - body->variable.pc2branchindex = rb_gc_new_location(body->variable.pc2branchindex); - body->location.label = rb_gc_new_location(body->location.label); - body->location.base_label = rb_gc_new_location(body->location.base_label); - body->location.pathobj = rb_gc_new_location(body->location.pathobj); - if (body->local_iseq) { - body->local_iseq = (struct rb_iseq_struct *)rb_gc_new_location((VALUE)body->local_iseq); - } - if (body->parent_iseq) { - body->parent_iseq = (struct rb_iseq_struct *)rb_gc_new_location((VALUE)body->parent_iseq); - } - if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) { - rb_iseq_each_value(iseq, update_each_insn_value, NULL); - } - - if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) { - int i, j; - - i = body->param.keyword->required_num; - - for (j = 0; i < body->param.keyword->num; i++, j++) { - VALUE obj = body->param.keyword->default_values[j]; - if (obj != Qundef) { - body->param.keyword->default_values[j] = rb_gc_new_location(obj); - } - } - } - - if (body->catch_table) { - struct iseq_catch_table *table = body->catch_table; - unsigned int i; - for(i = 0; i < table->size; i++) { - struct iseq_catch_table_entry *entry; - entry = &table->entries[i]; - if (entry->iseq) { - entry->iseq = (rb_iseq_t *)rb_gc_new_location((VALUE)entry->iseq); - } - } - } - } -} - -static VALUE +static void each_insn_value(void *ctx, VALUE obj) { - rb_gc_mark_no_pin(obj); - return obj; + rb_gc_mark(obj); } void @@ -285,12 +224,12 @@ rb_iseq_mark(const rb_iseq_t *iseq) rb_iseq_each_value(iseq, each_insn_value, NULL); } - rb_gc_mark_no_pin(body->variable.coverage); - rb_gc_mark_no_pin(body->variable.pc2branchindex); - rb_gc_mark_no_pin(body->location.label); - rb_gc_mark_no_pin(body->location.base_label); - rb_gc_mark_no_pin(body->location.pathobj); - RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)body->parent_iseq); + rb_gc_mark(body->variable.coverage); + rb_gc_mark(body->variable.pc2branchindex); + rb_gc_mark(body->location.label); + rb_gc_mark(body->location.base_label); + rb_gc_mark(body->location.pathobj); + RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) { const struct rb_iseq_param_keyword *const keyword = body->param.keyword; @@ -313,7 +252,7 @@ rb_iseq_mark(const rb_iseq_t *iseq) const struct iseq_catch_table_entry *entry; entry = &table->entries[i]; if (entry->iseq) { - rb_gc_mark_no_pin((VALUE)entry->iseq); + rb_gc_mark((VALUE)entry->iseq); } } } @@ -324,16 +263,11 @@ rb_iseq_mark(const rb_iseq_t *iseq) } else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) { const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq); - if (RTEST(compile_data->mark_ary)) { - rb_gc_mark(compile_data->mark_ary); - rb_gc_mark_values(RARRAY_LEN(compile_data->mark_ary), RARRAY_CONST_PTR(compile_data->mark_ary)); - } - RUBY_MARK_UNLESS_NULL(compile_data->err_info); - if (RTEST(compile_data->catch_table_ary)) { - rb_gc_mark(compile_data->catch_table_ary); - rb_gc_mark_values(RARRAY_LEN(compile_data->catch_table_ary), RARRAY_CONST_PTR(compile_data->catch_table_ary)); - } VM_ASSERT(compile_data != NULL); + + RUBY_MARK_UNLESS_NULL(compile_data->mark_ary); + RUBY_MARK_UNLESS_NULL(compile_data->err_info); + RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary); } else { /* executable */ @@ -234,7 +234,7 @@ struct iseq_catch_table_entry { * CATCH_TYPE_REDO, CATCH_TYPE_NEXT: * NULL. */ - rb_iseq_t *iseq; + const rb_iseq_t *iseq; unsigned int start; unsigned int end; diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 1c7e89ba14..fa9b19071a 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -1530,7 +1530,6 @@ module Net end @sock = SSLSocket.new(@sock, context) @sock.sync_close = true - @sock.hostname = @host if @sock.respond_to? :hostname= ssl_socket_connect(@sock, @open_timeout) if context.verify_mode != VERIFY_NONE @sock.post_connection_check(@host) @@ -40,9 +40,9 @@ typedef struct rb_scope_visi_struct { /*! CREF (Class REFerence) */ typedef struct rb_cref_struct { VALUE flags; - VALUE refinements; - VALUE klass; - struct rb_cref_struct * next; + const VALUE refinements; + const VALUE klass; + struct rb_cref_struct * const next; const rb_scope_visibility_t scope_visi; } rb_cref_t; @@ -50,10 +50,10 @@ typedef struct rb_cref_struct { typedef struct rb_method_entry_struct { VALUE flags; - VALUE defined_class; + const VALUE defined_class; struct rb_method_definition_struct * const def; ID called_id; - VALUE owner; + const VALUE owner; } rb_method_entry_t; typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_entry_t */ @@ -123,8 +123,8 @@ typedef struct rb_iseq_struct rb_iseq_t; #endif typedef struct rb_method_iseq_struct { - rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */ - rb_cref_t * cref; /*!< class reference, should be marked */ + const rb_iseq_t * const iseqptr; /*!< iseq pointer, should be separated from iseqval */ + rb_cref_t * const cref; /*!< class reference, should be marked */ } rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */ typedef struct rb_method_cfunc_struct { @@ -135,20 +135,20 @@ typedef struct rb_method_cfunc_struct { typedef struct rb_method_attr_struct { ID id; - VALUE location; /* should be marked */ + const VALUE location; /* should be marked */ } rb_method_attr_t; typedef struct rb_method_alias_struct { - struct rb_method_entry_struct * original_me; /* original_me->klass is original owner */ + const struct rb_method_entry_struct * const original_me; /* original_me->klass is original owner */ } rb_method_alias_t; typedef struct rb_method_refined_struct { - struct rb_method_entry_struct * orig_me; - VALUE owner; + const struct rb_method_entry_struct * const orig_me; + const VALUE owner; } rb_method_refined_t; typedef struct rb_method_bmethod_struct { - VALUE proc; /* should be marked */ + const VALUE proc; /* should be marked */ struct rb_hook_list_struct *hooks; } rb_method_bmethod_t; diff --git a/mjit_worker.c b/mjit_worker.c index 205082f7a9..a85e7e8eae 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -1180,8 +1180,7 @@ mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc if (UNLIKELY(mjit_opts.wait)) { mjit_copy_job_handler((void *)job); - } - else if (rb_workqueue_register(0, mjit_copy_job_handler, (void *)job)) { + } else if (rb_workqueue_register(0, mjit_copy_job_handler, (void *)job)) { CRITICAL_SECTION_START(3, "in MJIT copy job wait"); // checking `stop_worker_p` too because `RUBY_VM_CHECK_INTS(ec)` may not // lush mjit_copy_job_handler when EC_EXEC_TAG() is not TAG_NONE, and then @@ -9307,7 +9307,7 @@ void rb_parser_fatal(struct parser_params *p, const char *fmt, ...) { va_list ap; - VALUE mesg = rb_str_new_cstr("internal parser error: "); + VALUE mesg = rb_str_new_cstr("internal p error: "); va_start(ap, fmt); rb_str_vcatf(mesg, fmt, ap); @@ -9317,13 +9317,13 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...) mesg = rb_str_new(0, 0); append_lex_state_name(p->lex.state, mesg); - compile_error(p, "lex.state: %"PRIsVALUE, mesg); + compile_error(p, "p->lex.state: %"PRIsVALUE, mesg); rb_str_resize(mesg, 0); append_bitstack_value(p->cond_stack, mesg); - compile_error(p, "cond_stack: %"PRIsVALUE, mesg); + compile_error(p, "p->cond_stack: %"PRIsVALUE, mesg); rb_str_resize(mesg, 0); append_bitstack_value(p->cmdarg_stack, mesg); - compile_error(p, "cmdarg_stack: %"PRIsVALUE, mesg); + compile_error(p, "p->cmdarg_stack: %"PRIsVALUE, mesg); if (p->debug_output == rb_stdout) p->debug_output = rb_stderr; p->debug = TRUE; @@ -1548,7 +1548,7 @@ st_update(st_table *tab, st_data_t key, different for ST_CHECK and when the current element is removed during traversing. */ static inline int -st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg, +st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg, int check_p) { st_index_t bin; @@ -1572,15 +1572,6 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_update_callback_func rebuilds_num = tab->rebuilds_num; hash = curr_entry_ptr->hash; retval = (*func)(key, curr_entry_ptr->record, arg, 0); - - if (retval == ST_REPLACE && replace) { - st_data_t value; - value = curr_entry_ptr->record; - retval = (*replace)(&key, &value, arg, TRUE); - curr_entry_ptr->key = key; - curr_entry_ptr->record = value; - } - if (rebuilds_num != tab->rebuilds_num) { retry: entries = tab->entries; @@ -1609,8 +1600,6 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_update_callback_func curr_entry_ptr = &entries[i]; } switch (retval) { - case ST_REPLACE: - break; case ST_CONTINUE: break; case ST_CHECK: @@ -1659,15 +1648,9 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_update_callback_func } int -st_foreach_with_replace(st_table *tab, int (*func)(ANYARGS), st_update_callback_func *replace, st_data_t arg) -{ - return st_general_foreach(tab, func, replace, arg, TRUE); -} - -int st_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg) { - return st_general_foreach(tab, func, NULL, arg, FALSE); + return st_general_foreach(tab, func, arg, FALSE); } /* See comments for function st_delete_safe. */ @@ -1675,7 +1658,7 @@ int st_foreach_check(st_table *tab, int (*func)(ANYARGS), st_data_t arg, st_data_t never ATTRIBUTE_UNUSED) { - return st_general_foreach(tab, func, NULL, arg, TRUE); + return st_general_foreach(tab, func, arg, TRUE); } /* Set up array KEYS by at most SIZE keys of head table TAB entries. @@ -60,7 +60,12 @@ enum id_entry_type { ID_ENTRY_SIZE }; -rb_symbols_t global_symbols = {tNEXT_ID-1}; +static struct symbols { + rb_id_serial_t last_id; + st_table *str_sym; + VALUE ids; + VALUE dsymbol_fstr_hash; +} global_symbols = {tNEXT_ID-1}; static const struct st_hash_type symhash = { rb_str_hash_cmp, @@ -54,13 +54,6 @@ id_type(ID id) typedef uint32_t rb_id_serial_t; -typedef struct { - rb_id_serial_t last_id; - st_table *str_sym; - VALUE ids; - VALUE dsymbol_fstr_hash; -} rb_symbols_t; - static inline rb_id_serial_t rb_id_to_serial(ID id) { diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb index 0b5cd84241..274afba3bb 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -272,11 +272,6 @@ class OpenSSL::TestBN < OpenSSL::TestCase assert_equal(0, @e1.ucmp(-999)) assert_instance_of(String, @e1.hash.to_s) end - - def test_type_error - bug15760 = '[ruby-core:92231] [Bug #15760]' - assert_raise(TypeError, bug15760) { OpenSSL::BN.new(nil, 2) } - end end end diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 52ab9fc54a..3e17344bbc 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false require 'test/unit' -require 'fiddle' class TestGc < Test::Unit::TestCase class S diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb deleted file mode 100644 index 0b2acacdc9..0000000000 --- a/test/ruby/test_gc_compact.rb +++ /dev/null @@ -1,103 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'fiddle' - -class TestGCCompact < Test::Unit::TestCase - if Fiddle::SIZEOF_LONG == Fiddle::SIZEOF_VOIDP - def memory_location(obj) - (Fiddle.dlwrap(obj) >> 1) - end - elsif Fiddle::SIZEOF_LONG_LONG == Fiddle::SIZEOF_VOIDP - def memory_location(obj) - (Fiddle.dlwrap(obj) >> 1) / 2 - end - else - raise "Not supported" - end - - def assert_object_ids(list) - same_count = list.find_all { |obj| - memory_location(obj) == obj.object_id - }.count - list.count - same_count - end - - def big_list - 1000.times.map { - # try to make some empty slots by allocating an object and discarding - Object.new - Object.new - } # likely next to each other - end - - # Find an object that's allocated in a slot that had a previous - # tenant, and that tenant moved and is still alive - def find_object_in_recycled_slot(addresses) - new_object = nil - - loop do - new_object = Object.new - if addresses.include? memory_location(new_object) - break - end - end - - new_object - end - - def test_find_collided_object - list_of_objects = big_list - - ids = list_of_objects.map(&:object_id) # store id in map - addresses = list_of_objects.map(&self.:memory_location) - - # All object ids should be equal - assert_equal 0, assert_object_ids(list_of_objects) # should be 0 - - GC.compact - - # Some should have moved - id_count = assert_object_ids(list_of_objects) - skip "couldn't get objects to move" if id_count == 0 - assert_operator id_count, :>, 0 - - new_ids = list_of_objects.map(&:object_id) - - # Object ids should not change after compaction - assert_equal ids, new_ids - - new_tenant = find_object_in_recycled_slot(addresses) - assert new_tenant - - # This is the object that used to be in new_object's position - previous_tenant = list_of_objects[addresses.index(memory_location(new_tenant))] - - assert_not_equal previous_tenant.object_id, new_tenant.object_id - - # Should be able to look up object by object_id - assert_equal new_tenant, ObjectSpace._id2ref(new_tenant.object_id) - - # Should be able to look up object by object_id - assert_equal previous_tenant, ObjectSpace._id2ref(previous_tenant.object_id) - - int = (new_tenant.object_id >> 1) - # These two should be the same! but they are not :( - assert_equal int, ObjectSpace._id2ref(int.object_id) - end - - def test_many_collisions - list_of_objects = big_list - ids = list_of_objects.map(&:object_id) - addresses = list_of_objects.map(&self.:memory_location) - - GC.compact - - new_tenants = 10.times.map { - find_object_in_recycled_slot(addresses) - } - - collisions = GC.stat(:object_id_collisions) - skip "couldn't get objects to collide" if collisions == 0 - assert_operator collisions, :>, 0 - end -end @@ -1,9 +1,6 @@ #ifndef RUBY_TIMEV_H #define RUBY_TIMEV_H -#if 0 -struct vtm {/* dummy for TAGS */}; -#endif PACKED_STRUCT_UNALIGNED(struct vtm { VALUE year; /* 2000 for example. Integer. */ VALUE subsecx; /* 0 <= subsecx < TIME_SCALE. possibly Rational. */ diff --git a/transient_heap.c b/transient_heap.c index c89d705fa9..55a796325f 100644 --- a/transient_heap.c +++ b/transient_heap.c @@ -796,56 +796,6 @@ blocks_clear_marked_index(struct transient_heap_block* block) } } -static void -transient_heap_block_update_refs(struct transient_heap* theap, struct transient_heap_block* block) -{ - int i=0, n=0; - - while (i<block->info.index) { - void *ptr = &block->buff[i]; - struct transient_alloc_header *header = ptr; - - unpoison_memory_region(header, sizeof *header, false); - - void *poisoned = __asan_region_is_poisoned(header->obj, SIZEOF_VALUE); - unpoison_object(header->obj, false); - - header->obj = rb_gc_new_location(header->obj); - - if (poisoned) { - poison_object(header->obj); - } - - i += header->size; - poison_memory_region(header, sizeof *header); - n++; - } -} - -static void -transient_heap_blocks_update_refs(struct transient_heap* theap, struct transient_heap_block *block, const char *type_str) -{ - while (block) { - transient_heap_block_update_refs(theap, block); - block = block->info.next_block; - } -} - -void -rb_transient_heap_update_references(void) -{ - struct transient_heap* theap = transient_heap_get(); - int i; - - transient_heap_blocks_update_refs(theap, theap->using_blocks, "using_blocks"); - transient_heap_blocks_update_refs(theap, theap->marked_blocks, "marked_blocks"); - - for (i=0; i<theap->promoted_objects_index; i++) { - VALUE obj = theap->promoted_objects[i]; - theap->promoted_objects[i] == rb_gc_new_location(obj); - } -} - void rb_transient_heap_start_marking(int full_marking) { diff --git a/transient_heap.h b/transient_heap.h index 7b5c42ca8e..a34aa1e4f8 100644 --- a/transient_heap.h +++ b/transient_heap.h @@ -30,7 +30,6 @@ void rb_transient_heap_mark(VALUE obj, const void *ptr); void rb_transient_heap_promote(VALUE obj); void rb_transient_heap_start_marking(int full_marking); void rb_transient_heap_finish_marking(void); -void rb_transient_heap_update_references(void); /* for debug API */ void rb_transient_heap_dump(void); @@ -49,7 +48,6 @@ void rb_struct_transient_heap_evacuate(VALUE st, int promote); #define rb_transient_heap_verify() ((void)0) #define rb_transient_heap_promote(obj) ((void)0) #define rb_transient_heap_start_marking(full_marking) ((void)0) -#define rb_transient_heap_update_references() ((void)0) #define rb_transient_heap_finish_marking() ((void)0) #define rb_transient_heap_mark(obj, ptr) ((void)0) diff --git a/variable.c b/variable.c index 2c69e2169c..f4988b699d 100644 --- a/variable.c +++ b/variable.c @@ -1201,16 +1201,6 @@ rb_mark_generic_ivar(VALUE obj) } void -rb_mv_generic_ivar(VALUE rsrc, VALUE dst) -{ - st_data_t key = (st_data_t)rsrc; - struct gen_ivtbl *ivtbl; - - if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl)) - st_insert(generic_iv_tbl, (st_data_t)dst, (st_data_t)ivtbl); -} - -void rb_free_generic_ivar(VALUE obj) { st_data_t key = (st_data_t)obj; @@ -1960,7 +1950,7 @@ rb_mod_const_missing(VALUE klass, VALUE name) static void autoload_mark(void *ptr) { - rb_mark_tbl_no_pin((st_table *)ptr); + rb_mark_tbl((st_table *)ptr); } static void @@ -1976,15 +1966,9 @@ autoload_memsize(const void *ptr) return st_memsize(tbl); } -static void -autoload_compact(void *ptr) -{ - rb_gc_update_tbl_refs((st_table *)ptr); -} - static const rb_data_type_t autoload_data_type = { "autoload", - {autoload_mark, autoload_free, autoload_memsize, autoload_compact,}, + {autoload_mark, autoload_free, autoload_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -2031,18 +2015,11 @@ struct autoload_data_i { }; static void -autoload_i_compact(void *ptr) -{ - struct autoload_data_i *p = ptr; - p->feature = rb_gc_new_location(p->feature); -} - -static void autoload_i_mark(void *ptr) { struct autoload_data_i *p = ptr; - rb_gc_mark_no_pin(p->feature); + rb_gc_mark(p->feature); /* allow GC to free us if no modules refer to this via autoload_const.ad */ if (list_empty(&p->constants)) { @@ -2069,7 +2046,7 @@ autoload_i_memsize(const void *ptr) static const rb_data_type_t autoload_data_i_type = { "autoload_i", - {autoload_i_mark, autoload_i_free, autoload_i_memsize, autoload_i_compact}, + {autoload_i_mark, autoload_i_free, autoload_i_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -2994,7 +2971,6 @@ 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); rb_const_set(klass, id, val); } @@ -6,7 +6,7 @@ #define RUBY_RELEASE_YEAR 2019 #define RUBY_RELEASE_MONTH 4 -#define RUBY_RELEASE_DAY 10 +#define RUBY_RELEASE_DAY 9 #include "ruby/version.h" @@ -2203,15 +2203,6 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, /* vm */ void -rb_vm_update_references(void *ptr) -{ - if (ptr) { - rb_vm_t *vm = ptr; - rb_update_st_references(vm->frozen_strings); - } -} - -void rb_vm_mark(void *ptr) { RUBY_MARK_ENTER("vm"); @@ -2219,30 +2210,12 @@ rb_vm_mark(void *ptr) if (ptr) { rb_vm_t *vm = ptr; rb_thread_t *th = 0; - long i, len; - const VALUE *obj_ary; list_for_each(&vm->living_threads, th, vmlt_node) { rb_gc_mark(th->self); } rb_gc_mark(vm->thgroup_default); rb_gc_mark(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(vm->load_path); rb_gc_mark(vm->load_path_snapshot); RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); @@ -2252,8 +2225,6 @@ rb_vm_mark(void *ptr) rb_gc_mark(vm->top_self); RUBY_MARK_UNLESS_NULL(vm->coverages); rb_gc_mark(vm->defined_module_hash); - /* Prevent classes from moving */ - rb_mark_tbl(rb_hash_tbl(vm->defined_module_hash, __FILE__, __LINE__)); if (vm->loading_table) { rb_mark_tbl(vm->loading_table); @@ -2492,7 +2463,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec) rb_control_frame_t *cfp = ec->cfp; rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size); - rb_gc_mark_stack_values((long)(sp - p), p); + rb_gc_mark_values((long)(sp - p), p); while (cfp != limit_cfp) { const VALUE *ep = cfp->ep; @@ -36,7 +36,7 @@ enum arg_setup_type { static inline void arg_rest_dup(struct args_info *args) { - if (!args->rest_dupped) { + if(!args->rest_dupped) { args->rest = rb_ary_dup(args->rest); args->rest_dupped = TRUE; } @@ -346,7 +346,7 @@ struct rb_iseq_constant_body { } type; /* instruction sequence type */ unsigned int iseq_size; - VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */ + const VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */ /** * parameter information @@ -414,7 +414,7 @@ struct rb_iseq_constant_body { int bits_start; int rest_start; const ID *table; - VALUE *default_values; + const VALUE *default_values; } *keyword; } param; @@ -433,7 +433,7 @@ struct rb_iseq_constant_body { const ID *local_table; /* must free */ /* catch table */ - struct iseq_catch_table *catch_table; + const struct iseq_catch_table *catch_table; /* for child iseq */ const struct rb_iseq_struct *parent_iseq; @@ -1029,7 +1029,7 @@ typedef struct { typedef struct { VALUE flags; /* imemo header */ - rb_iseq_t *iseq; + const rb_iseq_t *iseq; const VALUE *ep; const VALUE *env; unsigned int env_size; @@ -484,7 +484,6 @@ rb_type_str(enum ruby_value_type type) case type_case(T_NODE); case type_case(T_ICLASS); case type_case(T_ZOMBIE); - case type_case(T_MOVED); case T_MASK: break; } #undef type_case diff --git a/vm_method.c b/vm_method.c index 672fac0462..c5ca644230 100644 --- a/vm_method.c +++ b/vm_method.c @@ -670,8 +670,13 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_ MJIT_FUNC_EXPORTED void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi) { - rb_method_iseq_t iseq_body = {(rb_iseq_t *)iseq, cref}; + struct { /* should be same fields with rb_method_iseq_struct */ + const rb_iseq_t *iseqptr; + rb_cref_t *cref; + } iseq_body; + iseq_body.iseqptr = iseq; + iseq_body.cref = cref; rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi); } |