summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2024-07-25 17:35:24 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2024-07-26 11:44:34 -0400
commit0ada02abe2c66f49159243b78994645a2936b706 (patch)
tree8df62d07aaf03d2b515a0d5120988e32b90877c3
parentcef959df905c1189dff463d74498f3bf8dbbc82e (diff)
Put the default GC implementation back into gc.o
We discovered that having gc.o and gc_impl.o in separate translation units diminishes codegen quality with GCC 11 on x86-64. This commit solves that problem by including default/gc.c into gc.c, letting the optimizer have visibility into the body of functions again in builds not using link-time optimization, which are common. This effectively restores things to the way they were before [Feature #20470] from the optimizer's perspective while maintaining the ability to build gc/default.c as a DSO. There were a few functions duplicated across gc.c and gc/default.c. Extract them and put them into gc/gc.h.
-rw-r--r--common.mk194
-rw-r--r--gc.c138
-rw-r--r--gc/default.c141
-rw-r--r--gc/gc.h146
-rw-r--r--gc/gc_impl.h148
5 files changed, 244 insertions, 523 deletions
diff --git a/common.mk b/common.mk
index b387c47a4a..a0c41e04e0 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 c67567f7e8..84c3d6dd3b 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"
@@ -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 362e5d4938..5dd7cc1df7 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)
@@ -7340,84 +7346,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)
{
@@ -8581,12 +8509,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)
{
@@ -9363,43 +9285,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
@@ -9654,14 +9539,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 5f9a7b218b..e8f3e2f6d6 100644
--- a/gc/gc.h
+++ b/gc/gc.h
@@ -1,7 +1,16 @@
#ifndef GC_GC_H
#define GC_GC_H
-
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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 18249dc58b..befeddccb6 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 <ruby-core@ruby-lang.org>
+ * @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