Ruby 4.1.0dev (2026-09-11 revision f3ebfe5d36e70ef36d6633a009173175b2b60460)
gc.h
1#ifndef GC_GC_H
2#define GC_GC_H
12#include "ruby/ruby.h"
13#include "ruby/assert.h"
14
15#include "ruby/thread_native.h"
16#include "ruby/debug.h"
17
18#ifndef VM_CHECK_MODE
19# define VM_CHECK_MODE RUBY_DEBUG
20#endif
21
22// From ractor_core.h
23#ifndef RACTOR_CHECK_MODE
24# define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
25#endif
26
29};
30
31typedef int (*vm_table_foreach_callback_func)(VALUE value, void *data);
32typedef int (*vm_table_update_callback_func)(VALUE *value, void *data);
33
34enum rb_gc_vm_weak_tables {
35 RB_GC_VM_CI_TABLE,
36 RB_GC_VM_OVERLOADED_CME_TABLE,
37 RB_GC_VM_GLOBAL_SYMBOLS_TABLE,
38 RB_GC_VM_GENERIC_FIELDS_TABLE,
39 RB_GC_VM_FROZEN_STRINGS_TABLE,
40 RB_GC_VM_WEAK_TABLE_COUNT
41};
42
43#define RB_GC_VM_LOCK() rb_gc_vm_lock(__FILE__, __LINE__)
44#define RB_GC_VM_UNLOCK(lev) rb_gc_vm_unlock(lev, __FILE__, __LINE__)
45#define RB_GC_VM_LOCK_NO_BARRIER() rb_gc_vm_lock_no_barrier(__FILE__, __LINE__)
46#define RB_GC_VM_UNLOCK_NO_BARRIER(lev) rb_gc_vm_unlock_no_barrier(lev, __FILE__, __LINE__)
47
48#if USE_MODULAR_GC
49# define MODULAR_GC_FN
50#else
51// This takes advantage of internal linkage winning when appearing first.
52// See C99 6.2.2p4.
53# define MODULAR_GC_FN static
54#endif
55
56#if USE_MODULAR_GC
57RUBY_SYMBOL_EXPORT_BEGIN
58#endif
59
60// These functions cannot be defined as static because they are used by other
61// files in Ruby.
62size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
63void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
64const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
65const char *rb_obj_info(VALUE obj);
66size_t rb_obj_memsize_of(VALUE obj);
67bool ruby_free_at_exit_p(void);
68void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
69void rb_gc_verify_shareable(VALUE);
70
71MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
72MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
73MODULAR_GC_FN unsigned int rb_gc_vm_lock_no_barrier(const char *file, int line);
74MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line);
75MODULAR_GC_FN void rb_gc_vm_barrier(void);
76MODULAR_GC_FN void rb_gc_vm_each_objspace(void (*func)(void *objspace, void *data), void *data);
77MODULAR_GC_FN size_t rb_gc_vm_zombie_total_pages(void);
78MODULAR_GC_FN unsigned int rb_gc_vm_ractor_count(void);
79MODULAR_GC_FN void rb_gc_vm_refresh_zombie_pages(void);
80/* No MODULAR_GC_FN: the VM side (ractor.c) calls this too, so it needs external
81 * linkage even in a non-modular build (see internal/gc.h). */
82bool rb_gc_single_objspace_p(void);
83/* Clear the "absorbed" flag once a global GC finishes (see rb_gc_single_objspace_p).
84 * No MODULAR_GC_FN, for the same reason as above. */
85void rb_gc_reset_absorbed_since_global_gc(void);
86MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj);
87MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj);
88MODULAR_GC_FN void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table);
89/* The global GC's weak pass over generic_fields (called from a gc-impl). */
90MODULAR_GC_FN void rb_gc_vm_generic_fields_mark_foreach(int (*cb)(VALUE key, VALUE val, void *arg), void *arg);
91MODULAR_GC_FN void rb_gc_vm_generic_fields_drain_dead(bool (*is_dead)(VALUE key));
92/* Exemptions for the shareable containment verifier (called from a gc-impl). */
93MODULAR_GC_FN VALUE rb_gc_vm_top_self(void);
94MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj);
95MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);
96MODULAR_GC_FN void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
97MODULAR_GC_FN void *rb_gc_get_objspace(void);
98MODULAR_GC_FN void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
99MODULAR_GC_FN void rb_gc_set_pending_interrupt(void);
100MODULAR_GC_FN void rb_gc_trigger_finalize_deferred(void *objspace, rb_postponed_job_handle_t pjob);
101MODULAR_GC_FN void rb_gc_unset_pending_interrupt(void);
102MODULAR_GC_FN void rb_gc_obj_free_vm_weak_references(VALUE obj);
103MODULAR_GC_FN bool rb_gc_obj_free(void *objspace, VALUE obj);
104MODULAR_GC_FN void rb_gc_save_machine_context(void);
105MODULAR_GC_FN void rb_gc_mark_roots(void *objspace, const char **categoryp);
106MODULAR_GC_FN bool rb_gc_multi_ractor_p(void);
107MODULAR_GC_FN bool rb_gc_ever_multi_ractor_p(void);
108/* Process-wide GC disable flag (GC.disable / rb_gc_disable). Every GC trigger in
109 * an impl checks it, so disabling stops automatic GC in every Ractor. The
110 * per-objspace switch is objspace->flags.dont_gc. */
111MODULAR_GC_FN bool rb_gc_gc_disabled_global_p(void);
112MODULAR_GC_FN bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
113MODULAR_GC_FN void rb_gc_obj_changed_slot_size(VALUE obj, size_t slot_size);
114MODULAR_GC_FN void rb_gc_prepare_heap_process_object(VALUE obj);
115MODULAR_GC_FN bool rb_memerror_reentered(void);
116MODULAR_GC_FN bool rb_obj_id_p(VALUE);
117MODULAR_GC_FN void rb_gc_before_updating_jit_code(void);
118MODULAR_GC_FN void rb_gc_after_updating_jit_code(void);
119MODULAR_GC_FN bool rb_gc_obj_shareable_p(VALUE);
120MODULAR_GC_FN void rb_gc_rp(VALUE);
121MODULAR_GC_FN void rb_gc_handle_weak_references(VALUE obj);
122MODULAR_GC_FN bool rb_gc_obj_needs_cleanup_p(VALUE obj);
123
124void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
125#if USE_MODULAR_GC
126MODULAR_GC_FN bool rb_gc_event_hook_required_p(rb_event_flag_t event);
127MODULAR_GC_FN void *rb_gc_get_ractor_newobj_cache(void);
128MODULAR_GC_FN void rb_gc_move_obj_during_marking(VALUE from, VALUE to);
129MODULAR_GC_FN void rb_gc_print_backtrace();
130#endif
131
132#if USE_MODULAR_GC
133RUBY_SYMBOL_EXPORT_END
134#endif
135
136void rb_ractor_finish_marking(bool full_mark);
137
138// -------------------Private section begin------------------------
139// Functions in this section are private to the default GC and gc.c
140
141#ifdef BUILDING_MODULAR_GC
143RBIMPL_WARNING_IGNORED(-Wunused-function)
144#endif
145
146/* RGENGC_CHECK_MODE
147 * 0: disable all assertions
148 * 1: enable assertions (to debug RGenGC)
149 * 2: enable internal consistency check at each GC (for debugging)
150 * 3: enable internal consistency check at each GC steps (for debugging)
151 * 4: enable liveness check
152 * 5: show all references
153 */
154#ifndef RGENGC_CHECK_MODE
155# define RGENGC_CHECK_MODE 0
156#endif
157
158#ifndef GC_ASSERT
159# define GC_ASSERT(expr, ...) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
160#endif
161
162static int
163hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
164{
165 if (rb_gc_location((VALUE)value) != (VALUE)value) {
166 return ST_REPLACE;
167 }
168 return ST_CONTINUE;
169}
170
171static int
172hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
173{
174 rb_gc_update_moved((VALUE *)value);
175
176 return ST_CONTINUE;
177}
178
179static void
180gc_ref_update_table_values_only(st_table *tbl)
181{
182 if (!tbl || tbl->num_entries == 0) return;
183
184 if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, 0)) {
185 rb_raise(rb_eRuntimeError, "hash modified during iteration");
186 }
187}
188
189static int
190gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
191{
192 rb_gc_mark_movable((VALUE)value);
193
194 return ST_CONTINUE;
195}
196
197static int
198gc_mark_set_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
199{
200 rb_gc_mark_movable((VALUE)key);
201
202 return ST_CONTINUE;
203}
204
205static int
206hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
207{
208 if (rb_gc_location((VALUE)key) != (VALUE)key) {
209 return ST_REPLACE;
210 }
211
212 if (rb_gc_location((VALUE)value) != (VALUE)value) {
213 return ST_REPLACE;
214 }
215
216 return ST_CONTINUE;
217}
218
219static int
220hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
221{
222 rb_gc_update_moved((VALUE *)key);
223 rb_gc_update_moved((VALUE *)value);
224
225 return ST_CONTINUE;
226}
227
228static void
229gc_update_table_refs(st_table *tbl)
230{
231 if (!tbl || tbl->num_entries == 0) return;
232
233 if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, 0)) {
234 rb_raise(rb_eRuntimeError, "hash modified during iteration");
235 }
236}
237
238static inline size_t
239xmalloc2_size(const size_t count, const size_t elsize)
240{
241 return rb_size_mul_or_raise(count, elsize, rb_eArgError);
242}
243
244static VALUE
245type_sym(size_t type)
246{
247 switch (type) {
248#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break;
249 COUNT_TYPE(T_NONE);
250 COUNT_TYPE(T_OBJECT);
251 COUNT_TYPE(T_CLASS);
252 COUNT_TYPE(T_MODULE);
253 COUNT_TYPE(T_FLOAT);
254 COUNT_TYPE(T_STRING);
255 COUNT_TYPE(T_REGEXP);
256 COUNT_TYPE(T_ARRAY);
257 COUNT_TYPE(T_HASH);
258 COUNT_TYPE(T_STRUCT);
259 COUNT_TYPE(T_BIGNUM);
260 COUNT_TYPE(T_FILE);
261 COUNT_TYPE(T_DATA);
262 COUNT_TYPE(T_MATCH);
263 COUNT_TYPE(T_COMPLEX);
264 COUNT_TYPE(T_RATIONAL);
265 COUNT_TYPE(T_NIL);
266 COUNT_TYPE(T_TRUE);
267 COUNT_TYPE(T_FALSE);
268 COUNT_TYPE(T_SYMBOL);
269 COUNT_TYPE(T_FIXNUM);
270 COUNT_TYPE(T_IMEMO);
271 COUNT_TYPE(T_UNDEF);
272 COUNT_TYPE(T_NODE);
273 COUNT_TYPE(T_ICLASS);
274 COUNT_TYPE(T_ZOMBIE);
275 COUNT_TYPE(T_MOVED);
276#undef COUNT_TYPE
277 default: return SIZET2NUM(type); break;
278 }
279}
280
281#ifdef BUILDING_MODULAR_GC
283#endif
284// -------------------Private section end------------------------
285
286#endif
unsigned int rb_postponed_job_handle_t
The type of a handle returned from rb_postponed_job_preregister and passed to rb_postponed_job_trigge...
Definition debug.h:703
uint32_t rb_event_flag_t
Represents event(s).
Definition event.h:108
#define T_COMPLEX
Old name of RUBY_T_COMPLEX.
Definition value_type.h:59
#define T_FILE
Old name of RUBY_T_FILE.
Definition value_type.h:62
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define T_NIL
Old name of RUBY_T_NIL.
Definition value_type.h:72
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition value_type.h:64
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
#define T_STRUCT
Old name of RUBY_T_STRUCT.
Definition value_type.h:79
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition value_type.h:63
#define T_DATA
Old name of RUBY_T_DATA.
Definition value_type.h:60
#define T_NONE
Old name of RUBY_T_NONE.
Definition value_type.h:74
#define T_NODE
Old name of RUBY_T_NODE.
Definition value_type.h:73
#define SIZET2NUM
Old name of RB_SIZE2NUM.
Definition size_t.h:62
#define T_MODULE
Old name of RUBY_T_MODULE.
Definition value_type.h:70
#define T_TRUE
Old name of RUBY_T_TRUE.
Definition value_type.h:81
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
#define T_HASH
Old name of RUBY_T_HASH.
Definition value_type.h:65
#define T_FALSE
Old name of RUBY_T_FALSE.
Definition value_type.h:61
#define T_UNDEF
Old name of RUBY_T_UNDEF.
Definition value_type.h:82
#define T_ZOMBIE
Old name of RUBY_T_ZOMBIE.
Definition value_type.h:83
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition value_type.h:80
#define T_MATCH
Old name of RUBY_T_MATCH.
Definition value_type.h:69
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
#define T_MOVED
Old name of RUBY_T_MOVED.
Definition value_type.h:71
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition value_type.h:77
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1461
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition st.h:79
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
#define RBIMPL_WARNING_PUSH()
Pushes compiler warning state.
#define RBIMPL_WARNING_POP()
Pops compiler warning state.