31 #include <sys/types.h>
35 # define __has_feature(x) 0
38 #ifndef HAVE_MALLOC_USABLE_SIZE
40 # define HAVE_MALLOC_USABLE_SIZE
41 # define malloc_usable_size(a) _msize(a)
42 # elif defined HAVE_MALLOC_SIZE
43 # define HAVE_MALLOC_USABLE_SIZE
44 # define malloc_usable_size(a) malloc_size(a)
47 #ifdef HAVE_MALLOC_USABLE_SIZE
50 # elif defined(HAVE_MALLOC_NP_H)
51 # include <malloc_np.h>
52 # elif defined(HAVE_MALLOC_MALLOC_H)
53 # include <malloc/malloc.h>
58 __has_feature(address_sanitizer) || \
59 defined(__SANITIZE_ADDRESS__)
60 #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
61 __attribute__((no_address_safety_analysis)) \
62 __attribute__((noinline))
64 #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
67 #ifdef HAVE_SYS_TIME_H
71 #ifdef HAVE_SYS_RESOURCE_H
72 #include <sys/resource.h>
74 #if defined(__native_client__) && defined(NACL_NEWLIB)
76 # undef HAVE_POSIX_MEMALIGN
81 #if defined _WIN32 || defined __CYGWIN__
83 #elif defined(HAVE_POSIX_MEMALIGN)
84 #elif defined(HAVE_MEMALIGN)
88 #define rb_setjmp(env) RUBY_SETJMP(env)
89 #define rb_jmp_buf rb_jmpbuf_t
91 #if defined(HAVE_RB_GC_GUARDED_PTR) && HAVE_RB_GC_GUARDED_PTR
99 #ifndef GC_HEAP_FREE_SLOTS
100 #define GC_HEAP_FREE_SLOTS 4096
102 #ifndef GC_HEAP_INIT_SLOTS
103 #define GC_HEAP_INIT_SLOTS 10000
105 #ifndef GC_HEAP_GROWTH_FACTOR
106 #define GC_HEAP_GROWTH_FACTOR 1.8
108 #ifndef GC_HEAP_GROWTH_MAX_SLOTS
109 #define GC_HEAP_GROWTH_MAX_SLOTS 0
111 #ifndef GC_HEAP_OLDOBJECT_LIMIT_FACTOR
112 #define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
115 #ifndef GC_MALLOC_LIMIT_MIN
116 #define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 )
118 #ifndef GC_MALLOC_LIMIT_MAX
119 #define GC_MALLOC_LIMIT_MAX (32 * 1024 * 1024 )
121 #ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR
122 #define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.4
125 #ifndef GC_OLDMALLOC_LIMIT_MIN
126 #define GC_OLDMALLOC_LIMIT_MIN (16 * 1024 * 1024 )
128 #ifndef GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
129 #define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR 1.2
131 #ifndef GC_OLDMALLOC_LIMIT_MAX
132 #define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 )
147 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
164 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
185 #define RGENGC_DEBUG 0
195 #ifndef RGENGC_CHECK_MODE
196 #define RGENGC_CHECK_MODE 0
204 #ifndef RGENGC_PROFILE
205 #define RGENGC_PROFILE 0
213 #ifndef RGENGC_THREEGEN
214 #define RGENGC_THREEGEN 0
223 #ifndef RGENGC_ESTIMATE_OLDMALLOC
224 #define RGENGC_ESTIMATE_OLDMALLOC 1
229 #define RGENGC_DEBUG 0
230 #define RGENGC_CHECK_MODE 0
231 #define RGENGC_PROFILE 0
232 #define RGENGC_THREEGEN 0
233 #define RGENGC_ESTIMATE_OLDMALLOC 0
237 #ifndef GC_PROFILE_MORE_DETAIL
238 #define GC_PROFILE_MORE_DETAIL 0
240 #ifndef GC_PROFILE_DETAIL_MEMORY
241 #define GC_PROFILE_DETAIL_MEMORY 0
243 #ifndef GC_ENABLE_LAZY_SWEEP
244 #define GC_ENABLE_LAZY_SWEEP 1
246 #ifndef CALC_EXACT_MALLOC_SIZE
247 #define CALC_EXACT_MALLOC_SIZE 0
249 #if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0
250 #ifndef MALLOC_ALLOCATED_SIZE
251 #define MALLOC_ALLOCATED_SIZE 0
254 #define MALLOC_ALLOCATED_SIZE 0
256 #ifndef MALLOC_ALLOCATED_SIZE_CHECK
257 #define MALLOC_ALLOCATED_SIZE_CHECK 0
268 #if RGENGC_ESTIMATE_OLDMALLOC
295 #if GC_PROFILE_MORE_DETAIL
297 double gc_sweep_time;
299 size_t heap_use_pages;
300 size_t heap_live_objects;
301 size_t heap_free_objects;
303 size_t allocate_increase;
304 size_t allocate_limit;
307 size_t removing_objects;
308 size_t empty_objects;
309 #if GC_PROFILE_DETAIL_MEMORY
315 #if MALLOC_ALLOCATED_SIZE
316 size_t allocated_size;
319 #if RGENGC_PROFILE > 0
321 size_t remembered_normal_objects;
322 size_t remembered_shady_objects;
326 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
327 #pragma pack(push, 1)
366 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
391 #define STACK_CHUNK_SIZE 500
421 #if MALLOC_ALLOCATED_SIZE
422 size_t allocated_size;
463 #if GC_PROFILE_MORE_DETAIL
471 #if RGENGC_PROFILE > 0
472 size_t generated_normal_object_count;
473 size_t generated_shady_object_count;
474 size_t shade_operation_count;
475 size_t promote_infant_count;
477 size_t promote_young_count;
479 size_t remembered_normal_object_count;
482 #if RGENGC_PROFILE >= 2
483 size_t generated_normal_object_count_types[
RUBY_T_MASK];
484 size_t generated_shady_object_count_types[
RUBY_T_MASK];
490 size_t remembered_normal_object_count_types[
RUBY_T_MASK];
491 size_t remembered_shady_object_count_types[
RUBY_T_MASK];
530 size_t young_object_count;
533 #if RGENGC_ESTIMATE_OLDMALLOC
538 #if RGENGC_CHECK_MODE >= 2
547 #ifndef HEAP_ALIGN_LOG
549 #define HEAP_ALIGN_LOG 14
551 #define CEILDIV(i, mod) (((i) + (mod) - 1)/(mod))
582 #define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK)))
583 #define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
584 #define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
585 #define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0])
586 #define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_PAGE(x)->rememberset_bits[0])
587 #define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_PAGE(x)->oldgen_bits[0])
588 #define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE))
589 #define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
590 #define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
591 #define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
593 #define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p))
594 #define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p))
595 #define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p))
598 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
599 #define rb_objspace (*GET_VM()->objspace)
600 #define ruby_initial_gc_stress gc_params.gc_stress
607 #define malloc_limit objspace->malloc_params.limit
608 #define malloc_increase objspace->malloc_params.increase
609 #define malloc_allocated_size objspace->malloc_params.allocated_size
610 #define heap_pages_sorted objspace->heap_pages.sorted
611 #define heap_pages_used objspace->heap_pages.used
612 #define heap_pages_length objspace->heap_pages.length
613 #define heap_pages_lomem objspace->heap_pages.range[0]
614 #define heap_pages_himem objspace->heap_pages.range[1]
615 #define heap_pages_swept_slots objspace->heap_pages.swept_slots
616 #define heap_pages_increment objspace->heap_pages.increment
617 #define heap_pages_min_free_slots objspace->heap_pages.min_free_slots
618 #define heap_pages_max_free_slots objspace->heap_pages.max_free_slots
619 #define heap_pages_final_slots objspace->heap_pages.final_slots
620 #define heap_pages_deferred_final objspace->heap_pages.deferred_final
621 #define heap_eden (&objspace->eden_heap)
622 #define heap_tomb (&objspace->tomb_heap)
623 #define dont_gc objspace->flags.dont_gc
624 #define during_gc objspace->flags.during_gc
625 #define finalizing objspace->flags.finalizing
626 #define finalizer_table objspace->finalizer_table
627 #define global_List objspace->global_list
628 #define ruby_gc_stress objspace->gc_stress
629 #define monitor_level objspace->rgengc.monitor_level
630 #define monitored_object_table objspace->rgengc.monitored_object_table
632 #define is_lazy_sweeping(heap) ((heap)->sweep_pages != 0)
633 #if SIZEOF_LONG == SIZEOF_VOIDP
634 # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
635 # define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG)
636 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
637 # define nonspecial_obj_id(obj) LL2NUM((SIGNED_VALUE)(obj) / 2)
638 # define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
639 ((objid) ^ FIXNUM_FLAG) : (NUM2PTR(objid) << 1))
641 # error not supported
644 #define RANY(o) ((RVALUE*)(o))
646 #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
690 #define gc_prof_record(objspace) (objspace)->profile.current_record
691 #define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record)
693 #define rgengc_report if (RGENGC_DEBUG) rgengc_report_body
704 #define FL_TEST2(x,f) ((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? (rb_bug("FL_TEST2: SPECIAL_CONST"), 0) : FL_TEST_RAW((x),(f)) != 0)
705 #define FL_SET2(x,f) do {if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) rb_bug("FL_SET2: SPECIAL_CONST"); RBASIC(x)->flags |= (f);} while (0)
706 #define FL_UNSET2(x,f) do {if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) rb_bug("FL_UNSET2: SPECIAL_CONST"); RBASIC(x)->flags &= ~(f);} while (0)
708 #define RVALUE_WB_PROTECTED_RAW(obj) FL_TEST2((obj), FL_WB_PROTECTED)
709 #define RVALUE_WB_PROTECTED(obj) RVALUE_WB_PROTECTED_RAW(check_gen_consistency((VALUE)obj))
711 #define RVALUE_OLDGEN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_OLDGEN_BITS(obj), (obj))
727 rb_bug(
"check_gen_consistency: %p (%s) is not Ruby object.", (
void *)obj,
obj_type_name(obj));
732 const char *
type = old_flag ?
"old" :
"young";
733 rb_bug(
"check_gen_consistency: %p (%s) is not WB protected, but %s object.", (
void *)obj,
obj_type_name(obj), type);
738 rb_bug(
"check_gen_consistency: %p (%s) is not infant, but is not old (on 2gen).", (
void *)obj,
obj_type_name(obj));
743 rb_bug(
"check_gen_consistency: %p (%s) is old, but is not marked while minor marking.", (
void *)obj,
obj_type_name(obj));
748 rb_bug(
"check_gen_consistency: %p (%s) is not infant, but is old.", (
void *)obj,
obj_type_name(obj));
798 #if RGENGC_PROFILE >= 1
801 objspace->
profile.promote_infant_count++;
803 #if RGENGC_PROFILE >= 2
816 RVALUE_YOUNG_P(
VALUE obj)
823 RVALUE_PROMOTE_YOUNG(
VALUE obj)
830 #if RGENGC_PROFILE >= 1
833 objspace->
profile.promote_young_count++;
834 #if RGENGC_PROFILE >= 2
842 RVALUE_DEMOTE_FROM_YOUNG(
VALUE obj)
845 rb_bug(
"RVALUE_DEMOTE_FROM_YOUNG: %p (%s) is not young object.", (
void *)obj,
obj_type_name(obj));
857 rb_bug(
"RVALUE_DEMOTE_FROM_OLD: %p (%s) is not old object.", (
void *)obj,
obj_type_name(obj));
871 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
876 memset(objspace, 0,
sizeof(*objspace));
885 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
937 rgengc_report(3, objspace,
"heap_pages_expand_sorted: next_length: %d, size: %d\n", (
int)next_length, (
int)size);
1006 if (0) fprintf(stderr,
"heap_pages_free_unused_pages: %d free page %p, heap_pages_swept_slots: %d, heap_pages_max_free_slots: %d\n",
1008 heap_pages_swept_slots -= page->
limit;
1022 assert(j == heap_pages_used);
1036 if (page_body == 0) {
1050 page->
body = page_body;
1058 mid = (lo +
hi) / 2;
1060 if (mid_page->
body < page_body) {
1063 else if (mid_page->
body > page_body) {
1086 end = start + limit;
1091 page->
start = start;
1092 page->
limit = limit;
1095 for (p = start; p != end; p++) {
1096 rgengc_report(3, objspace,
"assign_heap_page: %p is added to freelist\n");
1119 const char *method =
"recycle";
1122 method =
"allocate";
1124 if (0) fprintf(stderr,
"heap_page_create: %s - %p, heap_pages_used: %d, heap_pages_used: %d, tomb->page_length: %d\n",
1155 for (i = 0; i <
add; i++) {
1165 size_t next_used_limit = (size_t)(used * gc_params.
growth_factor);
1168 if (next_used_limit > max_used_limit) next_used_limit = max_used_limit;
1172 if (next_used_limit < minimum_limit) {
1173 next_used_limit = minimum_limit;
1179 if (0) fprintf(stderr,
"heap_set_increment: heap_pages_length: %d, heap_pages_used: %d, heap_pages_increment: %d, next_used_limit: %d\n",
1186 rgengc_report(5, objspace,
"heap_increment: heap_pages_length: %d, heap_pages_inc: %d, heap->page_length: %d\n",
1189 if (heap_pages_increment > 0) {
1190 heap_pages_increment--;
1216 #if GC_PROFILE_MORE_DETAIL
1217 objspace->
profile.prepare_time = 0;
1236 while (page ==
NULL) {
1278 #define gc_event_hook(objspace, event, data) do { \
1279 if (UNLIKELY((objspace)->hook_events & (event))) { \
1280 gc_event_hook_body((objspace), (event), (data)); \
1293 rb_bug(
"object allocation during garbage collection phase");
1306 RBASIC(obj)->flags = flags;
1309 RANY(obj)->as.values.v1 = v1;
1310 RANY(obj)->as.values.v2 = v2;
1311 RANY(obj)->as.values.v3 = v3;
1321 objspace->
profile.generated_normal_object_count++;
1322 #if RGENGC_PROFILE >= 2
1327 objspace->
profile.generated_shady_object_count++;
1328 #if RGENGC_PROFILE >= 2
1336 #if USE_RGENGC && RGENGC_CHECK_MODE
1356 return newobj_of(klass, flags, 0, 0, 0);
1409 register size_t hi,
lo, mid;
1418 mid = (lo +
hi) / 2;
1420 if (page->
start <= p) {
1499 rb_bug(
"obj_free() called for broken object");
1516 RANY(obj)->as.object.as.heap.ivptr) {
1517 xfree(
RANY(obj)->as.object.as.heap.ivptr);
1545 if (
RANY(obj)->as.klass.ptr)
1556 if (
RANY(obj)->as.hash.ntbl) {
1561 if (
RANY(obj)->as.regexp.ptr) {
1567 int free_immediately =
FALSE;
1571 RDATA(obj)->dfree =
RANY(obj)->as.typeddata.type->function.dfree;
1572 if (0 && free_immediately == 0)
1573 fprintf(stderr,
"not immediate -> %s\n",
RANY(obj)->as.typeddata.type->wrap_struct_name);
1578 else if (
RANY(obj)->as.data.dfree) {
1579 if (free_immediately) {
1590 if (
RANY(obj)->as.match.rmatch) {
1591 struct rmatch *rm =
RANY(obj)->as.match.rmatch;
1599 if (
RANY(obj)->as.file.fptr) {
1630 if (
RANY(obj)->as.node.u1.tbl) {
1635 if (
RANY(obj)->as.node.u3.args) {
1647 RANY(obj)->as.rstruct.as.heap.ptr) {
1648 xfree((
void *)
RANY(obj)->as.rstruct.as.heap.ptr);
1665 #if RGENGC_ESTIMATE_OLDMALLOC
1673 #ifdef USE_SIGALTSTACK
1677 void *tmp = th->altstack;
1711 last_body = page->
body;
1713 pstart = page->
start;
1714 pend = pstart + page->
limit;
1765 int prev_dont_lazy_sweep = objspace->flags.dont_lazy_sweep;
1768 objspace->flags.dont_lazy_sweep =
TRUE;
1773 if (prev_dont_lazy_sweep) {
1821 for (; p != pend; p++) {
1978 table = (
VALUE)data;
2006 table = (
VALUE)data;
2061 free_func =
RDATA(obj)->dfree;
2121 rb_bug(
"gc_finalize_deferred_register: can't register finalizer.");
2190 p->as.free.flags = 0;
2192 RDATA(p)->dfree =
RANY(p)->as.typeddata.type->function.dfree;
2197 else if (
RANY(p)->as.data.dfree) {
2202 if (
RANY(p)->as.file.fptr) {
2272 if (!
is_pointer_to_heap(objspace, (
void *)obj))
rb_bug(
"is_markable_object: %p is not pointer to heap", (
void *)obj);
2303 #if SIZEOF_LONG == SIZEOF_VOIDP
2304 #define NUM2PTR(x) NUM2ULONG(x)
2305 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
2306 #define NUM2PTR(x) NUM2ULL(x)
2322 if ((ptr %
sizeof(
RVALUE)) == (4 << 2)) {
2407 #if SIZEOF_LONG == SIZEOF_VOIDP
2441 ROBJECT(obj)->as.heap.ivptr) {
2460 if (
RCLASS(obj)->ptr->iv_tbl) {
2463 if (
RCLASS(obj)->ptr->const_tbl) {
2476 if (
RHASH(obj)->ntbl) {
2493 size +=
sizeof(
struct rmatch);
2497 if (
RFILE(obj)->fptr) {
2519 if (
RNODE(obj)->u1.tbl) {
2540 rb_bug(
"objspace/memsize_of(): unknown data type 0x%x(%p)",
2602 for (i = 0; i <=
T_MASK; i++) {
2611 for (;p < pend; p++) {
2619 total += page->
limit;
2631 for (i = 0; i <=
T_MASK; i++) {
2634 #define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t)); break;
2661 default: type =
INT2NUM(i);
break;
2719 size_t empty_slots = 0, freed_slots = 0,
final_slots = 0;
2720 RVALUE *p, *pend,*offset;
2727 p = sweep_page->
start; pend = p + sweep_page->
limit;
2743 #if USE_RGENGC && RGENGC_CHECK_MODE
2751 RDATA(p)->dfree = 0;
2774 #if GC_PROFILE_MORE_DETAIL
2777 record->removing_objects +=
final_slots + freed_slots;
2778 record->empty_objects += empty_slots;
2788 if (freed_slots + empty_slots > 0) {
2800 if (0) fprintf(stderr,
"gc_page_sweep(%d): freed?: %d, limt: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
2803 (
int)sweep_page->
limit, (
int)freed_slots, (
int)empty_slots, (
int)
final_slots);
2846 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
2847 __attribute__((noinline))
2853 size_t total_limit_slot;
2858 if (
GET_VM()->unlinked_method_entry_list) {
2873 if (0) fprintf(stderr,
"heap_pages_min_free_slots: %d, heap_pages_max_free_slots: %d\n",
2888 if (inc > malloc_limit) {
2896 malloc_limit = (size_t)(malloc_limit * 0.98);
2903 if (old_limit != malloc_limit) {
2915 #if RGENGC_ESTIMATE_OLDMALLOC
2927 if (0) fprintf(stderr,
"%d\t%d\t%u\t%u\t%d\n",
2956 rgengc_report(1, objspace,
"after_gc_sweep: heap->total_slots: %d, heap->swept_slots: %d, min_free_slots: %d\n",
2959 if (heap_pages_swept_slots < heap_pages_min_free_slots) {
2979 if (heap_pages_increment < heap_tomb->page_length) {
2983 #if RGENGC_PROFILE > 0
2985 fprintf(stderr,
"%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
2989 (
int)objspace->
profile.promote_infant_count,
2991 (
int)objspace->
profile.promote_young_count,
2995 (
int)objspace->
profile.remembered_normal_object_count,
3011 #if GC_ENABLE_LAZY_SWEEP
3030 #if GC_ENABLE_LAZY_SWEEP
3059 if (immediate_sweep) {
3060 #if !GC_ENABLE_LAZY_SWEEP
3065 #if !GC_ENABLE_LAZY_SWEEP
3111 stack->
cache = chunk;
3121 chunk = stack->
cache;
3136 next = stack->
cache;
3162 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
3169 while (chunk !=
NULL) {
3192 if (stack->
index == 1) {
3210 for (i=0; i < 4; i++) {
3219 #define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine.stack_end), th->machine.register_stack_end = rb_ia64_bsp())
3221 #define SET_STACK_END SET_MACHINE_STACK_END(&th->machine.stack_end)
3224 #define STACK_START (th->machine.stack_start)
3225 #define STACK_END (th->machine.stack_end)
3226 #define STACK_LEVEL_MAX (th->machine.stack_maxsize/sizeof(VALUE))
3228 #if STACK_GROW_DIRECTION < 0
3229 # define STACK_LENGTH (size_t)(STACK_START - STACK_END)
3230 #elif STACK_GROW_DIRECTION > 0
3231 # define STACK_LENGTH (size_t)(STACK_END - STACK_START + 1)
3233 # define STACK_LENGTH ((STACK_END < STACK_START) ? (size_t)(STACK_START - STACK_END) \
3234 : (size_t)(STACK_END - STACK_START + 1))
3236 #if !STACK_GROW_DIRECTION
3244 if (end > addr)
return ruby_stack_grow_direction = 1;
3245 return ruby_stack_grow_direction = -1;
3258 #if !(defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK))
3268 ret = (
VALUE*)rb_ia64_bsp() - th->
machine.register_stack_start >
3269 th->
machine.register_stack_maxsize/
sizeof(
VALUE) - water_mark;
3276 #define STACKFRAME_FOR_CALL_CFUNC 512
3281 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
3305 if (end <= start)
return;
3316 #define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, (start), (end))
3394 switch (def->
type) {
3434 if (!wrapper || !wrapper->
tbl)
return;
3439 if (wrapper->
serial == serial)
return;
3440 wrapper->
serial = serial;
3464 #if STACK_GROW_DIRECTION < 0
3465 #define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_END, (end) = STACK_START)
3466 #elif STACK_GROW_DIRECTION > 0
3467 #define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_START, (end) = STACK_END+(appendix))
3469 #define GET_STACK_BOUNDS(start, end, appendix) \
3470 ((STACK_END < STACK_START) ? \
3471 ((start) = STACK_END, (end) = STACK_START) : ((start) = STACK_START, (end) = STACK_END+(appendix)))
3480 } save_regs_gc_mark;
3481 VALUE *stack_start, *stack_end;
3499 #if defined(__mc68000__)
3509 VALUE *stack_start, *stack_end;
3655 objspace->
rgengc.young_object_count++;
3668 if (RVALUE_YOUNG_P((
VALUE)obj)) {
3670 RVALUE_PROMOTE_YOUNG((
VALUE)obj);
3701 rb_bug(
"rb_gc_mark() called for broken object");
3733 ptr = (
VALUE)obj->as.node.u3.node;
3768 ptr = (
VALUE)obj->as.node.u2.node;
3784 ptr = (
VALUE)obj->as.node.u1.node;
3791 ptr = (
VALUE)obj->as.node.u2.node;
3798 if (args->pre_init)
gc_mark(objspace, (
VALUE)args->pre_init);
3799 if (args->post_init)
gc_mark(objspace, (
VALUE)args->post_init);
3800 if (args->opt_args)
gc_mark(objspace, (
VALUE)args->opt_args);
3801 if (args->kw_args)
gc_mark(objspace, (
VALUE)args->kw_args);
3802 if (args->kw_rest_arg)
gc_mark(objspace, (
VALUE)args->kw_rest_arg);
3805 ptr = (
VALUE)obj->as.node.u2.node;
3829 (
VALUE*)obj->as.node.u1.value,
3830 obj->as.node.u3.cnt);
3835 gc_mark(objspace, obj->as.node.nd_refinements);
3837 ptr = (
VALUE)obj->as.node.nd_next;
3848 gc_mark(objspace, obj->as.basic.klass);
3862 ptr = obj->as.array.as.heap.aux.shared;
3868 for (i=0; i < len; i++) {
3876 ptr = obj->as.hash.ifnone;
3880 #define STR_ASSOC FL_USER3
3882 ptr = obj->as.string.as.heap.aux.shared;
3889 RUBY_DATA_FUNC mark_func = obj->as.typeddata.type->function.dmark;
3890 if (mark_func) (*mark_func)(
DATA_PTR(obj));
3893 if (obj->as.data.dmark) (*obj->as.data.dmark)(
DATA_PTR(obj));
3901 for (i = 0; i < len; i++) {
3908 if (obj->as.file.fptr) {
3909 gc_mark(objspace, obj->as.file.fptr->pathv);
3910 gc_mark(objspace, obj->as.file.fptr->tied_io_for_writing);
3911 gc_mark(objspace, obj->as.file.fptr->writeconv_asciicompat);
3912 gc_mark(objspace, obj->as.file.fptr->writeconv_pre_ecopts);
3913 gc_mark(objspace, obj->as.file.fptr->encs.ecopts);
3914 gc_mark(objspace, obj->as.file.fptr->write_lock);
3919 ptr = obj->as.regexp.src;
3927 gc_mark(objspace, obj->as.match.regexp);
3928 if (obj->as.match.str) {
3929 ptr = obj->as.match.str;
3935 gc_mark(objspace, obj->as.rational.num);
3936 ptr = obj->as.rational.den;
3940 gc_mark(objspace, obj->as.complex.real);
3941 ptr = obj->as.complex.imag;
3961 rb_bug(
"rb_gc_mark(): unknown data type 0x%x(%p) %s",
3973 if (!mstack->
index)
return;
3976 rb_bug(
"gc_mark_stacked_objects: %p (%s) is infant, but not marked.", (
void *)obj,
obj_type_name(obj));
3983 #ifndef RGENGC_PRINT_TICK
3984 #define RGENGC_PRINT_TICK 0
3993 #if RGENGC_PRINT_TICK
3994 #if defined(__GNUC__) && defined(__i386__)
3995 typedef unsigned long long tick_t;
3997 static inline tick_t
4000 unsigned long long int x;
4001 __asm__ __volatile__ (
"rdtsc" :
"=A" (x));
4005 #elif defined(__GNUC__) && defined(__x86_64__)
4006 typedef unsigned long long tick_t;
4008 static __inline__ tick_t
4011 unsigned long hi,
lo;
4012 __asm__ __volatile__ (
"rdtsc" :
"=a"(lo),
"=d"(hi));
4013 return ((
unsigned long long)lo)|( ((
unsigned long long)hi)<<32);
4016 #elif defined(_WIN32) && defined(_MSC_VER)
4018 typedef unsigned __int64 tick_t;
4020 static inline tick_t
4027 typedef clock_t tick_t;
4028 static inline tick_t
4035 #define MAX_TICKS 0x100
4036 static tick_t mark_ticks[MAX_TICKS];
4037 static const char *mark_ticks_categories[MAX_TICKS];
4040 show_mark_ticks(
void)
4043 fprintf(stderr,
"mark ticks result:\n");
4044 for (i=0; i<MAX_TICKS; i++) {
4045 const char *category = mark_ticks_categories[i];
4047 fprintf(stderr,
"%s\t%8lu\n", category, (
unsigned long)mark_ticks[i]);
4062 if (categoryp) *categoryp =
"xxx";
4064 #if RGENGC_PRINT_TICK
4065 tick_t start_tick = tick();
4067 const char *prev_category = 0;
4069 if (mark_ticks_categories[0] == 0) {
4070 atexit(show_mark_ticks);
4074 #if RGENGC_PRINT_TICK
4075 #define MARK_CHECKPOINT_PRINT_TICK(category) do { \
4076 if (prev_category) { \
4077 tick_t t = tick(); \
4078 mark_ticks[tick_count] = t - start_tick; \
4079 mark_ticks_categories[tick_count] = prev_category; \
4082 prev_category = category; \
4083 start_tick = tick(); \
4086 #define MARK_CHECKPOINT_PRINT_TICK(category)
4089 #define MARK_CHECKPOINT(category) do { \
4090 if (categoryp) *categoryp = category; \
4091 MARK_CHECKPOINT_PRINT_TICK(category); \
4139 #undef MARK_CHECKPOINT
4146 rgengc_report(1, objspace,
"gc_marks_body: start (%s)\n", full_mark ?
"full" :
"minor");
4165 rgengc_report(1, objspace,
"gc_marks_body: end (%s)\n", full_mark ?
"full" :
"minor");
4185 fprintf(stderr,
"verify_internal_consistency_reachable_i: WB miss %p (%s) -> %p (%s)\n",
4199 for (v = (
VALUE)page_start; v != (
VALUE)page_end; v += stride) {
4234 eo_args.
data = (
void *)&data;
4239 rb_bug(
"gc_verify_internal_consistency: found internal consistency.\n");
4244 #if RGENGC_CHECK_MODE >= 3
4246 #define MAKE_ROOTSIG(obj) (((VALUE)(obj) << 1) | 0x01)
4247 #define IS_ROOTSIG(obj) ((VALUE)(obj) & 0x01)
4248 #define GET_ROOTSIG(obj) ((const char *)((VALUE)(obj) >> 1))
4256 static struct reflist *
4257 reflist_create(
VALUE obj)
4259 struct reflist *refs =
xmalloc(
sizeof(
struct reflist));
4262 refs->list[0] = obj;
4268 reflist_destruct(
struct reflist *refs)
4275 reflist_add(
struct reflist *refs,
VALUE obj)
4277 if (refs->pos == refs->size) {
4282 refs->list[refs->pos++] = obj;
4286 reflist_dump(
struct reflist *refs)
4289 for (i=0; i<refs->pos; i++) {
4290 VALUE obj = refs->list[i];
4291 if (IS_ROOTSIG(obj)) {
4292 fprintf(stderr,
"<root@%s>", GET_ROOTSIG(obj));
4295 fprintf(stderr,
"<%p@%s>", (
void *)obj,
obj_type_name(obj));
4297 if (i+1 < refs->pos) fprintf(stderr,
", ");
4301 #if RGENGC_CHECK_MODE >= 3
4303 reflist_refered_from_machine_context(
struct reflist *refs)
4306 for (i=0; i<refs->pos; i++) {
4307 VALUE obj = refs->list[i];
4308 if (IS_ROOTSIG(obj) && strcmp(GET_ROOTSIG(obj),
"machine_context") == 0)
return 1;
4324 const char *category;
4329 allrefs_add(
struct allrefs *data,
VALUE obj)
4331 struct reflist *refs;
4334 reflist_add(refs, data->root_obj);
4338 refs = reflist_create(data->root_obj);
4345 allrefs_i(
VALUE obj,
void *ptr)
4347 struct allrefs *data = (
struct allrefs *)ptr;
4349 if (allrefs_add(data, obj)) {
4355 allrefs_roots_i(
VALUE obj,
void *ptr)
4357 struct allrefs *data = (
struct allrefs *)ptr;
4359 data->root_obj = MAKE_ROOTSIG(data->category);
4361 if (allrefs_add(data, obj)) {
4369 struct allrefs data;
4370 struct mark_func_data_struct mfd;
4373 data.objspace = objspace;
4376 mfd.mark_func = allrefs_roots_i;
4390 return data.references;
4396 struct reflist *refs = (
struct reflist *)value;
4397 reflist_destruct(refs);
4402 objspace_allrefs_destruct(
struct st_table *refs)
4404 st_foreach(refs, objspaec_allrefs_destruct_i, 0);
4408 #if RGENGC_CHECK_MODE >= 4
4413 struct reflist *refs = (
struct reflist *)v;
4414 fprintf(stderr,
"[allrefs_dump_i] %p (%s%s%s%s) <- ",
4420 fprintf(stderr,
"\n");
4427 fprintf(stderr,
"[all refs] (size: %d)\n", (
int)objspace->
rgengc.allrefs_table->num_entries);
4432 #if RGENGC_CHECK_MODE >= 3
4437 struct reflist *refs = (
struct reflist *)v;
4442 fprintf(stderr,
"gc_check_after_marks_i: %p (%s) is not marked and not oldgen.\n", (
void *)obj,
obj_type_name(obj));
4443 fprintf(stderr,
"gc_check_after_marks_i: %p is referred from ", (
void *)obj);
4446 if (reflist_refered_from_machine_context(refs)) {
4447 fprintf(stderr,
" (marked from machine stack).\n");
4451 objspace->
rgengc.error_count++;
4452 fprintf(stderr,
"\n");
4460 gc_marks_check(
rb_objspace_t *objspace,
int (*checker_func)(
ANYARGS),
const char *checker_name)
4464 #if RGENGC_ESTIMATE_OLDMALLOC
4469 objspace->
rgengc.allrefs_table = objspace_allrefs(objspace);
4472 if (objspace->
rgengc.error_count > 0) {
4473 #if RGENGC_CHECK_MODE >= 4
4474 allrefs_dump(objspace);
4476 rb_bug(
"%s: GC has problem.", checker_name);
4479 objspace_allrefs_destruct(objspace->
rgengc.allrefs_table);
4480 objspace->
rgengc.allrefs_table = 0;
4484 #if RGENGC_ESTIMATE_OLDMALLOC
4494 struct mark_func_data_struct *prev_mark_func_data;
4504 #if RGENGC_CHECK_MODE >= 2
4507 if (full_mark ==
TRUE) {
4511 objspace->
rgengc.young_object_count = 0;
4526 #if RGENGC_PROFILE > 0
4533 #if RGENGC_CHECK_MODE >= 3
4534 gc_marks_check(objspace, gc_check_after_marks_i,
"after_marks");
4555 const char *status =
" ";
4563 va_start(args, fmt);
4567 fprintf(out,
"%s|", status);
4606 #if RGENGC_CHECK_MODE > 0
4611 rb_bug(
"rgengc_remember: should not remember %p (%s)\n",
4621 #if RGENGC_PROFILE > 0
4623 objspace->
profile.remembered_normal_object_count++;
4624 #if RGENGC_PROFILE >= 2
4630 #if RGENGC_PROFILE >= 2
4658 #if RGENGC_PROFILE > 0
4659 size_t shady_object_count = 0, clear_count = 0;
4680 if (RVALUE_YOUNG_P((
VALUE)p)) RVALUE_PROMOTE_YOUNG((
VALUE)p);
4683 #if RGENGC_PROFILE > 0
4688 #if RGENGC_PROFILE > 0
4689 shady_object_count++;
4704 rgengc_report(2, objspace,
"rgengc_rememberset_mark: finished\n");
4706 #if RGENGC_PROFILE > 0
4707 rgengc_report(2, objspace,
"rgengc_rememberset_mark: clear_count: %"PRIdSIZE", shady_object_count: %"PRIdSIZE"\n", clear_count, shady_object_count);
4710 record->remembered_normal_objects = clear_count;
4711 record->remembered_shady_objects = shady_object_count;
4741 rgengc_report(2, objspace,
"rb_gc_wb: %p (%s) -> %p (%s)\n",
4768 objspace->
profile.shade_operation_count++;
4769 #if RGENGC_PROFILE >= 2
4776 RVALUE_DEMOTE_FROM_YOUNG(obj);
4793 fprintf(stderr,
"%s\t%d\n", (
char *)key, (
int)val);
4808 if (rgengc_unprotect_logging_table == 0) {
4851 static ID ID_marked;
4853 static ID ID_wb_protected, ID_old, ID_remembered;
4855 static ID ID_young, ID_infant;
4860 #define I(s) ID_##s = rb_intern(#s);
4876 flags[n++] = ID_wb_protected;
4878 flags[n++] = ID_old;
4880 if (RVALUE_YOUNG_P(obj) && n<max)
4881 flags[n++] = ID_young;
4883 flags[n++] = ID_infant;
4886 flags[n++] = ID_remembered;
4889 flags[n++] = ID_marked;
4944 if (tmp->
varptr == addr) {
4979 immediate_sweep = !(flag & 0x02);
4983 immediate_sweep =
TRUE;
5005 if (
GC_NOTIFY) fprintf(stderr,
"start garbage_collect(%d, %d, %d)\n", full_mark, immediate_sweep, reason);
5019 rb_bug(
"during_gc should not be 0. RUBY_INTERNAL_EVENT_GC_START user should not cause GC in events.");
5022 gc_sweep(objspace, immediate_sweep);
5027 if (
GC_NOTIFY) fprintf(stderr,
"end garbage_collect()\n");
5064 #if GC_PROFILE_MORE_DETAIL
5068 #if GC_PROFILE_MORE_DETAIL
5109 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
5156 static ID keyword_ids[2];
5163 if (!keyword_ids[0]) {
5164 keyword_ids[0] =
rb_intern(
"full_mark");
5165 keyword_ids[1] =
rb_intern(
"immediate_sweep");
5171 full_mark =
RTEST(kwvals[0]);
5173 immediate_sweep =
RTEST(kwvals[1]);
5204 #if RGENGC_PROFILE >= 2
5206 gc_count_add_each_types(
VALUE hash,
const char *
name,
const size_t *types)
5210 for (i=0; i<
T_MASK; i++) {
5243 static VALUE sym_major_by =
Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer;
5244 static VALUE sym_nofree, sym_oldgen, sym_shady, sym_rescan, sym_stress;
5245 #if RGENGC_ESTIMATE_OLDMALLOC
5246 static VALUE sym_oldmalloc;
5248 static VALUE sym_newobj, sym_malloc, sym_method, sym_capi;
5259 if (sym_major_by ==
Qnil) {
5260 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
5270 #if RGENGC_ESTIMATE_OLDMALLOC
5280 #define SET(name, attr) \
5281 if (key == sym_##name) \
5283 else if (hash != Qnil) \
5284 rb_hash_aset(hash, sym_##name, (attr));
5291 #if RGENGC_ESTIMATE_OLDMALLOC
5296 SET(major_by, major_by);
5354 static VALUE sym_count;
5355 static VALUE sym_heap_used, sym_heap_length, sym_heap_increment;
5356 static VALUE sym_heap_live_slot, sym_heap_free_slot, sym_heap_final_slot, sym_heap_swept_slot;
5357 static VALUE sym_heap_eden_page_length, sym_heap_tomb_page_length;
5358 static VALUE sym_total_allocated_object, sym_total_freed_object;
5359 static VALUE sym_malloc_increase, sym_malloc_limit;
5361 static VALUE sym_minor_gc_count, sym_major_gc_count;
5362 static VALUE sym_remembered_shady_object, sym_remembered_shady_object_limit;
5363 static VALUE sym_old_object, sym_old_object_limit;
5364 #if RGENGC_ESTIMATE_OLDMALLOC
5365 static VALUE sym_oldmalloc_increase, sym_oldmalloc_limit;
5368 static VALUE sym_generated_normal_object_count, sym_generated_shady_object_count;
5369 static VALUE sym_shade_operation_count, sym_promote_infant_count, sym_promote_young_count;
5370 static VALUE sym_remembered_normal_object_count, sym_remembered_shady_object_count;
5379 else if (
SYMBOL_P(hash_or_sym) && out)
5384 if (sym_count == 0) {
5385 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
5394 S(heap_eden_page_length);
5395 S(heap_tomb_page_length);
5396 S(total_allocated_object);
5397 S(total_freed_object);
5403 S(remembered_shady_object);
5404 S(remembered_shady_object_limit);
5406 S(old_object_limit);
5407 #if RGENGC_ESTIMATE_OLDMALLOC
5408 S(oldmalloc_increase);
5412 S(generated_normal_object_count);
5413 S(generated_shady_object_count);
5414 S(shade_operation_count);
5415 S(promote_infant_count);
5416 S(promote_young_count);
5417 S(remembered_normal_object_count);
5418 S(remembered_shady_object_count);
5424 #define SET(name, attr) \
5425 if (key == sym_##name) \
5426 return (*out = attr, Qnil); \
5427 else if (hash != Qnil) \
5428 rb_hash_aset(hash, sym_##name, SIZET2NUM(attr));
5453 #if RGENGC_ESTIMATE_OLDMALLOC
5459 SET(generated_normal_object_count, objspace->
profile.generated_normal_object_count);
5460 SET(generated_shady_object_count, objspace->
profile.generated_shady_object_count);
5461 SET(shade_operation_count, objspace->
profile.shade_operation_count);
5462 SET(promote_infant_count, objspace->
profile.promote_infant_count);
5464 SET(promote_young_count, objspace->
profile.promote_young_count);
5466 SET(remembered_normal_object_count, objspace->
profile.remembered_normal_object_count);
5475 #if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
5477 gc_count_add_each_types(hash,
"generated_normal_object_count_types", objspace->
profile.generated_normal_object_count_types);
5478 gc_count_add_each_types(hash,
"generated_shady_object_count_types", objspace->
profile.generated_shady_object_count_types);
5479 gc_count_add_each_types(hash,
"shade_operation_count_types", objspace->
profile.shade_operation_count_types);
5480 gc_count_add_each_types(hash,
"promote_infant_types", objspace->
profile.promote_infant_types);
5482 gc_count_add_each_types(hash,
"promote_young_types", objspace->
profile.promote_young_types);
5484 gc_count_add_each_types(hash,
"remembered_normal_object_count_types", objspace->
profile.remembered_normal_object_count_types);
5485 gc_count_add_each_types(hash,
"remembered_shady_object_count_types", objspace->
profile.remembered_shady_object_count_types);
5652 char *ptr =
getenv(name);
5657 if (val > lower_bound) {
5658 if (
RTEST(
ruby_verbose)) fprintf(stderr,
"%s=%d (default value: %d)\n", name, val, *default_value);
5659 *default_value =
val;
5663 if (
RTEST(
ruby_verbose)) fprintf(stderr,
"%s=%d (default value: %d) is ignored because it must be greater than %d.\n", name, val, *default_value, lower_bound);
5672 char *ptr =
getenv(name);
5677 if (val > lower_bound) {
5678 if (
RTEST(
ruby_verbose)) fprintf(stderr,
"%s=%f (%f)\n", name, val, *default_value);
5679 *default_value =
val;
5683 if (
RTEST(
ruby_verbose)) fprintf(stderr,
"%s=%f (default value: %f) is ignored because it must be greater than %f.\n", name, val, *default_value, lower_bound);
5696 if (min_pages >
heap_eden->page_length) {
5735 if (safe_level > 0)
return;
5742 rb_warn(
"RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead.");
5750 rb_warn(
"RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead.");
5762 #if RGENGC_ESTIMATE_OLDMALLOC
5784 struct mark_func_data_struct mfd;
5785 mfd.mark_func =
func;
5811 struct mark_func_data_struct mfd;
5814 data.
data = passing_data;
5850 fprintf(stderr,
"[FATAL] %s\n", msg);
5875 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
5887 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
5904 #if defined __MINGW32__
5905 res = __mingw_aligned_malloc(size, alignment);
5906 #elif defined _WIN32 && !defined __CYGWIN__
5907 void *_aligned_malloc(
size_t,
size_t);
5908 res = _aligned_malloc(size, alignment);
5909 #elif defined(HAVE_POSIX_MEMALIGN)
5910 if (posix_memalign(&res, alignment, size) == 0) {
5916 #elif defined(HAVE_MEMALIGN)
5917 res = memalign(alignment, size);
5920 res =
malloc(alignment + size +
sizeof(
void*));
5921 aligned = (
char*)res + alignment +
sizeof(
void*);
5922 aligned -= ((
VALUE)aligned & (alignment - 1));
5923 ((
void**)aligned)[-1] = res;
5924 res = (
void*)aligned;
5927 #if defined(_DEBUG) || GC_DEBUG
5929 assert(((alignment - 1) & alignment) == 0);
5930 assert(alignment %
sizeof(
void*) == 0);
5938 #if defined __MINGW32__
5939 __mingw_aligned_free(ptr);
5940 #elif defined _WIN32 && !defined __CYGWIN__
5942 #elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)
5945 free(((
void**)ptr)[-1]);
5949 static inline size_t
5952 #ifdef HAVE_MALLOC_USABLE_SIZE
5953 return malloc_usable_size(ptr);
5968 if (sub == 0)
return;
5972 if (val < sub) sub =
val;
5980 if (new_size > old_size) {
5982 #if RGENGC_ESTIMATE_OLDMALLOC
5988 #if RGENGC_ESTIMATE_OLDMALLOC
6009 #if MALLOC_ALLOCATED_SIZE
6010 if (new_size >= old_size) {
6014 size_t dec_size = old_size -
new_size;
6015 size_t allocated_size = objspace->
malloc_params.allocated_size;
6017 #if MALLOC_ALLOCATED_SIZE_CHECK
6018 if (allocated_size < dec_size) {
6019 rb_bug(
"objspace_malloc_increase: underflow malloc_params.allocated_size.");
6025 if (0) fprintf(stderr,
"incraese - ptr: %p, type: %s, new_size: %d, old_size: %d\n",
6030 (
int)new_size, (
int)old_size);
6039 if (allocations > 0) {
6042 #if MALLOC_ALLOCATED_SIZE_CHECK
6054 static inline size_t
6057 if ((ssize_t)size < 0) {
6060 if (size == 0) size = 1;
6062 #if CALC_EXACT_MALLOC_SIZE
6063 size +=
sizeof(size_t);
6069 static inline void *
6072 #if CALC_EXACT_MALLOC_SIZE
6073 ((
size_t *)mem)[0] =
size;
6074 mem = (
size_t *)mem + 1;
6080 #define TRY_WITH_GC(alloc) do { \
6082 (!garbage_collect_with_gvl(objspace, 1, 1, GPR_FLAG_MALLOC) || \
6105 if ((ssize_t)new_size < 0) {
6116 if (new_size == 0) {
6121 #if CALC_EXACT_MALLOC_SIZE
6122 new_size +=
sizeof(size_t);
6123 ptr = (
size_t *)ptr - 1;
6124 oldsize = ((
size_t *)ptr)[0];
6131 #if CALC_EXACT_MALLOC_SIZE
6133 mem = (
size_t *)mem + 1;
6144 #if CALC_EXACT_MALLOC_SIZE
6145 ptr = ((
size_t *)ptr) - 1;
6146 oldsize = ((
size_t*)ptr)[0];
6161 static inline size_t
6164 size_t len = size * n;
6165 if (n != 0 && size != len / n) {
6196 #ifdef ruby_sized_xrealloc
6197 #undef ruby_sized_xrealloc
6211 #ifdef ruby_sized_xrealloc2
6212 #undef ruby_sized_xrealloc2
6217 size_t len = size * n;
6218 if (n != 0 && size != len / n) {
6230 #ifdef ruby_sized_xfree
6231 #undef ruby_sized_xfree
6254 #if CALC_EXACT_MALLOC_SIZE
6255 size +=
sizeof(size_t);
6258 #if CALC_EXACT_MALLOC_SIZE
6260 ((
size_t *)mem)[0] = 0;
6261 mem = (
size_t *)mem + 1;
6269 size_t *mem = (
size_t *)ptr;
6270 #if CALC_EXACT_MALLOC_SIZE
6276 #if MALLOC_ALLOCATED_SIZE
6287 gc_malloc_allocated_size(
VALUE self)
6302 gc_malloc_allocations(
VALUE self)
6318 #define WMAP_DELETE_DEAD_OBJECT_IN_MARK 0
6320 #if WMAP_DELETE_DEAD_OBJECT_IN_MARK
6335 #if WMAP_DELETE_DEAD_OBJECT_IN_MARK
6362 *(
size_t *)arg += (ptr[0] + 1) *
sizeof(
VALUE);
6370 const struct weakmap *w = ptr;
6404 if (!existing)
return ST_STOP;
6406 for (i = j = 1, size = ptr[0]; i <=
size; ++i) {
6407 if (ptr[i] != wmap) {
6437 rids = (
VALUE *)data;
6439 for (i = 0; i <
size; ++i) {
6628 size = (ptr = optr = (
VALUE *)*val)[0];
6639 if (ptr == optr)
return ST_STOP;
6692 #if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
6703 #define GC_PROFILE_RECORD_DEFAULT_SIZE 100
6708 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
6710 static int try_clock_gettime = 1;
6712 if (try_clock_gettime &&
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
6716 try_clock_gettime = 0;
6723 struct rusage usage;
6725 if (
getrusage(RUSAGE_SELF, &usage) == 0) {
6726 time = usage.ru_utime;
6734 FILETIME creation_time, exit_time, kernel_time, user_time;
6739 if (GetProcessTimes(GetCurrentProcess(),
6740 &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
6741 memcpy(&ui, &user_time,
sizeof(FILETIME));
6742 q = ui.QuadPart / 10L;
6743 t = (
DWORD)(q % 1000000L) * 1e-6;
6748 t += (double)(
DWORD)(q >> 16) * (1 << 16);
6749 t += (
DWORD)q & ~(~0 << 16);
6778 rb_bug(
"gc_profile malloc or realloc miss");
6785 #if MALLOC_ALLOCATED_SIZE
6788 #if GC_PROFILE_DETAIL_MEMORY
6791 struct rusage usage;
6792 if (
getrusage(RUSAGE_SELF, &usage) == 0) {
6793 record->maxrss = usage.ru_maxrss;
6794 record->minflt = usage.ru_minflt;
6795 record->majflt = usage.ru_majflt;
6808 #if GC_PROFILE_MORE_DETAIL
6809 record->prepare_time = objspace->
profile.prepare_time;
6844 #if GC_PROFILE_MORE_DETAIL
6857 #if GC_PROFILE_MORE_DETAIL
6894 record->
gc_time += sweep_time;
6900 #if GC_PROFILE_MORE_DETAIL
6901 record->gc_sweep_time += sweep_time;
6911 #if GC_PROFILE_MORE_DETAIL
6928 #if GC_PROFILE_MORE_DETAIL
6930 record->heap_live_objects = live;
6931 record->heap_free_objects = total - live;
7038 #if GC_PROFILE_MORE_DETAIL
7053 #if RGENGC_PROFILE > 0
7064 #if GC_PROFILE_MORE_DETAIL
7065 #define MAJOR_REASON_MAX 0x10
7068 gc_profile_dump_major_reason(
int flags,
char *buff)
7079 if (reason & GPR_FLAG_MAJOR_BY_##x) { \
7080 buff[i++] = #x[0]; \
7081 if (i >= MAJOR_REASON_MAX) rb_bug("gc_profile_dump_major_reason: overflow"); \
7089 #if RGENGC_ESTIMATE_OLDMALLOC
7103 #ifdef MAJOR_REASON_MAX
7104 char reason_str[MAJOR_REASON_MAX];
7112 append(out,
rb_str_new_cstr(
"Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
7114 for (i = 0; i <
count; i++) {
7121 #if GC_PROFILE_MORE_DETAIL
7124 "Prepare Time = Previously GC's rest sweep time\n"
7125 "Index Flags Allocate Inc. Allocate Limit"
7129 " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
7131 " OldgenObj RemNormObj RemShadObj"
7134 " MaxRSS(KB) MinorFLT MajorFLT"
7138 for (i = 0; i <
count; i++) {
7154 gc_profile_dump_major_reason(record->
flags, reason_str),
7161 record->allocate_increase, record->allocate_limit,
7163 record->allocated_size,
7165 record->heap_use_pages,
7166 record->gc_mark_time*1000,
7167 record->gc_sweep_time*1000,
7168 record->prepare_time*1000,
7170 record->heap_live_objects,
7171 record->heap_free_objects,
7172 record->removing_objects,
7173 record->empty_objects
7176 record->old_objects,
7177 record->remembered_normal_objects,
7178 record->remembered_shady_objects
7182 record->maxrss / 1024,
7254 for (i = 0; i <
count; i++) {
7318 #define TYPE_NAME(t) case (t): return #t;
7369 fprintf(stderr,
"pointer to heap?: true\n");
7372 fprintf(stderr,
"pointer to heap?: false\n");
7379 fprintf(stderr,
"young? : %s\n", RVALUE_YOUNG_P(obj) ?
"true" :
"false");
7381 fprintf(stderr,
"old? : %s\n",
RVALUE_OLD_P(obj) ?
"true" :
"false");
7387 fprintf(stderr,
"lazy sweeping?: true\n");
7388 fprintf(stderr,
"swept?: %s\n",
is_swept_object(objspace, obj) ?
"done" :
"not yet");
7391 fprintf(stderr,
"lazy sweeping?: false\n");
7398 fprintf(stderr,
"WARNING: object %s(%p) is inadvertently collected\n", (
char *)name, (
void *)obj);
7403 rb_gcdebug_sentinel(
VALUE obj,
const char *name)
7549 #if MALLOC_ALLOCATED_SIZE
7558 #define OPT(o) if (o) rb_ary_push(opts, rb_str_new2(#o))
rb_event_flag_t hook_events
static int rgengc_unprotect_logging_exit_func_i(st_data_t key, st_data_t val)
#define RBASIC_CLEAR_CLASS(obj)
static void * objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
static void mark_hash(rb_objspace_t *objspace, st_table *tbl)
void rb_gc_finalize_deferred(void)
void rb_class_remove_from_super_subclasses(VALUE klass)
size_t heap_total_objects
static void gc_marks(rb_objspace_t *objspace, int full_mark)
static st_index_t new_size(st_index_t size)
void rb_class_detach_subclasses(VALUE klass)
struct rb_objspace::@104 flags
static void gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_heap_t *heap)
bits_t oldgen_bits[HEAP_BITMAP_LIMIT]
int ruby_thread_has_gvl_p(void)
void rb_gc_writebarrier(VALUE a, VALUE b)
static void root_objects_from(VALUE obj, void *ptr)
static void gc_mark_roots(rb_objspace_t *objspace, int full_mark, const char **categoryp)
void(* func)(const char *category, VALUE, void *)
void rb_bug(const char *fmt,...)
#define heap_pages_final_slots
static VALUE gc_profile_disable(void)
static void objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
static int set_zero(st_data_t key, st_data_t val, st_data_t arg)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_DTRACE_GC_SWEEP_END_ENABLED()
#define GC_PROFILE_MORE_DETAIL
VALUE rb_obj_id(VALUE obj)
size_t strlen(const char *)
#define rb_gc_mark_locations(start, end)
void rb_objspace_free(rb_objspace_t *objspace)
static void gc_prof_set_malloc_info(rb_objspace_t *)
#define RCLASS_CONST_TBL(c)
static VALUE wmap_each(VALUE self)
#define RUBY_DEFAULT_FREE
static void pop_mark_stack_chunk(mark_stack_t *stack)
static VALUE wmap_each_value(VALUE self)
double gc_sweep_start_time
size_t rb_io_memsize(const rb_io_t *)
static void gc_prof_timer_stop(rb_objspace_t *)
static int rgengc_remembered(rb_objspace_t *objspace, VALUE obj)
VALUE rb_yield_values(int n,...)
static int max(int a, int b)
static VALUE id2ref(VALUE obj, VALUE objid)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void * ruby_sized_xrealloc2(void *ptr, size_t n, size_t size, size_t old_n)
static int mark_keyvalue(st_data_t key, st_data_t value, st_data_t data)
#define GC_HEAP_GROWTH_FACTOR
static VALUE RVALUE_PROMOTED_P(VALUE obj)
static VALUE os_each_obj(int argc, VALUE *argv, VALUE os)
static int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
size_t ruby_stack_length(VALUE **p)
#define FLUSH_REGISTER_WINDOWS
static VALUE run_single_final(VALUE arg)
#define malloc_allocated_size
bits_t rememberset_bits[HEAP_BITMAP_LIMIT]
#define GC_HEAP_OLDOBJECT_LIMIT_FACTOR
static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
void rb_class_remove_from_module_subclasses(VALUE klass)
static void RVALUE_PROMOTE_INFANT(VALUE obj)
#define ATOMIC_EXCHANGE(var, val)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
static int wmap_each_i(st_data_t key, st_data_t val, st_data_t arg)
VALUE rb_obj_is_thread(VALUE obj)
int st_insert(st_table *, st_data_t, st_data_t)
static void wmap_mark(void *ptr)
static VALUE gc_verify_internal_consistency(VALUE self)
size_t onig_memsize(const regex_t *reg)
static void mark_m_tbl_wrapper(rb_objspace_t *objspace, struct method_table_wrapper *wrapper)
static void gc_finalize_deferred(void *dmy)
static size_t objspace_live_slot(rb_objspace_t *objspace)
static size_t objspace_malloc_prepare(rb_objspace_t *objspace, size_t size)
struct rb_method_entry_struct * orig_me
#define TypedData_Get_Struct(obj, type, data_type, sval)
static VALUE check_gen_consistency(VALUE obj)
void(* mark_func)(VALUE v, void *data)
static int stack_check(int water_mark)
void * ruby_xmalloc2(size_t n, size_t size)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
static VALUE gc_info_decode(int flags, VALUE hash_or_key)
void ruby_mimfree(void *ptr)
void rb_gcdebug_print_obj_condition(VALUE obj)
#define GC_ENABLE_LAZY_SWEEP
static int wmap_keys_i(st_data_t key, st_data_t val, st_data_t arg)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define SIZED_REALLOC_N(var, type, n, old_n)
static void gc_prof_mark_timer_start(rb_objspace_t *)
void st_free_table(st_table *)
size_t oldmalloc_increase
#define RGENGC_ESTIMATE_OLDMALLOC
void * ruby_xrealloc2(void *ptr, size_t n, size_t size)
static struct heap_page * heap_page_create(rb_objspace_t *objspace)
static VALUE count_objects(int argc, VALUE *argv, VALUE os)
#define RGENGC_CHECK_MODE
void ruby_sized_xfree(void *x, size_t size)
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *passing_data)
#define STACK_UPPER(x, a, b)
static double elapsed_time_from(double time)
static void * objspace_xmalloc(rb_objspace_t *objspace, size_t size)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
static void gc_prof_sweep_timer_start(rb_objspace_t *)
static void make_deferred(rb_objspace_t *objspace, RVALUE *p)
#define GC_MALLOC_LIMIT_MAX
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
int rb_io_fptr_finalize(rb_io_t *)
static void ruby_memerror(void)
static void rgengc_report_body(int level, rb_objspace_t *objspace, const char *fmt,...)
int ruby_get_stack_grow_direction(volatile VALUE *addr)
void rb_sweep_method_entry(void *vm)
#define GC_PROFILE_DETAIL_MEMORY
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
st_table * st_init_strtable(void)
#define RCLASS_M_TBL_WRAPPER(c)
static int wmap_memsize_map(st_data_t key, st_data_t val, st_data_t arg)
static int wmap_values_i(st_data_t key, st_data_t val, st_data_t arg)
static void gc_heap_rest_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
static VALUE gc_profile_total_time(VALUE self)
union rb_method_definition_struct::@126 body
static struct heap_page * heap_page_allocate(rb_objspace_t *objspace)
double oldobject_limit_factor
static int obj_free(rb_objspace_t *objspace, VALUE obj)
static int mark_key(st_data_t key, st_data_t value, st_data_t data)
static int heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr)
#define nd_set_type(n, t)
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
#define RSTRUCT_EMBED_LEN_MASK
void rb_include_module(VALUE klass, VALUE module)
#define GC_PROFILE_RECORD_DEFAULT_SIZE
void rb_gc_mark(VALUE ptr)
static int rgengc_remembersetbits_get(rb_objspace_t *objspace, VALUE obj)
int rb_objspace_markable_object_p(VALUE obj)
#define ATOMIC_PTR_EXCHANGE(var, val)
static struct heap_page * heap_prepare_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
#define RUBY_INTERNAL_EVENT_GC_START
void rb_gc_register_address(VALUE *addr)
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
VALUE rb_io_write(VALUE, VALUE)
#define VALGRIND_MAKE_MEM_UNDEFINED(p, n)
static const char * obj_type_name(VALUE obj)
void rb_gc_writebarrier_unprotect_promoted(VALUE obj)
void callback(ffi_cif *cif, void *resp, void **args, void *ctx)
size_t heap_used_at_gc_start
static VALUE wmap_each_key(VALUE self)
int char_offset_num_allocated
#define gc_event_hook(objspace, event, data)
#define heap_pages_min_free_slots
static size_t objspace_free_slot(rb_objspace_t *objspace)
VALUE rb_str_buf_append(VALUE, VALUE)
static int mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data)
static int heap_increment(rb_objspace_t *objspace, rb_heap_t *heap)
static size_t objspace_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint)
static int garbage_collect_body(rb_objspace_t *, int full_mark, int immediate_sweep, int reason)
static int wmap_free_map(st_data_t key, st_data_t val, st_data_t arg)
int ruby_stack_grow_direction
static VALUE gc_stat_internal(VALUE hash_or_sym, size_t *out)
struct rb_thread_struct::@169 machine
int ruby_stack_check(void)
void rb_mark_method_entry(const rb_method_entry_t *me)
struct heap_page_header header
static VALUE wmap_size(VALUE self)
const char * rb_obj_classname(VALUE)
struct rb_objspace::mark_func_data_struct * mark_func_data
static void push_mark_stack(mark_stack_t *, VALUE)
void rb_gc_force_recycle(VALUE p)
#define MARK_CHECKPOINT(category)
static size_t obj_memsize_of(VALUE obj, int use_tdata)
#define ATOMIC_SIZE_ADD(var, val)
#define ATOMIC_SIZE_CAS(var, oldval, val)
static VALUE objspace_each_objects(VALUE arg)
static void negative_size_allocation_error(const char *)
gc_profile_record * current_record
#define ruby_initial_gc_stress
static VALUE define_final(int argc, VALUE *argv, VALUE os)
#define RUBY_DTRACE_GC_SWEEP_END()
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
static int force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
#define heap_pages_deferred_final
#define GET_HEAP_OLDGEN_BITS(x)
static void RVALUE_DEMOTE_FROM_OLD(VALUE obj)
#define obj_id_to_ref(objid)
void rb_global_variable(VALUE *var)
static VALUE wmap_allocate(VALUE klass)
static void mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
static VALUE RVALUE_OLD_BITMAP_P(VALUE obj)
#define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
unsigned int malloc_limit_min
void rb_gc_unprotect_logging(void *objptr, const char *filename, int line)
static int mark_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data)
VALUE data[STACK_CHUNK_SIZE]
void rb_exc_raise(VALUE mesg)
void rb_objspace_set_event_hook(const rb_event_flag_t event)
static void finalize_list(rb_objspace_t *objspace, RVALUE *p)
void rb_free_m_tbl_wrapper(struct method_table_wrapper *wrapper)
VALUE rb_define_finalizer(VALUE obj, VALUE block)
static void gc_marks_body(rb_objspace_t *objspace, int full_mark)
#define RBASIC_SET_CLASS_RAW(obj, cls)
static size_t xmalloc2_size(size_t n, size_t size)
size_t rb_obj_memsize_of(VALUE obj)
#define RB_TYPE_P(obj, type)
void * ruby_xcalloc(size_t n, size_t size)
#define GET_STACK_BOUNDS(start, end, appendix)
static void gc_prof_timer_start(rb_objspace_t *)
#define ATOMIC_SET(var, val)
int st_lookup(st_table *, st_data_t, st_data_t *)
#define MEMZERO(p, type, n)
VALUE rb_obj_method(VALUE, VALUE)
struct rb_objspace::@102 malloc_params
size_t oldmalloc_increase_limit
#define heap_pages_max_free_slots
void rb_free_generic_ivar(VALUE)
static const char * type_name(int type, VALUE obj)
int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data)
static VALUE wmap_has_key(VALUE self, VALUE key)
static void * aligned_malloc(size_t, size_t)
int ruby_disable_gc_stress
void rb_ary_free(VALUE ary)
void rb_mark_end_proc(void)
static void gc_mark(rb_objspace_t *objspace, VALUE ptr)
#define GC_HEAP_GROWTH_MAX_SLOTS
VALUE rb_class_name(VALUE)
VALUE rb_undefine_finalizer(VALUE obj)
size_t total_allocated_object_num
void rb_vm_mark(void *ptr)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_sweep, int reason)
static void * gc_with_gvl(void *ptr)
void rb_gc_copy_finalizer(VALUE dest, VALUE obj)
void rb_mark_generic_ivar_tbl(void)
RUBY_EXTERN VALUE rb_cObject
static void finalize_deferred(rb_objspace_t *objspace)
static VALUE define_final0(VALUE obj, VALUE block)
static void * negative_size_allocation_error_with_gvl(void *ptr)
void rb_gc_unregister_address(VALUE *addr)
static void gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page)
static int pop_mark_stack(mark_stack_t *, VALUE *)
static VALUE gc_stress_get(VALUE self)
#define VALGRIND_MAKE_MEM_DEFINED(p, n)
static void gc_after_sweep(rb_objspace_t *objspace)
VALUE rb_str_cat2(VALUE, const char *)
static VALUE RVALUE_INFANT_P(VALUE obj)
RUBY_EXTERN VALUE rb_cBasicObject
static int gc_marked(rb_objspace_t *objspace, VALUE ptr)
struct gc_profile_record gc_profile_record
static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr)
void rb_free_method_entry(rb_method_entry_t *me)
RUBY_EXTERN VALUE rb_mKernel
#define RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()
static VALUE heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
static void push_mark_stack_chunk(mark_stack_t *stack)
#define nonspecial_obj_id(obj)
#define RUBY_DTRACE_GC_MARK_END_ENABLED()
void st_add_direct(st_table *, st_data_t, st_data_t)
static struct heap_page * heap_page_resurrect(rb_objspace_t *objspace)
VALUE rb_gc_latest_gc_info(VALUE key)
static VALUE os_obj_of(VALUE of)
static size_t wmap_memsize(const void *ptr)
static int gc_heap_lazy_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
int st_delete(st_table *, st_data_t *, st_data_t *)
void rb_define_const(VALUE, const char *, VALUE)
VALUE rb_obj_is_mutex(VALUE obj)
#define MALLOC_ALLOCATED_SIZE
static void heap_add_freepage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
rb_atomic_t cnt[RUBY_NSIG]
unsigned int oldmalloc_limit_max
void onig_region_free(OnigRegion *r, int free_self)
bits_t mark_bits[HEAP_BITMAP_LIMIT]
#define heap_pages_increment
size_t onig_region_memsize(const OnigRegion *regs)
struct force_finalize_list * next
static int free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data)
void rb_gc_register_mark_object(VALUE obj)
if((ID)(DISPID) nameid!=nameid)
#define ATOMIC_SIZE_EXCHANGE(var, val)
#define GC_MALLOC_LIMIT_GROWTH_FACTOR
static void gc_before_sweep(rb_objspace_t *objspace)
#define is_lazy_sweeping(heap)
#define RUBY_DTRACE_GC_MARK_END()
#define RSTRUCT_CONST_PTR(st)
static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap)
static RVALUE * heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
size_t rb_objspace_data_type_memsize(VALUE obj)
#define RBIGNUM_DIGITS(b)
NODE * rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
struct rb_objspace::@105 profile
#define RGENGC_WB_PROTECTED_NODE_CREF
void rb_gc_mark_machine_stack(rb_thread_t *th)
volatile VALUE * rb_gc_guarded_ptr(volatile VALUE *ptr)
static VALUE wmap_values(VALUE self)
static void run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
void * ruby_mimmalloc(size_t size)
st_table * finalizer_table
#define rb_thread_raised_clear(th)
#define RUBY_INTERNAL_EVENT_GC_END_MARK
static void gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
static int internal_object_p(VALUE obj)
#define OBJ_WB_PROTECTED(x)
static void gc_prof_set_heap_info(rb_objspace_t *)
static int is_dead_object(rb_objspace_t *objspace, VALUE ptr)
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
size_t total_freed_object_num
static void gc_profile_dump_on(VALUE out, VALUE(*append)(VALUE, VALUE))
#define RARRAY_CONST_PTR(a)
struct RRational rational
SSL_METHOD *(* func)(void)
static void rgengc_unprotect_logging_exit_func(void)
static double getrusage_time(void)
static VALUE gc_profile_report(int argc, VALUE *argv, VALUE self)
VALUE * ruby_initial_gc_stress_ptr
double malloc_limit_growth_factor
static void gc_set_initial_pages(void)
static void gc_prof_sweep_timer_stop(rb_objspace_t *)
VALUE rb_sprintf(const char *format,...)
int rb_objspace_internal_object_p(VALUE obj)
struct heap_page_body * body
#define GET_HEAP_MARK_BITS(x)
#define STACKFRAME_FOR_CALL_CFUNC
unsigned int oldmalloc_limit_min
int rb_obj_respond_to(VALUE, ID, int)
static void gc_prof_mark_timer_stop(rb_objspace_t *)
static void aligned_free(void *)
size_t rb_obj_gc_flags(VALUE obj, ID *flags, size_t max)
static void add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
#define MARKED_IN_BITMAP(bits, p)
#define MEMMOVE(p1, p2, type, n)
static void run_final(rb_objspace_t *objspace, VALUE obj)
static VALUE wmap_aset(VALUE self, VALUE wmap, VALUE orig)
#define RVALUE_OLDGEN_BITMAP(obj)
static int os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
static int rgengc_remember(rb_objspace_t *objspace, VALUE obj)
#define rb_thread_raised_set(th, f)
unsigned char buf[MIME_BUF_SIZE]
static int wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
static void mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
static void mark_tbl(rb_objspace_t *objspace, st_table *tbl)
void Init_stack(volatile VALUE *addr)
static st_table * rgengc_unprotect_logging_table
static size_t objspace_total_slot(rb_objspace_t *objspace)
static ruby_gc_params_t gc_params
struct RVALUE::@99::@100 free
static VALUE lazy_sweep_enable(void)
#define ATOMIC_SIZE_INC(var)
static void verify_internal_consistency_reachable_i(VALUE child, void *ptr)
#define MALLOC_ALLOCATED_SIZE_CHECK
static void atomic_sub_nounderflow(size_t *var, size_t sub)
void rb_gc_mark_symbols(int full_mark)
static VALUE newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
static void heap_pages_free_unused_pages(rb_objspace_t *objspace)
static int is_id_value(rb_objspace_t *objspace, VALUE ptr)
static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap)
static void heap_add_pages(rb_objspace_t *objspace, rb_heap_t *heap, size_t add)
VALUE rb_obj_rgengc_writebarrier_protected_p(VALUE obj)
static VALUE gc_profile_enable_get(VALUE self)
static void rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
static VALUE gc_start_internal(int argc, VALUE *argv, VALUE self)
static int mark_entry(st_data_t key, st_data_t value, st_data_t data)
#define gc_prof_record(objspace)
const char * rb_objspace_data_type_name(VALUE obj)
void rb_free_const_table(st_table *tbl)
static int is_markable_object(rb_objspace_t *objspace, VALUE obj)
unsigned int malloc_limit_max
static VALUE RVALUE_OLD_P(VALUE obj)
static void * ruby_memerror_body(void *dummy)
void rb_mark_tbl(st_table *tbl)
#define heap_pages_swept_slots
VALUE rb_gc_disable(void)
int clock_gettime(clockid_t, struct timespec *)
#define SET_MACHINE_STACK_END(p)
void ruby_init_stack(volatile VALUE *)
static int get_envparam_double(const char *name, double *default_value, double lower_bound)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
VALUE rb_str_new_cstr(const char *)
struct heap_page * free_next
int rb_sigaltstack_size(void)
void * ruby_xrealloc(void *ptr, size_t new_size)
#define RVALUE_WB_PROTECTED(obj)
st_table * st_init_numtable(void)
static VALUE gc_stress_set(VALUE self, VALUE flag)
unsigned int heap_free_slots
void ruby_gc_set_params(int safe_level)
void rb_class_detach_module_subclasses(VALUE klass)
static void wmap_free(void *ptr)
static int is_mark_stack_empty(mark_stack_t *stack)
int rb_garbage_collect(void)
struct RVALUE::@99::@101 values
static VALUE gc_latest_gc_info(int argc, VALUE *argv, VALUE self)
size_t rb_ary_memsize(VALUE)
unsigned int growth_max_slots
static const rb_data_type_t weakmap_type
VALUE rb_define_module_under(VALUE outer, const char *name)
void rb_gc_set_params(void)
static void heap_assign_page(rb_objspace_t *objspace, rb_heap_t *heap)
static void heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
void rb_free_m_tbl(st_table *tbl)
void * ruby_xmalloc(size_t size)
static VALUE gc_profile_result(void)
static VALUE wmap_aref(VALUE self, VALUE wmap)
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
#define MARK_IN_BITMAP(bits, p)
static VALUE wmap_keys(VALUE self)
void * ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
#define GC_HEAP_FREE_SLOTS
static int rgengc_remembersetbits_set(rb_objspace_t *objspace, VALUE obj)
void rb_gc_mark_parser(void)
static void free_stack_chunks(mark_stack_t *)
static VALUE gc_profile_record_get(void)
void rb_mark_generic_ivar(VALUE)
static void gc_rest_sweep(rb_objspace_t *objspace)
static int wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
static int ready_to_gc(rb_objspace_t *objspace)
#define RARRAY_AREF(a, i)
static void mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
VALUE rb_block_proc(void)
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
rb_method_definition_t * def
size_t st_memsize(const st_table *)
#define RUBY_INTERNAL_EVENT_NEWOBJ
#define RUBY_INTERNAL_EVENT_FREEOBJ
void rb_set_errinfo(VALUE err)
static int wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
#define RUBY_DTRACE_GC_SWEEP_BEGIN()
void(* RUBY_DATA_FUNC)(void *)
int getrusage(int who, struct rusage *usage)
unsigned long rb_event_flag_t
size_t rb_gc_stat(VALUE key)
void rb_mark_set(st_table *tbl)
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
static VALUE gc_count(VALUE self)
static int is_swept_object(rb_objspace_t *objspace, VALUE ptr)
VALUE rb_newobj_of(VALUE klass, VALUE flags)
#define RCLASS_IV_INDEX_TBL(c)
static void heap_pages_expand_sorted(rb_objspace_t *objspace)
struct gc_list * global_list
static void * objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size)
static void heap_add_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
static VALUE wmap_inspect(VALUE self)
static void gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
VALUE rb_obj_is_fiber(VALUE obj)
static stack_chunk_t * stack_chunk_alloc(void)
static int rb_special_const_p(VALUE obj)
void rb_gc_writebarrier_remember_promoted(VALUE obj)
gc_profile_record * records
VALUE rb_proc_new(VALUE(*)(ANYARGS), VALUE)
void rb_gc_resurrect(VALUE obj)
static void rb_objspace_call_finalizer(rb_objspace_t *objspace)
size_t total_allocated_object_num_at_gc_start
VALUE rb_obj_rgengc_promoted_p(VALUE obj)
struct rb_encoding_entry * list
static int get_envparam_int(const char *name, unsigned int *default_value, int lower_bound)
static int wmap_each_value_i(st_data_t key, st_data_t val, st_data_t arg)
void rb_gc_mark_unlinked_live_method_entries(void *pvm)
#define heap_pages_length
int each_obj_callback(void *, void *, size_t, void *)
struct rb_heap_struct rb_heap_t
rb_objspace_t * rb_objspace_alloc(void)
struct rb_classext_struct rb_classext_t
static int free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_eval_cmd(VALUE, VALUE, int)
struct mark_stack mark_stack_t
#define rb_thread_raised_p(th, f)
static unsigned int hash(const char *str, unsigned int len)
#define RETURN_ENUMERATOR(obj, argc, argv)
#define heap_pages_sorted
struct rmatch_offset * char_offset
#define RVALUE_WB_PROTECTED_RAW(obj)
static void gc_event_hook_body(rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data)
static void init_mark_stack(mark_stack_t *stack)
void rb_gc_mark_maybe(VALUE obj)
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, klass_, data_)
#define assert(condition)
static void shrink_stack_chunk_cache(mark_stack_t *stack)
#define GC_HEAP_INIT_SLOTS
static int heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
const char * rb_id2name(ID id)
static void gc_prof_setup_new_record(rb_objspace_t *objspace, int reason)
void rb_gc_mark_global_tbl(void)
#define ruby_native_thread_p()
struct rb_objspace::@103 heap_pages
static int is_live_object(rb_objspace_t *objspace, VALUE ptr)
#define GC_OLDMALLOC_LIMIT_MIN
unsigned int heap_init_slots
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
static void make_io_deferred(rb_objspace_t *objspace, RVALUE *p)
static void gc_mark_stacked_objects(rb_objspace_t *)
static int garbage_collect_with_gvl(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
#define RTYPEDDATA_DATA(v)
struct heap_page * using_page
#define rb_check_frozen(obj)
#define RBIGNUM_EMBED_FLAG
struct RTypedData typeddata
RUBY_EXTERN VALUE rb_stdout
#define RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()
void rb_gc_call_finalizer_at_exit(void)
size_t rb_generic_ivar_memsize(VALUE)
size_t remembered_shady_object_count
VALUE rb_obj_freeze(VALUE)
#define SPECIAL_CONST_P(x)
struct rb_objspace rb_objspace_t
static int verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, void *ptr)
#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK
static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
#define RUBY_INTERNAL_EVENT_GC_END_SWEEP
static void gc_before_heap_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
VALUE rb_define_module(const char *name)
#define RUBY_DTRACE_GC_MARK_BEGIN()
#define gc_prof_enabled(objspace)
static void heap_set_increment(rb_objspace_t *objspace, size_t minimum_limit)
void rb_mark_hash(st_table *tbl)
#define GC_MALLOC_LIMIT_MIN
each_obj_callback * callback
static VALUE undefine_final(VALUE os, VALUE obj)
VALUE rb_str_buf_new(long)
static VALUE gc_profile_clear(void)
void rb_gc_mark_encodings(void)
static void * objspace_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
static int wmap_each_key_i(st_data_t key, st_data_t val, st_data_t arg)
#define GET_HEAP_REMEMBERSET_BITS(x)
static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size)
#define RTYPEDDATA_TYPE(v)
#define GC_OLDMALLOC_LIMIT_MAX
static VALUE wmap_finalize(VALUE self, VALUE objid)
static VALUE gc_stat(int argc, VALUE *argv, VALUE self)
static void mark_set(rb_objspace_t *objspace, st_table *tbl)
void onig_free(regex_t *reg)
static rb_thread_t * GET_THREAD(void)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
#define CALC_EXACT_MALLOC_SIZE
struct heap_page ** sorted
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
static ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS void mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
double oldmalloc_limit_growth_factor
size_t rb_str_memsize(VALUE)
struct stack_chunk stack_chunk_t
void rb_warn(const char *fmt,...)
static VALUE gc_profile_enable(void)
#define CLEAR_IN_BITMAP(bits, p)
struct rb_objspace::@106 rgengc
VALUE rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
static void should_be_finalizable(VALUE obj)
static void should_be_callable(VALUE block)
struct heap_page * free_pages
static void gc_setup_mark_bits(struct heap_page *page)
static void heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
static void gc_finalize_deferred_register(void)
#define TRY_WITH_GC(alloc)
struct stack_chunk * next
struct heap_page * sweep_pages
static int gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr)
size_t remembered_shady_object_limit