11#include "ruby/internal/config.h"
15#include "internal/compilers.h"
19#if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__)
20#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
21#elif defined(__i386) && defined(__GNUC__)
22#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p)))
23#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && !defined(_AIX) && !defined(__APPLE__)
24#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr\t%0, %%r1" : "=r" (*(p)))
25#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && defined(_AIX)
26#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr %0,1" : "=r" (*(p)))
27#elif defined(__POWERPC__) && defined(__APPLE__)
28#define SET_MACHINE_STACK_END(p) __asm__ volatile("mr %0, r1" : "=r" (*(p)))
29#elif defined(__aarch64__) && defined(__GNUC__)
30#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mov\t%0, sp" : "=r" (*(p)))
32NOINLINE(
void rb_gc_set_stack_end(
VALUE **stack_end_p));
33#define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p)
34#define USE_CONSERVATIVE_STACK_END
39#ifndef RUBY_MARK_FREE_DEBUG
40#define RUBY_MARK_FREE_DEBUG 0
43#if RUBY_MARK_FREE_DEBUG
44extern int ruby_gc_debug_indent;
47rb_gc_debug_indent(
void)
49 ruby_debug_printf(
"%*s", ruby_gc_debug_indent,
"");
53rb_gc_debug_body(
const char *mode,
const char *msg,
int st,
void *ptr)
56 ruby_gc_debug_indent--;
59 ruby_debug_printf(
"%s: %s %s (%p)\n", mode, st ?
"->" :
"<-", msg, ptr);
62 ruby_gc_debug_indent++;
68#define RUBY_MARK_ENTER(msg) rb_gc_debug_body("mark", (msg), 1, ptr)
69#define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", (msg), 0, ptr)
70#define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", (msg), 1, ptr)
71#define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", (msg), 0, ptr)
72#define RUBY_GC_INFO rb_gc_debug_indent(), ruby_debug_printf
75#define RUBY_MARK_ENTER(msg)
76#define RUBY_MARK_LEAVE(msg)
77#define RUBY_FREE_ENTER(msg)
78#define RUBY_FREE_LEAVE(msg)
79#define RUBY_GC_INFO if(0)printf
82#define RUBY_MARK_MOVABLE_UNLESS_NULL(ptr) do { \
83 VALUE markobj = (ptr); \
84 if (RTEST(markobj)) {rb_gc_mark_movable(markobj);} \
86#define RUBY_MARK_UNLESS_NULL(ptr) do { \
87 VALUE markobj = (ptr); \
88 if (RTEST(markobj)) {rb_gc_mark(markobj);} \
90#define RUBY_FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);(ptr)=NULL;}
92#if STACK_GROW_DIRECTION > 0
93# define STACK_UPPER(x, a, b) (a)
94#elif STACK_GROW_DIRECTION < 0
95# define STACK_UPPER(x, a, b) (b)
98int ruby_get_stack_grow_direction(
volatile VALUE *addr);
99# define stack_growup_p(x) ( \
100 (ruby_stack_grow_direction ? \
101 ruby_stack_grow_direction : \
102 ruby_get_stack_grow_direction(x)) > 0)
103# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? (a) : (b))
114#if STACK_GROW_DIRECTION
115#define STACK_GROW_DIR_DETECTION
116#define STACK_DIR_UPPER(a,b) STACK_UPPER(0, (a), (b))
118#define STACK_GROW_DIR_DETECTION VALUE stack_grow_dir_detection
119#define STACK_DIR_UPPER(a,b) STACK_UPPER(&stack_grow_dir_detection, (a), (b))
121#define IS_STACK_DIR_UPPER() STACK_DIR_UPPER(1,0)
123const char *rb_obj_info(
VALUE obj);
124const char *rb_raw_obj_info(
char *
const buff,
const size_t buff_size,
VALUE obj);
126size_t rb_size_pool_slot_size(
unsigned char pool_id);
136#define NEWOBJ_OF_0(var, T, c, f, s, ec) \
137 T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
138 rb_wb_protected_newobj_of(GET_EC(), (c), (f) & ~FL_WB_PROTECTED, s) : \
139 rb_wb_unprotected_newobj_of((c), (f), s))
140#define NEWOBJ_OF_ec(var, T, c, f, s, ec) \
141 T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
142 rb_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, s) : \
143 rb_wb_unprotected_newobj_of((c), (f), s))
145#define NEWOBJ_OF(var, T, c, f, s, ec) \
146 NEWOBJ_OF_HELPER(ec)(var, T, c, f, s, ec)
148#define NEWOBJ_OF_HELPER(ec) NEWOBJ_OF_ ## ec
150#define RB_OBJ_GC_FLAGS_MAX 6
152#ifndef USE_UNALIGNED_MEMBER_ACCESS
153# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
154#elif ! USE_UNALIGNED_MEMBER_ACCESS
155# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
156#elif ! (__has_warning("-Waddress-of-packed-member") || GCC_VERSION_SINCE(9, 0, 0))
157# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
159# include "internal/warnings.h"
160# define UNALIGNED_MEMBER_ACCESS(expr) __extension__({ \
161 COMPILER_WARNING_PUSH; \
162 COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \
163 __typeof__(expr) unaligned_member_access_result = (expr); \
164 COMPILER_WARNING_POP; \
165 unaligned_member_access_result; \
168# define UNALIGNED_MEMBER_PTR(ptr, mem) __extension__({ \
169 COMPILER_WARNING_PUSH; \
170 COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \
171 const volatile void *unaligned_member_ptr_result = &(ptr)->mem; \
172 COMPILER_WARNING_POP; \
173 (__typeof__((ptr)->mem) *)unaligned_member_ptr_result; \
177#ifndef UNALIGNED_MEMBER_PTR
178# define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem)
181#define RB_OBJ_WRITE_UNALIGNED(old, slot, young) do { \
182 VALUE *_slot = UNALIGNED_MEMBER_ACCESS(slot); \
183 RB_OBJ_WRITE(old, _slot, young); \
188#ifndef SIZE_POOL_COUNT
189# define SIZE_POOL_COUNT 5
196#define DURING_GC_COULD_MALLOC_REGION_START() \
197 assert(rb_during_gc()); \
198 VALUE _already_disabled = rb_gc_disable_no_rest()
200#define DURING_GC_COULD_MALLOC_REGION_END() \
201 if (_already_disabled == Qfalse) rb_gc_enable()
206} rb_ractor_newobj_size_pool_cache_t;
209 size_t incremental_mark_step_allocated_slots;
210 rb_ractor_newobj_size_pool_cache_t size_pool_caches[SIZE_POOL_COUNT];
211} rb_ractor_newobj_cache_t;
214extern VALUE *ruby_initial_gc_stress_ptr;
215extern int ruby_disable_gc;
216RUBY_ATTR_MALLOC
void *ruby_mimmalloc(
size_t size);
217void ruby_mimfree(
void *ptr);
218void rb_gc_prepare_heap(
void);
220VALUE rb_objspace_gc_enable(
struct rb_objspace *);
221VALUE rb_objspace_gc_disable(
struct rb_objspace *);
222void ruby_gc_set_params(
void);
223void rb_copy_wb_protected_attribute(
VALUE dest,
VALUE obj);
224#if __has_attribute(alloc_align)
227RUBY_ATTR_MALLOC
void *rb_aligned_malloc(
size_t,
size_t) RUBY_ATTR_ALLOC_SIZE((2));
228size_t rb_size_mul_or_raise(
size_t,
size_t,
VALUE);
229size_t rb_size_mul_add_or_raise(
size_t,
size_t,
size_t,
VALUE);
230size_t rb_malloc_grow_capa(
size_t current_capacity,
size_t type_size);
231RUBY_ATTR_MALLOC
void *rb_xmalloc_mul_add(
size_t,
size_t,
size_t);
232RUBY_ATTR_MALLOC
void *rb_xcalloc_mul_add(
size_t,
size_t,
size_t);
233void *rb_xrealloc_mul_add(
const void *,
size_t,
size_t,
size_t);
234RUBY_ATTR_MALLOC
void *rb_xmalloc_mul_add_mul(
size_t,
size_t,
size_t,
size_t);
235RUBY_ATTR_MALLOC
void *rb_xcalloc_mul_add_mul(
size_t,
size_t,
size_t,
size_t);
236static inline void *ruby_sized_xrealloc_inlined(
void *ptr,
size_t new_size,
size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
237static inline void *ruby_sized_xrealloc2_inlined(
void *ptr,
size_t new_count,
size_t elemsiz,
size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
238static inline void ruby_sized_xfree_inlined(
void *ptr,
size_t size);
240void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache);
241size_t rb_gc_obj_slot_size(
VALUE obj);
242bool rb_gc_size_allocatable_p(
size_t size);
243int rb_objspace_garbage_object_p(
VALUE obj);
244bool rb_gc_is_ptr_to_obj(
void *ptr);
248void rb_gc_mark_and_move(
VALUE *ptr);
250void rb_gc_mark_weak(
VALUE *ptr);
251void rb_gc_remove_weak(
VALUE parent_obj,
VALUE *ptr);
253void rb_gc_ref_update_table_values_only(st_table *tbl);
255#define rb_gc_mark_and_move_ptr(ptr) do { \
256 VALUE _obj = (VALUE)*(ptr); \
257 rb_gc_mark_and_move(&_obj); \
258 if (_obj != (VALUE)*(ptr)) *(ptr) = (void *)_obj; \
261RUBY_SYMBOL_EXPORT_BEGIN
263size_t rb_objspace_data_type_memsize(
VALUE obj);
264void rb_objspace_reachable_objects_from(
VALUE obj,
void (func)(
VALUE,
void *),
void *data);
265void rb_objspace_reachable_objects_from_root(
void (func)(
const char *category,
VALUE,
void *),
void *data);
266int rb_objspace_markable_object_p(
VALUE obj);
267int rb_objspace_internal_object_p(
VALUE obj);
268int rb_objspace_marked_object_p(
VALUE obj);
270void rb_objspace_each_objects(
271 int (*callback)(
void *start,
void *end,
size_t stride,
void *data),
274void rb_objspace_each_objects_without_setup(
275 int (*callback)(
void *,
void *,
size_t,
void *),
278size_t rb_gc_obj_slot_size(
VALUE obj);
280VALUE rb_gc_disable_no_rest(
void);
284const char *rb_objspace_data_type_name(
VALUE obj);
287size_t rb_obj_memsize_of(
VALUE);
288void rb_gc_verify_internal_consistency(
void);
289size_t rb_obj_gc_flags(
VALUE,
ID[],
size_t);
290void rb_gc_mark_values(
long n,
const VALUE *values);
291void rb_gc_mark_vm_stack_values(
long n,
const VALUE *values);
292void rb_gc_update_values(
long n,
VALUE *values);
293void *ruby_sized_xrealloc(
void *ptr,
size_t new_size,
size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
294void *ruby_sized_xrealloc2(
void *ptr,
size_t new_count,
size_t element_size,
size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
295void ruby_sized_xfree(
void *x,
size_t size);
296RUBY_SYMBOL_EXPORT_END
299void rb_gc_writebarrier_remember(
VALUE obj);
300const char *rb_obj_info(
VALUE obj);
302#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32)
305ruby_sized_xrealloc_inlined(
void *ptr,
size_t new_size,
size_t old_size)
307 return ruby_xrealloc(ptr, new_size);
311ruby_sized_xrealloc2_inlined(
void *ptr,
size_t new_count,
size_t elemsiz,
size_t old_count)
313 return ruby_xrealloc2(ptr, new_count, elemsiz);
317ruby_sized_xfree_inlined(
void *ptr,
size_t size)
322# define SIZED_REALLOC_N(x, y, z, w) REALLOC_N(x, y, z)
325ruby_sized_realloc_n(
void *ptr,
size_t new_count,
size_t element_size,
size_t old_count)
327 return ruby_xrealloc2(ptr, new_count, element_size);
333ruby_sized_xrealloc_inlined(
void *ptr,
size_t new_size,
size_t old_size)
335 return ruby_sized_xrealloc(ptr, new_size, old_size);
339ruby_sized_xrealloc2_inlined(
void *ptr,
size_t new_count,
size_t elemsiz,
size_t old_count)
341 return ruby_sized_xrealloc2(ptr, new_count, elemsiz, old_count);
345ruby_sized_xfree_inlined(
void *ptr,
size_t size)
347 ruby_sized_xfree(ptr, size);
350# define SIZED_REALLOC_N(v, T, m, n) \
351 ((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n)))
354ruby_sized_realloc_n(
void *ptr,
size_t new_count,
size_t element_size,
size_t old_count)
356 return ruby_sized_xrealloc2(ptr, new_count, element_size, old_count);
361#define ruby_sized_xrealloc ruby_sized_xrealloc_inlined
362#define ruby_sized_xrealloc2 ruby_sized_xrealloc2_inlined
363#define ruby_sized_xfree ruby_sized_xfree_inlined
#define RUBY_EXTERN
Declaration of externally visible global variables.
uint32_t rb_event_flag_t
Represents event(s).
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.