Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)
gc.h
1#ifndef GC_GC_H
2#define GC_GC_H
12#include "ruby/ruby.h"
13
14#if USE_MODULAR_GC
15#include "ruby/thread_native.h"
16
17struct rb_gc_vm_context {
18 rb_nativethread_lock_t lock;
19
20 struct rb_execution_context_struct *ec;
21};
22#endif
23
24typedef int (*vm_table_foreach_callback_func)(VALUE value, void *data);
25typedef int (*vm_table_update_callback_func)(VALUE *value, void *data);
26
27enum rb_gc_vm_weak_tables {
28 RB_GC_VM_CI_TABLE,
29 RB_GC_VM_OVERLOADED_CME_TABLE,
30 RB_GC_VM_GLOBAL_SYMBOLS_TABLE,
31 RB_GC_VM_ID2REF_TABLE,
32 RB_GC_VM_GENERIC_FIELDS_TABLE,
33 RB_GC_VM_FROZEN_STRINGS_TABLE,
34 RB_GC_VM_CC_REFINEMENT_TABLE,
35 RB_GC_VM_WEAK_TABLE_COUNT
36};
37
38#define RB_GC_VM_LOCK() rb_gc_vm_lock(__FILE__, __LINE__)
39#define RB_GC_VM_UNLOCK(lev) rb_gc_vm_unlock(lev, __FILE__, __LINE__)
40#define RB_GC_CR_LOCK() rb_gc_cr_lock(__FILE__, __LINE__)
41#define RB_GC_CR_UNLOCK(lev) rb_gc_cr_unlock(lev, __FILE__, __LINE__)
42#define RB_GC_VM_LOCK_NO_BARRIER() rb_gc_vm_lock_no_barrier(__FILE__, __LINE__)
43#define RB_GC_VM_UNLOCK_NO_BARRIER(lev) rb_gc_vm_unlock_no_barrier(lev, __FILE__, __LINE__)
44
45#if USE_MODULAR_GC
46# define MODULAR_GC_FN
47#else
48// This takes advantage of internal linkage winning when appearing first.
49// See C99 6.2.2p4.
50# define MODULAR_GC_FN static
51#endif
52
53#if USE_MODULAR_GC
54RUBY_SYMBOL_EXPORT_BEGIN
55#endif
56
57// These functions cannot be defined as static because they are used by other
58// files in Ruby.
59size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
60void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
61const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
62const char *rb_obj_info(VALUE obj);
63size_t rb_obj_memsize_of(VALUE obj);
64bool ruby_free_at_exit_p(void);
65void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
66void rb_gc_verify_shareable(VALUE);
67
68MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
69MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
70MODULAR_GC_FN unsigned int rb_gc_cr_lock(const char *file, int line);
71MODULAR_GC_FN void rb_gc_cr_unlock(unsigned int lev, const char *file, int line);
72MODULAR_GC_FN unsigned int rb_gc_vm_lock_no_barrier(const char *file, int line);
73MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line);
74MODULAR_GC_FN void rb_gc_vm_barrier(void);
75MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj);
76MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj);
77MODULAR_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);
78MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj);
79MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);
80MODULAR_GC_FN void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
81MODULAR_GC_FN void *rb_gc_get_objspace(void);
82MODULAR_GC_FN void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
83MODULAR_GC_FN void rb_gc_set_pending_interrupt(void);
84MODULAR_GC_FN void rb_gc_unset_pending_interrupt(void);
85MODULAR_GC_FN void rb_gc_obj_free_vm_weak_references(VALUE obj);
86MODULAR_GC_FN bool rb_gc_obj_free(void *objspace, VALUE obj);
87MODULAR_GC_FN void rb_gc_save_machine_context(void);
88MODULAR_GC_FN void rb_gc_mark_roots(void *objspace, const char **categoryp);
89MODULAR_GC_FN void rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data);
90MODULAR_GC_FN bool rb_gc_multi_ractor_p(void);
91MODULAR_GC_FN bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
92MODULAR_GC_FN uint32_t rb_gc_get_shape(VALUE obj);
93MODULAR_GC_FN void rb_gc_set_shape(VALUE obj, uint32_t shape_id);
94MODULAR_GC_FN uint32_t rb_gc_rebuild_shape(VALUE obj, size_t heap_id);
95MODULAR_GC_FN void rb_gc_prepare_heap_process_object(VALUE obj);
96MODULAR_GC_FN bool rb_memerror_reentered(void);
97MODULAR_GC_FN bool rb_obj_id_p(VALUE);
98MODULAR_GC_FN void rb_gc_before_updating_jit_code(void);
99MODULAR_GC_FN void rb_gc_after_updating_jit_code(void);
100MODULAR_GC_FN bool rb_gc_obj_shareable_p(VALUE);
101MODULAR_GC_FN void rb_gc_rp(VALUE);
102
103#if USE_MODULAR_GC
104MODULAR_GC_FN bool rb_gc_event_hook_required_p(rb_event_flag_t event);
105MODULAR_GC_FN void *rb_gc_get_ractor_newobj_cache(void);
106MODULAR_GC_FN void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
107MODULAR_GC_FN void rb_gc_worker_thread_set_vm_context(struct rb_gc_vm_context *context);
108MODULAR_GC_FN void rb_gc_worker_thread_unset_vm_context(struct rb_gc_vm_context *context);
109#endif
110
111#if USE_MODULAR_GC
112RUBY_SYMBOL_EXPORT_END
113#endif
114
115void rb_ractor_finish_marking(void);
116
117// -------------------Private section begin------------------------
118// Functions in this section are private to the default GC and gc.c
119
120#ifdef BUILDING_MODULAR_GC
122RBIMPL_WARNING_IGNORED(-Wunused-function)
123#endif
124
125/* RGENGC_CHECK_MODE
126 * 0: disable all assertions
127 * 1: enable assertions (to debug RGenGC)
128 * 2: enable internal consistency check at each GC (for debugging)
129 * 3: enable internal consistency check at each GC steps (for debugging)
130 * 4: enable liveness check
131 * 5: show all references
132 */
133#ifndef RGENGC_CHECK_MODE
134# define RGENGC_CHECK_MODE 0
135#endif
136
137#ifndef GC_ASSERT
138# define GC_ASSERT(expr, ...) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
139#endif
140
141static int
142hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
143{
144 if (rb_gc_location((VALUE)value) != (VALUE)value) {
145 return ST_REPLACE;
146 }
147 return ST_CONTINUE;
148}
149
150static int
151hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
152{
153 *value = rb_gc_location((VALUE)*value);
154
155 return ST_CONTINUE;
156}
157
158static void
159gc_ref_update_table_values_only(st_table *tbl)
160{
161 if (!tbl || tbl->num_entries == 0) return;
162
163 if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, 0)) {
164 rb_raise(rb_eRuntimeError, "hash modified during iteration");
165 }
166}
167
168static int
169gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
170{
171 rb_gc_mark_movable((VALUE)value);
172
173 return ST_CONTINUE;
174}
175
176static int
177hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
178{
179 if (rb_gc_location((VALUE)key) != (VALUE)key) {
180 return ST_REPLACE;
181 }
182
183 if (rb_gc_location((VALUE)value) != (VALUE)value) {
184 return ST_REPLACE;
185 }
186
187 return ST_CONTINUE;
188}
189
190static int
191hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
192{
193 if (rb_gc_location((VALUE)*key) != (VALUE)*key) {
194 *key = rb_gc_location((VALUE)*key);
195 }
196
197 if (rb_gc_location((VALUE)*value) != (VALUE)*value) {
198 *value = rb_gc_location((VALUE)*value);
199 }
200
201 return ST_CONTINUE;
202}
203
204static void
205gc_update_table_refs(st_table *tbl)
206{
207 if (!tbl || tbl->num_entries == 0) return;
208
209 if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, 0)) {
210 rb_raise(rb_eRuntimeError, "hash modified during iteration");
211 }
212}
213
214static inline size_t
215xmalloc2_size(const size_t count, const size_t elsize)
216{
217 return rb_size_mul_or_raise(count, elsize, rb_eArgError);
218}
219
220static VALUE
221type_sym(size_t type)
222{
223 switch (type) {
224#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break;
225 COUNT_TYPE(T_NONE);
226 COUNT_TYPE(T_OBJECT);
227 COUNT_TYPE(T_CLASS);
228 COUNT_TYPE(T_MODULE);
229 COUNT_TYPE(T_FLOAT);
230 COUNT_TYPE(T_STRING);
231 COUNT_TYPE(T_REGEXP);
232 COUNT_TYPE(T_ARRAY);
233 COUNT_TYPE(T_HASH);
234 COUNT_TYPE(T_STRUCT);
235 COUNT_TYPE(T_BIGNUM);
236 COUNT_TYPE(T_FILE);
237 COUNT_TYPE(T_DATA);
238 COUNT_TYPE(T_MATCH);
239 COUNT_TYPE(T_COMPLEX);
240 COUNT_TYPE(T_RATIONAL);
241 COUNT_TYPE(T_NIL);
242 COUNT_TYPE(T_TRUE);
243 COUNT_TYPE(T_FALSE);
244 COUNT_TYPE(T_SYMBOL);
245 COUNT_TYPE(T_FIXNUM);
246 COUNT_TYPE(T_IMEMO);
247 COUNT_TYPE(T_UNDEF);
248 COUNT_TYPE(T_NODE);
249 COUNT_TYPE(T_ICLASS);
250 COUNT_TYPE(T_ZOMBIE);
251 COUNT_TYPE(T_MOVED);
252#undef COUNT_TYPE
253 default: return SIZET2NUM(type); break;
254 }
255}
256
257#ifdef BUILDING_MODULAR_GC
259#endif
260// -------------------Private section end------------------------
261
262#endif
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:1429
bool ruby_free_at_exit_p(void)
Returns whether the Ruby VM will free all memory at shutdown.
Definition vm.c:4807
VALUE type(ANYARGS)
ANYARGS-ed function type.
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.