Ruby 4.1.0dev (2026-09-27 revision b58bea071d47d44220efd6e71a3d8584963640c3)
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
71typedef void (*rb_gc_registered_addr_cb)(VALUE *slot, VALUE initial_value, void *owner_objspace, void *data);
72
73MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
74MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
75MODULAR_GC_FN unsigned int rb_gc_vm_lock_no_barrier(const char *file, int line);
76MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line);
77MODULAR_GC_FN void rb_gc_vm_barrier(void);
78MODULAR_GC_FN void rb_gc_vm_each_objspace(void (*func)(void *objspace, void *data), void *data);
79MODULAR_GC_FN void rb_gc_each_registered_addr(rb_gc_registered_addr_cb func, void *data);
80/* Verifier support, valid only with the world stopped (no extra locking inside). */
81MODULAR_GC_FN bool rb_gc_registered_addr_owned_by_registrant_p(VALUE *addr, void *objspace);
82MODULAR_GC_FN bool rb_gc_vm_zombie_objspace_p(void *objspace);
83MODULAR_GC_FN size_t rb_gc_vm_zombie_total_pages(void);
84MODULAR_GC_FN unsigned int rb_gc_vm_ractor_count(void);
85MODULAR_GC_FN void rb_gc_vm_refresh_zombie_pages(void);
86/* No MODULAR_GC_FN: the VM side (ractor.c) calls this too, so it needs external
87 * linkage even in a non-modular build (see internal/gc.h). */
88bool rb_gc_single_objspace_p(void);
89/* Clear the "absorbed" flag once a global GC finishes (see rb_gc_single_objspace_p).
90 * No MODULAR_GC_FN, for the same reason as above. */
91void rb_gc_reset_absorbed_since_global_gc(void);
92MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj);
93MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj);
94MODULAR_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);
95/* The global GC's weak pass over generic_fields (called from a gc-impl). */
96MODULAR_GC_FN void rb_gc_vm_generic_fields_mark_foreach(int (*cb)(VALUE key, VALUE val, void *arg), void *arg);
97MODULAR_GC_FN void rb_gc_vm_generic_fields_drain_dead(bool (*is_dead)(VALUE key));
98/* Exemptions for the shareable containment verifier (called from a gc-impl). */
99MODULAR_GC_FN VALUE rb_gc_vm_top_self(void);
100MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj);
101MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);
102MODULAR_GC_FN void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
103MODULAR_GC_FN void *rb_gc_get_objspace(void);
104MODULAR_GC_FN void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
105MODULAR_GC_FN void rb_gc_set_pending_interrupt(void);
106MODULAR_GC_FN void rb_gc_trigger_finalize_deferred(void *objspace, rb_postponed_job_handle_t pjob);
107MODULAR_GC_FN void rb_gc_trigger_postponed_job_on_main(rb_postponed_job_handle_t pjob);
108MODULAR_GC_FN void rb_gc_unset_pending_interrupt(void);
109MODULAR_GC_FN void rb_gc_obj_free_vm_weak_references(VALUE obj);
110MODULAR_GC_FN bool rb_gc_obj_free(void *objspace, VALUE obj);
111MODULAR_GC_FN void rb_gc_save_machine_context(void);
112MODULAR_GC_FN void rb_gc_mark_roots(void *objspace, const char **categoryp);
113MODULAR_GC_FN bool rb_gc_multi_ractor_p(void);
114MODULAR_GC_FN bool rb_gc_ever_multi_ractor_p(void);
115/* Process-wide GC disable flag (GC.disable / rb_gc_disable). Every GC trigger in
116 * an impl checks it, so disabling stops automatic GC in every Ractor. The
117 * per-objspace switch is objspace->flags.dont_gc. */
118MODULAR_GC_FN bool rb_gc_gc_disabled_global_p(void);
119MODULAR_GC_FN bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
120MODULAR_GC_FN void rb_gc_obj_changed_slot_size(VALUE obj, size_t slot_size);
121MODULAR_GC_FN void rb_gc_prepare_heap_process_object(VALUE obj);
122MODULAR_GC_FN bool rb_memerror_reentered(void);
123MODULAR_GC_FN bool rb_obj_id_p(VALUE);
124MODULAR_GC_FN void rb_gc_before_updating_jit_code(void);
125MODULAR_GC_FN void rb_gc_after_updating_jit_code(void);
126MODULAR_GC_FN bool rb_gc_obj_shareable_p(VALUE);
127MODULAR_GC_FN void rb_gc_rp(VALUE);
128MODULAR_GC_FN void rb_gc_handle_weak_references(VALUE obj);
129MODULAR_GC_FN bool rb_gc_obj_needs_cleanup_p(VALUE obj);
130
131/* True when a dead T_DATA of this type cannot have its dfree run during a parallel
132 * local sweep. Such a type is never embedded, which lets the sweep reclaim the slot
133 * immediately. */
134static inline bool
135rb_gc_data_type_deferred_free_p(const rb_data_type_t *type)
136{
137 void (*dfree)(void *) = type->function.dfree;
138 if (!dfree || dfree == RUBY_DEFAULT_FREE) return false;
139 return !(type->flags & RUBY_TYPED_THREAD_SAFE_FREE);
140}
141
142void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
143#if USE_MODULAR_GC
144MODULAR_GC_FN bool rb_gc_event_hook_required_p(rb_event_flag_t event);
145MODULAR_GC_FN void *rb_gc_get_ractor_newobj_cache(void);
146MODULAR_GC_FN void rb_gc_move_obj_during_marking(VALUE from, VALUE to);
147MODULAR_GC_FN void rb_gc_print_backtrace();
148#endif
149
150#if USE_MODULAR_GC
151RUBY_SYMBOL_EXPORT_END
152#endif
153
154void rb_ractor_finish_marking(bool full_mark);
155
156// -------------------Private section begin------------------------
157// Functions in this section are private to the default GC and gc.c
158
159#ifdef BUILDING_MODULAR_GC
161RBIMPL_WARNING_IGNORED(-Wunused-function)
162#endif
163
164/* RGENGC_CHECK_MODE
165 * 0: disable all assertions
166 * 1: enable assertions (to debug RGenGC)
167 * 2: enable internal consistency check at each GC (for debugging)
168 * 3: enable internal consistency check at each GC steps (for debugging)
169 * 4: enable liveness check
170 * 5: show all references
171 */
172#ifndef RGENGC_CHECK_MODE
173# define RGENGC_CHECK_MODE 0
174#endif
175
176#ifndef GC_ASSERT
177# define GC_ASSERT(expr, ...) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
178#endif
179
180static int
181hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
182{
183 if (rb_gc_location((VALUE)value) != (VALUE)value) {
184 return ST_REPLACE;
185 }
186 return ST_CONTINUE;
187}
188
189static int
190hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
191{
192 rb_gc_update_moved((VALUE *)value);
193
194 return ST_CONTINUE;
195}
196
197static void
198gc_ref_update_table_values_only(st_table *tbl)
199{
200 if (!tbl || tbl->num_entries == 0) return;
201
202 if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, 0)) {
203 rb_raise(rb_eRuntimeError, "hash modified during iteration");
204 }
205}
206
207static int
208gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
209{
210 rb_gc_mark_movable((VALUE)value);
211
212 return ST_CONTINUE;
213}
214
215static int
216gc_mark_set_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
217{
218 rb_gc_mark_movable((VALUE)key);
219
220 return ST_CONTINUE;
221}
222
223static int
224hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
225{
226 if (rb_gc_location((VALUE)key) != (VALUE)key) {
227 return ST_REPLACE;
228 }
229
230 if (rb_gc_location((VALUE)value) != (VALUE)value) {
231 return ST_REPLACE;
232 }
233
234 return ST_CONTINUE;
235}
236
237static int
238hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
239{
240 rb_gc_update_moved((VALUE *)key);
241 rb_gc_update_moved((VALUE *)value);
242
243 return ST_CONTINUE;
244}
245
246static void
247gc_update_table_refs(st_table *tbl)
248{
249 if (!tbl || tbl->num_entries == 0) return;
250
251 if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, 0)) {
252 rb_raise(rb_eRuntimeError, "hash modified during iteration");
253 }
254}
255
256static inline size_t
257xmalloc2_size(const size_t count, const size_t elsize)
258{
259 return rb_size_mul_or_raise(count, elsize, rb_eArgError);
260}
261
262static VALUE
263type_sym(size_t type)
264{
265 switch (type) {
266#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break;
267 COUNT_TYPE(T_NONE);
268 COUNT_TYPE(T_OBJECT);
269 COUNT_TYPE(T_CLASS);
270 COUNT_TYPE(T_MODULE);
271 COUNT_TYPE(T_FLOAT);
272 COUNT_TYPE(T_STRING);
273 COUNT_TYPE(T_REGEXP);
274 COUNT_TYPE(T_ARRAY);
275 COUNT_TYPE(T_HASH);
276 COUNT_TYPE(T_STRUCT);
277 COUNT_TYPE(T_BIGNUM);
278 COUNT_TYPE(T_FILE);
279 COUNT_TYPE(T_DATA);
280 COUNT_TYPE(T_MATCH);
281 COUNT_TYPE(T_COMPLEX);
282 COUNT_TYPE(T_RATIONAL);
283 COUNT_TYPE(T_NIL);
284 COUNT_TYPE(T_TRUE);
285 COUNT_TYPE(T_FALSE);
286 COUNT_TYPE(T_SYMBOL);
287 COUNT_TYPE(T_FIXNUM);
288 COUNT_TYPE(T_IMEMO);
289 COUNT_TYPE(T_UNDEF);
290 COUNT_TYPE(T_NODE);
291 COUNT_TYPE(T_ICLASS);
292 COUNT_TYPE(T_ZOMBIE);
293 COUNT_TYPE(T_MOVED);
294#undef COUNT_TYPE
295 default: return SIZET2NUM(type); break;
296 }
297}
298
299#ifdef BUILDING_MODULAR_GC
301#endif
302// -------------------Private section end------------------------
303
304#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:1471
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RUBY_DEFAULT_FREE
This is a value you can set to RData::dfree.
Definition rdata.h:56
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:242
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.