diff --git a/common.mk b/common.mk index b387c47a4a0241..a0c41e04e00d59 100644 --- a/common.mk +++ b/common.mk @@ -130,7 +130,6 @@ COMMONOBJS = array.$(OBJEXT) \ eval.$(OBJEXT) \ file.$(OBJEXT) \ gc.$(OBJEXT) \ - gc_impl.$(OBJEXT) \ hash.$(OBJEXT) \ inits.$(OBJEXT) \ imemo.$(OBJEXT) \ @@ -7238,6 +7237,7 @@ gc.$(OBJEXT): $(CCAN_DIR)/str/str.h gc.$(OBJEXT): $(hdrdir)/ruby.h gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h gc.$(OBJEXT): $(hdrdir)/ruby/version.h +gc.$(OBJEXT): $(top_srcdir)/gc/default.c gc.$(OBJEXT): $(top_srcdir)/gc/gc.h gc.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h gc.$(OBJEXT): $(top_srcdir)/internal/array.h @@ -7503,198 +7503,6 @@ gc.$(OBJEXT): {$(VPATH)}vm_core.h gc.$(OBJEXT): {$(VPATH)}vm_debug.h gc.$(OBJEXT): {$(VPATH)}vm_opts.h gc.$(OBJEXT): {$(VPATH)}vm_sync.h -gc_impl.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h -gc_impl.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h -gc_impl.$(OBJEXT): $(CCAN_DIR)/list/list.h -gc_impl.$(OBJEXT): $(CCAN_DIR)/str/str.h -gc_impl.$(OBJEXT): $(hdrdir)/ruby/ruby.h -gc_impl.$(OBJEXT): $(top_srcdir)/gc/default.c -gc_impl.$(OBJEXT): $(top_srcdir)/gc/gc.h -gc_impl.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/bits.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/compilers.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/hash.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/static_assert.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/string.h -gc_impl.$(OBJEXT): $(top_srcdir)/internal/warnings.h -gc_impl.$(OBJEXT): {$(VPATH)}assert.h -gc_impl.$(OBJEXT): {$(VPATH)}atomic.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/assume.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/bool.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/limits.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -gc_impl.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -gc_impl.$(OBJEXT): {$(VPATH)}config.h -gc_impl.$(OBJEXT): {$(VPATH)}darray.h -gc_impl.$(OBJEXT): {$(VPATH)}debug.h -gc_impl.$(OBJEXT): {$(VPATH)}debug_counter.h -gc_impl.$(OBJEXT): {$(VPATH)}defines.h -gc_impl.$(OBJEXT): {$(VPATH)}encoding.h -gc_impl.$(OBJEXT): {$(VPATH)}intern.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/abi.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/anyargs.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/assume.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/const.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/error.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/format.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/cast.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/config.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/constant_p.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/robject.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/ctype.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/dllexport.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/dosish.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/error.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/eval.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/event.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/fl_type.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/gc.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/glob.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/globals.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/extension.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/feature.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/has/warning.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/array.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/class.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/error.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/file.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/io.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/load.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/object.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/process.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/random.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/range.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/re.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/select.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/string.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/time.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/interpreter.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/iterator.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/memory.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/method.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/module.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/newobj.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/scan_args.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/special_consts.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/static_assert.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/stdalign.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/stdbool.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/stdckdint.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/symbol.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/value.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/value_type.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/variable.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/warning_push.h -gc_impl.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -gc_impl.$(OBJEXT): {$(VPATH)}missing.h -gc_impl.$(OBJEXT): {$(VPATH)}onigmo.h -gc_impl.$(OBJEXT): {$(VPATH)}oniguruma.h -gc_impl.$(OBJEXT): {$(VPATH)}probes.dmyh -gc_impl.$(OBJEXT): {$(VPATH)}probes.h -gc_impl.$(OBJEXT): {$(VPATH)}st.h -gc_impl.$(OBJEXT): {$(VPATH)}subst.h -gc_impl.$(OBJEXT): {$(VPATH)}thread.h -gc_impl.$(OBJEXT): {$(VPATH)}util.h -gc_impl.$(OBJEXT): {$(VPATH)}vm.h goruby.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h goruby.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h goruby.$(OBJEXT): $(CCAN_DIR)/list/list.h diff --git a/gc.c b/gc.c index c67567f7e8187f..402107f59541bf 100644 --- a/gc.c +++ b/gc.c @@ -83,7 +83,6 @@ #include "debug_counter.h" #include "eval_intern.h" #include "gc/gc.h" -#include "gc/gc_impl.h" #include "id_table.h" #include "internal.h" #include "internal/class.h" @@ -158,7 +157,7 @@ rb_gc_cr_unlock(unsigned int lev) unsigned int rb_gc_vm_lock_no_barrier(void) { - unsigned int lev; + unsigned int lev = 0; RB_VM_LOCK_ENTER_LEV_NB(&lev); return lev; } @@ -565,6 +564,10 @@ rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val) } #endif +static const char *obj_type_name(VALUE obj); +#define RB_AMALGAMATED_DEFAULT_GC +#include "gc/default.c" + #if USE_SHARED_GC && !defined(HAVE_DLOPEN) # error "Shared GC requires dlopen" #elif USE_SHARED_GC @@ -1899,43 +1902,6 @@ set_zero(st_data_t key, st_data_t val, st_data_t arg) return ST_CONTINUE; } -static VALUE -type_sym(size_t type) -{ - switch (type) { -#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break; - COUNT_TYPE(T_NONE); - COUNT_TYPE(T_OBJECT); - COUNT_TYPE(T_CLASS); - COUNT_TYPE(T_MODULE); - COUNT_TYPE(T_FLOAT); - COUNT_TYPE(T_STRING); - COUNT_TYPE(T_REGEXP); - COUNT_TYPE(T_ARRAY); - COUNT_TYPE(T_HASH); - COUNT_TYPE(T_STRUCT); - COUNT_TYPE(T_BIGNUM); - COUNT_TYPE(T_FILE); - COUNT_TYPE(T_DATA); - COUNT_TYPE(T_MATCH); - COUNT_TYPE(T_COMPLEX); - COUNT_TYPE(T_RATIONAL); - COUNT_TYPE(T_NIL); - COUNT_TYPE(T_TRUE); - COUNT_TYPE(T_FALSE); - COUNT_TYPE(T_SYMBOL); - COUNT_TYPE(T_FIXNUM); - COUNT_TYPE(T_IMEMO); - COUNT_TYPE(T_UNDEF); - COUNT_TYPE(T_NODE); - COUNT_TYPE(T_ICLASS); - COUNT_TYPE(T_ZOMBIE); - COUNT_TYPE(T_MOVED); -#undef COUNT_TYPE - default: return SIZET2NUM(type); break; - } -} - struct count_objects_data { size_t counts[T_MASK+1]; size_t freed; @@ -2392,16 +2358,6 @@ rb_mark_tbl(st_table *tbl) st_foreach(tbl, rb_mark_tbl_i, (st_data_t)rb_gc_get_objspace()); } -static int -gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data) -{ - void *objspace = (void *)data; - - rb_gc_impl_mark(objspace, (VALUE)value); - - return ST_CONTINUE; -} - static void gc_mark_tbl_no_pin(void *objspace, st_table *tbl) { @@ -2963,8 +2919,6 @@ gc_ref_update_array(void *objspace, VALUE v) } } -static void gc_ref_update_table_values_only(void *objspace, st_table *tbl); - static void gc_ref_update_object(void *objspace, VALUE v) { @@ -2990,90 +2944,12 @@ gc_ref_update_object(void *objspace, VALUE v) } } -static int -hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - void *objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*key)) { - *key = rb_gc_impl_location(objspace, (VALUE)*key); - } - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_impl_location(objspace, (VALUE)*value); - } - - return ST_CONTINUE; -} - -static int -hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error) -{ - void *objspace; - - objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)key)) { - return ST_REPLACE; - } - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { - return ST_REPLACE; - } - return ST_CONTINUE; -} - -static int -hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - void *objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_impl_location(objspace, (VALUE)*value); - } - - return ST_CONTINUE; -} - -static int -hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error) -{ - void *objspace; - - objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { - return ST_REPLACE; - } - return ST_CONTINUE; -} - -static void -gc_ref_update_table_values_only(void *objspace, st_table *tbl) -{ - if (!tbl || tbl->num_entries == 0) return; - - if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, (st_data_t)objspace)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } -} - void rb_gc_ref_update_table_values_only(st_table *tbl) { gc_ref_update_table_values_only(rb_gc_get_objspace(), tbl); } -static void -gc_update_table_refs(void *objspace, st_table *tbl) -{ - if (!tbl || tbl->num_entries == 0) return; - - if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } -} - /* Update MOVED references in a VALUE=>VALUE st_table */ void rb_gc_update_tbl_refs(st_table *ptr) @@ -4257,12 +4133,6 @@ ruby_malloc_size_overflow(size_t count, size_t elsize) count, elsize); } -static inline size_t -xmalloc2_size(const size_t count, const size_t elsize) -{ - return size_mul_or_raise(count, elsize, rb_eArgError); -} - void * ruby_xmalloc2(size_t n, size_t size) { diff --git a/gc/default.c b/gc/default.c index fc093b1c2786ce..04a0fd7bb54829 100644 --- a/gc/default.c +++ b/gc/default.c @@ -248,8 +248,10 @@ int ruby_rgengc_debug; # define RGENGC_CHECK_MODE 0 #endif +#ifndef GC_ASSERT // Note: using RUBY_ASSERT_WHEN() extend a macro in expr (info by nobu). -#define GC_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr) +# define GC_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr) +#endif /* RGENGC_PROFILE * 0: disable RGenGC profiling @@ -875,13 +877,17 @@ RVALUE_AGE_SET(VALUE obj, int age) #define gc_config_full_mark_set(b) (((int)b), objspace->gc_config.full_mark = (b)) #define gc_config_full_mark_val (objspace->gc_config.full_mark) -#define DURING_GC_COULD_MALLOC_REGION_START() \ +#ifndef DURING_GC_COULD_MALLOC_REGION_START +# define DURING_GC_COULD_MALLOC_REGION_START() \ assert(rb_during_gc()); \ bool _prev_enabled = rb_gc_impl_gc_enabled_p(objspace); \ rb_gc_impl_gc_disable(objspace, false) +#endif -#define DURING_GC_COULD_MALLOC_REGION_END() \ +#ifndef DURING_GC_COULD_MALLOC_REGION_END +# define DURING_GC_COULD_MALLOC_REGION_END() \ if (_prev_enabled) rb_gc_impl_gc_enable(objspace) +#endif static inline enum gc_mode gc_mode_verify(enum gc_mode mode) @@ -2564,53 +2570,63 @@ rb_gc_impl_size_pool_sizes(void *objspace_ptr) return size_pool_sizes; } +NOINLINE(static VALUE newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked)); + static VALUE -newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked) +newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked) { rb_size_pool_t *size_pool = &size_pools[size_pool_idx]; rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool); + VALUE obj = Qfalse; - VALUE obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); + unsigned int lev = 0; + bool unlock_vm = false; - if (RB_UNLIKELY(obj == Qfalse)) { - unsigned int lev = 0; - bool unlock_vm = false; + if (!vm_locked) { + lev = rb_gc_cr_lock(); + vm_locked = true; + unlock_vm = true; + } - if (!vm_locked) { - lev = rb_gc_cr_lock(); - vm_locked = true; - unlock_vm = true; + { + if (is_incremental_marking(objspace)) { + gc_continue(objspace, size_pool, heap); + cache->incremental_mark_step_allocated_slots = 0; + + // Retry allocation after resetting incremental_mark_step_allocated_slots + obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); } - { - if (is_incremental_marking(objspace)) { - gc_continue(objspace, size_pool, heap); - cache->incremental_mark_step_allocated_slots = 0; + if (obj == Qfalse) { + // Get next free page (possibly running GC) + struct heap_page *page = heap_next_free_page(objspace, size_pool, heap); + ractor_cache_set_page(objspace, cache, size_pool_idx, page); - // Retry allocation after resetting incremental_mark_step_allocated_slots - obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); - } + // Retry allocation after moving to new page + obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); + } + } - if (obj == Qfalse) { - // Get next free page (possibly running GC) - struct heap_page *page = heap_next_free_page(objspace, size_pool, heap); - ractor_cache_set_page(objspace, cache, size_pool_idx, page); + if (unlock_vm) { + rb_gc_cr_unlock(lev); + } - // Retry allocation after moving to new page - obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); - } - } + if (RB_UNLIKELY(obj == Qfalse)) { + rb_memerror(); + } + return obj; +} - if (unlock_vm) { - rb_gc_cr_unlock(lev); - } +static VALUE +newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked) +{ + VALUE obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx); - if (RB_UNLIKELY(obj == Qfalse)) { - rb_memerror(); - } + if (RB_UNLIKELY(obj == Qfalse)) { + obj = newobj_cache_miss(objspace, cache, size_pool_idx, vm_locked); } - size_pool->total_allocated_objects++; + size_pools[size_pool_idx].total_allocated_objects++; return obj; } @@ -3014,21 +3030,6 @@ rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj) FL_UNSET(obj, FL_FINALIZE); } -VALUE -rb_gc_impl_get_finalizers(void *objspace_ptr, VALUE obj) -{ - rb_objspace_t *objspace = objspace_ptr; - - if (FL_TEST(obj, FL_FINALIZE)) { - st_data_t data; - if (st_lookup(finalizer_table, obj, &data)) { - return (VALUE)data; - } - } - - return Qnil; -} - void rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj) { @@ -7355,84 +7356,6 @@ gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t *objspace, return 0; } -static int -hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - void *objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_impl_location(objspace, (VALUE)*value); - } - - return ST_CONTINUE; -} - -static int -hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error) -{ - void *objspace; - - objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { - return ST_REPLACE; - } - return ST_CONTINUE; -} - -static void -gc_ref_update_table_values_only(void *objspace, st_table *tbl) -{ - if (!tbl || tbl->num_entries == 0) return; - - if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, (st_data_t)objspace)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } -} - -static int -hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error) -{ - void *objspace; - - objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)key)) { - return ST_REPLACE; - } - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { - return ST_REPLACE; - } - return ST_CONTINUE; -} - -static int -hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - void *objspace = (void *)argp; - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*key)) { - *key = rb_gc_impl_location(objspace, (VALUE)*key); - } - - if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { - *value = rb_gc_impl_location(objspace, (VALUE)*value); - } - - return ST_CONTINUE; -} - -static void -gc_update_table_refs(void *objspace, st_table *tbl) -{ - if (!tbl || tbl->num_entries == 0) return; - - if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } -} - static void gc_update_references(rb_objspace_t *objspace) { @@ -8596,12 +8519,6 @@ rb_gc_impl_calloc(void *objspace_ptr, size_t size) return objspace_malloc_fixup(objspace, mem, size); } -static inline size_t -xmalloc2_size(const size_t count, const size_t elsize) -{ - return rb_size_mul_or_raise(count, elsize, rb_eArgError); -} - void * rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size) { @@ -9378,43 +9295,6 @@ gc_get_auto_compact(VALUE _) #endif #if GC_CAN_COMPILE_COMPACTION -static VALUE -type_sym(size_t type) -{ - switch (type) { -#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break; - COUNT_TYPE(T_NONE); - COUNT_TYPE(T_OBJECT); - COUNT_TYPE(T_CLASS); - COUNT_TYPE(T_MODULE); - COUNT_TYPE(T_FLOAT); - COUNT_TYPE(T_STRING); - COUNT_TYPE(T_REGEXP); - COUNT_TYPE(T_ARRAY); - COUNT_TYPE(T_HASH); - COUNT_TYPE(T_STRUCT); - COUNT_TYPE(T_BIGNUM); - COUNT_TYPE(T_FILE); - COUNT_TYPE(T_DATA); - COUNT_TYPE(T_MATCH); - COUNT_TYPE(T_COMPLEX); - COUNT_TYPE(T_RATIONAL); - COUNT_TYPE(T_NIL); - COUNT_TYPE(T_TRUE); - COUNT_TYPE(T_FALSE); - COUNT_TYPE(T_SYMBOL); - COUNT_TYPE(T_FIXNUM); - COUNT_TYPE(T_IMEMO); - COUNT_TYPE(T_UNDEF); - COUNT_TYPE(T_NODE); - COUNT_TYPE(T_ICLASS); - COUNT_TYPE(T_ZOMBIE); - COUNT_TYPE(T_MOVED); -#undef COUNT_TYPE - default: return SIZET2NUM(type); break; - } -} - /* * call-seq: * GC.latest_compact_info -> hash @@ -9669,14 +9549,6 @@ pin_value(st_data_t key, st_data_t value, st_data_t data) void rb_gc_impl_mark(void *objspace_ptr, VALUE obj); -static int -gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data) -{ - rb_gc_impl_mark((void *)data, (VALUE)value); - - return ST_CONTINUE; -} - #if MALLOC_ALLOCATED_SIZE /* * call-seq: diff --git a/gc/gc.h b/gc/gc.h index 5f9a7b218b2474..e8f3e2f6d6d656 100644 --- a/gc/gc.h +++ b/gc/gc.h @@ -1,7 +1,16 @@ #ifndef GC_GC_H #define GC_GC_H - +/** + * @author Ruby developers + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @brief Private header for the default GC and other GC implementations + * first introduced for [Feature #20470]. + */ #include "ruby/ruby.h" +#include "gc/gc_impl.h" RUBY_SYMBOL_EXPORT_BEGIN unsigned int rb_gc_vm_lock(void); @@ -39,4 +48,139 @@ RUBY_SYMBOL_EXPORT_END void rb_ractor_finish_marking(void); +// -------------------Private section begin------------------------ +// Functions in this section are private to the default GC and gc.c + +static int +hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error) +{ + void *objspace; + + objspace = (void *)argp; + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { + return ST_REPLACE; + } + return ST_CONTINUE; +} + +static int +hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing) +{ + void *objspace = (void *)argp; + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { + *value = rb_gc_impl_location(objspace, (VALUE)*value); + } + + return ST_CONTINUE; +} + +static void +gc_ref_update_table_values_only(void *objspace, st_table *tbl) +{ + if (!tbl || tbl->num_entries == 0) return; + + if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, (st_data_t)objspace)) { + rb_raise(rb_eRuntimeError, "hash modified during iteration"); + } +} + +static int +gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data) +{ + void *objspace = (void *)data; + + rb_gc_impl_mark(objspace, (VALUE)value); + + return ST_CONTINUE; +} + +static int +hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error) +{ + void *objspace; + + objspace = (void *)argp; + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)key)) { + return ST_REPLACE; + } + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)value)) { + return ST_REPLACE; + } + return ST_CONTINUE; +} + +static int +hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing) +{ + void *objspace = (void *)argp; + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)*key)) { + *key = rb_gc_impl_location(objspace, (VALUE)*key); + } + + if (rb_gc_impl_object_moved_p(objspace, (VALUE)*value)) { + *value = rb_gc_impl_location(objspace, (VALUE)*value); + } + + return ST_CONTINUE; +} + +static void +gc_update_table_refs(void *objspace, st_table *tbl) +{ + if (!tbl || tbl->num_entries == 0) return; + + if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace)) { + rb_raise(rb_eRuntimeError, "hash modified during iteration"); + } +} + +static inline size_t +xmalloc2_size(const size_t count, const size_t elsize) +{ + return rb_size_mul_or_raise(count, elsize, rb_eArgError); +} + +static VALUE +type_sym(size_t type) +{ + switch (type) { +#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break; + COUNT_TYPE(T_NONE); + COUNT_TYPE(T_OBJECT); + COUNT_TYPE(T_CLASS); + COUNT_TYPE(T_MODULE); + COUNT_TYPE(T_FLOAT); + COUNT_TYPE(T_STRING); + COUNT_TYPE(T_REGEXP); + COUNT_TYPE(T_ARRAY); + COUNT_TYPE(T_HASH); + COUNT_TYPE(T_STRUCT); + COUNT_TYPE(T_BIGNUM); + COUNT_TYPE(T_FILE); + COUNT_TYPE(T_DATA); + COUNT_TYPE(T_MATCH); + COUNT_TYPE(T_COMPLEX); + COUNT_TYPE(T_RATIONAL); + COUNT_TYPE(T_NIL); + COUNT_TYPE(T_TRUE); + COUNT_TYPE(T_FALSE); + COUNT_TYPE(T_SYMBOL); + COUNT_TYPE(T_FIXNUM); + COUNT_TYPE(T_IMEMO); + COUNT_TYPE(T_UNDEF); + COUNT_TYPE(T_NODE); + COUNT_TYPE(T_ICLASS); + COUNT_TYPE(T_ZOMBIE); + COUNT_TYPE(T_MOVED); +#undef COUNT_TYPE + default: return SIZET2NUM(type); break; + } +} +// -------------------Private section end------------------------ + #endif diff --git a/gc/gc_impl.h b/gc/gc_impl.h index 18249dc58beaef..befeddccb6f496 100644 --- a/gc/gc_impl.h +++ b/gc/gc_impl.h @@ -1,83 +1,105 @@ #ifndef GC_GC_IMPL_H #define GC_GC_IMPL_H - +/** + * @author Ruby developers + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @brief Header for GC implementations introduced in [Feature #20470]. + */ #include "ruby/ruby.h" +// `GC_IMPL_FN` is an implementation detail of `!USE_SHARED_GC` builds +// to have the default GC in the same translation unit as gc.c for +// the sake of optimizer visibility. It expands to nothing unless +// you're the default GC. +// +// For the default GC, do not copy-paste this when implementing +// these functions. This takes advantage of internal linkage winning +// when appearing first. See C99 6.2.2p4. +#ifdef RB_AMALGAMATED_DEFAULT_GC +# define GC_IMPL_FN static +#else +# define GC_IMPL_FN +#endif + // Bootup -void *rb_gc_impl_objspace_alloc(void); -void rb_gc_impl_objspace_init(void *objspace_ptr); -void rb_gc_impl_objspace_free(void *objspace_ptr); -void *rb_gc_impl_ractor_cache_alloc(void *objspace_ptr); -void rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache); -void rb_gc_impl_set_params(void *objspace_ptr); -void rb_gc_impl_init(void); -void rb_gc_impl_initial_stress_set(VALUE flag); -size_t *rb_gc_impl_size_pool_sizes(void *objspace_ptr); +GC_IMPL_FN void *rb_gc_impl_objspace_alloc(void); +GC_IMPL_FN void rb_gc_impl_objspace_init(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_objspace_free(void *objspace_ptr); +GC_IMPL_FN void *rb_gc_impl_ractor_cache_alloc(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache); +GC_IMPL_FN void rb_gc_impl_set_params(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_init(void); +GC_IMPL_FN void rb_gc_impl_initial_stress_set(VALUE flag); +GC_IMPL_FN size_t *rb_gc_impl_size_pool_sizes(void *objspace_ptr); // Shutdown -void rb_gc_impl_shutdown_free_objects(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_shutdown_free_objects(void *objspace_ptr); // GC -void rb_gc_impl_start(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact); -bool rb_gc_impl_during_gc_p(void *objspace_ptr); -void rb_gc_impl_prepare_heap(void *objspace_ptr); -void rb_gc_impl_gc_enable(void *objspace_ptr); -void rb_gc_impl_gc_disable(void *objspace_ptr, bool finish_current_gc); -bool rb_gc_impl_gc_enabled_p(void *objspace_ptr); -void rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag); -VALUE rb_gc_impl_stress_get(void *objspace_ptr); -VALUE rb_gc_impl_config_get(void *objspace_ptr); -VALUE rb_gc_impl_config_set(void *objspace_ptr, VALUE hash); +GC_IMPL_FN void rb_gc_impl_start(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact); +GC_IMPL_FN bool rb_gc_impl_during_gc_p(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_prepare_heap(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_gc_enable(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_gc_disable(void *objspace_ptr, bool finish_current_gc); +GC_IMPL_FN bool rb_gc_impl_gc_enabled_p(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag); +GC_IMPL_FN VALUE rb_gc_impl_stress_get(void *objspace_ptr); +GC_IMPL_FN VALUE rb_gc_impl_config_get(void *objspace_ptr); +GC_IMPL_FN VALUE rb_gc_impl_config_set(void *objspace_ptr, VALUE hash); // Object allocation -VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, bool wb_protected, size_t alloc_size); -size_t rb_gc_impl_obj_slot_size(VALUE obj); -size_t rb_gc_impl_size_pool_id_for_size(void *objspace_ptr, size_t size); -bool rb_gc_impl_size_allocatable_p(size_t size); +GC_IMPL_FN VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, bool wb_protected, size_t alloc_size); +GC_IMPL_FN size_t rb_gc_impl_obj_slot_size(VALUE obj); +GC_IMPL_FN size_t rb_gc_impl_size_pool_id_for_size(void *objspace_ptr, size_t size); +GC_IMPL_FN bool rb_gc_impl_size_allocatable_p(size_t size); // Malloc -void *rb_gc_impl_malloc(void *objspace_ptr, size_t size); -void *rb_gc_impl_calloc(void *objspace_ptr, size_t size); -void *rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size); -void rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size); -void rb_gc_impl_adjust_memory_usage(void *objspace_ptr, ssize_t diff); +GC_IMPL_FN void *rb_gc_impl_malloc(void *objspace_ptr, size_t size); +GC_IMPL_FN void *rb_gc_impl_calloc(void *objspace_ptr, size_t size); +GC_IMPL_FN void *rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size); +GC_IMPL_FN void rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size); +GC_IMPL_FN void rb_gc_impl_adjust_memory_usage(void *objspace_ptr, ssize_t diff); // Marking -void rb_gc_impl_mark(void *objspace_ptr, VALUE obj); -void rb_gc_impl_mark_and_move(void *objspace_ptr, VALUE *ptr); -void rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj); -void rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj); -void rb_gc_impl_mark_weak(void *objspace_ptr, VALUE *ptr); -void rb_gc_impl_remove_weak(void *objspace_ptr, VALUE parent_obj, VALUE *ptr); -void rb_gc_impl_objspace_mark(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_mark(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_mark_and_move(void *objspace_ptr, VALUE *ptr); +GC_IMPL_FN void rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_mark_weak(void *objspace_ptr, VALUE *ptr); +GC_IMPL_FN void rb_gc_impl_remove_weak(void *objspace_ptr, VALUE parent_obj, VALUE *ptr); +GC_IMPL_FN void rb_gc_impl_objspace_mark(void *objspace_ptr); // Compaction -bool rb_gc_impl_object_moved_p(void *objspace_ptr, VALUE obj); -VALUE rb_gc_impl_location(void *objspace_ptr, VALUE value); +GC_IMPL_FN bool rb_gc_impl_object_moved_p(void *objspace_ptr, VALUE obj); +GC_IMPL_FN VALUE rb_gc_impl_location(void *objspace_ptr, VALUE value); // Write barriers -void rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b); -void rb_gc_impl_writebarrier_unprotect(void *objspace_ptr, VALUE obj); -void rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b); +GC_IMPL_FN void rb_gc_impl_writebarrier_unprotect(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj); // Heap walking -void rb_gc_impl_each_objects(void *objspace_ptr, int (*callback)(void *, void *, size_t, void *), void *data); -void rb_gc_impl_each_object(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data); +GC_IMPL_FN void rb_gc_impl_each_objects(void *objspace_ptr, int (*callback)(void *, void *, size_t, void *), void *data); +GC_IMPL_FN void rb_gc_impl_each_object(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data); // Finalizers -void rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data); -VALUE rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block); -void rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj); -void rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj); -void rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr); +GC_IMPL_FN void rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data); +GC_IMPL_FN VALUE rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block); +GC_IMPL_FN void rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj); +GC_IMPL_FN void rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr); // Object ID -VALUE rb_gc_impl_object_id(void *objspace_ptr, VALUE obj); -VALUE rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id); +GC_IMPL_FN VALUE rb_gc_impl_object_id(void *objspace_ptr, VALUE obj); +GC_IMPL_FN VALUE rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id); // Statistics -VALUE rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag); -VALUE rb_gc_impl_get_measure_total_time(void *objspace_ptr); -VALUE rb_gc_impl_get_profile_total_time(void *objspace_ptr); -size_t rb_gc_impl_gc_count(void *objspace_ptr); -VALUE rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE key); -size_t rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym); -size_t rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym); +GC_IMPL_FN VALUE rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag); +GC_IMPL_FN VALUE rb_gc_impl_get_measure_total_time(void *objspace_ptr); +GC_IMPL_FN VALUE rb_gc_impl_get_profile_total_time(void *objspace_ptr); +GC_IMPL_FN size_t rb_gc_impl_gc_count(void *objspace_ptr); +GC_IMPL_FN VALUE rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE key); +GC_IMPL_FN size_t rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym); +GC_IMPL_FN size_t rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym); // Miscellaneous -size_t rb_gc_impl_obj_flags(void *objspace_ptr, VALUE obj, ID* flags, size_t max); -bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr); -bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj); -void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event); -void rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj); +GC_IMPL_FN size_t rb_gc_impl_obj_flags(void *objspace_ptr, VALUE obj, ID* flags, size_t max); +GC_IMPL_FN bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr); +GC_IMPL_FN bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj); +GC_IMPL_FN void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event); +GC_IMPL_FN void rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj); +#undef GC_IMPL_FN #endif