summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-17 09:41:41 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-17 09:41:41 +0000
commit744e5df7156c8bb3fea61bacb1bf27d3d8698548 (patch)
treeedb3f475ee4fde34b9804504b359ea1bb17325c6
parentf399134e8ff61faa81d624e2dd2e05ed61d32af1 (diff)
Reverting compaction for now
For some reason symbols (or classes) are being overridden in trunk git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--NEWS9
-rw-r--r--class.c8
-rw-r--r--constant.h4
-rw-r--r--ext/json/generator/generator.c2
-rw-r--r--ext/json/parser/parser.c2
-rw-r--r--gc.c1291
-rw-r--r--gc.h4
-rw-r--r--hash.c40
-rw-r--r--id_table.c22
-rw-r--r--id_table.h3
-rw-r--r--include/ruby/intern.h6
-rw-r--r--include/ruby/ruby.h12
-rw-r--r--include/ruby/st.h3
-rw-r--r--internal.h42
-rw-r--r--iseq.c100
-rw-r--r--iseq.h2
-rw-r--r--method.h24
-rw-r--r--st.c23
-rw-r--r--symbol.c7
-rw-r--r--symbol.h7
-rw-r--r--test/ruby/test_gc_compact.rb97
-rw-r--r--thread.c6
-rw-r--r--transient_heap.c50
-rw-r--r--transient_heap.h2
-rw-r--r--variable.c32
-rw-r--r--vm.c31
-rw-r--r--vm_core.h8
-rw-r--r--vm_eval.c1
28 files changed, 107 insertions, 1731 deletions
diff --git a/NEWS b/NEWS
index 1d1591d84a..5b7a66c51a 100644
--- a/NEWS
+++ b/NEWS
@@ -109,15 +109,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]
diff --git a/class.c b/class.c
index d0ff92b6eb..b76af269bb 100644
--- a/class.c
+++ b/class.c
@@ -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;
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/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/gc.c b/gc.c
index cff8fc083d..d49f7c5660 100644
--- a/gc.c
+++ b/gc.c
@@ -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>
@@ -405,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;
@@ -583,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;
@@ -638,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;
@@ -652,9 +643,6 @@ typedef struct rb_objspace {
#endif
#endif /* USE_RGENGC */
- st_table *id_to_obj_tbl;
- st_table *obj_to_id_tbl;
-
#if GC_DEBUG_STRESS_TO_CLASS
VALUE stress_to_class;
#endif
@@ -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)
@@ -1419,8 +1363,6 @@ rb_objspace_free(rb_objspace_t *objspace)
objspace->eden_heap.total_pages = 0;
objspace->eden_heap.total_slots = 0;
}
- st_free_table(objspace->id_to_obj_tbl);
- st_free_table(objspace->obj_to_id_tbl);
free_stack_chunks(&objspace->mark_stack);
#if !(defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE)
if (objspace == &rb_objspace) return;
@@ -2265,19 +2207,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
FL_UNSET(obj, FL_EXIVAR);
}
- if (FL_TEST(obj, FL_SEEN_OBJ_ID)) {
- VALUE id;
-
- FL_UNSET(obj, FL_SEEN_OBJ_ID);
-
- if (st_delete(objspace->obj_to_id_tbl, (st_data_t *)&obj, &id)) {
- assert(id);
- st_delete(objspace->id_to_obj_tbl, (st_data_t *)&id, NULL);
- } else {
- rb_bug("Object ID see, but not in mapping table: %s\n", obj_info(obj));
- }
- }
-
#if USE_RGENGC
if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
@@ -2445,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 */
@@ -2568,9 +2496,6 @@ Init_heap(void)
{
rb_objspace_t *objspace = &rb_objspace;
- objspace->id_to_obj_tbl = st_init_numtable();
- objspace->obj_to_id_tbl = st_init_numtable();
-
gc_stress_set(objspace, ruby_initial_gc_stress);
#if RGENGC_ESTIMATE_OLDMALLOC
@@ -2714,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:
@@ -3290,7 +3214,6 @@ id2ref(VALUE obj, VALUE objid)
#endif
rb_objspace_t *objspace = &rb_objspace;
VALUE ptr;
- VALUE orig;
void *p0;
ptr = NUM2PTR(objid);
@@ -3303,10 +3226,6 @@ id2ref(VALUE obj, VALUE objid)
if (FLONUM_P(ptr)) return (VALUE)ptr;
ptr = obj_id_to_ref(objid);
- if (st_lookup(objspace->id_to_obj_tbl, ptr, &orig)) {
- return orig;
- }
-
if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
ID symid = ptr / sizeof(RVALUE);
if (rb_id2str(symid) == 0)
@@ -3326,70 +3245,6 @@ id2ref(VALUE obj, VALUE objid)
return (VALUE)ptr;
}
-static VALUE
-rb_find_object_id(VALUE obj, VALUE (*get_heap_object_id)(VALUE))
-{
- if (STATIC_SYM_P(obj)) {
- return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
- }
- else if (FLONUM_P(obj)) {
-#if SIZEOF_LONG == SIZEOF_VOIDP
- return LONG2NUM((SIGNED_VALUE)obj);
-#else
- return LL2NUM((SIGNED_VALUE)obj);
-#endif
- }
- else if (SPECIAL_CONST_P(obj)) {
- return LONG2NUM((SIGNED_VALUE)obj);
- }
-
- return get_heap_object_id(obj);
-}
-
-static VALUE
-cached_object_id(VALUE obj)
-{
- VALUE id;
- rb_objspace_t *objspace = &rb_objspace;
-
- if (st_lookup(objspace->obj_to_id_tbl, (st_data_t)obj, &id)) {
- assert(FL_TEST(obj, FL_SEEN_OBJ_ID));
- return nonspecial_obj_id(id);
- }
- else {
- assert(!FL_TEST(obj, FL_SEEN_OBJ_ID));
- id = obj;
-
- while (1) {
- /* id is the object id */
- if (st_lookup(objspace->id_to_obj_tbl, (st_data_t)id, 0)) {
- objspace->profile.object_id_collisions++;
- id += sizeof(VALUE);
- }
- else {
- st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id);
- st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj);
- FL_SET(obj, FL_SEEN_OBJ_ID);
- return nonspecial_obj_id(id);
- }
- }
- }
- return nonspecial_obj_id(obj);
-}
-
-static VALUE
-nonspecial_obj_id_(VALUE obj)
-{
- return nonspecial_obj_id(obj);
-}
-
-
-VALUE
-rb_memory_id(VALUE obj)
-{
- return rb_find_object_id(obj, nonspecial_obj_id_);
-}
-
/*
* Document-method: __id__
* Document-method: object_id
@@ -3446,8 +3301,20 @@ rb_obj_id(VALUE obj)
* 24 if 32-bit, double is 8-byte aligned
* 40 if 64-bit
*/
-
- return rb_find_object_id(obj, cached_object_id);
+ if (STATIC_SYM_P(obj)) {
+ return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
+ }
+ else if (FLONUM_P(obj)) {
+#if SIZEOF_LONG == SIZEOF_VOIDP
+ return LONG2NUM((SIGNED_VALUE)obj);
+#else
+ return LL2NUM((SIGNED_VALUE)obj);
+#endif
+ }
+ else if (SPECIAL_CONST_P(obj)) {
+ return LONG2NUM((SIGNED_VALUE)obj);
+ }
+ return nonspecial_obj_id(obj);
}
#include "regint.h"
@@ -3570,7 +3437,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
break;
case T_ZOMBIE:
- case T_MOVED:
break;
default:
@@ -3627,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;
}
@@ -4339,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++;
}
}
@@ -4361,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]);
}
}
@@ -4374,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;
@@ -4453,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;
}
@@ -4638,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)) {
@@ -4654,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
@@ -4818,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;
@@ -4840,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.
@@ -4861,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)
{
@@ -4888,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;
@@ -4983,7 +4759,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
gc_mark(objspace, RCLASS_SUPER((VALUE)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));
break;
@@ -5110,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",
@@ -5590,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 */
@@ -6345,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;
@@ -6600,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) {
@@ -6611,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
}
@@ -6623,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;
}
@@ -7197,967 +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(objspace->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(objspace->obj_to_id_tbl, (st_data_t *)&src, 0);
- st_insert(objspace->obj_to_id_tbl, (VALUE)dest, id);
- st_update(objspace->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));
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- 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));
- break;
-
- case T_ICLASS:
- if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
- update_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- 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));
- 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 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);
- gc_check_references_for_moved(mod);
-
- 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);
-}
-
VALUE
rb_gc_start(void)
{
@@ -8370,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,
@@ -8446,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);
@@ -8619,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);
@@ -9825,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
@@ -10843,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)) {
@@ -10892,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,
@@ -10923,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));
@@ -10952,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
@@ -10993,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',
@@ -11158,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");
}
@@ -11173,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");
@@ -11332,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();
@@ -11393,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);
diff --git a/gc.h b/gc.h
index 727890181a..2c91e06620 100644
--- a/gc.h
+++ b/gc.h
@@ -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);} \
diff --git a/hash.c b/hash.c
index 4841cbb198..a7ed5aaca4 100644
--- a/hash.c
+++ b/hash.c
@@ -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 e962380080..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);
@@ -627,7 +622,6 @@ VALUE rb_obj_trust(VALUE);
VALUE rb_obj_freeze(VALUE);
PUREFUNC(VALUE rb_obj_frozen_p(VALUE));
VALUE rb_obj_id(VALUE);
-VALUE rb_memory_id(VALUE);
VALUE rb_obj_class(VALUE);
PUREFUNC(VALUE rb_class_real(VALUE));
PUREFUNC(VALUE rb_class_inherited_p(VALUE, VALUE));
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index c73fd63941..ed4d43dedb 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)
@@ -847,7 +845,6 @@ enum ruby_fl_type {
RUBY_FL_FINALIZE = (1<<7),
RUBY_FL_TAINT = (1<<8),
RUBY_FL_UNTRUSTED = RUBY_FL_TAINT,
- RUBY_FL_SEEN_OBJ_ID = (1<<9),
RUBY_FL_EXIVAR = (1<<10),
RUBY_FL_FREEZE = (1<<11),
@@ -886,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);
@@ -1108,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)
@@ -1147,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;
@@ -1259,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))
@@ -1278,7 +1273,6 @@ int rb_big_sign(VALUE);
#define FL_FINALIZE ((VALUE)RUBY_FL_FINALIZE)
#define FL_TAINT ((VALUE)RUBY_FL_TAINT)
#define FL_UNTRUSTED ((VALUE)RUBY_FL_UNTRUSTED)
-#define FL_SEEN_OBJ_ID ((VALUE)RUBY_FL_SEEN_OBJ_ID)
#define FL_EXIVAR ((VALUE)RUBY_FL_EXIVAR)
#define FL_FREEZE ((VALUE)RUBY_FL_FREEZE)
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 17bd7f1fe9..5eed6b2ed6 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;
};
@@ -1572,7 +1567,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 */
@@ -2337,7 +2331,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);
@@ -2349,10 +2342,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);
diff --git a/iseq.c b/iseq.c
index 82f045d62a..67fc862a33 100644
--- a/iseq.c
+++ b/iseq.c
@@ -137,11 +137,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);
@@ -157,10 +157,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;
}
@@ -168,10 +165,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;
}
@@ -187,7 +181,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;
@@ -211,65 +205,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
@@ -286,12 +225,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;
@@ -314,7 +253,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);
}
}
}
@@ -325,14 +264,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);
- }
- RUBY_MARK_UNLESS_NULL(compile_data->err_info);
- if (RTEST(compile_data->catch_table_ary)) {
- rb_gc_mark(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 */
diff --git a/iseq.h b/iseq.h
index 0326577c5a..ac037d0a3b 100644
--- a/iseq.h
+++ b/iseq.h
@@ -236,7 +236,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/method.h b/method.h
index 2a6d85a2dd..65ea9dd0c2 100644
--- a/method.h
+++ b/method.h
@@ -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/st.c b/st.c
index cecc2ac67f..ed235c674e 100644
--- a/st.c
+++ b/st.c
@@ -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.
diff --git a/symbol.c b/symbol.c
index a3422501a8..09fe7ecb33 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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,
diff --git a/symbol.h b/symbol.h
index 3b9866d80f..56568a91fc 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
deleted file mode 100644
index a854fc5c00..0000000000
--- a/test/ruby/test_gc_compact.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'fiddle'
-
-class TestGCCompact < Test::Unit::TestCase
- def memory_location(obj)
- (Fiddle.dlwrap(obj) >> 1)
- 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)
-
- assert_equal ids, addresses
-
- # All object ids should be equal
- assert_equal 0, assert_object_ids(list_of_objects) # should be 0
-
- GC.verify_compaction_references
-
- # 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.verify_compaction_references
-
- 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
diff --git a/thread.c b/thread.c
index e88ed87306..213a3e5fb7 100644
--- a/thread.c
+++ b/thread.c
@@ -4957,7 +4957,7 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
struct exec_recursive_params p;
int outermost;
p.list = recursive_list_access(sym);
- p.objid = rb_memory_id(obj);
+ p.objid = rb_obj_id(obj);
p.obj = obj;
p.pairid = pairid;
p.arg = arg;
@@ -5026,7 +5026,7 @@ rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
VALUE
rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
{
- return exec_recursive(func, obj, rb_memory_id(paired_obj), arg, 0);
+ return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 0);
}
/*
@@ -5050,7 +5050,7 @@ rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
VALUE
rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
{
- return exec_recursive(func, obj, rb_memory_id(paired_obj), arg, 1);
+ return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 1);
}
/*
diff --git a/transient_heap.c b/transient_heap.c
index 334bd4f320..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);
}
diff --git a/vm.c b/vm.c
index c4144b5b99..24a43ed189 100644
--- a/vm.c
+++ b/vm.c
@@ -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;
diff --git a/vm_core.h b/vm_core.h
index 2e8ddfe37f..e9e0f50eb2 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -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;
diff --git a/vm_eval.c b/vm_eval.c
index fc271415a6..f05621e2b4 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -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