Ruby  2.1.3p242(2014-09-19revision47630)
gc.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  gc.c -
4 
5  $Author: nagachika $
6  created at: Tue Oct 5 09:44:46 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/ruby.h"
15 #include "ruby/st.h"
16 #include "ruby/re.h"
17 #include "ruby/io.h"
18 #include "ruby/thread.h"
19 #include "ruby/util.h"
20 #include "ruby/debug.h"
21 #include "eval_intern.h"
22 #include "vm_core.h"
23 #include "internal.h"
24 #include "gc.h"
25 #include "constant.h"
26 #include "ruby_atomic.h"
27 #include "probes.h"
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <setjmp.h>
31 #include <sys/types.h>
32 #include <assert.h>
33 
34 #ifndef __has_feature
35 # define __has_feature(x) 0
36 #endif
37 
38 #ifndef HAVE_MALLOC_USABLE_SIZE
39 # ifdef _WIN32
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)
45 # endif
46 #endif
47 #ifdef HAVE_MALLOC_USABLE_SIZE
48 # ifdef HAVE_MALLOC_H
49 # include <malloc.h>
50 # elif defined(HAVE_MALLOC_NP_H)
51 # include <malloc_np.h>
52 # elif defined(HAVE_MALLOC_MALLOC_H)
53 # include <malloc/malloc.h>
54 # endif
55 #endif
56 
57 #if /* is ASAN enabled? */ \
58  __has_feature(address_sanitizer) /* Clang */ || \
59  defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x */
60  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
61  __attribute__((no_address_safety_analysis)) \
62  __attribute__((noinline))
63 #else
64  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
65 #endif
66 
67 #ifdef HAVE_SYS_TIME_H
68 #include <sys/time.h>
69 #endif
70 
71 #ifdef HAVE_SYS_RESOURCE_H
72 #include <sys/resource.h>
73 #endif
74 #if defined(__native_client__) && defined(NACL_NEWLIB)
75 # include "nacl/resource.h"
76 # undef HAVE_POSIX_MEMALIGN
77 # undef HAVE_MEMALIGN
78 
79 #endif
80 
81 #if defined _WIN32 || defined __CYGWIN__
82 #include <windows.h>
83 #elif defined(HAVE_POSIX_MEMALIGN)
84 #elif defined(HAVE_MEMALIGN)
85 #include <malloc.h>
86 #endif
87 
88 #define rb_setjmp(env) RUBY_SETJMP(env)
89 #define rb_jmp_buf rb_jmpbuf_t
90 
91 #if defined(HAVE_RB_GC_GUARDED_PTR) && HAVE_RB_GC_GUARDED_PTR
92 volatile VALUE *
93 rb_gc_guarded_ptr(volatile VALUE *ptr)
94 {
95  return ptr;
96 }
97 #endif
98 
99 #ifndef GC_HEAP_FREE_SLOTS
100 #define GC_HEAP_FREE_SLOTS 4096
101 #endif
102 #ifndef GC_HEAP_INIT_SLOTS
103 #define GC_HEAP_INIT_SLOTS 10000
104 #endif
105 #ifndef GC_HEAP_GROWTH_FACTOR
106 #define GC_HEAP_GROWTH_FACTOR 1.8
107 #endif
108 #ifndef GC_HEAP_GROWTH_MAX_SLOTS
109 #define GC_HEAP_GROWTH_MAX_SLOTS 0 /* 0 is disable */
110 #endif
111 #ifndef GC_HEAP_OLDOBJECT_LIMIT_FACTOR
112 #define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
113 #endif
114 
115 #ifndef GC_MALLOC_LIMIT_MIN
116 #define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
117 #endif
118 #ifndef GC_MALLOC_LIMIT_MAX
119 #define GC_MALLOC_LIMIT_MAX (32 * 1024 * 1024 /* 32MB */)
120 #endif
121 #ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR
122 #define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.4
123 #endif
124 
125 #ifndef GC_OLDMALLOC_LIMIT_MIN
126 #define GC_OLDMALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
127 #endif
128 #ifndef GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
129 #define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR 1.2
130 #endif
131 #ifndef GC_OLDMALLOC_LIMIT_MAX
132 #define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 /* 128MB */)
133 #endif
134 
135 typedef struct {
136  unsigned int heap_init_slots;
137  unsigned int heap_free_slots;
139  unsigned int growth_max_slots;
141  unsigned int malloc_limit_min;
142  unsigned int malloc_limit_max;
144  unsigned int oldmalloc_limit_min;
145  unsigned int oldmalloc_limit_max;
147 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
149 #endif
151 
164 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
165  FALSE,
166 #endif
167 };
168 
169 /* GC_DEBUG:
170  * enable to embed GC debugging information.
171  */
172 #ifndef GC_DEBUG
173 #define GC_DEBUG 0
174 #endif
175 
176 #if USE_RGENGC
177 /* RGENGC_DEBUG:
178  * 1: basic information
179  * 2: remember set operation
180  * 3: mark
181  * 4:
182  * 5: sweep
183  */
184 #ifndef RGENGC_DEBUG
185 #define RGENGC_DEBUG 0
186 #endif
187 
188 /* RGENGC_CHECK_MODE
189  * 0: disable all assertions
190  * 1: enable assertions (to debug RGenGC)
191  * 2: enable generational bits check (for debugging)
192  * 3: enable livness check
193  * 4: show all references
194  */
195 #ifndef RGENGC_CHECK_MODE
196 #define RGENGC_CHECK_MODE 0
197 #endif
198 
199 /* RGENGC_PROFILE
200  * 0: disable RGenGC profiling
201  * 1: enable profiling for basic information
202  * 2: enable profiling for each types
203  */
204 #ifndef RGENGC_PROFILE
205 #define RGENGC_PROFILE 0
206 #endif
207 
208 /* RGENGC_THREEGEN
209  * Enable/disable three gen GC.
210  * 0: Infant gen -> Old gen
211  * 1: Infant gen -> Young -> Old gen
212  */
213 #ifndef RGENGC_THREEGEN
214 #define RGENGC_THREEGEN 0
215 #endif
216 
217 /* RGENGC_ESTIMATE_OLDMALLOC
218  * Enable/disable to estimate increase size of malloc'ed size by old objects.
219  * If estimation exceeds threashold, then will invoke full GC.
220  * 0: disable estimation.
221  * 1: enable estimation.
222  */
223 #ifndef RGENGC_ESTIMATE_OLDMALLOC
224 #define RGENGC_ESTIMATE_OLDMALLOC 1
225 #endif
226 
227 #else /* USE_RGENGC */
228 
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
234 
235 #endif /* USE_RGENGC */
236 
237 #ifndef GC_PROFILE_MORE_DETAIL
238 #define GC_PROFILE_MORE_DETAIL 0
239 #endif
240 #ifndef GC_PROFILE_DETAIL_MEMORY
241 #define GC_PROFILE_DETAIL_MEMORY 0
242 #endif
243 #ifndef GC_ENABLE_LAZY_SWEEP
244 #define GC_ENABLE_LAZY_SWEEP 1
245 #endif
246 #ifndef CALC_EXACT_MALLOC_SIZE
247 #define CALC_EXACT_MALLOC_SIZE 0
248 #endif
249 #if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0
250 #ifndef MALLOC_ALLOCATED_SIZE
251 #define MALLOC_ALLOCATED_SIZE 0
252 #endif
253 #else
254 #define MALLOC_ALLOCATED_SIZE 0
255 #endif
256 #ifndef MALLOC_ALLOCATED_SIZE_CHECK
257 #define MALLOC_ALLOCATED_SIZE_CHECK 0
258 #endif
259 
260 typedef enum {
261  GPR_FLAG_NONE = 0x000,
262  /* major reason */
268 #if RGENGC_ESTIMATE_OLDMALLOC
270 #endif
272 
273  /* gc reason */
277  GPR_FLAG_CAPI = 0x800,
278  GPR_FLAG_STRESS = 0x1000,
279 
280  /* others */
284 
285 typedef struct gc_profile_record {
286  int flags;
287 
288  double gc_time;
290 
294 
295 #if GC_PROFILE_MORE_DETAIL
296  double gc_mark_time;
297  double gc_sweep_time;
298 
299  size_t heap_use_pages;
300  size_t heap_live_objects;
301  size_t heap_free_objects;
302 
303  size_t allocate_increase;
304  size_t allocate_limit;
305 
306  double prepare_time;
307  size_t removing_objects;
308  size_t empty_objects;
309 #if GC_PROFILE_DETAIL_MEMORY
310  long maxrss;
311  long minflt;
312  long majflt;
313 #endif
314 #endif
315 #if MALLOC_ALLOCATED_SIZE
316  size_t allocated_size;
317 #endif
318 
319 #if RGENGC_PROFILE > 0
320  size_t old_objects;
321  size_t remembered_normal_objects;
322  size_t remembered_shady_objects;
323 #endif
325 
326 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
327 #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
328 #endif
329 
330 typedef struct RVALUE {
331  union {
332  struct {
333  VALUE flags; /* always 0 for freed obj */
334  struct RVALUE *next;
335  } free;
336  struct RBasic basic;
337  struct RObject object;
338  struct RClass klass;
339  struct RFloat flonum;
340  struct RString string;
341  struct RArray array;
342  struct RRegexp regexp;
343  struct RHash hash;
344  struct RData data;
346  struct RStruct rstruct;
347  struct RBignum bignum;
348  struct RFile file;
349  struct RNode node;
350  struct RMatch match;
353  struct {
354  struct RBasic basic;
358  } values;
359  } as;
360 #if GC_DEBUG
361  const char *file;
362  VALUE line;
363 #endif
364 } RVALUE;
365 
366 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
367 #pragma pack(pop)
368 #endif
369 
371 enum {
372  BITS_SIZE = sizeof(bits_t),
374 };
375 
377  struct heap_page *page;
378 };
379 
382  /* char gap[]; */
383  /* RVALUE values[]; */
384 };
385 
386 struct gc_list {
388  struct gc_list *next;
389 };
390 
391 #define STACK_CHUNK_SIZE 500
392 
393 typedef struct stack_chunk {
395  struct stack_chunk *next;
396 } stack_chunk_t;
397 
398 typedef struct mark_stack {
401  size_t index;
402  size_t limit;
403  size_t cache_size;
405 } mark_stack_t;
406 
407 typedef struct rb_heap_struct {
408  struct heap_page *pages;
413  size_t page_length; /* total page count in a heap */
414  size_t total_slots; /* total slot count (page_length * HEAP_OBJ_LIMIT) */
415 } rb_heap_t;
416 
417 typedef struct rb_objspace {
418  struct {
419  size_t limit;
420  size_t increase;
421 #if MALLOC_ALLOCATED_SIZE
422  size_t allocated_size;
423  size_t allocations;
424 #endif
425  } malloc_params;
426 
428  rb_heap_t tomb_heap; /* heap for zombies and ghosts */
429 
430  struct {
431  struct heap_page **sorted;
432  size_t used;
433  size_t length;
435 
436  size_t limit;
437  size_t increment;
438 
439  size_t swept_slots;
442 
443  /* final */
444  size_t final_slots;
446  } heap_pages;
447 
448  struct {
449  int dont_gc;
453  } flags;
456  struct {
457  int run;
460  size_t next_index;
461  size_t size;
462 
463 #if GC_PROFILE_MORE_DETAIL
464  double prepare_time;
465 #endif
466  double invoke_time;
467 
468 #if USE_RGENGC
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;
476 #if RGENGC_THREEGEN
477  size_t promote_young_count;
478 #endif
479  size_t remembered_normal_object_count;
481 
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];
485  size_t shade_operation_count_types[RUBY_T_MASK];
486  size_t promote_infant_types[RUBY_T_MASK];
487 #if RGENGC_THREEGEN
488  size_t promote_young_types[RUBY_T_MASK];
489 #endif
490  size_t remembered_normal_object_count_types[RUBY_T_MASK];
491  size_t remembered_shady_object_count_types[RUBY_T_MASK];
492 #endif
493 #endif /* RGENGC_PROFILE */
494 #endif /* USE_RGENGC */
495 
496  /* temporary profiling space */
500 
501  /* basic statistics */
502  size_t count;
506  } profile;
508  rb_event_flag_t hook_events; /* this place may be affinity with memory cache */
510 
512  void *data;
513  void (*mark_func)(VALUE v, void *data);
514  } *mark_func_data;
515 
516 #if USE_RGENGC
517  struct {
520 
522 
524 
529 #if RGENGC_THREEGEN
530  size_t young_object_count;
531 #endif
532 
533 #if RGENGC_ESTIMATE_OLDMALLOC
536 #endif
537 
538 #if RGENGC_CHECK_MODE >= 2
539  struct st_table *allrefs_table;
540  size_t error_count;
541 #endif
542  } rgengc;
543 #endif /* USE_RGENGC */
544 } rb_objspace_t;
545 
546 
547 #ifndef HEAP_ALIGN_LOG
548 /* default tiny heap size: 16KB */
549 #define HEAP_ALIGN_LOG 14
550 #endif
551 #define CEILDIV(i, mod) (((i) + (mod) - 1)/(mod))
552 enum {
555  REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5),
557  HEAP_OBJ_LIMIT = (unsigned int)((HEAP_SIZE - sizeof(struct heap_page_header))/sizeof(struct RVALUE)),
560  HEAP_BITMAP_PLANES = USE_RGENGC ? 3 : 1 /* RGENGC: mark bits, rememberset bits and oldgen bits */
561 };
562 
563 struct heap_page {
567  size_t final_slots;
568  size_t limit;
569  struct heap_page *next;
570  struct heap_page *prev;
574 
576 #if USE_RGENGC
579 #endif
580 };
581 
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))
592 /* Bitmap Operations */
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))
596 
597 /* Aliases */
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
602 #else
604 VALUE *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
605 #endif
606 
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
631 
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) /* unset 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))
640 #else
641 # error not supported
642 #endif
643 
644 #define RANY(o) ((RVALUE*)(o))
645 
646 #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
647 
651 
653 
654 static void rb_objspace_call_finalizer(rb_objspace_t *objspace);
655 static VALUE define_final0(VALUE obj, VALUE block);
656 
657 static void negative_size_allocation_error(const char *);
658 static void *aligned_malloc(size_t, size_t);
659 static void aligned_free(void *);
660 
661 static void init_mark_stack(mark_stack_t *stack);
662 
663 static VALUE lazy_sweep_enable(void);
664 static int ready_to_gc(rb_objspace_t *objspace);
665 static int heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap);
666 static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_sweep, int reason);
667 static int garbage_collect_body(rb_objspace_t *, int full_mark, int immediate_sweep, int reason);
668 static int gc_heap_lazy_sweep(rb_objspace_t *objspace, rb_heap_t *heap);
669 static void gc_rest_sweep(rb_objspace_t *objspace);
670 static void gc_heap_rest_sweep(rb_objspace_t *objspace, rb_heap_t *heap);
671 
673 static void gc_mark(rb_objspace_t *objspace, VALUE ptr);
674 static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr);
675 static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr);
676 
677 static size_t obj_memsize_of(VALUE obj, int use_tdata);
678 
679 static double getrusage_time(void);
680 static inline void gc_prof_setup_new_record(rb_objspace_t *objspace, int reason);
681 static inline void gc_prof_timer_start(rb_objspace_t *);
682 static inline void gc_prof_timer_stop(rb_objspace_t *);
683 static inline void gc_prof_mark_timer_start(rb_objspace_t *);
684 static inline void gc_prof_mark_timer_stop(rb_objspace_t *);
685 static inline void gc_prof_sweep_timer_start(rb_objspace_t *);
686 static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
687 static inline void gc_prof_set_malloc_info(rb_objspace_t *);
688 static inline void gc_prof_set_heap_info(rb_objspace_t *);
689 
690 #define gc_prof_record(objspace) (objspace)->profile.current_record
691 #define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record)
692 
693 #define rgengc_report if (RGENGC_DEBUG) rgengc_report_body
694 static void rgengc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...);
695 static const char * type_name(int type, VALUE obj);
696 static const char *obj_type_name(VALUE obj);
697 
698 #if USE_RGENGC
699 static int rgengc_remembered(rb_objspace_t *objspace, VALUE obj);
700 static int rgengc_remember(rb_objspace_t *objspace, VALUE obj);
702 static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap);
703 
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)
707 
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))
710 
711 #define RVALUE_OLDGEN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_OLDGEN_BITS(obj), (obj))
712 
713 static inline int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr);
714 static inline int gc_marked(rb_objspace_t *objspace, VALUE ptr);
715 
716 static inline VALUE
718 {
719  if (RGENGC_CHECK_MODE > 0) {
720  int old_flag = RVALUE_OLDGEN_BITMAP(obj) != 0;
721  int promoted_flag = FL_TEST2(obj, FL_PROMOTED);
722  rb_objspace_t *objspace = &rb_objspace;
723 
724  obj_memsize_of((VALUE)obj, FALSE);
725 
726  if (!is_pointer_to_heap(objspace, (void *)obj)) {
727  rb_bug("check_gen_consistency: %p (%s) is not Ruby object.", (void *)obj, obj_type_name(obj));
728  }
729 
730  if (promoted_flag) {
731  if (!RVALUE_WB_PROTECTED_RAW(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);
734  }
735 
736 #if !RGENGC_THREEGEN
737  if (!old_flag) {
738  rb_bug("check_gen_consistency: %p (%s) is not infant, but is not old (on 2gen).", (void *)obj, obj_type_name(obj));
739  }
740 #endif
741 
742  if (old_flag && objspace->rgengc.during_minor_gc && !gc_marked(objspace, obj)) {
743  rb_bug("check_gen_consistency: %p (%s) is old, but is not marked while minor marking.", (void *)obj, obj_type_name(obj));
744  }
745  }
746  else {
747  if (old_flag) {
748  rb_bug("check_gen_consistency: %p (%s) is not infant, but is old.", (void *)obj, obj_type_name(obj));
749  }
750  }
751  }
752  return obj;
753 }
754 
755 static inline VALUE
757 {
759  return !FL_TEST2(obj, FL_PROMOTED);
760 }
761 
762 static inline VALUE
764 {
766  return (RVALUE_OLDGEN_BITMAP(obj) != 0);
767 }
768 
769 static inline VALUE
771 {
773 #if RGENGC_THREEGEN
774  return FL_TEST2(obj, FL_PROMOTED) && RVALUE_OLD_BITMAP_P(obj);
775 #else
776  return FL_TEST2(obj, FL_PROMOTED);
777 #endif
778 }
779 
780 static inline VALUE
782 {
784  return FL_TEST2(obj, FL_PROMOTED);
785 }
786 
787 static inline void
789 {
791  if (RGENGC_CHECK_MODE && !RVALUE_INFANT_P(obj)) rb_bug("RVALUE_PROMOTE_INFANT: %p (%s) is not infant object.", (void *)obj, obj_type_name(obj));
792  FL_SET2(obj, FL_PROMOTED);
793 #if !RGENGC_THREEGEN
795 #endif
797 
798 #if RGENGC_PROFILE >= 1
799  {
800  rb_objspace_t *objspace = &rb_objspace;
801  objspace->profile.promote_infant_count++;
802 
803 #if RGENGC_PROFILE >= 2
804  objspace->profile.promote_infant_types[BUILTIN_TYPE(obj)]++;
805 #endif
806  }
807 #endif
808 }
809 
810 #if RGENGC_THREEGEN
811 /*
812  * Two gen: Infant -> Old.
813  * Three gen: Infant -> Young -> Old.
814  */
815 static inline VALUE
816 RVALUE_YOUNG_P(VALUE obj)
817 {
819  return FL_TEST2(obj, FL_PROMOTED) && (RVALUE_OLDGEN_BITMAP(obj) == 0);
820 }
821 
822 static inline void
823 RVALUE_PROMOTE_YOUNG(VALUE obj)
824 {
826  if (RGENGC_CHECK_MODE && !RVALUE_YOUNG_P(obj)) rb_bug("RVALUE_PROMOTE_YOUNG: %p (%s) is not young object.", (void *)obj, obj_type_name(obj));
829 
830 #if RGENGC_PROFILE >= 1
831  {
832  rb_objspace_t *objspace = &rb_objspace;
833  objspace->profile.promote_young_count++;
834 #if RGENGC_PROFILE >= 2
835  objspace->profile.promote_young_types[BUILTIN_TYPE(obj)]++;
836 #endif
837  }
838 #endif
839 }
840 
841 static inline void
842 RVALUE_DEMOTE_FROM_YOUNG(VALUE obj)
843 {
844  if (RGENGC_CHECK_MODE && !RVALUE_YOUNG_P(obj))
845  rb_bug("RVALUE_DEMOTE_FROM_YOUNG: %p (%s) is not young object.", (void *)obj, obj_type_name(obj));
846 
848  FL_UNSET2(obj, FL_PROMOTED);
850 }
851 #endif
852 
853 static inline void
855 {
856  if (RGENGC_CHECK_MODE && !RVALUE_OLD_P(obj))
857  rb_bug("RVALUE_DEMOTE_FROM_OLD: %p (%s) is not old object.", (void *)obj, obj_type_name(obj));
858 
860  FL_UNSET2(obj, FL_PROMOTED);
863 }
864 
865 #endif /* USE_RGENGC */
866 
867 /*
868  --------------------------- ObjectSpace -----------------------------
869 */
870 
871 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
874 {
875  rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t));
876  memset(objspace, 0, sizeof(*objspace));
878 
879  malloc_limit = gc_params.malloc_limit_min;
880 
881  return objspace;
882 }
883 #endif
884 
885 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
886 static void free_stack_chunks(mark_stack_t *);
887 static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page);
888 
889 void
891 {
892  gc_rest_sweep(objspace);
893 
894  if (objspace->profile.records) {
895  free(objspace->profile.records);
896  objspace->profile.records = 0;
897  }
898 
899  if (global_List) {
900  struct gc_list *list, *next;
901  for (list = global_List; list; list = next) {
902  next = list->next;
903  xfree(list);
904  }
905  }
906  if (heap_pages_sorted) {
907  size_t i;
908  for (i = 0; i < heap_pages_used; ++i) {
909  heap_page_free(objspace, heap_pages_sorted[i]);
910  }
912  heap_pages_used = 0;
913  heap_pages_length = 0;
914  heap_pages_lomem = 0;
915  heap_pages_himem = 0;
916 
917  objspace->eden_heap.page_length = 0;
918  objspace->eden_heap.total_slots = 0;
919  objspace->eden_heap.pages = NULL;
920  }
921  free_stack_chunks(&objspace->mark_stack);
922  free(objspace);
923 }
924 #endif
925 
926 static void
928 {
929  size_t next_length = heap_pages_increment;
930  next_length += heap_eden->page_length;
931  next_length += heap_tomb->page_length;
932 
933  if (next_length > heap_pages_length) {
934  struct heap_page **sorted;
935  size_t size = next_length * sizeof(struct heap_page *);
936 
937  rgengc_report(3, objspace, "heap_pages_expand_sorted: next_length: %d, size: %d\n", (int)next_length, (int)size);
938 
939  if (heap_pages_length > 0) {
940  sorted = (struct heap_page **)realloc(heap_pages_sorted, size);
941  if (sorted) heap_pages_sorted = sorted;
942  }
943  else {
944  sorted = heap_pages_sorted = (struct heap_page **)malloc(size);
945  }
946 
947  if (sorted == 0) {
948  during_gc = 0;
949  rb_memerror();
950  }
951 
952  heap_pages_length = next_length;
953  }
954 }
955 
956 static inline void
957 heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
958 {
959  RVALUE *p = (RVALUE *)obj;
960  p->as.free.flags = 0;
961  p->as.free.next = page->freelist;
962  page->freelist = p;
963  rgengc_report(3, objspace, "heap_page_add_freeobj: %p (%s) is added to freelist\n", p, obj_type_name(obj));
964 }
965 
966 static inline void
968 {
969  if (page->freelist) {
970  page->free_next = heap->free_pages;
971  heap->free_pages = page;
972  }
973 }
974 
975 static void
977 {
978  if (page->prev) page->prev->next = page->next;
979  if (page->next) page->next->prev = page->prev;
980  if (heap->pages == page) heap->pages = page->next;
981  page->prev = NULL;
982  page->next = NULL;
983  page->heap = NULL;
984  heap->page_length--;
985  heap->total_slots -= page->limit;
986 }
987 
988 static void
989 heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
990 {
991  heap_pages_used--;
992  aligned_free(page->body);
993  free(page);
994 }
995 
996 static void
998 {
999  size_t i, j;
1000 
1001  for (i = j = 1; j < heap_pages_used; i++) {
1002  struct heap_page *page = heap_pages_sorted[i];
1003 
1004  if (page->heap == heap_tomb && page->final_slots == 0) {
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",
1007  (int)i, page, (int)heap_pages_swept_slots, (int)heap_pages_max_free_slots);
1008  heap_pages_swept_slots -= page->limit;
1009  heap_unlink_page(objspace, heap_tomb, page);
1010  heap_page_free(objspace, page);
1011  continue;
1012  }
1013  else {
1014  /* fprintf(stderr, "heap_pages_free_unused_pages: remain!!\n"); */
1015  }
1016  }
1017  if (i != j) {
1018  heap_pages_sorted[j] = page;
1019  }
1020  j++;
1021  }
1022  assert(j == heap_pages_used);
1023 }
1024 
1025 static struct heap_page *
1027 {
1028  RVALUE *start, *end, *p;
1029  struct heap_page *page;
1030  struct heap_page_body *page_body = 0;
1031  size_t hi, lo, mid;
1032  size_t limit = HEAP_OBJ_LIMIT;
1033 
1034  /* assign heap_page body (contains heap_page_header and RVALUEs) */
1035  page_body = (struct heap_page_body *)aligned_malloc(HEAP_ALIGN, HEAP_SIZE);
1036  if (page_body == 0) {
1037  during_gc = 0;
1038  rb_memerror();
1039  }
1040 
1041  /* assign heap_page entry */
1042  page = (struct heap_page *)malloc(sizeof(struct heap_page));
1043  if (page == 0) {
1044  aligned_free(page_body);
1045  during_gc = 0;
1046  rb_memerror();
1047  }
1048  MEMZERO((void*)page, struct heap_page, 1);
1049 
1050  page->body = page_body;
1051 
1052  /* setup heap_pages_sorted */
1053  lo = 0;
1054  hi = heap_pages_used;
1055  while (lo < hi) {
1056  struct heap_page *mid_page;
1057 
1058  mid = (lo + hi) / 2;
1059  mid_page = heap_pages_sorted[mid];
1060  if (mid_page->body < page_body) {
1061  lo = mid + 1;
1062  }
1063  else if (mid_page->body > page_body) {
1064  hi = mid;
1065  }
1066  else {
1067  rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
1068  }
1069  }
1070  if (hi < heap_pages_used) {
1072  }
1073 
1074  heap_pages_sorted[hi] = page;
1075 
1076  heap_pages_used++;
1078 
1079  /* adjust obj_limit (object number available in this page) */
1080  start = (RVALUE*)((VALUE)page_body + sizeof(struct heap_page_header));
1081  if ((VALUE)start % sizeof(RVALUE) != 0) {
1082  int delta = (int)(sizeof(RVALUE) - ((VALUE)start % sizeof(RVALUE)));
1083  start = (RVALUE*)((VALUE)start + delta);
1084  limit = (HEAP_SIZE - (size_t)((VALUE)start - (VALUE)page_body))/sizeof(RVALUE);
1085  }
1086  end = start + limit;
1087 
1088  if (heap_pages_lomem == 0 || heap_pages_lomem > start) heap_pages_lomem = start;
1089  if (heap_pages_himem < end) heap_pages_himem = end;
1090 
1091  page->start = start;
1092  page->limit = limit;
1093  page_body->header.page = page;
1094 
1095  for (p = start; p != end; p++) {
1096  rgengc_report(3, objspace, "assign_heap_page: %p is added to freelist\n");
1097  heap_page_add_freeobj(objspace, page, (VALUE)p);
1098  }
1099 
1100  return page;
1101 }
1102 
1103 static struct heap_page *
1105 {
1106  struct heap_page *page;
1107 
1108  if ((page = heap_tomb->pages) != NULL) {
1109  heap_unlink_page(objspace, heap_tomb, page);
1110  return page;
1111  }
1112  return NULL;
1113 }
1114 
1115 static struct heap_page *
1117 {
1118  struct heap_page *page = heap_page_resurrect(objspace);
1119  const char *method = "recycle";
1120  if (page == NULL) {
1121  page = heap_page_allocate(objspace);
1122  method = "allocate";
1123  }
1124  if (0) fprintf(stderr, "heap_page_create: %s - %p, heap_pages_used: %d, heap_pages_used: %d, tomb->page_length: %d\n",
1125  method, page, (int)heap_pages_length, (int)heap_pages_used, (int)heap_tomb->page_length);
1126  return page;
1127 }
1128 
1129 static void
1131 {
1132  page->heap = heap;
1133  page->next = heap->pages;
1134  if (heap->pages) heap->pages->prev = page;
1135  heap->pages = page;
1136  heap->page_length++;
1137  heap->total_slots += page->limit;
1138 }
1139 
1140 static void
1142 {
1143  struct heap_page *page = heap_page_create(objspace);
1144  heap_add_page(objspace, heap, page);
1145  heap_add_freepage(objspace, heap, page);
1146 }
1147 
1148 static void
1150 {
1151  size_t i;
1152 
1154  heap_pages_expand_sorted(objspace);
1155  for (i = 0; i < add; i++) {
1156  heap_assign_page(objspace, heap);
1157  }
1159 }
1160 
1161 static void
1162 heap_set_increment(rb_objspace_t *objspace, size_t minimum_limit)
1163 {
1164  size_t used = heap_pages_used - heap_tomb->page_length;
1165  size_t next_used_limit = (size_t)(used * gc_params.growth_factor);
1166  if (gc_params.growth_max_slots > 0) {
1167  size_t max_used_limit = (size_t)(used + gc_params.growth_max_slots/HEAP_OBJ_LIMIT);
1168  if (next_used_limit > max_used_limit) next_used_limit = max_used_limit;
1169  }
1170  if (next_used_limit == heap_pages_used) next_used_limit++;
1171 
1172  if (next_used_limit < minimum_limit) {
1173  next_used_limit = minimum_limit;
1174  }
1175 
1176  heap_pages_increment = next_used_limit - used;
1177  heap_pages_expand_sorted(objspace);
1178 
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",
1180  (int)heap_pages_length, (int)heap_pages_used, (int)heap_pages_increment, (int)next_used_limit);
1181 }
1182 
1183 static int
1185 {
1186  rgengc_report(5, objspace, "heap_increment: heap_pages_length: %d, heap_pages_inc: %d, heap->page_length: %d\n",
1187  (int)heap_pages_length, (int)heap_pages_increment, (int)heap->page_length);
1188 
1189  if (heap_pages_increment > 0) {
1190  heap_pages_increment--;
1191  heap_assign_page(objspace, heap);
1192  return TRUE;
1193  }
1194  return FALSE;
1195 }
1196 
1197 static struct heap_page *
1199 {
1200  if (!GC_ENABLE_LAZY_SWEEP && objspace->flags.dont_lazy_sweep) {
1201  if (heap_increment(objspace, heap) == 0 &&
1202  garbage_collect(objspace, FALSE, TRUE, GPR_FLAG_NEWOBJ) == 0) {
1203  goto err;
1204  }
1205  goto ok;
1206  }
1207 
1208  if (!heap_ready_to_gc(objspace, heap)) return heap->free_pages;
1209 
1210  during_gc++;
1211 
1212  if ((is_lazy_sweeping(heap) && gc_heap_lazy_sweep(objspace, heap)) || heap_increment(objspace, heap)) {
1213  goto ok;
1214  }
1215 
1216 #if GC_PROFILE_MORE_DETAIL
1217  objspace->profile.prepare_time = 0;
1218 #endif
1219  if (garbage_collect_body(objspace, 0, 0, GPR_FLAG_NEWOBJ) == 0) {
1220  err:
1221  during_gc = 0;
1222  rb_memerror();
1223  }
1224  ok:
1225  during_gc = 0;
1226  return heap->free_pages;
1227 }
1228 
1229 static RVALUE *
1231 {
1232  struct heap_page *page;
1233  RVALUE *p;
1234 
1235  page = heap->free_pages;
1236  while (page == NULL) {
1237  page = heap_prepare_freepage(objspace, heap);
1238  }
1239  heap->free_pages = page->free_next;
1240  heap->using_page = page;
1241 
1242  p = page->freelist;
1243  page->freelist = NULL;
1244 
1245  return p;
1246 }
1247 
1248 static inline VALUE
1250 {
1251  RVALUE *p = heap->freelist;
1252 
1253  while (1) {
1254  if (p) {
1255  heap->freelist = p->as.free.next;
1256  return (VALUE)p;
1257  }
1258  else {
1259  p = heap_get_freeobj_from_next_freepage(objspace, heap);
1260  }
1261  }
1262 }
1263 
1264 void
1266 {
1267  rb_objspace_t *objspace = &rb_objspace;
1268  objspace->hook_events = event & RUBY_INTERNAL_EVENT_OBJSPACE_MASK;
1269 }
1270 
1271 static void
1273 {
1274  rb_thread_t *th = GET_THREAD();
1275  EXEC_EVENT_HOOK(th, event, th->cfp->self, 0, 0, data);
1276 }
1277 
1278 #define gc_event_hook(objspace, event, data) do { \
1279  if (UNLIKELY((objspace)->hook_events & (event))) { \
1280  gc_event_hook_body((objspace), (event), (data)); \
1281  } \
1282 } while (0)
1283 
1284 static VALUE
1285 newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
1286 {
1287  rb_objspace_t *objspace = &rb_objspace;
1288  VALUE obj;
1289 
1290  if (UNLIKELY(during_gc)) {
1291  dont_gc = 1;
1292  during_gc = 0;
1293  rb_bug("object allocation during garbage collection phase");
1294  }
1295 
1296  if (UNLIKELY(ruby_gc_stress && !ruby_disable_gc_stress)) {
1297  if (!garbage_collect(objspace, FALSE, FALSE, GPR_FLAG_NEWOBJ)) {
1298  during_gc = 0;
1299  rb_memerror();
1300  }
1301  }
1302 
1303  obj = heap_get_freeobj(objspace, heap_eden);
1304 
1305  /* OBJSETUP */
1306  RBASIC(obj)->flags = flags;
1307  RBASIC_SET_CLASS_RAW(obj, klass);
1308  if (rb_safe_level() >= 3) FL_SET((obj), FL_TAINT);
1309  RANY(obj)->as.values.v1 = v1;
1310  RANY(obj)->as.values.v2 = v2;
1311  RANY(obj)->as.values.v3 = v3;
1312 
1313 #if GC_DEBUG
1314  RANY(obj)->file = rb_sourcefile();
1315  RANY(obj)->line = rb_sourceline();
1316  assert(!SPECIAL_CONST_P(obj)); /* check alignment */
1317 #endif
1318 
1319 #if RGENGC_PROFILE
1320  if (flags & FL_WB_PROTECTED) {
1321  objspace->profile.generated_normal_object_count++;
1322 #if RGENGC_PROFILE >= 2
1323  objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++;
1324 #endif
1325  }
1326  else {
1327  objspace->profile.generated_shady_object_count++;
1328 #if RGENGC_PROFILE >= 2
1329  objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++;
1330 #endif
1331  }
1332 #endif
1333 
1334  rgengc_report(5, objspace, "newobj: %p (%s)\n", (void *)obj, obj_type_name(obj));
1335 
1336 #if USE_RGENGC && RGENGC_CHECK_MODE
1337  if (RVALUE_PROMOTED_P(obj)) rb_bug("newobj: %p (%s) is promoted.\n", (void *)obj, obj_type_name(obj));
1338  if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %p (%s) is remembered.\n", (void *)obj, obj_type_name(obj));
1339 #endif
1340 
1341  objspace->profile.total_allocated_object_num++;
1342  gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj);
1343 
1344  return obj;
1345 }
1346 
1347 VALUE
1349 {
1350  return newobj_of(0, T_NONE, 0, 0, 0);
1351 }
1352 
1353 VALUE
1354 rb_newobj_of(VALUE klass, VALUE flags)
1355 {
1356  return newobj_of(klass, flags, 0, 0, 0);
1357 }
1358 
1359 NODE*
1361 {
1362  VALUE flags = (RGENGC_WB_PROTECTED_NODE_CREF && type == NODE_CREF ? FL_WB_PROTECTED : 0);
1363  NODE *n = (NODE *)newobj_of(0, T_NODE | flags, a0, a1, a2);
1364  nd_set_type(n, type);
1365  return n;
1366 }
1367 
1368 VALUE
1369 rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
1370 {
1371  if (klass) Check_Type(klass, T_CLASS);
1372  return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap);
1373 }
1374 
1375 VALUE
1377 {
1378  if (klass) Check_Type(klass, T_CLASS);
1379  return newobj_of(klass, T_DATA | (type->flags & ~T_MASK), (VALUE)type, (VALUE)1, (VALUE)datap);
1380 }
1381 
1382 size_t
1384 {
1385  if (RTYPEDDATA_P(obj) && RTYPEDDATA_TYPE(obj)->function.dsize) {
1386  return RTYPEDDATA_TYPE(obj)->function.dsize(RTYPEDDATA_DATA(obj));
1387  }
1388  else {
1389  return 0;
1390  }
1391 }
1392 
1393 const char *
1395 {
1396  if (RTYPEDDATA_P(obj)) {
1397  return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
1398  }
1399  else {
1400  return 0;
1401  }
1402 }
1403 
1404 static inline int
1405 is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
1406 {
1407  register RVALUE *p = RANY(ptr);
1408  register struct heap_page *page;
1409  register size_t hi, lo, mid;
1410 
1411  if (p < heap_pages_lomem || p > heap_pages_himem) return FALSE;
1412  if ((VALUE)p % sizeof(RVALUE) != 0) return FALSE;
1413 
1414  /* check if p looks like a pointer using bsearch*/
1415  lo = 0;
1416  hi = heap_pages_used;
1417  while (lo < hi) {
1418  mid = (lo + hi) / 2;
1419  page = heap_pages_sorted[mid];
1420  if (page->start <= p) {
1421  if (p < page->start + page->limit) {
1422  return TRUE;
1423  }
1424  lo = mid + 1;
1425  }
1426  else {
1427  hi = mid;
1428  }
1429  }
1430  return FALSE;
1431 }
1432 
1433 static int
1435 {
1436  if (!me->mark) {
1438  }
1439  return ST_CONTINUE;
1440 }
1441 
1442 void
1444 {
1446  st_free_table(tbl);
1447 }
1448 
1449 void
1451 {
1452  if (wrapper->tbl) {
1453  rb_free_m_tbl(wrapper->tbl);
1454  }
1455  xfree(wrapper);
1456 }
1457 
1458 static int
1460 {
1461  xfree(ce);
1462  return ST_CONTINUE;
1463 }
1464 
1465 void
1467 {
1468  st_foreach(tbl, free_const_entry_i, 0);
1469  st_free_table(tbl);
1470 }
1471 
1472 static inline void
1474 {
1475  p->as.basic.flags = T_ZOMBIE;
1476  p->as.free.next = heap_pages_deferred_final;
1478 }
1479 
1480 static inline void
1482 {
1483  rb_io_t *fptr = p->as.file.fptr;
1484  make_deferred(objspace, p);
1485  p->as.data.dfree = (void (*)(void*))rb_io_fptr_finalize;
1486  p->as.data.data = fptr;
1487 }
1488 
1489 static int
1491 {
1493 
1494  switch (BUILTIN_TYPE(obj)) {
1495  case T_NIL:
1496  case T_FIXNUM:
1497  case T_TRUE:
1498  case T_FALSE:
1499  rb_bug("obj_free() called for broken object");
1500  break;
1501  }
1502 
1503  if (FL_TEST(obj, FL_EXIVAR)) {
1505  FL_UNSET(obj, FL_EXIVAR);
1506  }
1507 
1508 #if USE_RGENGC
1509  if (MARKED_IN_BITMAP(GET_HEAP_OLDGEN_BITS(obj),obj))
1511 #endif
1512 
1513  switch (BUILTIN_TYPE(obj)) {
1514  case T_OBJECT:
1515  if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
1516  RANY(obj)->as.object.as.heap.ivptr) {
1517  xfree(RANY(obj)->as.object.as.heap.ivptr);
1518  }
1519  break;
1520  case T_MODULE:
1521  case T_CLASS:
1522  if (RCLASS_M_TBL_WRAPPER(obj)) {
1524  }
1525  if (RCLASS_IV_TBL(obj)) {
1527  }
1528  if (RCLASS_CONST_TBL(obj)) {
1530  }
1531  if (RCLASS_IV_INDEX_TBL(obj)) {
1533  }
1534  if (RCLASS_EXT(obj)->subclasses) {
1535  if (BUILTIN_TYPE(obj) == T_MODULE) {
1537  }
1538  else {
1540  }
1541  RCLASS_EXT(obj)->subclasses = NULL;
1542  }
1545  if (RANY(obj)->as.klass.ptr)
1546  xfree(RANY(obj)->as.klass.ptr);
1547  RANY(obj)->as.klass.ptr = NULL;
1548  break;
1549  case T_STRING:
1550  rb_str_free(obj);
1551  break;
1552  case T_ARRAY:
1553  rb_ary_free(obj);
1554  break;
1555  case T_HASH:
1556  if (RANY(obj)->as.hash.ntbl) {
1557  st_free_table(RANY(obj)->as.hash.ntbl);
1558  }
1559  break;
1560  case T_REGEXP:
1561  if (RANY(obj)->as.regexp.ptr) {
1562  onig_free(RANY(obj)->as.regexp.ptr);
1563  }
1564  break;
1565  case T_DATA:
1566  if (DATA_PTR(obj)) {
1567  int free_immediately = FALSE;
1568 
1569  if (RTYPEDDATA_P(obj)) {
1570  free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
1571  RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->function.dfree;
1572  if (0 && free_immediately == 0) /* to expose non-free-immediate T_DATA */
1573  fprintf(stderr, "not immediate -> %s\n", RANY(obj)->as.typeddata.type->wrap_struct_name);
1574  }
1575  if (RANY(obj)->as.data.dfree == RUBY_DEFAULT_FREE) {
1576  xfree(DATA_PTR(obj));
1577  }
1578  else if (RANY(obj)->as.data.dfree) {
1579  if (free_immediately) {
1580  (RDATA(obj)->dfree)(DATA_PTR(obj));
1581  }
1582  else {
1583  make_deferred(objspace, RANY(obj));
1584  return 1;
1585  }
1586  }
1587  }
1588  break;
1589  case T_MATCH:
1590  if (RANY(obj)->as.match.rmatch) {
1591  struct rmatch *rm = RANY(obj)->as.match.rmatch;
1592  onig_region_free(&rm->regs, 0);
1593  if (rm->char_offset)
1594  xfree(rm->char_offset);
1595  xfree(rm);
1596  }
1597  break;
1598  case T_FILE:
1599  if (RANY(obj)->as.file.fptr) {
1600  make_io_deferred(objspace, RANY(obj));
1601  return 1;
1602  }
1603  break;
1604  case T_RATIONAL:
1605  case T_COMPLEX:
1606  break;
1607  case T_ICLASS:
1608  /* iClass shares table with the module */
1609  if (RCLASS_EXT(obj)->subclasses) {
1611  RCLASS_EXT(obj)->subclasses = NULL;
1612  }
1615  xfree(RANY(obj)->as.klass.ptr);
1616  RANY(obj)->as.klass.ptr = NULL;
1617  break;
1618 
1619  case T_FLOAT:
1620  break;
1621 
1622  case T_BIGNUM:
1623  if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
1624  xfree(RBIGNUM_DIGITS(obj));
1625  }
1626  break;
1627  case T_NODE:
1628  switch (nd_type(obj)) {
1629  case NODE_SCOPE:
1630  if (RANY(obj)->as.node.u1.tbl) {
1631  xfree(RANY(obj)->as.node.u1.tbl);
1632  }
1633  break;
1634  case NODE_ARGS:
1635  if (RANY(obj)->as.node.u3.args) {
1636  xfree(RANY(obj)->as.node.u3.args);
1637  }
1638  break;
1639  case NODE_ALLOCA:
1640  xfree(RANY(obj)->as.node.u1.node);
1641  break;
1642  }
1643  break; /* no need to free iv_tbl */
1644 
1645  case T_STRUCT:
1646  if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
1647  RANY(obj)->as.rstruct.as.heap.ptr) {
1648  xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr);
1649  }
1650  break;
1651 
1652  default:
1653  rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE,
1654  BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
1655  }
1656 
1657  return 0;
1658 }
1659 
1660 void
1662 {
1663  rb_objspace_t *objspace = &rb_objspace;
1664 
1665 #if RGENGC_ESTIMATE_OLDMALLOC
1666  objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
1667 #endif
1668 
1669  heap_add_pages(objspace, heap_eden, gc_params.heap_init_slots / HEAP_OBJ_LIMIT);
1670 
1671  init_mark_stack(&objspace->mark_stack);
1672 
1673 #ifdef USE_SIGALTSTACK
1674  {
1675  /* altstack of another threads are allocated in another place */
1676  rb_thread_t *th = GET_THREAD();
1677  void *tmp = th->altstack;
1678  th->altstack = malloc(rb_sigaltstack_size());
1679  free(tmp); /* free previously allocated area */
1680  }
1681 #endif
1682 
1683  objspace->profile.invoke_time = getrusage_time();
1685 }
1686 
1687 typedef int each_obj_callback(void *, void *, size_t, void *);
1688 
1691  void *data;
1692 };
1693 
1694 static VALUE
1696 {
1697  size_t i;
1698  struct heap_page_body *last_body = 0;
1699  struct heap_page *page;
1700  RVALUE *pstart, *pend;
1701  rb_objspace_t *objspace = &rb_objspace;
1702  struct each_obj_args *args = (struct each_obj_args *)arg;
1703 
1704  i = 0;
1705  while (i < heap_pages_used) {
1706  while (0 < i && last_body < heap_pages_sorted[i-1]->body) i--;
1707  while (i < heap_pages_used && heap_pages_sorted[i]->body <= last_body) i++;
1708  if (heap_pages_used <= i) break;
1709 
1710  page = heap_pages_sorted[i];
1711  last_body = page->body;
1712 
1713  pstart = page->start;
1714  pend = pstart + page->limit;
1715 
1716  if ((*args->callback)(pstart, pend, sizeof(RVALUE), args->data)) {
1717  break;
1718  }
1719  }
1720 
1721  return Qnil;
1722 }
1723 
1724 /*
1725  * rb_objspace_each_objects() is special C API to walk through
1726  * Ruby object space. This C API is too difficult to use it.
1727  * To be frank, you should not use it. Or you need to read the
1728  * source code of this function and understand what this function does.
1729  *
1730  * 'callback' will be called several times (the number of heap page,
1731  * at current implementation) with:
1732  * vstart: a pointer to the first living object of the heap_page.
1733  * vend: a pointer to next to the valid heap_page area.
1734  * stride: a distance to next VALUE.
1735  *
1736  * If callback() returns non-zero, the iteration will be stopped.
1737  *
1738  * This is a sample callback code to iterate liveness objects:
1739  *
1740  * int
1741  * sample_callback(void *vstart, void *vend, int stride, void *data) {
1742  * VALUE v = (VALUE)vstart;
1743  * for (; v != (VALUE)vend; v += stride) {
1744  * if (RBASIC(v)->flags) { // liveness check
1745  * // do something with live object 'v'
1746  * }
1747  * return 0; // continue to iteration
1748  * }
1749  *
1750  * Note: 'vstart' is not a top of heap_page. This point the first
1751  * living object to grasp at least one object to avoid GC issue.
1752  * This means that you can not walk through all Ruby object page
1753  * including freed object page.
1754  *
1755  * Note: On this implementation, 'stride' is same as sizeof(RVALUE).
1756  * However, there are possibilities to pass variable values with
1757  * 'stride' with some reasons. You must use stride instead of
1758  * use some constant value in the iteration.
1759  */
1760 void
1762 {
1763  struct each_obj_args args;
1764  rb_objspace_t *objspace = &rb_objspace;
1765  int prev_dont_lazy_sweep = objspace->flags.dont_lazy_sweep;
1766 
1767  gc_rest_sweep(objspace);
1768  objspace->flags.dont_lazy_sweep = TRUE;
1769 
1770  args.callback = callback;
1771  args.data = data;
1772 
1773  if (prev_dont_lazy_sweep) {
1774  objspace_each_objects((VALUE)&args);
1775  }
1776  else {
1778  }
1779 }
1780 
1782  size_t num;
1784 };
1785 
1786 static int
1788 {
1789  RVALUE *p = (RVALUE *)obj;
1790 
1791  if (p->as.basic.flags) {
1792  switch (BUILTIN_TYPE(p)) {
1793  case T_NONE:
1794  case T_ICLASS:
1795  case T_NODE:
1796  case T_ZOMBIE:
1797  break;
1798  case T_CLASS:
1799  if (FL_TEST(p, FL_SINGLETON))
1800  break;
1801  default:
1802  if (!p->as.basic.klass) break;
1803  return 0;
1804  }
1805  }
1806  return 1;
1807 }
1808 
1809 int
1811 {
1812  return internal_object_p(obj);
1813 }
1814 
1815 static int
1816 os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
1817 {
1818  struct os_each_struct *oes = (struct os_each_struct *)data;
1819  RVALUE *p = (RVALUE *)vstart, *pend = (RVALUE *)vend;
1820 
1821  for (; p != pend; p++) {
1822  volatile VALUE v = (VALUE)p;
1823  if (!internal_object_p(v)) {
1824  if (!oes->of || rb_obj_is_kind_of(v, oes->of)) {
1825  rb_yield(v);
1826  oes->num++;
1827  }
1828  }
1829  }
1830 
1831  return 0;
1832 }
1833 
1834 static VALUE
1836 {
1837  struct os_each_struct oes;
1838 
1839  oes.num = 0;
1840  oes.of = of;
1842  return SIZET2NUM(oes.num);
1843 }
1844 
1845 /*
1846  * call-seq:
1847  * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum
1848  * ObjectSpace.each_object([module]) -> an_enumerator
1849  *
1850  * Calls the block once for each living, nonimmediate object in this
1851  * Ruby process. If <i>module</i> is specified, calls the block
1852  * for only those classes or modules that match (or are a subclass of)
1853  * <i>module</i>. Returns the number of objects found. Immediate
1854  * objects (<code>Fixnum</code>s, <code>Symbol</code>s
1855  * <code>true</code>, <code>false</code>, and <code>nil</code>) are
1856  * never returned. In the example below, <code>each_object</code>
1857  * returns both the numbers we defined and several constants defined in
1858  * the <code>Math</code> module.
1859  *
1860  * If no block is given, an enumerator is returned instead.
1861  *
1862  * a = 102.7
1863  * b = 95 # Won't be returned
1864  * c = 12345678987654321
1865  * count = ObjectSpace.each_object(Numeric) {|x| p x }
1866  * puts "Total count: #{count}"
1867  *
1868  * <em>produces:</em>
1869  *
1870  * 12345678987654321
1871  * 102.7
1872  * 2.71828182845905
1873  * 3.14159265358979
1874  * 2.22044604925031e-16
1875  * 1.7976931348623157e+308
1876  * 2.2250738585072e-308
1877  * Total count: 7
1878  *
1879  */
1880 
1881 static VALUE
1883 {
1884  VALUE of;
1885 
1886  if (argc == 0) {
1887  of = 0;
1888  }
1889  else {
1890  rb_scan_args(argc, argv, "01", &of);
1891  }
1892  RETURN_ENUMERATOR(os, 1, &of);
1893  return os_obj_of(of);
1894 }
1895 
1896 /*
1897  * call-seq:
1898  * ObjectSpace.undefine_finalizer(obj)
1899  *
1900  * Removes all finalizers for <i>obj</i>.
1901  *
1902  */
1903 
1904 static VALUE
1906 {
1907  return rb_undefine_finalizer(obj);
1908 }
1909 
1910 VALUE
1912 {
1913  rb_objspace_t *objspace = &rb_objspace;
1914  st_data_t data = obj;
1915  rb_check_frozen(obj);
1916  st_delete(finalizer_table, &data, 0);
1917  FL_UNSET(obj, FL_FINALIZE);
1918  return obj;
1919 }
1920 
1921 static void
1923 {
1924  if (!rb_obj_respond_to(block, rb_intern("call"), TRUE)) {
1925  rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
1926  rb_obj_classname(block));
1927  }
1928 }
1929 static void
1931 {
1932  rb_check_frozen(obj);
1933  if (!FL_ABLE(obj)) {
1934  rb_raise(rb_eArgError, "cannot define finalizer for %s",
1935  rb_obj_classname(obj));
1936  }
1937 }
1938 
1939 /*
1940  * call-seq:
1941  * ObjectSpace.define_finalizer(obj, aProc=proc())
1942  *
1943  * Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
1944  * was destroyed.
1945  *
1946  */
1947 
1948 static VALUE
1950 {
1951  VALUE obj, block;
1952 
1953  rb_scan_args(argc, argv, "11", &obj, &block);
1954  should_be_finalizable(obj);
1955  if (argc == 1) {
1956  block = rb_block_proc();
1957  }
1958  else {
1959  should_be_callable(block);
1960  }
1961 
1962  return define_final0(obj, block);
1963 }
1964 
1965 static VALUE
1967 {
1968  rb_objspace_t *objspace = &rb_objspace;
1969  VALUE table;
1970  st_data_t data;
1971 
1972  RBASIC(obj)->flags |= FL_FINALIZE;
1973 
1974  block = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
1975  OBJ_FREEZE(block);
1976 
1977  if (st_lookup(finalizer_table, obj, &data)) {
1978  table = (VALUE)data;
1979  rb_ary_push(table, block);
1980  }
1981  else {
1982  table = rb_ary_new3(1, block);
1983  RBASIC_CLEAR_CLASS(table);
1984  st_add_direct(finalizer_table, obj, table);
1985  }
1986  return block;
1987 }
1988 
1989 VALUE
1991 {
1992  should_be_finalizable(obj);
1993  should_be_callable(block);
1994  return define_final0(obj, block);
1995 }
1996 
1997 void
1999 {
2000  rb_objspace_t *objspace = &rb_objspace;
2001  VALUE table;
2002  st_data_t data;
2003 
2004  if (!FL_TEST(obj, FL_FINALIZE)) return;
2005  if (st_lookup(finalizer_table, obj, &data)) {
2006  table = (VALUE)data;
2007  st_insert(finalizer_table, dest, table);
2008  }
2009  FL_SET(dest, FL_FINALIZE);
2010 }
2011 
2012 static VALUE
2014 {
2015  VALUE *args = (VALUE *)arg;
2016  rb_eval_cmd(args[0], args[1], (int)args[2]);
2017  return Qnil;
2018 }
2019 
2020 static void
2021 run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
2022 {
2023  long i;
2024  int status;
2025  VALUE args[3];
2026  VALUE objid = nonspecial_obj_id(obj);
2027 
2028  if (RARRAY_LEN(table) > 0) {
2029  args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
2030  }
2031  else {
2032  args[1] = 0;
2033  }
2034 
2035  args[2] = (VALUE)rb_safe_level();
2036  for (i=0; i<RARRAY_LEN(table); i++) {
2037  VALUE final = RARRAY_AREF(table, i);
2038  args[0] = RARRAY_AREF(final, 1);
2039  args[2] = FIX2INT(RARRAY_AREF(final, 0));
2040  status = 0;
2041  rb_protect(run_single_final, (VALUE)args, &status);
2042  if (status)
2044  }
2045 }
2046 
2047 static void
2049 {
2050  RUBY_DATA_FUNC free_func = 0;
2051  st_data_t key, table;
2052 
2054 
2055  RBASIC_CLEAR_CLASS(obj);
2056 
2057  if (RTYPEDDATA_P(obj)) {
2058  free_func = RTYPEDDATA_TYPE(obj)->function.dfree;
2059  }
2060  else {
2061  free_func = RDATA(obj)->dfree;
2062  }
2063  if (free_func) {
2064  (*free_func)(DATA_PTR(obj));
2065  }
2066 
2067  key = (st_data_t)obj;
2068  if (st_delete(finalizer_table, &key, &table)) {
2069  run_finalizer(objspace, obj, (VALUE)table);
2070  }
2071 }
2072 
2073 static void
2075 {
2076  while (p) {
2077  RVALUE *tmp = p->as.free.next;
2078  struct heap_page *page = GET_HEAP_PAGE(p);
2079 
2080  run_final(objspace, (VALUE)p);
2081  objspace->profile.total_freed_object_num++;
2082 
2083  page->final_slots--;
2084  heap_page_add_freeobj(objspace, GET_HEAP_PAGE(p), (VALUE)p);
2086 
2087  p = tmp;
2088  }
2089 }
2090 
2091 static void
2093 {
2094  RVALUE *p;
2095 
2096  while ((p = ATOMIC_PTR_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
2097  finalize_list(objspace, p);
2098  }
2099 }
2100 
2101 static void
2103 {
2104  rb_objspace_t *objspace = &rb_objspace;
2105  if (ATOMIC_EXCHANGE(finalizing, 1)) return;
2106  finalize_deferred(objspace);
2107  ATOMIC_SET(finalizing, 0);
2108 }
2109 
2110 /* TODO: to keep compatibility, maybe unused. */
2111 void
2113 {
2115 }
2116 
2117 static void
2119 {
2121  rb_bug("gc_finalize_deferred_register: can't register finalizer.");
2122  }
2123 }
2124 
2129 };
2130 
2131 static int
2133 {
2134  struct force_finalize_list **prev = (struct force_finalize_list **)arg;
2135  struct force_finalize_list *curr = ALLOC(struct force_finalize_list);
2136  curr->obj = key;
2137  curr->table = val;
2138  curr->next = *prev;
2139  *prev = curr;
2140  return ST_CONTINUE;
2141 }
2142 
2143 void
2145 {
2146  rb_objspace_call_finalizer(&rb_objspace);
2147 }
2148 
2149 static void
2151 {
2152  RVALUE *p, *pend;
2153  size_t i;
2154 
2155  gc_rest_sweep(objspace);
2156 
2157  if (ATOMIC_EXCHANGE(finalizing, 1)) return;
2158 
2159  /* run finalizers */
2160  finalize_deferred(objspace);
2162 
2163  /* force to run finalizer */
2164  while (finalizer_table->num_entries) {
2165  struct force_finalize_list *list = 0;
2167  while (list) {
2168  struct force_finalize_list *curr = list;
2169  st_data_t obj = (st_data_t)curr->obj;
2170  run_finalizer(objspace, curr->obj, curr->table);
2171  st_delete(finalizer_table, &obj, 0);
2172  list = curr->next;
2173  xfree(curr);
2174  }
2175  }
2176 
2177  /* finalizers are part of garbage collection */
2178  during_gc++;
2179 
2180  /* run data object's finalizers */
2181  for (i = 0; i < heap_pages_used; i++) {
2182  p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->limit;
2183  while (p < pend) {
2184  switch (BUILTIN_TYPE(p)) {
2185  case T_DATA:
2186  if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
2187  if (rb_obj_is_thread((VALUE)p)) break;
2188  if (rb_obj_is_mutex((VALUE)p)) break;
2189  if (rb_obj_is_fiber((VALUE)p)) break;
2190  p->as.free.flags = 0;
2191  if (RTYPEDDATA_P(p)) {
2192  RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree;
2193  }
2194  if (RANY(p)->as.data.dfree == (RUBY_DATA_FUNC)-1) {
2195  xfree(DATA_PTR(p));
2196  }
2197  else if (RANY(p)->as.data.dfree) {
2198  make_deferred(objspace, RANY(p));
2199  }
2200  break;
2201  case T_FILE:
2202  if (RANY(p)->as.file.fptr) {
2203  make_io_deferred(objspace, RANY(p));
2204  }
2205  break;
2206  }
2207  p++;
2208  }
2209  }
2210  during_gc = 0;
2213  }
2214 
2216  finalizer_table = 0;
2217  ATOMIC_SET(finalizing, 0);
2218 }
2219 
2220 static inline int
2222 {
2223  if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE;
2224  if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE;
2225  if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE;
2226  return TRUE;
2227 }
2228 
2229 static inline int
2231 {
2232  struct heap_page *page = GET_HEAP_PAGE(ptr);
2233  return page->before_sweep ? FALSE : TRUE;
2234 }
2235 
2236 static inline int
2238 {
2239  if (heap_is_swept_object(objspace, heap_eden, ptr)) {
2240  return TRUE;
2241  }
2242  else {
2243  return FALSE;
2244  }
2245 }
2246 
2247 static inline int
2249 {
2251  if (!is_swept_object(objspace, ptr)) return TRUE;
2252  return FALSE;
2253 }
2254 
2255 static inline int
2257 {
2258  switch (BUILTIN_TYPE(ptr)) {
2259  case 0: case T_ZOMBIE:
2260  return FALSE;
2261  }
2262  if (is_dead_object(objspace, ptr)) return FALSE;
2263  return TRUE;
2264 }
2265 
2266 static inline int
2268 {
2269  if (rb_special_const_p(obj)) return 0; /* special const is not markable */
2270 
2271  if (RGENGC_CHECK_MODE) {
2272  if (!is_pointer_to_heap(objspace, (void *)obj)) rb_bug("is_markable_object: %p is not pointer to heap", (void *)obj);
2273  if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("is_markable_object: %p is T_NONE", (void *)obj);
2274  if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("is_markable_object: %p is T_ZOMBIE", (void *)obj);
2275  }
2276 
2277  return 1;
2278 }
2279 
2280 int
2282 {
2283  rb_objspace_t *objspace = &rb_objspace;
2284  return is_markable_object(objspace, obj) && is_live_object(objspace, obj);
2285 }
2286 
2287 /*
2288  * call-seq:
2289  * ObjectSpace._id2ref(object_id) -> an_object
2290  *
2291  * Converts an object id to a reference to the object. May not be
2292  * called on an object id passed as a parameter to a finalizer.
2293  *
2294  * s = "I am a string" #=> "I am a string"
2295  * r = ObjectSpace._id2ref(s.object_id) #=> "I am a string"
2296  * r == s #=> true
2297  *
2298  */
2299 
2300 static VALUE
2301 id2ref(VALUE obj, VALUE objid)
2302 {
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)
2307 #endif
2308  rb_objspace_t *objspace = &rb_objspace;
2309  VALUE ptr;
2310  void *p0;
2311 
2312  ptr = NUM2PTR(objid);
2313  p0 = (void *)ptr;
2314 
2315  if (ptr == Qtrue) return Qtrue;
2316  if (ptr == Qfalse) return Qfalse;
2317  if (ptr == Qnil) return Qnil;
2318  if (FIXNUM_P(ptr)) return (VALUE)ptr;
2319  if (FLONUM_P(ptr)) return (VALUE)ptr;
2320  ptr = obj_id_to_ref(objid);
2321 
2322  if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
2323  ID symid = ptr / sizeof(RVALUE);
2324  if (rb_id2name(symid) == 0)
2325  rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
2326  return ID2SYM(symid);
2327  }
2328 
2329  if (!is_id_value(objspace, ptr)) {
2330  rb_raise(rb_eRangeError, "%p is not id value", p0);
2331  }
2332  if (!is_live_object(objspace, ptr)) {
2333  rb_raise(rb_eRangeError, "%p is recycled object", p0);
2334  }
2335  return (VALUE)ptr;
2336 }
2337 
2338 /*
2339  * Document-method: __id__
2340  * Document-method: object_id
2341  *
2342  * call-seq:
2343  * obj.__id__ -> integer
2344  * obj.object_id -> integer
2345  *
2346  * Returns an integer identifier for +obj+.
2347  *
2348  * The same number will be returned on all calls to +id+ for a given object,
2349  * and no two active objects will share an id.
2350  *
2351  * Object#object_id is a different concept from the +:name+ notation, which
2352  * returns the symbol id of +name+.
2353  *
2354  * Replaces the deprecated Object#id.
2355  */
2356 
2357 /*
2358  * call-seq:
2359  * obj.hash -> fixnum
2360  *
2361  * Generates a Fixnum hash value for this object.
2362  *
2363  * This function must have the property that <code>a.eql?(b)</code> implies
2364  * <code>a.hash == b.hash</code>.
2365  *
2366  * The hash value is used by Hash class.
2367  *
2368  * Any hash value that exceeds the capacity of a Fixnum will be truncated
2369  * before being used.
2370  */
2371 
2372 VALUE
2374 {
2375  /*
2376  * 32-bit VALUE space
2377  * MSB ------------------------ LSB
2378  * false 00000000000000000000000000000000
2379  * true 00000000000000000000000000000010
2380  * nil 00000000000000000000000000000100
2381  * undef 00000000000000000000000000000110
2382  * symbol ssssssssssssssssssssssss00001110
2383  * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
2384  * fixnum fffffffffffffffffffffffffffffff1
2385  *
2386  * object_id space
2387  * LSB
2388  * false 00000000000000000000000000000000
2389  * true 00000000000000000000000000000010
2390  * nil 00000000000000000000000000000100
2391  * undef 00000000000000000000000000000110
2392  * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
2393  * object oooooooooooooooooooooooooooooo0 o...o % A = 0
2394  * fixnum fffffffffffffffffffffffffffffff1 bignum if required
2395  *
2396  * where A = sizeof(RVALUE)/4
2397  *
2398  * sizeof(RVALUE) is
2399  * 20 if 32-bit, double is 4-byte aligned
2400  * 24 if 32-bit, double is 8-byte aligned
2401  * 40 if 64-bit
2402  */
2403  if (SYMBOL_P(obj)) {
2404  return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
2405  }
2406  else if (FLONUM_P(obj)) {
2407 #if SIZEOF_LONG == SIZEOF_VOIDP
2408  return LONG2NUM((SIGNED_VALUE)obj);
2409 #else
2410  return LL2NUM((SIGNED_VALUE)obj);
2411 #endif
2412  }
2413  else if (SPECIAL_CONST_P(obj)) {
2414  return LONG2NUM((SIGNED_VALUE)obj);
2415  }
2416  return nonspecial_obj_id(obj);
2417 }
2418 
2419 size_t rb_str_memsize(VALUE);
2420 size_t rb_ary_memsize(VALUE);
2421 size_t rb_io_memsize(const rb_io_t *);
2423 #include "regint.h"
2424 
2425 static size_t
2426 obj_memsize_of(VALUE obj, int use_tdata)
2427 {
2428  size_t size = 0;
2429 
2430  if (SPECIAL_CONST_P(obj)) {
2431  return 0;
2432  }
2433 
2434  if (FL_TEST(obj, FL_EXIVAR)) {
2435  size += rb_generic_ivar_memsize(obj);
2436  }
2437 
2438  switch (BUILTIN_TYPE(obj)) {
2439  case T_OBJECT:
2440  if (!(RBASIC(obj)->flags & ROBJECT_EMBED) &&
2441  ROBJECT(obj)->as.heap.ivptr) {
2442  size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE);
2443  }
2444  break;
2445  case T_MODULE:
2446  case T_CLASS:
2447  if (RCLASS_M_TBL_WRAPPER(obj)) {
2448  size += sizeof(struct method_table_wrapper);
2449  }
2450  if (RCLASS_M_TBL(obj)) {
2451  size += st_memsize(RCLASS_M_TBL(obj));
2452  }
2453  if (RCLASS_EXT(obj)) {
2454  if (RCLASS_IV_TBL(obj)) {
2455  size += st_memsize(RCLASS_IV_TBL(obj));
2456  }
2457  if (RCLASS_IV_INDEX_TBL(obj)) {
2458  size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
2459  }
2460  if (RCLASS(obj)->ptr->iv_tbl) {
2461  size += st_memsize(RCLASS(obj)->ptr->iv_tbl);
2462  }
2463  if (RCLASS(obj)->ptr->const_tbl) {
2464  size += st_memsize(RCLASS(obj)->ptr->const_tbl);
2465  }
2466  size += sizeof(rb_classext_t);
2467  }
2468  break;
2469  case T_STRING:
2470  size += rb_str_memsize(obj);
2471  break;
2472  case T_ARRAY:
2473  size += rb_ary_memsize(obj);
2474  break;
2475  case T_HASH:
2476  if (RHASH(obj)->ntbl) {
2477  size += st_memsize(RHASH(obj)->ntbl);
2478  }
2479  break;
2480  case T_REGEXP:
2481  if (RREGEXP(obj)->ptr) {
2482  size += onig_memsize(RREGEXP(obj)->ptr);
2483  }
2484  break;
2485  case T_DATA:
2486  if (use_tdata) size += rb_objspace_data_type_memsize(obj);
2487  break;
2488  case T_MATCH:
2489  if (RMATCH(obj)->rmatch) {
2490  struct rmatch *rm = RMATCH(obj)->rmatch;
2491  size += onig_region_memsize(&rm->regs);
2492  size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated;
2493  size += sizeof(struct rmatch);
2494  }
2495  break;
2496  case T_FILE:
2497  if (RFILE(obj)->fptr) {
2498  size += rb_io_memsize(RFILE(obj)->fptr);
2499  }
2500  break;
2501  case T_RATIONAL:
2502  case T_COMPLEX:
2503  break;
2504  case T_ICLASS:
2505  /* iClass shares table with the module */
2506  break;
2507 
2508  case T_FLOAT:
2509  break;
2510 
2511  case T_BIGNUM:
2512  if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
2513  size += RBIGNUM_LEN(obj) * sizeof(BDIGIT);
2514  }
2515  break;
2516  case T_NODE:
2517  switch (nd_type(obj)) {
2518  case NODE_SCOPE:
2519  if (RNODE(obj)->u1.tbl) {
2520  /* TODO: xfree(RANY(obj)->as.node.u1.tbl); */
2521  }
2522  break;
2523  case NODE_ALLOCA:
2524  /* TODO: xfree(RANY(obj)->as.node.u1.node); */
2525  ;
2526  }
2527  break; /* no need to free iv_tbl */
2528 
2529  case T_STRUCT:
2530  if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
2531  RSTRUCT(obj)->as.heap.ptr) {
2532  size += sizeof(VALUE) * RSTRUCT_LEN(obj);
2533  }
2534  break;
2535 
2536  case T_ZOMBIE:
2537  break;
2538 
2539  default:
2540  rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)",
2541  BUILTIN_TYPE(obj), (void*)obj);
2542  }
2543 
2544  return size;
2545 }
2546 
2547 size_t
2549 {
2550  return obj_memsize_of(obj, TRUE);
2551 }
2552 
2553 static int
2555 {
2556  VALUE k = (VALUE)key;
2557  VALUE hash = (VALUE)arg;
2558  rb_hash_aset(hash, k, INT2FIX(0));
2559  return ST_CONTINUE;
2560 }
2561 
2562 /*
2563  * call-seq:
2564  * ObjectSpace.count_objects([result_hash]) -> hash
2565  *
2566  * Counts objects for each type.
2567  *
2568  * It returns a hash, such as:
2569  * {
2570  * :TOTAL=>10000,
2571  * :FREE=>3011,
2572  * :T_OBJECT=>6,
2573  * :T_CLASS=>404,
2574  * # ...
2575  * }
2576  *
2577  * The contents of the returned hash are implementation specific.
2578  * It may be changed in future.
2579  *
2580  * If the optional argument +result_hash+ is given,
2581  * it is overwritten and returned. This is intended to avoid probe effect.
2582  *
2583  * This method is only expected to work on C Ruby.
2584  *
2585  */
2586 
2587 static VALUE
2589 {
2590  rb_objspace_t *objspace = &rb_objspace;
2591  size_t counts[T_MASK+1];
2592  size_t freed = 0;
2593  size_t total = 0;
2594  size_t i;
2595  VALUE hash;
2596 
2597  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
2598  if (!RB_TYPE_P(hash, T_HASH))
2599  rb_raise(rb_eTypeError, "non-hash given");
2600  }
2601 
2602  for (i = 0; i <= T_MASK; i++) {
2603  counts[i] = 0;
2604  }
2605 
2606  for (i = 0; i < heap_pages_used; i++) {
2607  struct heap_page *page = heap_pages_sorted[i];
2608  RVALUE *p, *pend;
2609 
2610  p = page->start; pend = p + page->limit;
2611  for (;p < pend; p++) {
2612  if (p->as.basic.flags) {
2613  counts[BUILTIN_TYPE(p)]++;
2614  }
2615  else {
2616  freed++;
2617  }
2618  }
2619  total += page->limit;
2620  }
2621 
2622  if (hash == Qnil) {
2623  hash = rb_hash_new();
2624  }
2625  else if (!RHASH_EMPTY_P(hash)) {
2626  st_foreach(RHASH_TBL_RAW(hash), set_zero, hash);
2627  }
2628  rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
2629  rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));
2630 
2631  for (i = 0; i <= T_MASK; i++) {
2632  VALUE type;
2633  switch (i) {
2634 #define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t)); break;
2635  COUNT_TYPE(T_NONE);
2643  COUNT_TYPE(T_HASH);
2646  COUNT_TYPE(T_FILE);
2647  COUNT_TYPE(T_DATA);
2651  COUNT_TYPE(T_NIL);
2652  COUNT_TYPE(T_TRUE);
2657  COUNT_TYPE(T_NODE);
2660 #undef COUNT_TYPE
2661  default: type = INT2NUM(i); break;
2662  }
2663  if (counts[i])
2664  rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
2665  }
2666 
2667  return hash;
2668 }
2669 
2670 /*
2671  ------------------------ Garbage Collection ------------------------
2672 */
2673 
2674 /* Sweeping */
2675 
2676 static VALUE
2678 {
2679  rb_objspace_t *objspace = &rb_objspace;
2680 
2681  objspace->flags.dont_lazy_sweep = FALSE;
2682  return Qnil;
2683 }
2684 
2685 static size_t
2687 {
2689 }
2690 
2691 static size_t
2693 {
2694  return heap_eden->total_slots + heap_tomb->total_slots;
2695 }
2696 
2697 static size_t
2699 {
2700  return objspace_total_slot(objspace) - (objspace_live_slot(objspace) - heap_pages_final_slots);
2701 }
2702 
2703 static void
2705 {
2706 #if USE_RGENGC
2707  /* copy oldgen bitmap to mark bitmap */
2708  memcpy(&page->mark_bits[0], &page->oldgen_bits[0], HEAP_BITMAP_SIZE);
2709 #else
2710  /* clear mark bitmap */
2711  memset(&page->mark_bits[0], 0, HEAP_BITMAP_SIZE);
2712 #endif
2713 }
2714 
2715 static inline void
2716 gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page)
2717 {
2718  int i;
2719  size_t empty_slots = 0, freed_slots = 0, final_slots = 0;
2720  RVALUE *p, *pend,*offset;
2721  bits_t *bits, bitset;
2722 
2723  rgengc_report(1, objspace, "page_sweep: start.\n");
2724 
2725  sweep_page->before_sweep = 0;
2726 
2727  p = sweep_page->start; pend = p + sweep_page->limit;
2728  offset = p - NUM_IN_PAGE(p);
2729  bits = sweep_page->mark_bits;
2730 
2731  /* create guard : fill 1 out-of-range */
2732  bits[BITMAP_INDEX(p)] |= BITMAP_BIT(p)-1;
2733  bits[BITMAP_INDEX(pend)] |= ~(BITMAP_BIT(pend) - 1);
2734 
2735  for (i=0; i < HEAP_BITMAP_LIMIT; i++) {
2736  bitset = ~bits[i];
2737  if (bitset) {
2738  p = offset + i * BITS_BITLENGTH;
2739  do {
2740  if ((bitset & 1) && BUILTIN_TYPE(p) != T_ZOMBIE) {
2741  if (p->as.basic.flags) {
2742  rgengc_report(3, objspace, "page_sweep: free %p (%s)\n", p, obj_type_name((VALUE)p));
2743 #if USE_RGENGC && RGENGC_CHECK_MODE
2744  if (objspace->rgengc.during_minor_gc && RVALUE_OLD_P((VALUE)p)) rb_bug("page_sweep: %p (%s) is old while minor GC.\n", p, obj_type_name((VALUE)p));
2745  if (rgengc_remembered(objspace, (VALUE)p)) rb_bug("page_sweep: %p (%s) is remembered.\n", p, obj_type_name((VALUE)p));
2746 #endif
2747  if (obj_free(objspace, (VALUE)p)) {
2748  final_slots++;
2749  }
2750  else if (FL_TEST(p, FL_FINALIZE)) {
2751  RDATA(p)->dfree = 0;
2752  make_deferred(objspace,p);
2753  final_slots++;
2754  }
2755  else {
2756  (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
2757  heap_page_add_freeobj(objspace, sweep_page, (VALUE)p);
2758  rgengc_report(3, objspace, "page_sweep: %p (%s) is added to freelist\n", p, obj_type_name((VALUE)p));
2759  freed_slots++;
2760  }
2761  }
2762  else {
2763  empty_slots++;
2764  }
2765  }
2766  p++;
2767  bitset >>= 1;
2768  } while (bitset);
2769  }
2770  }
2771 
2772  gc_setup_mark_bits(sweep_page);
2773 
2774 #if GC_PROFILE_MORE_DETAIL
2775  if (gc_prof_enabled(objspace)) {
2776  gc_profile_record *record = gc_prof_record(objspace);
2777  record->removing_objects += final_slots + freed_slots;
2778  record->empty_objects += empty_slots;
2779  }
2780 #endif
2781 
2782  if (final_slots + freed_slots + empty_slots == sweep_page->limit) {
2783  /* there are no living objects -> move this page to tomb heap */
2784  heap_unlink_page(objspace, heap, sweep_page);
2785  heap_add_page(objspace, heap_tomb, sweep_page);
2786  }
2787  else {
2788  if (freed_slots + empty_slots > 0) {
2789  heap_add_freepage(objspace, heap, sweep_page);
2790  }
2791  else {
2792  sweep_page->free_next = NULL;
2793  }
2794  }
2795  heap_pages_swept_slots += freed_slots + empty_slots;
2796  objspace->profile.total_freed_object_num += freed_slots;
2798  sweep_page->final_slots = final_slots;
2799 
2800  if (0) fprintf(stderr, "gc_page_sweep(%d): freed?: %d, limt: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
2801  (int)rb_gc_count(),
2802  final_slots + freed_slots + empty_slots == sweep_page->limit,
2803  (int)sweep_page->limit, (int)freed_slots, (int)empty_slots, (int)final_slots);
2804 
2806  rb_thread_t *th = GET_THREAD();
2807  if (th) {
2809  }
2810  }
2811 
2812  rgengc_report(1, objspace, "page_sweep: end.\n");
2813 }
2814 
2815 /* allocate additional minimum page to work */
2816 static void
2818 {
2819  if (!heap->free_pages) {
2820  /* there is no free after page_sweep() */
2821  heap_set_increment(objspace, 0);
2822  if (!heap_increment(objspace, heap)) { /* can't allocate additional free objects */
2823  during_gc = 0;
2824  rb_memerror();
2825  }
2826  }
2827 }
2828 
2829 static void
2831 {
2832  heap->sweep_pages = heap->pages;
2833  heap->free_pages = NULL;
2834 
2835  if (heap->using_page) {
2836  RVALUE **p = &heap->using_page->freelist;
2837  while (*p) {
2838  p = &(*p)->as.free.next;
2839  }
2840  *p = heap->freelist;
2841  heap->using_page = NULL;
2842  }
2843  heap->freelist = NULL;
2844 }
2845 
2846 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
2847 __attribute__((noinline))
2848 #endif
2849 static void
2851 {
2852  rb_heap_t *heap;
2853  size_t total_limit_slot;
2854 
2855  rgengc_report(1, objspace, "gc_before_sweep\n");
2856 
2857  /* sweep unlinked method entries */
2858  if (GET_VM()->unlinked_method_entry_list) {
2860  }
2861 
2863  total_limit_slot = objspace_total_slot(objspace);
2864 
2865  heap_pages_min_free_slots = (size_t)(total_limit_slot * 0.30);
2866  if (heap_pages_min_free_slots < gc_params.heap_free_slots) {
2868  }
2869  heap_pages_max_free_slots = (size_t)(total_limit_slot * 0.80);
2870  if (heap_pages_max_free_slots < gc_params.heap_init_slots) {
2872  }
2873  if (0) fprintf(stderr, "heap_pages_min_free_slots: %d, heap_pages_max_free_slots: %d\n",
2875 
2876  heap = heap_eden;
2877  gc_before_heap_sweep(objspace, heap);
2878 
2879  gc_prof_set_malloc_info(objspace);
2880 
2881  /* reset malloc info */
2882  if (0) fprintf(stderr, "%d\t%d\t%d\n", (int)rb_gc_count(), (int)malloc_increase, (int)malloc_limit);
2883 
2884  {
2885  size_t inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
2886  size_t old_limit = malloc_limit;
2887 
2888  if (inc > malloc_limit) {
2889  malloc_limit = (size_t)(inc * gc_params.malloc_limit_growth_factor);
2890  if (gc_params.malloc_limit_max > 0 && /* ignore max-check if 0 */
2891  malloc_limit > gc_params.malloc_limit_max) {
2892  malloc_limit = gc_params.malloc_limit_max;
2893  }
2894  }
2895  else {
2896  malloc_limit = (size_t)(malloc_limit * 0.98); /* magic number */
2897  if (malloc_limit < gc_params.malloc_limit_min) {
2898  malloc_limit = gc_params.malloc_limit_min;
2899  }
2900  }
2901 
2902  if (0) {
2903  if (old_limit != malloc_limit) {
2904  fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: %"PRIuSIZE" -> %"PRIuSIZE"\n",
2905  rb_gc_count(), old_limit, malloc_limit);
2906  }
2907  else {
2908  fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: not changed (%"PRIuSIZE")\n",
2909  rb_gc_count(), malloc_limit);
2910  }
2911  }
2912  }
2913 
2914  /* reset oldmalloc info */
2915 #if RGENGC_ESTIMATE_OLDMALLOC
2916  if (objspace->rgengc.during_minor_gc) {
2917  if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
2919  objspace->rgengc.oldmalloc_increase_limit =
2920  (size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
2921 
2922  if (objspace->rgengc.oldmalloc_increase_limit > gc_params.oldmalloc_limit_max) {
2923  objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_max;
2924  }
2925  }
2926 
2927  if (0) fprintf(stderr, "%d\t%d\t%u\t%u\t%d\n",
2928  (int)rb_gc_count(),
2929  (int)objspace->rgengc.need_major_gc,
2930  (unsigned int)objspace->rgengc.oldmalloc_increase,
2931  (unsigned int)objspace->rgengc.oldmalloc_increase_limit,
2932  (unsigned int)gc_params.oldmalloc_limit_max);
2933  }
2934  else {
2935  /* major GC */
2936  objspace->rgengc.oldmalloc_increase = 0;
2937 
2938  if ((objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC) == 0) {
2939  objspace->rgengc.oldmalloc_increase_limit =
2940  (size_t)(objspace->rgengc.oldmalloc_increase_limit / ((gc_params.oldmalloc_limit_growth_factor - 1)/10 + 1));
2941  if (objspace->rgengc.oldmalloc_increase_limit < gc_params.oldmalloc_limit_min) {
2942  objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
2943  }
2944  }
2945  }
2946 
2947 #endif
2948 
2949 }
2950 
2951 static void
2953 {
2955 
2956  rgengc_report(1, objspace, "after_gc_sweep: heap->total_slots: %d, heap->swept_slots: %d, min_free_slots: %d\n",
2958 
2959  if (heap_pages_swept_slots < heap_pages_min_free_slots) {
2960 #if USE_RGENGC
2961  if (objspace->rgengc.during_minor_gc && objspace->profile.count - objspace->rgengc.last_major_gc > 2 /* magic number */) {
2963  }
2964  else {
2965  heap_set_increment(objspace, (heap_pages_min_free_slots - heap_pages_swept_slots) / HEAP_OBJ_LIMIT);
2966  heap_increment(objspace, heap);
2967  }
2968 #else
2969  heap_set_increment(objspace, (heap_pages_min_free_slots - heap_pages_swept_slots) / HEAP_OBJ_LIMIT);
2970  heap_increment(objspace, heap);
2971 #endif
2972  }
2973 
2974  gc_prof_set_heap_info(objspace);
2975 
2976  heap_pages_free_unused_pages(objspace);
2977 
2978  /* if heap_pages has unused pages, then assign them to increment */
2979  if (heap_pages_increment < heap_tomb->page_length) {
2980  heap_pages_increment = heap_tomb->page_length;
2981  }
2982 
2983 #if RGENGC_PROFILE > 0
2984  if (0) {
2985  fprintf(stderr, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
2986  (int)rb_gc_count(),
2987  (int)objspace->profile.major_gc_count,
2988  (int)objspace->profile.minor_gc_count,
2989  (int)objspace->profile.promote_infant_count,
2990 #if RGENGC_THREEGEN
2991  (int)objspace->profile.promote_young_count,
2992 #else
2993  0,
2994 #endif
2995  (int)objspace->profile.remembered_normal_object_count,
2996  (int)objspace->rgengc.remembered_shady_object_count);
2997  }
2998 #endif
2999 
3001 }
3002 
3003 static int
3005 {
3006  struct heap_page *page = heap->sweep_pages, *next;
3007  int result = FALSE;
3008 
3009  if (page == NULL) return FALSE;
3010 
3011 #if GC_ENABLE_LAZY_SWEEP
3012  gc_prof_sweep_timer_start(objspace);
3013 #endif
3014 
3015  while (page) {
3016  heap->sweep_pages = next = page->next;
3017 
3018  gc_page_sweep(objspace, heap, page);
3019 
3020  if (!next) gc_after_sweep(objspace);
3021 
3022  if (heap->free_pages) {
3023  result = TRUE;
3024  break;
3025  }
3026 
3027  page = next;
3028  }
3029 
3030 #if GC_ENABLE_LAZY_SWEEP
3031  gc_prof_sweep_timer_stop(objspace);
3032 #endif
3033 
3034  return result;
3035 }
3036 
3037 static void
3039 {
3040  if (is_lazy_sweeping(heap)) {
3041  during_gc++;
3042  while (is_lazy_sweeping(heap)) {
3043  gc_heap_lazy_sweep(objspace, heap);
3044  }
3045  during_gc = 0;
3046  }
3047 }
3048 
3049 static void
3051 {
3052  rb_heap_t *heap = heap_eden; /* lazy sweep only for eden */
3053  gc_heap_rest_sweep(objspace, heap);
3054 }
3055 
3056 static void
3057 gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
3058 {
3059  if (immediate_sweep) {
3060 #if !GC_ENABLE_LAZY_SWEEP
3061  gc_prof_sweep_timer_start(objspace);
3062 #endif
3063  gc_before_sweep(objspace);
3064  gc_heap_rest_sweep(objspace, heap_eden);
3065 #if !GC_ENABLE_LAZY_SWEEP
3066  gc_prof_sweep_timer_stop(objspace);
3067 #endif
3068  }
3069  else {
3070  struct heap_page *page;
3071  gc_before_sweep(objspace);
3072  page = heap_eden->sweep_pages;
3073  while (page) {
3074  page->before_sweep = 1;
3075  page = page->next;
3076  }
3077  gc_heap_lazy_sweep(objspace, heap_eden);
3078  }
3079 
3081 }
3082 
3083 /* Marking - Marking stack */
3084 
3085 static void push_mark_stack(mark_stack_t *, VALUE);
3086 static int pop_mark_stack(mark_stack_t *, VALUE *);
3087 static void shrink_stack_chunk_cache(mark_stack_t *stack);
3088 
3089 static stack_chunk_t *
3091 {
3092  stack_chunk_t *res;
3093 
3094  res = malloc(sizeof(stack_chunk_t));
3095  if (!res)
3096  rb_memerror();
3097 
3098  return res;
3099 }
3100 
3101 static inline int
3103 {
3104  return stack->chunk == NULL;
3105 }
3106 
3107 static void
3109 {
3110  chunk->next = stack->cache;
3111  stack->cache = chunk;
3112  stack->cache_size++;
3113 }
3114 
3115 static void
3117 {
3118  stack_chunk_t *chunk;
3119 
3120  if (stack->unused_cache_size > (stack->cache_size/2)) {
3121  chunk = stack->cache;
3122  stack->cache = stack->cache->next;
3123  stack->cache_size--;
3124  free(chunk);
3125  }
3126  stack->unused_cache_size = stack->cache_size;
3127 }
3128 
3129 static void
3131 {
3133 
3134  assert(stack->index == stack->limit);
3135  if (stack->cache_size > 0) {
3136  next = stack->cache;
3137  stack->cache = stack->cache->next;
3138  stack->cache_size--;
3139  if (stack->unused_cache_size > stack->cache_size)
3140  stack->unused_cache_size = stack->cache_size;
3141  }
3142  else {
3143  next = stack_chunk_alloc();
3144  }
3145  next->next = stack->chunk;
3146  stack->chunk = next;
3147  stack->index = 0;
3148 }
3149 
3150 static void
3152 {
3154 
3155  prev = stack->chunk->next;
3156  assert(stack->index == 0);
3157  add_stack_chunk_cache(stack, stack->chunk);
3158  stack->chunk = prev;
3159  stack->index = stack->limit;
3160 }
3161 
3162 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
3163 static void
3165 {
3166  stack_chunk_t *chunk = stack->chunk;
3167  stack_chunk_t *next = NULL;
3168 
3169  while (chunk != NULL) {
3170  next = chunk->next;
3171  free(chunk);
3172  chunk = next;
3173  }
3174 }
3175 #endif
3176 
3177 static void
3179 {
3180  if (stack->index == stack->limit) {
3181  push_mark_stack_chunk(stack);
3182  }
3183  stack->chunk->data[stack->index++] = data;
3184 }
3185 
3186 static int
3188 {
3189  if (is_mark_stack_empty(stack)) {
3190  return FALSE;
3191  }
3192  if (stack->index == 1) {
3193  *data = stack->chunk->data[--stack->index];
3194  pop_mark_stack_chunk(stack);
3195  }
3196  else {
3197  *data = stack->chunk->data[--stack->index];
3198  }
3199  return TRUE;
3200 }
3201 
3202 static void
3204 {
3205  int i;
3206 
3207  if (0) push_mark_stack_chunk(stack);
3208  stack->index = stack->limit = STACK_CHUNK_SIZE;
3209 
3210  for (i=0; i < 4; i++) {
3212  }
3213  stack->unused_cache_size = stack->cache_size;
3214 }
3215 
3216 /* Marking */
3217 
3218 #ifdef __ia64
3219 #define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine.stack_end), th->machine.register_stack_end = rb_ia64_bsp())
3220 #else
3221 #define SET_STACK_END SET_MACHINE_STACK_END(&th->machine.stack_end)
3222 #endif
3223 
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))
3227 
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)
3232 #else
3233 # define STACK_LENGTH ((STACK_END < STACK_START) ? (size_t)(STACK_START - STACK_END) \
3234  : (size_t)(STACK_END - STACK_START + 1))
3235 #endif
3236 #if !STACK_GROW_DIRECTION
3238 int
3240 {
3241  VALUE *end;
3242  SET_MACHINE_STACK_END(&end);
3243 
3244  if (end > addr) return ruby_stack_grow_direction = 1;
3245  return ruby_stack_grow_direction = -1;
3246 }
3247 #endif
3248 
3249 size_t
3251 {
3252  rb_thread_t *th = GET_THREAD();
3253  SET_STACK_END;
3254  if (p) *p = STACK_UPPER(STACK_END, STACK_START, STACK_END);
3255  return STACK_LENGTH;
3256 }
3257 
3258 #if !(defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK))
3259 static int
3260 stack_check(int water_mark)
3261 {
3262  int ret;
3263  rb_thread_t *th = GET_THREAD();
3264  SET_STACK_END;
3265  ret = STACK_LENGTH > STACK_LEVEL_MAX - water_mark;
3266 #ifdef __ia64
3267  if (!ret) {
3268  ret = (VALUE*)rb_ia64_bsp() - th->machine.register_stack_start >
3269  th->machine.register_stack_maxsize/sizeof(VALUE) - water_mark;
3270  }
3271 #endif
3272  return ret;
3273 }
3274 #endif
3275 
3276 #define STACKFRAME_FOR_CALL_CFUNC 512
3277 
3278 int
3280 {
3281 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
3282  return 0;
3283 #else
3285 #endif
3286 }
3287 
3289 static void
3290 mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
3291 {
3292  VALUE v;
3293  while (n--) {
3294  v = *x;
3295  gc_mark_maybe(objspace, v);
3296  x++;
3297  }
3298 }
3299 
3300 static void
3302 {
3303  long n;
3304 
3305  if (end <= start) return;
3306  n = end - start;
3307  mark_locations_array(objspace, start, n);
3308 }
3309 
3310 void
3312 {
3313  gc_mark_locations(&rb_objspace, start, end);
3314 }
3315 
3316 #define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, (start), (end))
3317 
3320 };
3321 
3322 static int
3324 {
3325  struct mark_tbl_arg *arg = (void*)data;
3326  gc_mark(arg->objspace, (VALUE)value);
3327  return ST_CONTINUE;
3328 }
3329 
3330 static void
3332 {
3333  struct mark_tbl_arg arg;
3334  if (!tbl || tbl->num_entries == 0) return;
3335  arg.objspace = objspace;
3336  st_foreach(tbl, mark_entry, (st_data_t)&arg);
3337 }
3338 
3339 static int
3341 {
3342  struct mark_tbl_arg *arg = (void*)data;
3343  gc_mark(arg->objspace, (VALUE)key);
3344  return ST_CONTINUE;
3345 }
3346 
3347 static void
3349 {
3350  struct mark_tbl_arg arg;
3351  if (!tbl) return;
3352  arg.objspace = objspace;
3353  st_foreach(tbl, mark_key, (st_data_t)&arg);
3354 }
3355 
3356 void
3358 {
3359  mark_set(&rb_objspace, tbl);
3360 }
3361 
3362 static int
3364 {
3365  struct mark_tbl_arg *arg = (void*)data;
3366  gc_mark(arg->objspace, (VALUE)key);
3367  gc_mark(arg->objspace, (VALUE)value);
3368  return ST_CONTINUE;
3369 }
3370 
3371 static void
3373 {
3374  struct mark_tbl_arg arg;
3375  if (!tbl) return;
3376  arg.objspace = objspace;
3377  st_foreach(tbl, mark_keyvalue, (st_data_t)&arg);
3378 }
3379 
3380 void
3382 {
3383  mark_hash(&rb_objspace, tbl);
3384 }
3385 
3386 static void
3388 {
3389  const rb_method_definition_t *def = me->def;
3390 
3391  gc_mark(objspace, me->klass);
3392  again:
3393  if (!def) return;
3394  switch (def->type) {
3395  case VM_METHOD_TYPE_ISEQ:
3396  gc_mark(objspace, def->body.iseq->self);
3397  break;
3399  gc_mark(objspace, def->body.proc);
3400  break;
3402  case VM_METHOD_TYPE_IVAR:
3403  gc_mark(objspace, def->body.attr.location);
3404  break;
3406  if (def->body.orig_me) {
3407  def = def->body.orig_me->def;
3408  goto again;
3409  }
3410  break;
3411  default:
3412  break; /* ignore */
3413  }
3414 }
3415 
3416 void
3418 {
3419  mark_method_entry(&rb_objspace, me);
3420 }
3421 
3422 static int
3424 {
3425  struct mark_tbl_arg *arg = (void*)data;
3426  mark_method_entry(arg->objspace, me);
3427  return ST_CONTINUE;
3428 }
3429 
3430 static void
3432 {
3433  struct mark_tbl_arg arg;
3434  if (!wrapper || !wrapper->tbl) return;
3435  if (LIKELY(objspace->mark_func_data == 0)) {
3436  /* prevent multiple marking during same GC cycle,
3437  * since m_tbl is shared between several T_ICLASS */
3438  size_t serial = rb_gc_count();
3439  if (wrapper->serial == serial) return;
3440  wrapper->serial = serial;
3441  }
3442  arg.objspace = objspace;
3443  st_foreach(wrapper->tbl, mark_method_entry_i, (st_data_t)&arg);
3444 }
3445 
3446 static int
3448 {
3449  struct mark_tbl_arg *arg = (void*)data;
3450  gc_mark(arg->objspace, ce->value);
3451  gc_mark(arg->objspace, ce->file);
3452  return ST_CONTINUE;
3453 }
3454 
3455 static void
3457 {
3458  struct mark_tbl_arg arg;
3459  if (!tbl) return;
3460  arg.objspace = objspace;
3462 }
3463 
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))
3468 #else
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)))
3472 #endif
3473 
3474 static void
3476 {
3477  union {
3478  rb_jmp_buf j;
3479  VALUE v[sizeof(rb_jmp_buf) / sizeof(VALUE)];
3480  } save_regs_gc_mark;
3481  VALUE *stack_start, *stack_end;
3482 
3484  /* This assumes that all registers are saved into the jmp_buf (and stack) */
3485  rb_setjmp(save_regs_gc_mark.j);
3486 
3487  /* SET_STACK_END must be called in this function because
3488  * the stack frame of this function may contain
3489  * callee save registers and they should be marked. */
3490  SET_STACK_END;
3491  GET_STACK_BOUNDS(stack_start, stack_end, 1);
3492 
3493  mark_locations_array(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v));
3494 
3495  rb_gc_mark_locations(stack_start, stack_end);
3496 #ifdef __ia64
3497  rb_gc_mark_locations(th->machine.register_stack_start, th->machine.register_stack_end);
3498 #endif
3499 #if defined(__mc68000__)
3500  mark_locations_array(objspace, (VALUE*)((char*)STACK_END + 2),
3501  (STACK_START - STACK_END));
3502 #endif
3503 }
3504 
3505 void
3507 {
3508  rb_objspace_t *objspace = &rb_objspace;
3509  VALUE *stack_start, *stack_end;
3510 
3511  GET_STACK_BOUNDS(stack_start, stack_end, 0);
3512  rb_gc_mark_locations(stack_start, stack_end);
3513 #ifdef __ia64
3514  rb_gc_mark_locations(th->machine.register_stack_start, th->machine.register_stack_end);
3515 #endif
3516 }
3517 
3518 void
3520 {
3521  mark_tbl(&rb_objspace, tbl);
3522 }
3523 
3524 static void
3526 {
3527  (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj));
3528  if (is_pointer_to_heap(objspace, (void *)obj)) {
3529  int type = BUILTIN_TYPE(obj);
3530  if (type != T_ZOMBIE && type != T_NONE) {
3531  gc_mark(objspace, obj);
3532  }
3533  }
3534 }
3535 
3536 void
3538 {
3539  gc_mark_maybe(&rb_objspace, obj);
3540 }
3541 
3542 static inline int
3544 {
3545  register bits_t *bits = GET_HEAP_MARK_BITS(ptr);
3546  if (MARKED_IN_BITMAP(bits, ptr)) return 1;
3547  return 0;
3548 }
3549 
3550 static inline int
3552 {
3553  register bits_t *bits = GET_HEAP_MARK_BITS(ptr);
3554  if (gc_marked(objspace, ptr)) return 0;
3555  MARK_IN_BITMAP(bits, ptr);
3556  return 1;
3557 }
3558 
3559 static void
3561 {
3562 #if USE_RGENGC
3563  if (objspace->rgengc.parent_object_is_old) {
3564  if (!RVALUE_WB_PROTECTED(obj)) {
3565  if (rgengc_remember(objspace, obj)) {
3567  }
3568  }
3569 #if RGENGC_THREEGEN
3570  else {
3571  if (gc_marked(objspace, obj)) {
3572  if (!RVALUE_OLD_P(obj)) {
3573  /* An object pointed from an OLD object should be OLD. */
3574  rgengc_remember(objspace, obj);
3575  }
3576  }
3577  else {
3578  if (RVALUE_INFANT_P(obj)) {
3579  RVALUE_PROMOTE_INFANT(obj);
3580  }
3581  }
3582  }
3583 #endif
3584  }
3585 #endif
3586 }
3587 
3588 static void
3589 gc_mark(rb_objspace_t *objspace, VALUE ptr)
3590 {
3591  if (!is_markable_object(objspace, ptr)) return;
3592 
3593  if (LIKELY(objspace->mark_func_data == 0)) {
3594  rgengc_check_relation(objspace, ptr);
3595  if (!gc_mark_ptr(objspace, ptr)) return; /* already marked */
3596  push_mark_stack(&objspace->mark_stack, ptr);
3597  }
3598  else {
3599  objspace->mark_func_data->mark_func(ptr, objspace->mark_func_data->data);
3600  }
3601 }
3602 
3603 void
3605 {
3606  gc_mark(&rb_objspace, ptr);
3607 }
3608 
3609 /* resurrect non-marked `obj' if obj is before swept */
3610 
3611 void
3613 {
3614  rb_objspace_t *objspace = &rb_objspace;
3615 
3616  if (is_lazy_sweeping(heap_eden) &&
3617  !gc_marked(objspace, obj) &&
3618  !is_swept_object(objspace, obj)) {
3619  gc_mark_ptr(objspace, obj);
3620  }
3621 }
3622 
3623 static void
3625 {
3626  register RVALUE *obj = RANY(ptr);
3627 
3628  goto marking; /* skip */
3629 
3630  again:
3631  if (LIKELY(objspace->mark_func_data == 0)) {
3632  obj = RANY(ptr);
3633  if (!is_markable_object(objspace, ptr)) return;
3634  rgengc_check_relation(objspace, ptr);
3635  if (!gc_mark_ptr(objspace, ptr)) return; /* already marked */
3636  }
3637  else {
3638  gc_mark(objspace, ptr);
3639  return;
3640  }
3641 
3642  marking:
3643 
3644 #if USE_RGENGC
3646 
3647  if (LIKELY(objspace->mark_func_data == 0)) {
3648  /* minor/major common */
3649  if (RVALUE_WB_PROTECTED(obj)) {
3650  if (RVALUE_INFANT_P((VALUE)obj)) {
3651  /* infant -> young */
3653 #if RGENGC_THREEGEN
3654  /* infant -> young */
3655  objspace->rgengc.young_object_count++;
3656  objspace->rgengc.parent_object_is_old = FALSE;
3657 #else
3658  /* infant -> old */
3659  objspace->rgengc.old_object_count++;
3660  objspace->rgengc.parent_object_is_old = TRUE;
3661 #endif
3662  rgengc_report(3, objspace, "gc_mark_children: promote infant -> young %p (%s).\n", (void *)obj, obj_type_name((VALUE)obj));
3663  }
3664  else {
3665  objspace->rgengc.parent_object_is_old = TRUE;
3666 
3667 #if RGENGC_THREEGEN
3668  if (RVALUE_YOUNG_P((VALUE)obj)) {
3669  /* young -> old */
3670  RVALUE_PROMOTE_YOUNG((VALUE)obj);
3671  objspace->rgengc.old_object_count++;
3672  rgengc_report(3, objspace, "gc_mark_children: promote young -> old %p (%s).\n", (void *)obj, obj_type_name((VALUE)obj));
3673  }
3674  else {
3675 #endif
3676  if (!objspace->rgengc.during_minor_gc) {
3677  /* major/full GC */
3678  objspace->rgengc.old_object_count++;
3679  }
3680 #if RGENGC_THREEGEN
3681  }
3682 #endif
3683  }
3684  }
3685  else {
3686  rgengc_report(3, objspace, "gc_mark_children: do not promote non-WB-protected %p (%s).\n", (void *)obj, obj_type_name((VALUE)obj));
3687  objspace->rgengc.parent_object_is_old = FALSE;
3688  }
3689  }
3690 
3692 #endif /* USE_RGENGC */
3693 
3694  if (FL_TEST(obj, FL_EXIVAR)) {
3695  rb_mark_generic_ivar(ptr);
3696  }
3697 
3698  switch (BUILTIN_TYPE(obj)) {
3699  case T_NIL:
3700  case T_FIXNUM:
3701  rb_bug("rb_gc_mark() called for broken object");
3702  break;
3703 
3704  case T_NODE:
3705  switch (nd_type(obj)) {
3706  case NODE_IF: /* 1,2,3 */
3707  case NODE_FOR:
3708  case NODE_ITER:
3709  case NODE_WHEN:
3710  case NODE_MASGN:
3711  case NODE_RESCUE:
3712  case NODE_RESBODY:
3713  case NODE_CLASS:
3714  case NODE_BLOCK_PASS:
3715  gc_mark(objspace, (VALUE)obj->as.node.u2.node);
3716  /* fall through */
3717  case NODE_BLOCK: /* 1,3 */
3718  case NODE_ARRAY:
3719  case NODE_DSTR:
3720  case NODE_DXSTR:
3721  case NODE_DREGX:
3722  case NODE_DREGX_ONCE:
3723  case NODE_ENSURE:
3724  case NODE_CALL:
3725  case NODE_DEFS:
3726  case NODE_OP_ASGN1:
3727  gc_mark(objspace, (VALUE)obj->as.node.u1.node);
3728  /* fall through */
3729  case NODE_SUPER: /* 3 */
3730  case NODE_FCALL:
3731  case NODE_DEFN:
3732  case NODE_ARGS_AUX:
3733  ptr = (VALUE)obj->as.node.u3.node;
3734  goto again;
3735 
3736  case NODE_WHILE: /* 1,2 */
3737  case NODE_UNTIL:
3738  case NODE_AND:
3739  case NODE_OR:
3740  case NODE_CASE:
3741  case NODE_SCLASS:
3742  case NODE_DOT2:
3743  case NODE_DOT3:
3744  case NODE_FLIP2:
3745  case NODE_FLIP3:
3746  case NODE_MATCH2:
3747  case NODE_MATCH3:
3748  case NODE_OP_ASGN_OR:
3749  case NODE_OP_ASGN_AND:
3750  case NODE_MODULE:
3751  case NODE_ALIAS:
3752  case NODE_VALIAS:
3753  case NODE_ARGSCAT:
3754  gc_mark(objspace, (VALUE)obj->as.node.u1.node);
3755  /* fall through */
3756  case NODE_GASGN: /* 2 */
3757  case NODE_LASGN:
3758  case NODE_DASGN:
3759  case NODE_DASGN_CURR:
3760  case NODE_IASGN:
3761  case NODE_IASGN2:
3762  case NODE_CVASGN:
3763  case NODE_COLON3:
3764  case NODE_OPT_N:
3765  case NODE_EVSTR:
3766  case NODE_UNDEF:
3767  case NODE_POSTEXE:
3768  ptr = (VALUE)obj->as.node.u2.node;
3769  goto again;
3770 
3771  case NODE_HASH: /* 1 */
3772  case NODE_LIT:
3773  case NODE_STR:
3774  case NODE_XSTR:
3775  case NODE_DEFINED:
3776  case NODE_MATCH:
3777  case NODE_RETURN:
3778  case NODE_BREAK:
3779  case NODE_NEXT:
3780  case NODE_YIELD:
3781  case NODE_COLON2:
3782  case NODE_SPLAT:
3783  case NODE_TO_ARY:
3784  ptr = (VALUE)obj->as.node.u1.node;
3785  goto again;
3786 
3787  case NODE_SCOPE: /* 2,3 */
3788  case NODE_CDECL:
3789  case NODE_OPT_ARG:
3790  gc_mark(objspace, (VALUE)obj->as.node.u3.node);
3791  ptr = (VALUE)obj->as.node.u2.node;
3792  goto again;
3793 
3794  case NODE_ARGS: /* custom */
3795  {
3796  struct rb_args_info *args = obj->as.node.u3.args;
3797  if (args) {
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);
3803  }
3804  }
3805  ptr = (VALUE)obj->as.node.u2.node;
3806  goto again;
3807 
3808  case NODE_ZARRAY: /* - */
3809  case NODE_ZSUPER:
3810  case NODE_VCALL:
3811  case NODE_GVAR:
3812  case NODE_LVAR:
3813  case NODE_DVAR:
3814  case NODE_IVAR:
3815  case NODE_CVAR:
3816  case NODE_NTH_REF:
3817  case NODE_BACK_REF:
3818  case NODE_REDO:
3819  case NODE_RETRY:
3820  case NODE_SELF:
3821  case NODE_NIL:
3822  case NODE_TRUE:
3823  case NODE_FALSE:
3824  case NODE_ERRINFO:
3825  case NODE_BLOCK_ARG:
3826  break;
3827  case NODE_ALLOCA:
3828  mark_locations_array(objspace,
3829  (VALUE*)obj->as.node.u1.value,
3830  obj->as.node.u3.cnt);
3831  gc_mark(objspace, (VALUE)obj->as.node.u2.node);
3832  break;
3833 
3834  case NODE_CREF:
3835  gc_mark(objspace, obj->as.node.nd_refinements);
3836  gc_mark(objspace, (VALUE)obj->as.node.nd_clss);
3837  ptr = (VALUE)obj->as.node.nd_next;
3838  goto again;
3839 
3840  default: /* unlisted NODE */
3841  gc_mark_maybe(objspace, (VALUE)obj->as.node.u1.node);
3842  gc_mark_maybe(objspace, (VALUE)obj->as.node.u2.node);
3843  gc_mark_maybe(objspace, (VALUE)obj->as.node.u3.node);
3844  }
3845  return; /* no need to mark class. */
3846  }
3847 
3848  gc_mark(objspace, obj->as.basic.klass);
3849  switch (BUILTIN_TYPE(obj)) {
3850  case T_ICLASS:
3851  case T_CLASS:
3852  case T_MODULE:
3853  mark_m_tbl_wrapper(objspace, RCLASS_M_TBL_WRAPPER(obj));
3854  if (!RCLASS_EXT(obj)) break;
3855  mark_tbl(objspace, RCLASS_IV_TBL(obj));
3856  mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
3857  ptr = RCLASS_SUPER((VALUE)obj);
3858  goto again;
3859 
3860  case T_ARRAY:
3861  if (FL_TEST(obj, ELTS_SHARED)) {
3862  ptr = obj->as.array.as.heap.aux.shared;
3863  goto again;
3864  }
3865  else {
3866  long i, len = RARRAY_LEN(obj);
3867  const VALUE *ptr = RARRAY_CONST_PTR(obj);
3868  for (i=0; i < len; i++) {
3869  gc_mark(objspace, *ptr++);
3870  }
3871  }
3872  break;
3873 
3874  case T_HASH:
3875  mark_hash(objspace, obj->as.hash.ntbl);
3876  ptr = obj->as.hash.ifnone;
3877  goto again;
3878 
3879  case T_STRING:
3880 #define STR_ASSOC FL_USER3 /* copied from string.c */
3881  if (FL_TEST(obj, RSTRING_NOEMBED) && FL_ANY(obj, ELTS_SHARED|STR_ASSOC)) {
3882  ptr = obj->as.string.as.heap.aux.shared;
3883  goto again;
3884  }
3885  break;
3886 
3887  case T_DATA:
3888  if (RTYPEDDATA_P(obj)) {
3889  RUBY_DATA_FUNC mark_func = obj->as.typeddata.type->function.dmark;
3890  if (mark_func) (*mark_func)(DATA_PTR(obj));
3891  }
3892  else {
3893  if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
3894  }
3895  break;
3896 
3897  case T_OBJECT:
3898  {
3899  long i, len = ROBJECT_NUMIV(obj);
3900  VALUE *ptr = ROBJECT_IVPTR(obj);
3901  for (i = 0; i < len; i++) {
3902  gc_mark(objspace, *ptr++);
3903  }
3904  }
3905  break;
3906 
3907  case T_FILE:
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);
3915  }
3916  break;
3917 
3918  case T_REGEXP:
3919  ptr = obj->as.regexp.src;
3920  goto again;
3921 
3922  case T_FLOAT:
3923  case T_BIGNUM:
3924  break;
3925 
3926  case T_MATCH:
3927  gc_mark(objspace, obj->as.match.regexp);
3928  if (obj->as.match.str) {
3929  ptr = obj->as.match.str;
3930  goto again;
3931  }
3932  break;
3933 
3934  case T_RATIONAL:
3935  gc_mark(objspace, obj->as.rational.num);
3936  ptr = obj->as.rational.den;
3937  goto again;
3938 
3939  case T_COMPLEX:
3940  gc_mark(objspace, obj->as.complex.real);
3941  ptr = obj->as.complex.imag;
3942  goto again;
3943 
3944  case T_STRUCT:
3945  {
3946  long len = RSTRUCT_LEN(obj);
3947  const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
3948 
3949  while (len--) {
3950  gc_mark(objspace, *ptr++);
3951  }
3952  }
3953  break;
3954 
3955  default:
3956 #if GC_DEBUG
3958 #endif
3959  if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj);
3960  if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj);
3961  rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
3962  BUILTIN_TYPE(obj), (void *)obj,
3963  is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
3964  }
3965 }
3966 
3967 static void
3969 {
3970  mark_stack_t *mstack = &objspace->mark_stack;
3971  VALUE obj = 0;
3972 
3973  if (!mstack->index) return;
3974  while (pop_mark_stack(mstack, &obj)) {
3975  if (RGENGC_CHECK_MODE > 0 && !gc_marked(objspace, obj)) {
3976  rb_bug("gc_mark_stacked_objects: %p (%s) is infant, but not marked.", (void *)obj, obj_type_name(obj));
3977  }
3978  gc_mark_children(objspace, obj);
3979  }
3980  shrink_stack_chunk_cache(mstack);
3981 }
3982 
3983 #ifndef RGENGC_PRINT_TICK
3984 #define RGENGC_PRINT_TICK 0
3985 #endif
3986 /* the following code is only for internal tuning. */
3987 
3988 /* Source code to use RDTSC is quoted and modified from
3989  * http://www.mcs.anl.gov/~kazutomo/rdtsc.html
3990  * written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
3991  */
3992 
3993 #if RGENGC_PRINT_TICK
3994 #if defined(__GNUC__) && defined(__i386__)
3995 typedef unsigned long long tick_t;
3996 
3997 static inline tick_t
3998 tick(void)
3999 {
4000  unsigned long long int x;
4001  __asm__ __volatile__ ("rdtsc" : "=A" (x));
4002  return x;
4003 }
4004 
4005 #elif defined(__GNUC__) && defined(__x86_64__)
4006 typedef unsigned long long tick_t;
4007 
4008 static __inline__ tick_t
4009 tick(void)
4010 {
4011  unsigned long hi, lo;
4012  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
4013  return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32);
4014 }
4015 
4016 #elif defined(_WIN32) && defined(_MSC_VER)
4017 #include <intrin.h>
4018 typedef unsigned __int64 tick_t;
4019 
4020 static inline tick_t
4021 tick(void)
4022 {
4023  return __rdtsc();
4024 }
4025 
4026 #else /* use clock */
4027 typedef clock_t tick_t;
4028 static inline tick_t
4029 tick(void)
4030 {
4031  return clock();
4032 }
4033 #endif
4034 
4035 #define MAX_TICKS 0x100
4036 static tick_t mark_ticks[MAX_TICKS];
4037 static const char *mark_ticks_categories[MAX_TICKS];
4038 
4039 static void
4040 show_mark_ticks(void)
4041 {
4042  int i;
4043  fprintf(stderr, "mark ticks result:\n");
4044  for (i=0; i<MAX_TICKS; i++) {
4045  const char *category = mark_ticks_categories[i];
4046  if (category) {
4047  fprintf(stderr, "%s\t%8lu\n", category, (unsigned long)mark_ticks[i]);
4048  }
4049  else {
4050  break;
4051  }
4052  }
4053 }
4054 
4055 #endif /* RGENGC_PRINT_TICK */
4056 
4057 static void
4058 gc_mark_roots(rb_objspace_t *objspace, int full_mark, const char **categoryp)
4059 {
4060  struct gc_list *list;
4061  rb_thread_t *th = GET_THREAD();
4062  if (categoryp) *categoryp = "xxx";
4063 
4064 #if RGENGC_PRINT_TICK
4065  tick_t start_tick = tick();
4066  int tick_count = 0;
4067  const char *prev_category = 0;
4068 
4069  if (mark_ticks_categories[0] == 0) {
4070  atexit(show_mark_ticks);
4071  }
4072 #endif
4073 
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; \
4080  tick_count++; \
4081  } \
4082  prev_category = category; \
4083  start_tick = tick(); \
4084 } while (0)
4085 #else /* RGENGC_PRINT_TICK */
4086 #define MARK_CHECKPOINT_PRINT_TICK(category)
4087 #endif
4088 
4089 #define MARK_CHECKPOINT(category) do { \
4090  if (categoryp) *categoryp = category; \
4091  MARK_CHECKPOINT_PRINT_TICK(category); \
4092 } while (0)
4093 
4094  MARK_CHECKPOINT("vm");
4095  SET_STACK_END;
4096  th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
4097 
4098  MARK_CHECKPOINT("finalizers");
4099  mark_tbl(objspace, finalizer_table);
4100 
4101  MARK_CHECKPOINT("machine_context");
4102  mark_current_machine_context(objspace, th);
4103 
4104  MARK_CHECKPOINT("symbols");
4105 #if USE_RGENGC
4106  objspace->rgengc.parent_object_is_old = TRUE;
4107  rb_gc_mark_symbols(full_mark);
4108  objspace->rgengc.parent_object_is_old = FALSE;
4109 #else
4110  rb_gc_mark_symbols(full_mark);
4111 #endif
4112 
4113  MARK_CHECKPOINT("encodings");
4115 
4116  /* mark protected global variables */
4117  MARK_CHECKPOINT("global_list");
4118  for (list = global_List; list; list = list->next) {
4119  rb_gc_mark_maybe(*list->varptr);
4120  }
4121 
4122  MARK_CHECKPOINT("end_proc");
4123  rb_mark_end_proc();
4124 
4125  MARK_CHECKPOINT("global_tbl");
4127 
4128  /* mark generic instance variables for special constants */
4129  MARK_CHECKPOINT("generic_ivars");
4131 
4132  MARK_CHECKPOINT("parser");
4134 
4135  MARK_CHECKPOINT("live_method_entries");
4137 
4138  MARK_CHECKPOINT("finish");
4139 #undef MARK_CHECKPOINT
4140 }
4141 
4142 static void
4143 gc_marks_body(rb_objspace_t *objspace, int full_mark)
4144 {
4145  /* start marking */
4146  rgengc_report(1, objspace, "gc_marks_body: start (%s)\n", full_mark ? "full" : "minor");
4147 
4148 #if USE_RGENGC
4149  objspace->rgengc.parent_object_is_old = FALSE;
4150  objspace->rgengc.during_minor_gc = full_mark ? FALSE : TRUE;
4151 
4152  if (objspace->rgengc.during_minor_gc) {
4153  objspace->profile.minor_gc_count++;
4155  }
4156  else {
4157  objspace->profile.major_gc_count++;
4159  }
4160 #endif
4161  gc_mark_roots(objspace, full_mark, 0);
4162  gc_mark_stacked_objects(objspace);
4163 
4165  rgengc_report(1, objspace, "gc_marks_body: end (%s)\n", full_mark ? "full" : "minor");
4166 }
4167 
4172 };
4173 
4174 #if USE_RGENGC
4175 static void
4177 {
4179 
4180  assert(RVALUE_OLD_P(data->parent));
4181 
4182  if (!RVALUE_OLD_P(child)) {
4183  if (!MARKED_IN_BITMAP(GET_HEAP_PAGE(data->parent)->rememberset_bits, data->parent) &&
4184  !MARKED_IN_BITMAP(GET_HEAP_PAGE(child)->rememberset_bits, child)) {
4185  fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss %p (%s) -> %p (%s)\n",
4186  (void *)data->parent, obj_type_name(data->parent),
4187  (void *)child, obj_type_name(child));
4188  data->err_count++;
4189  }
4190  }
4191 }
4192 
4193 static int
4194 verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, void *ptr)
4195 {
4197  VALUE v;
4198 
4199  for (v = (VALUE)page_start; v != (VALUE)page_end; v += stride) {
4200  if (is_live_object(data->objspace, v)) {
4201  if (RVALUE_OLD_P(v)) {
4202  data->parent = v;
4203  /* reachable objects from an oldgen object should be old or (young with remember) */
4205  }
4206  }
4207  }
4208 
4209  return 0;
4210 }
4211 #endif /* USE_RGENGC */
4212 
4213 /*
4214  * call-seq:
4215  * GC.verify_internal_consistency -> nil
4216  *
4217  * Verify internal consistency.
4218  *
4219  * This method is implementation specific.
4220  * Now this method checks generatioanl consistency
4221  * if RGenGC is supported.
4222  */
4223 static VALUE
4225 {
4227  data.objspace = &rb_objspace;
4228  data.err_count = 0;
4229 
4230 #if USE_RGENGC
4231  {
4232  struct each_obj_args eo_args;
4234  eo_args.data = (void *)&data;
4235  objspace_each_objects((VALUE)&eo_args);
4236  }
4237 #endif
4238  if (data.err_count != 0) {
4239  rb_bug("gc_verify_internal_consistency: found internal consistency.\n");
4240  }
4241  return Qnil;
4242 }
4243 
4244 #if RGENGC_CHECK_MODE >= 3
4245 
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))
4249 
4250 struct reflist {
4251  VALUE *list;
4252  int pos;
4253  int size;
4254 };
4255 
4256 static struct reflist *
4257 reflist_create(VALUE obj)
4258 {
4259  struct reflist *refs = xmalloc(sizeof(struct reflist));
4260  refs->size = 1;
4261  refs->list = ALLOC_N(VALUE, refs->size);
4262  refs->list[0] = obj;
4263  refs->pos = 1;
4264  return refs;
4265 }
4266 
4267 static void
4268 reflist_destruct(struct reflist *refs)
4269 {
4270  xfree(refs->list);
4271  xfree(refs);
4272 }
4273 
4274 static void
4275 reflist_add(struct reflist *refs, VALUE obj)
4276 {
4277  if (refs->pos == refs->size) {
4278  refs->size *= 2;
4279  SIZED_REALLOC_N(refs->list, VALUE, refs->size, refs->size/2);
4280  }
4281 
4282  refs->list[refs->pos++] = obj;
4283 }
4284 
4285 static void
4286 reflist_dump(struct reflist *refs)
4287 {
4288  int i;
4289  for (i=0; i<refs->pos; i++) {
4290  VALUE obj = refs->list[i];
4291  if (IS_ROOTSIG(obj)) { /* root */
4292  fprintf(stderr, "<root@%s>", GET_ROOTSIG(obj));
4293  }
4294  else {
4295  fprintf(stderr, "<%p@%s>", (void *)obj, obj_type_name(obj));
4296  }
4297  if (i+1 < refs->pos) fprintf(stderr, ", ");
4298  }
4299 }
4300 
4301 #if RGENGC_CHECK_MODE >= 3
4302 static int
4303 reflist_refered_from_machine_context(struct reflist *refs)
4304 {
4305  int i;
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;
4309  }
4310  return 0;
4311 }
4312 #endif
4313 
4314 struct allrefs {
4315  rb_objspace_t *objspace;
4316  /* a -> obj1
4317  * b -> obj1
4318  * c -> obj1
4319  * c -> obj2
4320  * d -> obj3
4321  * #=> {obj1 => [a, b, c], obj2 => [c, d]}
4322  */
4323  struct st_table *references;
4324  const char *category;
4325  VALUE root_obj;
4326 };
4327 
4328 static int
4329 allrefs_add(struct allrefs *data, VALUE obj)
4330 {
4331  struct reflist *refs;
4332 
4333  if (st_lookup(data->references, obj, (st_data_t *)&refs)) {
4334  reflist_add(refs, data->root_obj);
4335  return 0;
4336  }
4337  else {
4338  refs = reflist_create(data->root_obj);
4339  st_insert(data->references, obj, (st_data_t)refs);
4340  return 1;
4341  }
4342 }
4343 
4344 static void
4345 allrefs_i(VALUE obj, void *ptr)
4346 {
4347  struct allrefs *data = (struct allrefs *)ptr;
4348 
4349  if (allrefs_add(data, obj)) {
4350  push_mark_stack(&data->objspace->mark_stack, obj);
4351  }
4352 }
4353 
4354 static void
4355 allrefs_roots_i(VALUE obj, void *ptr)
4356 {
4357  struct allrefs *data = (struct allrefs *)ptr;
4358  if (strlen(data->category) == 0) rb_bug("!!!");
4359  data->root_obj = MAKE_ROOTSIG(data->category);
4360 
4361  if (allrefs_add(data, obj)) {
4362  push_mark_stack(&data->objspace->mark_stack, obj);
4363  }
4364 }
4365 
4366 static st_table *
4367 objspace_allrefs(rb_objspace_t *objspace)
4368 {
4369  struct allrefs data;
4370  struct mark_func_data_struct mfd;
4371  VALUE obj;
4372 
4373  data.objspace = objspace;
4374  data.references = st_init_numtable();
4375 
4376  mfd.mark_func = allrefs_roots_i;
4377  mfd.data = &data;
4378 
4379  /* traverse root objects */
4380  objspace->mark_func_data = &mfd;
4381  gc_mark_roots(objspace, TRUE, &data.category);
4382  objspace->mark_func_data = 0;
4383 
4384  /* traverse rest objects reachable from root objects */
4385  while (pop_mark_stack(&objspace->mark_stack, &obj)) {
4386  rb_objspace_reachable_objects_from(data.root_obj = obj, allrefs_i, &data);
4387  }
4389 
4390  return data.references;
4391 }
4392 
4393 static int
4394 objspaec_allrefs_destruct_i(st_data_t key, st_data_t value, void *ptr)
4395 {
4396  struct reflist *refs = (struct reflist *)value;
4397  reflist_destruct(refs);
4398  return ST_CONTINUE;
4399 }
4400 
4401 static void
4402 objspace_allrefs_destruct(struct st_table *refs)
4403 {
4404  st_foreach(refs, objspaec_allrefs_destruct_i, 0);
4405  st_free_table(refs);
4406 }
4407 
4408 #if RGENGC_CHECK_MODE >= 4
4409 static int
4410 allrefs_dump_i(st_data_t k, st_data_t v, st_data_t ptr)
4411 {
4412  VALUE obj = (VALUE)k;
4413  struct reflist *refs = (struct reflist *)v;
4414  fprintf(stderr, "[allrefs_dump_i] %p (%s%s%s%s) <- ",
4415  (void *)obj, obj_type_name(obj),
4416  RVALUE_OLD_P(obj) ? "[O]" : "[Y]",
4417  RVALUE_WB_PROTECTED(obj) ? "[W]" : "",
4418  MARKED_IN_BITMAP(GET_HEAP_REMEMBERSET_BITS(obj), obj) ? "[R]" : "");
4419  reflist_dump(refs);
4420  fprintf(stderr, "\n");
4421  return ST_CONTINUE;
4422 }
4423 
4424 static void
4425 allrefs_dump(rb_objspace_t *objspace)
4426 {
4427  fprintf(stderr, "[all refs] (size: %d)\n", (int)objspace->rgengc.allrefs_table->num_entries);
4428  st_foreach(objspace->rgengc.allrefs_table, allrefs_dump_i, 0);
4429 }
4430 #endif
4431 
4432 #if RGENGC_CHECK_MODE >= 3
4433 static int
4434 gc_check_after_marks_i(st_data_t k, st_data_t v, void *ptr)
4435 {
4436  VALUE obj = k;
4437  struct reflist *refs = (struct reflist *)v;
4438  rb_objspace_t *objspace = (rb_objspace_t *)ptr;
4439 
4440  /* object should be marked or oldgen */
4441  if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj)) {
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);
4444  reflist_dump(refs);
4445 
4446  if (reflist_refered_from_machine_context(refs)) {
4447  fprintf(stderr, " (marked from machine stack).\n");
4448  /* marked from machine context can be false positive */
4449  }
4450  else {
4451  objspace->rgengc.error_count++;
4452  fprintf(stderr, "\n");
4453  }
4454  }
4455  return ST_CONTINUE;
4456 }
4457 #endif
4458 
4459 static void
4460 gc_marks_check(rb_objspace_t *objspace, int (*checker_func)(ANYARGS), const char *checker_name)
4461 {
4462 
4463  size_t saved_malloc_increase = objspace->malloc_params.increase;
4464 #if RGENGC_ESTIMATE_OLDMALLOC
4465  size_t saved_oldmalloc_increase = objspace->rgengc.oldmalloc_increase;
4466 #endif
4467  VALUE already_disabled = rb_gc_disable();
4468 
4469  objspace->rgengc.allrefs_table = objspace_allrefs(objspace);
4470  st_foreach(objspace->rgengc.allrefs_table, checker_func, (st_data_t)objspace);
4471 
4472  if (objspace->rgengc.error_count > 0) {
4473 #if RGENGC_CHECK_MODE >= 4
4474  allrefs_dump(objspace);
4475 #endif
4476  rb_bug("%s: GC has problem.", checker_name);
4477  }
4478 
4479  objspace_allrefs_destruct(objspace->rgengc.allrefs_table);
4480  objspace->rgengc.allrefs_table = 0;
4481 
4482  if (already_disabled == Qfalse) rb_gc_enable();
4483  objspace->malloc_params.increase = saved_malloc_increase;
4484 #if RGENGC_ESTIMATE_OLDMALLOC
4485  objspace->rgengc.oldmalloc_increase = saved_oldmalloc_increase;
4486 #endif
4487 }
4488 
4489 #endif /* RGENGC_CHECK_MODE >= 2 */
4490 
4491 static void
4492 gc_marks(rb_objspace_t *objspace, int full_mark)
4493 {
4494  struct mark_func_data_struct *prev_mark_func_data;
4495 
4496  gc_prof_mark_timer_start(objspace);
4497  {
4498  /* setup marking */
4499  prev_mark_func_data = objspace->mark_func_data;
4500  objspace->mark_func_data = 0;
4501 
4502 #if USE_RGENGC
4503 
4504 #if RGENGC_CHECK_MODE >= 2
4506 #endif
4507  if (full_mark == TRUE) { /* major/full GC */
4508  objspace->rgengc.remembered_shady_object_count = 0;
4509  objspace->rgengc.old_object_count = 0;
4510 #if RGENGC_THREEGEN
4511  objspace->rgengc.young_object_count = 0;
4512 #endif
4513 
4514  gc_marks_body(objspace, TRUE);
4515  {
4516  /* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
4517  const double r = gc_params.oldobject_limit_factor;
4518  objspace->rgengc.remembered_shady_object_limit = (size_t)(objspace->rgengc.remembered_shady_object_count * r);
4519  objspace->rgengc.old_object_limit = (size_t)(objspace->rgengc.old_object_count * r);
4520  }
4521  }
4522  else { /* minor GC */
4523  gc_marks_body(objspace, FALSE);
4524  }
4525 
4526 #if RGENGC_PROFILE > 0
4527  if (gc_prof_record(objspace)) {
4528  gc_profile_record *record = gc_prof_record(objspace);
4529  record->old_objects = objspace->rgengc.old_object_count;
4530  }
4531 #endif
4532 
4533 #if RGENGC_CHECK_MODE >= 3
4534  gc_marks_check(objspace, gc_check_after_marks_i, "after_marks");
4535 #endif
4536 
4537 #else /* USE_RGENGC */
4538  gc_marks_body(objspace, TRUE);
4539 #endif
4540 
4541  objspace->mark_func_data = prev_mark_func_data;
4542  }
4543  gc_prof_mark_timer_stop(objspace);
4544 }
4545 
4546 /* RGENGC */
4547 
4548 static void
4549 rgengc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
4550 {
4551  if (level <= RGENGC_DEBUG) {
4552  char buf[1024];
4553  FILE *out = stderr;
4554  va_list args;
4555  const char *status = " ";
4556 
4557 #if USE_RGENGC
4558  if (during_gc) {
4559  status = objspace->rgengc.during_minor_gc ? "-" : "+";
4560  }
4561 #endif
4562 
4563  va_start(args, fmt);
4564  vsnprintf(buf, 1024, fmt, args);
4565  va_end(args);
4566 
4567  fprintf(out, "%s|", status);
4568  fputs(buf, out);
4569  }
4570 }
4571 
4572 #if USE_RGENGC
4573 
4574 /* bit operations */
4575 
4576 static int
4578 {
4579  bits_t *bits = GET_HEAP_REMEMBERSET_BITS(obj);
4580  return MARKED_IN_BITMAP(bits, obj) ? 1 : 0;
4581 }
4582 
4583 static int
4585 {
4586  bits_t *bits = GET_HEAP_REMEMBERSET_BITS(obj);
4587  if (MARKED_IN_BITMAP(bits, obj)) {
4588  return FALSE;
4589  }
4590  else {
4591  MARK_IN_BITMAP(bits, obj);
4592  return TRUE;
4593  }
4594 }
4595 
4596 /* wb, etc */
4597 
4598 /* return FALSE if already remembered */
4599 static int
4601 {
4602  rgengc_report(2, objspace, "rgengc_remember: %p (%s, %s) %s\n", (void *)obj, obj_type_name(obj),
4603  RVALUE_WB_PROTECTED(obj) ? "WB-protected" : "non-WB-protected",
4604  rgengc_remembersetbits_get(objspace, obj) ? "was already remembered" : "is remembered now");
4605 
4606 #if RGENGC_CHECK_MODE > 0
4607  {
4608  switch (BUILTIN_TYPE(obj)) {
4609  case T_NONE:
4610  case T_ZOMBIE:
4611  rb_bug("rgengc_remember: should not remember %p (%s)\n",
4612  (void *)obj, obj_type_name(obj));
4613  default:
4614  ;
4615  }
4616  }
4617 #endif
4618 
4619  if (RGENGC_PROFILE) {
4620  if (!rgengc_remembered(objspace, obj)) {
4621 #if RGENGC_PROFILE > 0
4622  if (RVALUE_WB_PROTECTED(obj)) {
4623  objspace->profile.remembered_normal_object_count++;
4624 #if RGENGC_PROFILE >= 2
4625  objspace->profile.remembered_normal_object_count_types[BUILTIN_TYPE(obj)]++;
4626 #endif
4627  }
4628  else {
4630 #if RGENGC_PROFILE >= 2
4631  objspace->profile.remembered_shady_object_count_types[BUILTIN_TYPE(obj)]++;
4632 #endif
4633  }
4634 #endif /* RGENGC_PROFILE > 0 */
4635  }
4636  }
4637 
4638  return rgengc_remembersetbits_set(objspace, obj);
4639 }
4640 
4641 static int
4643 {
4644  int result = rgengc_remembersetbits_get(objspace, obj);
4645  check_gen_consistency(obj);
4646  rgengc_report(6, objspace, "gc_remembered: %p (%s) => %d\n", (void *)obj, obj_type_name(obj), result);
4647  return result;
4648 }
4649 
4650 static void
4652 {
4653  size_t j;
4654  RVALUE *p, *offset;
4655  bits_t *bits, bitset;
4656  struct heap_page *page = heap->pages;
4657 
4658 #if RGENGC_PROFILE > 0
4659  size_t shady_object_count = 0, clear_count = 0;
4660 #endif
4661 
4662  while (page) {
4663  p = page->start;
4664  bits = page->rememberset_bits;
4665  offset = p - NUM_IN_PAGE(p);
4666 
4667  for (j=0; j < HEAP_BITMAP_LIMIT; j++) {
4668  if (bits[j]) {
4669  p = offset + j * BITS_BITLENGTH;
4670  bitset = bits[j];
4671  do {
4672  if (bitset & 1) {
4673  /* mark before RVALUE_PROMOTE_... */
4674  gc_mark_ptr(objspace, (VALUE)p);
4675 
4676  if (RVALUE_WB_PROTECTED(p)) {
4677  rgengc_report(2, objspace, "rgengc_rememberset_mark: clear %p (%s)\n", p, obj_type_name((VALUE)p));
4678 #if RGENGC_THREEGEN
4680  if (RVALUE_YOUNG_P((VALUE)p)) RVALUE_PROMOTE_YOUNG((VALUE)p);
4681 #endif
4682  CLEAR_IN_BITMAP(bits, p);
4683 #if RGENGC_PROFILE > 0
4684  clear_count++;
4685 #endif
4686  }
4687  else {
4688 #if RGENGC_PROFILE > 0
4689  shady_object_count++;
4690 #endif
4691  }
4692 
4693  rgengc_report(2, objspace, "rgengc_rememberset_mark: mark %p (%s)\n", p, obj_type_name((VALUE)p));
4694  gc_mark_children(objspace, (VALUE) p);
4695  }
4696  p++;
4697  bitset >>= 1;
4698  } while (bitset);
4699  }
4700  }
4701  page = page->next;
4702  }
4703 
4704  rgengc_report(2, objspace, "rgengc_rememberset_mark: finished\n");
4705 
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);
4708  if (gc_prof_record(objspace)) {
4709  gc_profile_record *record = gc_prof_record(objspace);
4710  record->remembered_normal_objects = clear_count;
4711  record->remembered_shady_objects = shady_object_count;
4712  }
4713 #endif
4714 }
4715 
4716 static void
4718 {
4719  struct heap_page *page = heap->pages;
4720 
4721  while (page) {
4722  memset(&page->mark_bits[0], 0, HEAP_BITMAP_SIZE);
4723  memset(&page->rememberset_bits[0], 0, HEAP_BITMAP_SIZE);
4724  page = page->next;
4725  }
4726 }
4727 
4728 /* RGENGC: APIs */
4729 
4730 void
4732 {
4733  if (RGENGC_CHECK_MODE) {
4734  if (!RVALUE_PROMOTED_P(a)) rb_bug("rb_gc_writebarrier: referer object %p (%s) is not promoted.\n", (void *)a, obj_type_name(a));
4735  }
4736 
4737  if (!RVALUE_OLD_P(b) && RVALUE_OLD_BITMAP_P(a)) {
4738  rb_objspace_t *objspace = &rb_objspace;
4739 
4740  if (!rgengc_remembered(objspace, a)) {
4741  rgengc_report(2, objspace, "rb_gc_wb: %p (%s) -> %p (%s)\n",
4742  (void *)a, obj_type_name(a), (void *)b, obj_type_name(b));
4743  rgengc_remember(objspace, a);
4744  }
4745  }
4746 }
4747 
4748 void
4750 {
4751  rb_objspace_t *objspace = &rb_objspace;
4752 
4753  if (RGENGC_CHECK_MODE) {
4754  if (!RVALUE_PROMOTED_P(obj)) rb_bug("rb_gc_writebarrier_unprotect_promoted: called on non-promoted object");
4755  if (!RVALUE_WB_PROTECTED(obj)) rb_bug("rb_gc_writebarrier_unprotect_promoted: called on shady object");
4756  }
4757 
4758  rgengc_report(0, objspace, "rb_gc_writebarrier_unprotect_promoted: %p (%s)%s\n", (void *)obj, obj_type_name(obj),
4759  rgengc_remembered(objspace, obj) ? " (already remembered)" : "");
4760 
4761  if (RVALUE_OLD_P(obj)) {
4763 
4764  rgengc_remember(objspace, obj);
4766 
4767 #if RGENGC_PROFILE
4768  objspace->profile.shade_operation_count++;
4769 #if RGENGC_PROFILE >= 2
4770  objspace->profile.shade_operation_count_types[BUILTIN_TYPE(obj)]++;
4771 #endif /* RGENGC_PROFILE >= 2 */
4772 #endif /* RGENGC_PROFILE */
4773  }
4774 #if RGENGC_THREEGEN
4775  else {
4776  RVALUE_DEMOTE_FROM_YOUNG(obj);
4777  }
4778 #endif
4779 }
4780 
4781 void
4783 {
4784  rb_objspace_t *objspace = &rb_objspace;
4785  rgengc_remember(objspace, obj);
4786 }
4787 
4789 
4790 static int
4792 {
4793  fprintf(stderr, "%s\t%d\n", (char *)key, (int)val);
4794  return ST_CONTINUE;
4795 }
4796 
4797 static void
4799 {
4800  st_foreach(rgengc_unprotect_logging_table, rgengc_unprotect_logging_exit_func_i, 0);
4801 }
4802 
4803 void
4804 rb_gc_unprotect_logging(void *objptr, const char *filename, int line)
4805 {
4806  VALUE obj = (VALUE)objptr;
4807 
4808  if (rgengc_unprotect_logging_table == 0) {
4809  rgengc_unprotect_logging_table = st_init_strtable();
4811  }
4812 
4813  if (OBJ_WB_PROTECTED(obj)) {
4814  char buff[0x100];
4815  st_data_t cnt = 1;
4816  char *ptr = buff;
4817 
4818  snprintf(ptr, 0x100 - 1, "%s|%s:%d", obj_type_name(obj), filename, line);
4819 
4820  if (st_lookup(rgengc_unprotect_logging_table, (st_data_t)ptr, &cnt)) {
4821  cnt++;
4822  }
4823  else {
4824  ptr = (char *)malloc(strlen(buff) + 1);
4825  strcpy(ptr, buff);
4826  }
4827  st_insert(rgengc_unprotect_logging_table, (st_data_t)ptr, cnt);
4828  }
4829 }
4830 
4831 #endif /* USE_RGENGC */
4832 
4833 /* RGENGC analysis information */
4834 
4835 VALUE
4837 {
4838  return OBJ_WB_PROTECTED(obj) ? Qtrue : Qfalse;
4839 }
4840 
4841 VALUE
4843 {
4844  return OBJ_PROMOTED(obj) ? Qtrue : Qfalse;
4845 }
4846 
4847 size_t
4848 rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
4849 {
4850  size_t n = 0;
4851  static ID ID_marked;
4852 #if USE_RGENGC
4853  static ID ID_wb_protected, ID_old, ID_remembered;
4854 #if RGENGC_THREEGEN
4855  static ID ID_young, ID_infant;
4856 #endif
4857 #endif
4858 
4859  if (!ID_marked) {
4860 #define I(s) ID_##s = rb_intern(#s);
4861  I(marked);
4862 #if USE_RGENGC
4863  I(wb_protected);
4864  I(old);
4865  I(remembered);
4866 #if RGENGC_THREEGEN
4867  I(young);
4868  I(infant);
4869 #endif
4870 #endif
4871 #undef I
4872  }
4873 
4874 #if USE_RGENGC
4875  if (OBJ_WB_PROTECTED(obj) && n<max)
4876  flags[n++] = ID_wb_protected;
4877  if (RVALUE_OLD_P(obj) && n<max)
4878  flags[n++] = ID_old;
4879 #if RGENGC_THREEGEN
4880  if (RVALUE_YOUNG_P(obj) && n<max)
4881  flags[n++] = ID_young;
4882  if (RVALUE_INFANT_P(obj) && n<max)
4883  flags[n++] = ID_infant;
4884 #endif
4885  if (MARKED_IN_BITMAP(GET_HEAP_REMEMBERSET_BITS(obj), obj) && n<max)
4886  flags[n++] = ID_remembered;
4887 #endif
4888  if (MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) && n<max)
4889  flags[n++] = ID_marked;
4890 
4891  return n;
4892 }
4893 
4894 /* GC */
4895 
4896 void
4898 {
4899  rb_objspace_t *objspace = &rb_objspace;
4900 
4901 #if USE_RGENGC
4904  if (!GET_HEAP_PAGE(p)->before_sweep) {
4906  }
4907 #endif
4908 
4909  objspace->profile.total_freed_object_num++;
4910  heap_page_add_freeobj(objspace, GET_HEAP_PAGE(p), p);
4911 
4912  /* Disable counting swept_slots because there are no meaning.
4913  * if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
4914  * objspace->heap.swept_slots++;
4915  * }
4916  */
4917 }
4918 
4919 void
4921 {
4922  VALUE ary = GET_THREAD()->vm->mark_object_ary;
4923  rb_ary_push(ary, obj);
4924 }
4925 
4926 void
4928 {
4929  rb_objspace_t *objspace = &rb_objspace;
4930  struct gc_list *tmp;
4931 
4932  tmp = ALLOC(struct gc_list);
4933  tmp->next = global_List;
4934  tmp->varptr = addr;
4935  global_List = tmp;
4936 }
4937 
4938 void
4940 {
4941  rb_objspace_t *objspace = &rb_objspace;
4942  struct gc_list *tmp = global_List;
4943 
4944  if (tmp->varptr == addr) {
4945  global_List = tmp->next;
4946  xfree(tmp);
4947  return;
4948  }
4949  while (tmp->next) {
4950  if (tmp->next->varptr == addr) {
4951  struct gc_list *t = tmp->next;
4952 
4953  tmp->next = tmp->next->next;
4954  xfree(t);
4955  break;
4956  }
4957  tmp = tmp->next;
4958  }
4959 }
4960 
4961 void
4963 {
4965 }
4966 
4967 #define GC_NOTIFY 0
4968 
4969 static int
4970 garbage_collect_body(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
4971 {
4972  if (ruby_gc_stress && !ruby_disable_gc_stress) {
4973  int flag = FIXNUM_P(ruby_gc_stress) ? FIX2INT(ruby_gc_stress) : 0;
4974 
4975  if (flag & 0x01)
4976  reason &= ~GPR_FLAG_MAJOR_MASK;
4977  else
4978  reason |= GPR_FLAG_MAJOR_BY_STRESS;
4979  immediate_sweep = !(flag & 0x02);
4980  }
4981  else {
4982  if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_lazy_sweep) {
4983  immediate_sweep = TRUE;
4984  }
4985 #if USE_RGENGC
4986  if (full_mark) {
4987  reason |= GPR_FLAG_MAJOR_BY_NOFREE;
4988  }
4989  if (objspace->rgengc.need_major_gc) {
4990  reason |= objspace->rgengc.need_major_gc;
4991  objspace->rgengc.need_major_gc = GPR_FLAG_NONE;
4992  }
4994  reason |= GPR_FLAG_MAJOR_BY_SHADY;
4995  }
4996  if (objspace->rgengc.old_object_count > objspace->rgengc.old_object_limit) {
4997  reason |= GPR_FLAG_MAJOR_BY_OLDGEN;
4998  }
4999 #endif
5000  }
5001 
5002  if (immediate_sweep) reason |= GPR_FLAG_IMMEDIATE_SWEEP;
5003  full_mark = (reason & GPR_FLAG_MAJOR_MASK) ? TRUE : FALSE;
5004 
5005  if (GC_NOTIFY) fprintf(stderr, "start garbage_collect(%d, %d, %d)\n", full_mark, immediate_sweep, reason);
5006 
5007  objspace->profile.count++;
5008  objspace->profile.latest_gc_info = reason;
5009 
5010  gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_START, 0 /* TODO: pass minor/immediate flag? */);
5011 
5014 
5015  gc_prof_setup_new_record(objspace, reason);
5016  gc_prof_timer_start(objspace);
5017  {
5018  if (during_gc == 0) {
5019  rb_bug("during_gc should not be 0. RUBY_INTERNAL_EVENT_GC_START user should not cause GC in events.");
5020  }
5021  gc_marks(objspace, full_mark);
5022  gc_sweep(objspace, immediate_sweep);
5023  during_gc = 0;
5024  }
5025  gc_prof_timer_stop(objspace);
5026 
5027  if (GC_NOTIFY) fprintf(stderr, "end garbage_collect()\n");
5028  return TRUE;
5029 }
5030 
5031 static int
5033 {
5034  if (dont_gc || during_gc) {
5035  if (!heap->freelist && !heap->free_pages) {
5036  if (!heap_increment(objspace, heap)) {
5037  heap_set_increment(objspace, 0);
5038  heap_increment(objspace, heap);
5039  }
5040  }
5041  return FALSE;
5042  }
5043  return TRUE;
5044 }
5045 
5046 static int
5048 {
5049  return heap_ready_to_gc(objspace, heap_eden);
5050 }
5051 
5052 static int
5053 garbage_collect(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
5054 {
5055  if (!heap_pages_used) {
5056  during_gc = 0;
5057  return FALSE;
5058  }
5059  if (!ready_to_gc(objspace)) {
5060  during_gc = 0;
5061  return TRUE;
5062  }
5063 
5064 #if GC_PROFILE_MORE_DETAIL
5065  objspace->profile.prepare_time = getrusage_time();
5066 #endif
5067  gc_rest_sweep(objspace);
5068 #if GC_PROFILE_MORE_DETAIL
5069  objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time;
5070 #endif
5071 
5072  during_gc++;
5073 
5074  return garbage_collect_body(objspace, full_mark, immediate_sweep, reason);
5075 }
5076 
5079  int reason;
5082 };
5083 
5084 static void *
5085 gc_with_gvl(void *ptr)
5086 {
5087  struct objspace_and_reason *oar = (struct objspace_and_reason *)ptr;
5088  return (void *)(VALUE)garbage_collect(oar->objspace, oar->full_mark, oar->immediate_sweep, oar->reason);
5089 }
5090 
5091 static int
5093 {
5094  if (dont_gc) return TRUE;
5095  if (ruby_thread_has_gvl_p()) {
5096  return garbage_collect(objspace, full_mark, immediate_sweep, reason);
5097  }
5098  else {
5099  if (ruby_native_thread_p()) {
5100  struct objspace_and_reason oar;
5101  oar.objspace = objspace;
5102  oar.reason = reason;
5103  oar.full_mark = full_mark;
5105  return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
5106  }
5107  else {
5108  /* no ruby thread */
5109  fprintf(stderr, "[FATAL] failed to allocate memory\n");
5110  exit(EXIT_FAILURE);
5111  }
5112  }
5113 }
5114 
5115 int
5117 {
5118  return garbage_collect(&rb_objspace, TRUE, TRUE, GPR_FLAG_CAPI);
5119 }
5120 
5121 #undef Init_stack
5122 
5123 void
5124 Init_stack(volatile VALUE *addr)
5125 {
5126  ruby_init_stack(addr);
5127 }
5128 
5129 /*
5130  * call-seq:
5131  * GC.start -> nil
5132  * GC.garbage_collect -> nil
5133  * ObjectSpace.garbage_collect -> nil
5134  * GC.start(full_mark: false) -> nil
5135  *
5136  * Initiates garbage collection, unless manually disabled.
5137  *
5138  * This method is defined with keyword arguments that default to true:
5139  *
5140  * def GC.start(full_mark: true, immediate_sweep: true) end
5141  *
5142  * Use full_mark: false to perform a minor GC.
5143  * Use immediate_sweep: false to defer sweeping (use lazy sweep).
5144  *
5145  * Note: These keyword arguments are implementation and version dependent. They
5146  * are not guaranteed to be future-compatible, and may be ignored if the
5147  * underlying implementation does not support them.
5148  */
5149 
5150 static VALUE
5152 {
5153  rb_objspace_t *objspace = &rb_objspace;
5155  VALUE opt = Qnil;
5156  static ID keyword_ids[2];
5157 
5158  rb_scan_args(argc, argv, "0:", &opt);
5159 
5160  if (!NIL_P(opt)) {
5161  VALUE kwvals[2];
5162 
5163  if (!keyword_ids[0]) {
5164  keyword_ids[0] = rb_intern("full_mark");
5165  keyword_ids[1] = rb_intern("immediate_sweep");
5166  }
5167 
5168  rb_get_kwargs(opt, keyword_ids, 0, 2, kwvals);
5169 
5170  if (kwvals[0] != Qundef)
5171  full_mark = RTEST(kwvals[0]);
5172  if (kwvals[1] != Qundef)
5173  immediate_sweep = RTEST(kwvals[1]);
5174  }
5175 
5176  garbage_collect(objspace, full_mark, immediate_sweep, GPR_FLAG_METHOD);
5177  if (!finalizing) finalize_deferred(objspace);
5178 
5179  return Qnil;
5180 }
5181 
5182 VALUE
5184 {
5185  rb_gc();
5186  return Qnil;
5187 }
5188 
5189 void
5190 rb_gc(void)
5191 {
5192  rb_objspace_t *objspace = &rb_objspace;
5193  garbage_collect(objspace, TRUE, TRUE, GPR_FLAG_CAPI);
5194  if (!finalizing) finalize_deferred(objspace);
5195 }
5196 
5197 int
5199 {
5200  rb_objspace_t *objspace = &rb_objspace;
5201  return during_gc;
5202 }
5203 
5204 #if RGENGC_PROFILE >= 2
5205 static void
5206 gc_count_add_each_types(VALUE hash, const char *name, const size_t *types)
5207 {
5208  VALUE result = rb_hash_new();
5209  int i;
5210  for (i=0; i<T_MASK; i++) {
5211  const char *type = type_name(i, 0);
5212  rb_hash_aset(result, ID2SYM(rb_intern(type)), SIZET2NUM(types[i]));
5213  }
5214  rb_hash_aset(hash, ID2SYM(rb_intern(name)), result);
5215 }
5216 #endif
5217 
5218 size_t
5220 {
5221  return rb_objspace.profile.count;
5222 }
5223 
5224 /*
5225  * call-seq:
5226  * GC.count -> Integer
5227  *
5228  * The number of times GC occurred.
5229  *
5230  * It returns the number of times GC occurred since the process started.
5231  *
5232  */
5233 
5234 static VALUE
5236 {
5237  return SIZET2NUM(rb_gc_count());
5238 }
5239 
5240 static VALUE
5241 gc_info_decode(int flags, VALUE hash_or_key)
5242 {
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;
5247 #endif
5248  static VALUE sym_newobj, sym_malloc, sym_method, sym_capi;
5249  VALUE hash = Qnil, key = Qnil;
5250  VALUE major_by;
5251 
5252  if (SYMBOL_P(hash_or_key))
5253  key = hash_or_key;
5254  else if (RB_TYPE_P(hash_or_key, T_HASH))
5255  hash = hash_or_key;
5256  else
5257  rb_raise(rb_eTypeError, "non-hash or symbol given");
5258 
5259  if (sym_major_by == Qnil) {
5260 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
5261  S(major_by);
5262  S(gc_by);
5263  S(immediate_sweep);
5264  S(have_finalizer);
5265  S(nofree);
5266  S(oldgen);
5267  S(shady);
5268  S(rescan);
5269  S(stress);
5270 #if RGENGC_ESTIMATE_OLDMALLOC
5271  S(oldmalloc);
5272 #endif
5273  S(newobj);
5274  S(malloc);
5275  S(method);
5276  S(capi);
5277 #undef S
5278  }
5279 
5280 #define SET(name, attr) \
5281  if (key == sym_##name) \
5282  return (attr); \
5283  else if (hash != Qnil) \
5284  rb_hash_aset(hash, sym_##name, (attr));
5285 
5286  major_by =
5287  (flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
5288  (flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
5289  (flags & GPR_FLAG_MAJOR_BY_RESCAN) ? sym_rescan :
5290  (flags & GPR_FLAG_MAJOR_BY_STRESS) ? sym_stress :
5291 #if RGENGC_ESTIMATE_OLDMALLOC
5292  (flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
5293 #endif
5294  (flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
5295  Qnil;
5296  SET(major_by, major_by);
5297 
5298  SET(gc_by,
5299  (flags & GPR_FLAG_NEWOBJ) ? sym_newobj :
5300  (flags & GPR_FLAG_MALLOC) ? sym_malloc :
5301  (flags & GPR_FLAG_METHOD) ? sym_method :
5302  (flags & GPR_FLAG_CAPI) ? sym_capi :
5303  (flags & GPR_FLAG_STRESS) ? sym_stress :
5304  Qnil
5305  );
5306 
5307  SET(have_finalizer, (flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse);
5308  SET(immediate_sweep, (flags & GPR_FLAG_IMMEDIATE_SWEEP) ? Qtrue : Qfalse);
5309 #undef SET
5310 
5311  if (key != Qnil) /* matched key should return above */
5312  rb_raise(rb_eArgError, "unknown key: %s", RSTRING_PTR(rb_id2str(SYM2ID(key))));
5313 
5314  return hash;
5315 }
5316 
5317 VALUE
5319 {
5320  rb_objspace_t *objspace = &rb_objspace;
5321  return gc_info_decode(objspace->profile.latest_gc_info, key);
5322 }
5323 
5324 /*
5325  * call-seq:
5326  * GC.latest_gc_info -> {:gc_by=>:newobj}
5327  * GC.latest_gc_info(hash) -> hash
5328  * GC.latest_gc_info(:major_by) -> :malloc
5329  *
5330  * Returns information about the most recent garbage collection.
5331  */
5332 
5333 static VALUE
5335 {
5336  rb_objspace_t *objspace = &rb_objspace;
5337  VALUE arg = Qnil;
5338 
5339  if (rb_scan_args(argc, argv, "01", &arg) == 1) {
5340  if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) {
5341  rb_raise(rb_eTypeError, "non-hash or symbol given");
5342  }
5343  }
5344 
5345  if (arg == Qnil)
5346  arg = rb_hash_new();
5347 
5348  return gc_info_decode(objspace->profile.latest_gc_info, arg);
5349 }
5350 
5351 static VALUE
5352 gc_stat_internal(VALUE hash_or_sym, size_t *out)
5353 {
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;
5360 #if USE_RGENGC
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;
5366 #endif
5367 #if RGENGC_PROFILE
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;
5371 #endif /* RGENGC_PROFILE */
5372 #endif /* USE_RGENGC */
5373 
5374  rb_objspace_t *objspace = &rb_objspace;
5375  VALUE hash = Qnil, key = Qnil;
5376 
5377  if (RB_TYPE_P(hash_or_sym, T_HASH))
5378  hash = hash_or_sym;
5379  else if (SYMBOL_P(hash_or_sym) && out)
5380  key = hash_or_sym;
5381  else
5382  rb_raise(rb_eTypeError, "non-hash or symbol argument");
5383 
5384  if (sym_count == 0) {
5385 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
5386  S(count);
5387  S(heap_used);
5388  S(heap_length);
5389  S(heap_increment);
5390  S(heap_live_slot);
5391  S(heap_free_slot);
5392  S(heap_final_slot);
5393  S(heap_swept_slot);
5394  S(heap_eden_page_length);
5395  S(heap_tomb_page_length);
5396  S(total_allocated_object);
5397  S(total_freed_object);
5398  S(malloc_increase);
5399  S(malloc_limit);
5400 #if USE_RGENGC
5401  S(minor_gc_count);
5402  S(major_gc_count);
5403  S(remembered_shady_object);
5404  S(remembered_shady_object_limit);
5405  S(old_object);
5406  S(old_object_limit);
5407 #if RGENGC_ESTIMATE_OLDMALLOC
5408  S(oldmalloc_increase);
5409  S(oldmalloc_limit);
5410 #endif
5411 #if RGENGC_PROFILE
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);
5419 #endif /* USE_RGENGC */
5420 #endif /* RGENGC_PROFILE */
5421 #undef S
5422  }
5423 
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));
5429 
5430  SET(count, objspace->profile.count);
5431 
5432  /* implementation dependent counters */
5433  SET(heap_used, heap_pages_used);
5434  SET(heap_length, heap_pages_length);
5436  SET(heap_live_slot, objspace_live_slot(objspace));
5437  SET(heap_free_slot, objspace_free_slot(objspace));
5438  SET(heap_final_slot, heap_pages_final_slots);
5439  SET(heap_swept_slot, heap_pages_swept_slots);
5440  SET(heap_eden_page_length, heap_eden->page_length);
5441  SET(heap_tomb_page_length, heap_tomb->page_length);
5442  SET(total_allocated_object, objspace->profile.total_allocated_object_num);
5443  SET(total_freed_object, objspace->profile.total_freed_object_num);
5446 #if USE_RGENGC
5447  SET(minor_gc_count, objspace->profile.minor_gc_count);
5448  SET(major_gc_count, objspace->profile.major_gc_count);
5449  SET(remembered_shady_object, objspace->rgengc.remembered_shady_object_count);
5450  SET(remembered_shady_object_limit, objspace->rgengc.remembered_shady_object_limit);
5451  SET(old_object, objspace->rgengc.old_object_count);
5452  SET(old_object_limit, objspace->rgengc.old_object_limit);
5453 #if RGENGC_ESTIMATE_OLDMALLOC
5454  SET(oldmalloc_increase, objspace->rgengc.oldmalloc_increase);
5455  SET(oldmalloc_limit, objspace->rgengc.oldmalloc_increase_limit);
5456 #endif
5457 
5458 #if RGENGC_PROFILE
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);
5463 #if RGENGC_THREEGEN
5464  SET(promote_young_count, objspace->profile.promote_young_count);
5465 #endif
5466  SET(remembered_normal_object_count, objspace->profile.remembered_normal_object_count);
5467  SET(remembered_shady_object_count, objspace->profile.remembered_shady_object_count);
5468 #endif /* RGENGC_PROFILE */
5469 #endif /* USE_RGENGC */
5470 #undef SET
5471 
5472  if (key != Qnil) /* matched key should return above */
5473  rb_raise(rb_eArgError, "unknown key: %s", RSTRING_PTR(rb_id2str(SYM2ID(key))));
5474 
5475 #if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
5476  if (hash != Qnil) {
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);
5481 #if RGENGC_THREEGEN
5482  gc_count_add_each_types(hash, "promote_young_types", objspace->profile.promote_young_types);
5483 #endif
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);
5486  }
5487 #endif
5488 
5489  return hash;
5490 }
5491 
5492 /*
5493  * call-seq:
5494  * GC.stat -> Hash
5495  * GC.stat(hash) -> hash
5496  * GC.stat(:key) -> Numeric
5497  *
5498  * Returns a Hash containing information about the GC.
5499  *
5500  * The hash includes information about internal statistics about GC such as:
5501  *
5502  * {
5503  * :count=>2,
5504  * :heap_used=>9,
5505  * :heap_length=>11,
5506  * :heap_increment=>2,
5507  * :heap_live_slot=>6836,
5508  * :heap_free_slot=>519,
5509  * :heap_final_slot=>0,
5510  * :heap_swept_slot=>818,
5511  * :total_allocated_object=>7674,
5512  * :total_freed_object=>838,
5513  * :malloc_increase=>181034,
5514  * :malloc_limit=>16777216,
5515  * :minor_gc_count=>2,
5516  * :major_gc_count=>0,
5517  * :remembered_shady_object=>55,
5518  * :remembered_shady_object_limit=>0,
5519  * :old_object=>2422,
5520  * :old_object_limit=>0,
5521  * :oldmalloc_increase=>277386,
5522  * :oldmalloc_limit=>16777216
5523  * }
5524  *
5525  * The contents of the hash are implementation specific and may be changed in
5526  * the future.
5527  *
5528  * This method is only expected to work on C Ruby.
5529  *
5530  */
5531 
5532 static VALUE
5534 {
5535  VALUE arg = Qnil;
5536 
5537  if (rb_scan_args(argc, argv, "01", &arg) == 1) {
5538  if (SYMBOL_P(arg)) {
5539  size_t value = 0;
5540  gc_stat_internal(arg, &value);
5541  return SIZET2NUM(value);
5542  } else if (!RB_TYPE_P(arg, T_HASH)) {
5543  rb_raise(rb_eTypeError, "non-hash or symbol given");
5544  }
5545  }
5546 
5547  if (arg == Qnil) {
5548  arg = rb_hash_new();
5549  }
5550  gc_stat_internal(arg, 0);
5551  return arg;
5552 }
5553 
5554 size_t
5556 {
5557  if (SYMBOL_P(key)) {
5558  size_t value = 0;
5559  gc_stat_internal(key, &value);
5560  return value;
5561  } else {
5562  gc_stat_internal(key, 0);
5563  return 0;
5564  }
5565 }
5566 
5567 /*
5568  * call-seq:
5569  * GC.stress -> fixnum, true or false
5570  *
5571  * Returns current status of GC stress mode.
5572  */
5573 
5574 static VALUE
5576 {
5577  rb_objspace_t *objspace = &rb_objspace;
5578  return ruby_gc_stress;
5579 }
5580 
5581 /*
5582  * call-seq:
5583  * GC.stress = bool -> bool
5584  *
5585  * Updates the GC stress mode.
5586  *
5587  * When stress mode is enabled, the GC is invoked at every GC opportunity:
5588  * all memory and object allocations.
5589  *
5590  * Enabling stress mode will degrade performance, it is only for debugging.
5591  */
5592 
5593 static VALUE
5595 {
5596  rb_objspace_t *objspace = &rb_objspace;
5597  rb_secure(2);
5598  ruby_gc_stress = FIXNUM_P(flag) ? flag : (RTEST(flag) ? Qtrue : Qfalse);
5599  return flag;
5600 }
5601 
5602 /*
5603  * call-seq:
5604  * GC.enable -> true or false
5605  *
5606  * Enables garbage collection, returning +true+ if garbage
5607  * collection was previously disabled.
5608  *
5609  * GC.disable #=> false
5610  * GC.enable #=> true
5611  * GC.enable #=> false
5612  *
5613  */
5614 
5615 VALUE
5617 {
5618  rb_objspace_t *objspace = &rb_objspace;
5619  int old = dont_gc;
5620 
5621  dont_gc = FALSE;
5622  return old ? Qtrue : Qfalse;
5623 }
5624 
5625 /*
5626  * call-seq:
5627  * GC.disable -> true or false
5628  *
5629  * Disables garbage collection, returning +true+ if garbage
5630  * collection was already disabled.
5631  *
5632  * GC.disable #=> false
5633  * GC.disable #=> true
5634  *
5635  */
5636 
5637 VALUE
5639 {
5640  rb_objspace_t *objspace = &rb_objspace;
5641  int old = dont_gc;
5642 
5643  gc_rest_sweep(objspace);
5644 
5645  dont_gc = TRUE;
5646  return old ? Qtrue : Qfalse;
5647 }
5648 
5649 static int
5650 get_envparam_int(const char *name, unsigned int *default_value, int lower_bound)
5651 {
5652  char *ptr = getenv(name);
5653  int val;
5654 
5655  if (ptr != NULL) {
5656  val = atoi(ptr);
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;
5660  return 1;
5661  }
5662  else {
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);
5664  }
5665  }
5666  return 0;
5667 }
5668 
5669 static int
5670 get_envparam_double(const char *name, double *default_value, double lower_bound)
5671 {
5672  char *ptr = getenv(name);
5673  double val;
5674 
5675  if (ptr != NULL) {
5676  val = strtod(ptr, NULL);
5677  if (val > lower_bound) {
5678  if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (%f)\n", name, val, *default_value);
5679  *default_value = val;
5680  return 1;
5681  }
5682  else {
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);
5684  }
5685  }
5686  return 0;
5687 }
5688 
5689 static void
5691 {
5692  size_t min_pages;
5693  rb_objspace_t *objspace = &rb_objspace;
5694 
5695  min_pages = gc_params.heap_init_slots / HEAP_OBJ_LIMIT;
5696  if (min_pages > heap_eden->page_length) {
5697  heap_add_pages(objspace, heap_eden, min_pages - heap_eden->page_length);
5698  }
5699 }
5700 
5701 /*
5702  * GC tuning environment variables
5703  *
5704  * * RUBY_GC_HEAP_INIT_SLOTS
5705  * - Initial allocation slots.
5706  * * RUBY_GC_HEAP_FREE_SLOTS
5707  * - Prepare at least this ammount of slots after GC.
5708  * - Allocate slots if there are not enough slots.
5709  * * RUBY_GC_HEAP_GROWTH_FACTOR (new from 2.1)
5710  * - Allocate slots by this factor.
5711  * - (next slots number) = (current slots number) * (this factor)
5712  * * RUBY_GC_HEAP_GROWTH_MAX_SLOTS (new from 2.1)
5713  * - Allocation rate is limited to this factor.
5714  * * RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR (new from 2.1.1)
5715  * - Do full GC when the number of old objects is more than R * N
5716  * where R is this factor and
5717  * N is the number of old objects just after last full GC.
5718  *
5719  * * obsolete
5720  * * RUBY_FREE_MIN -> RUBY_GC_HEAP_FREE_SLOTS (from 2.1)
5721  * * RUBY_HEAP_MIN_SLOTS -> RUBY_GC_HEAP_INIT_SLOTS (from 2.1)
5722  *
5723  * * RUBY_GC_MALLOC_LIMIT
5724  * * RUBY_GC_MALLOC_LIMIT_MAX (new from 2.1)
5725  * * RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
5726  *
5727  * * RUBY_GC_OLDMALLOC_LIMIT (new from 2.1)
5728  * * RUBY_GC_OLDMALLOC_LIMIT_MAX (new from 2.1)
5729  * * RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
5730  */
5731 
5732 void
5733 ruby_gc_set_params(int safe_level)
5734 {
5735  if (safe_level > 0) return;
5736 
5737  /* RUBY_GC_HEAP_FREE_SLOTS */
5738  if (get_envparam_int("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) {
5739  /* ok */
5740  }
5741  else if (get_envparam_int("RUBY_FREE_MIN", &gc_params.heap_free_slots, 0)) {
5742  rb_warn("RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead.");
5743  }
5744 
5745  /* RUBY_GC_HEAP_INIT_SLOTS */
5746  if (get_envparam_int("RUBY_GC_HEAP_INIT_SLOTS", &gc_params.heap_init_slots, 0)) {
5748  }
5749  else if (get_envparam_int("RUBY_HEAP_MIN_SLOTS", &gc_params.heap_init_slots, 0)) {
5750  rb_warn("RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead.");
5752  }
5753 
5754  get_envparam_double("RUBY_GC_HEAP_GROWTH_FACTOR", &gc_params.growth_factor, 1.0);
5755  get_envparam_int ("RUBY_GC_HEAP_GROWTH_MAX_SLOTS", &gc_params.growth_max_slots, 0);
5756  get_envparam_double("RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR", &gc_params.oldobject_limit_factor, 0.0);
5757 
5758  get_envparam_int("RUBY_GC_MALLOC_LIMIT", &gc_params.malloc_limit_min, 0);
5759  get_envparam_int("RUBY_GC_MALLOC_LIMIT_MAX", &gc_params.malloc_limit_max, 0);
5760  get_envparam_double("RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR", &gc_params.malloc_limit_growth_factor, 1.0);
5761 
5762 #if RGENGC_ESTIMATE_OLDMALLOC
5763  if (get_envparam_int("RUBY_GC_OLDMALLOC_LIMIT", &gc_params.oldmalloc_limit_min, 0)) {
5764  rb_objspace_t *objspace = &rb_objspace;
5765  objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
5766  }
5767  get_envparam_int("RUBY_GC_OLDMALLOC_LIMIT_MAX", &gc_params.oldmalloc_limit_max, 0);
5768  get_envparam_double("RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR", &gc_params.oldmalloc_limit_growth_factor, 1.0);
5769 #endif
5770 }
5771 
5772 void
5774 {
5776 }
5777 
5778 void
5779 rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data)
5780 {
5781  rb_objspace_t *objspace = &rb_objspace;
5782 
5783  if (is_markable_object(objspace, obj)) {
5784  struct mark_func_data_struct mfd;
5785  mfd.mark_func = func;
5786  mfd.data = data;
5787  objspace->mark_func_data = &mfd;
5788  gc_mark_children(objspace, obj);
5789  objspace->mark_func_data = 0;
5790  }
5791 }
5792 
5794  const char *category;
5795  void (*func)(const char *category, VALUE, void *);
5796  void *data;
5797 };
5798 
5799 static void
5800 root_objects_from(VALUE obj, void *ptr)
5801 {
5802  const struct root_objects_data *data = (struct root_objects_data *)ptr;
5803  (*data->func)(data->category, obj, data->data);
5804 }
5805 
5806 void
5807 rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data)
5808 {
5809  rb_objspace_t *objspace = &rb_objspace;
5810  struct root_objects_data data;
5811  struct mark_func_data_struct mfd;
5812 
5813  data.func = func;
5814  data.data = passing_data;
5815 
5816  mfd.mark_func = root_objects_from;
5817  mfd.data = &data;
5818 
5819  objspace->mark_func_data = &mfd;
5820  {
5821  gc_mark_roots(objspace, TRUE, &data.category);
5822  }
5823  objspace->mark_func_data = 0;
5824 }
5825 
5826 /*
5827  ------------------------ Extended allocator ------------------------
5828 */
5829 
5830 static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size);
5831 
5832 static void *
5834 {
5835  rb_raise(rb_eNoMemError, "%s", (const char *)ptr);
5836  return 0; /* should not be reached */
5837 }
5838 
5839 static void
5841 {
5842  if (ruby_thread_has_gvl_p()) {
5843  rb_raise(rb_eNoMemError, "%s", msg);
5844  }
5845  else {
5846  if (ruby_native_thread_p()) {
5848  }
5849  else {
5850  fprintf(stderr, "[FATAL] %s\n", msg);
5851  exit(EXIT_FAILURE);
5852  }
5853  }
5854 }
5855 
5856 static void *
5858 {
5859  rb_memerror();
5860  return 0;
5861 }
5862 
5863 static void
5865 {
5866  if (ruby_thread_has_gvl_p()) {
5867  rb_memerror();
5868  }
5869  else {
5870  if (ruby_native_thread_p()) {
5872  }
5873  else {
5874  /* no ruby thread */
5875  fprintf(stderr, "[FATAL] failed to allocate memory\n");
5876  exit(EXIT_FAILURE);
5877  }
5878  }
5879 }
5880 
5881 void
5883 {
5884  rb_thread_t *th = GET_THREAD();
5885  if (!nomem_error ||
5887  fprintf(stderr, "[FATAL] failed to allocate memory\n");
5888  exit(EXIT_FAILURE);
5889  }
5894  }
5897 }
5898 
5899 static void *
5900 aligned_malloc(size_t alignment, size_t size)
5901 {
5902  void *res;
5903 
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) {
5911  return res;
5912  }
5913  else {
5914  return NULL;
5915  }
5916 #elif defined(HAVE_MEMALIGN)
5917  res = memalign(alignment, size);
5918 #else
5919  char* aligned;
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;
5925 #endif
5926 
5927 #if defined(_DEBUG) || GC_DEBUG
5928  /* alignment must be a power of 2 */
5929  assert(((alignment - 1) & alignment) == 0);
5930  assert(alignment % sizeof(void*) == 0);
5931 #endif
5932  return res;
5933 }
5934 
5935 static void
5936 aligned_free(void *ptr)
5937 {
5938 #if defined __MINGW32__
5939  __mingw_aligned_free(ptr);
5940 #elif defined _WIN32 && !defined __CYGWIN__
5941  _aligned_free(ptr);
5942 #elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)
5943  free(ptr);
5944 #else
5945  free(((void**)ptr)[-1]);
5946 #endif
5947 }
5948 
5949 static inline size_t
5950 objspace_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint)
5951 {
5952 #ifdef HAVE_MALLOC_USABLE_SIZE
5953  return malloc_usable_size(ptr);
5954 #else
5955  return hint;
5956 #endif
5957 }
5958 
5963 };
5964 
5965 static inline void
5966 atomic_sub_nounderflow(size_t *var, size_t sub)
5967 {
5968  if (sub == 0) return;
5969 
5970  while (1) {
5971  size_t val = *var;
5972  if (val < sub) sub = val;
5973  if (ATOMIC_SIZE_CAS(*var, val, val-sub) == val) break;
5974  }
5975 }
5976 
5977 static void
5978 objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
5979 {
5980  if (new_size > old_size) {
5981  ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size);
5982 #if RGENGC_ESTIMATE_OLDMALLOC
5983  ATOMIC_SIZE_ADD(objspace->rgengc.oldmalloc_increase, new_size - old_size);
5984 #endif
5985  }
5986  else {
5987  atomic_sub_nounderflow(&malloc_increase, old_size - new_size);
5988 #if RGENGC_ESTIMATE_OLDMALLOC
5989  atomic_sub_nounderflow(&objspace->rgengc.oldmalloc_increase, old_size - new_size);
5990 #endif
5991  }
5992 
5993  if (type == MEMOP_TYPE_MALLOC) {
5994  if (ruby_gc_stress && !ruby_disable_gc_stress) {
5996  }
5997  else {
5998  retry:
5999  if (malloc_increase > malloc_limit) {
6001  gc_rest_sweep(objspace); /* rest_sweep can reduce malloc_increase */
6002  goto retry;
6003  }
6005  }
6006  }
6007  }
6008 
6009 #if MALLOC_ALLOCATED_SIZE
6010  if (new_size >= old_size) {
6011  ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size);
6012  }
6013  else {
6014  size_t dec_size = old_size - new_size;
6015  size_t allocated_size = objspace->malloc_params.allocated_size;
6016 
6017 #if MALLOC_ALLOCATED_SIZE_CHECK
6018  if (allocated_size < dec_size) {
6019  rb_bug("objspace_malloc_increase: underflow malloc_params.allocated_size.");
6020  }
6021 #endif
6022  atomic_sub_nounderflow(objspace->malloc_params.allocated_size, dec_size);
6023  }
6024 
6025  if (0) fprintf(stderr, "incraese - ptr: %p, type: %s, new_size: %d, old_size: %d\n",
6026  mem,
6027  type == MEMOP_TYPE_MALLOC ? "malloc" :
6028  type == MEMOP_TYPE_FREE ? "free " :
6029  type == MEMOP_TYPE_REALLOC ? "realloc": "error",
6030  (int)new_size, (int)old_size);
6031 
6032  switch (type) {
6033  case MEMOP_TYPE_MALLOC:
6034  ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
6035  break;
6036  case MEMOP_TYPE_FREE:
6037  {
6038  size_t allocations = objspace->malloc_params.allocations;
6039  if (allocations > 0) {
6040  atomic_sub_nounderflow(objspace->malloc_params.allocations, 1);
6041  }
6042 #if MALLOC_ALLOCATED_SIZE_CHECK
6043  else {
6044  assert(objspace->malloc_params.allocations > 0);
6045  }
6046 #endif
6047  }
6048  break;
6049  case MEMOP_TYPE_REALLOC: /* ignore */ break;
6050  }
6051 #endif
6052 }
6053 
6054 static inline size_t
6056 {
6057  if ((ssize_t)size < 0) {
6058  negative_size_allocation_error("negative allocation size (or too big)");
6059  }
6060  if (size == 0) size = 1;
6061 
6062 #if CALC_EXACT_MALLOC_SIZE
6063  size += sizeof(size_t);
6064 #endif
6065 
6066  return size;
6067 }
6068 
6069 static inline void *
6070 objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
6071 {
6072 #if CALC_EXACT_MALLOC_SIZE
6073  ((size_t *)mem)[0] = size;
6074  mem = (size_t *)mem + 1;
6075 #endif
6076 
6077  return mem;
6078 }
6079 
6080 #define TRY_WITH_GC(alloc) do { \
6081  if (!(alloc) && \
6082  (!garbage_collect_with_gvl(objspace, 1, 1, GPR_FLAG_MALLOC) || /* full mark && immediate sweep */ \
6083  !(alloc))) { \
6084  ruby_memerror(); \
6085  } \
6086  } while (0)
6087 
6088 static void *
6090 {
6091  void *mem;
6092 
6093  size = objspace_malloc_prepare(objspace, size);
6094  TRY_WITH_GC(mem = malloc(size));
6095  size = objspace_malloc_size(objspace, mem, size);
6096  objspace_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC);
6097  return objspace_malloc_fixup(objspace, mem, size);
6098 }
6099 
6100 static void *
6101 objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size)
6102 {
6103  void *mem;
6104 
6105  if ((ssize_t)new_size < 0) {
6106  negative_size_allocation_error("negative re-allocation size");
6107  }
6108 
6109  if (!ptr) return objspace_xmalloc(objspace, new_size);
6110 
6111  /*
6112  * The behavior of realloc(ptr, 0) is implementation defined.
6113  * Therefore we don't use realloc(ptr, 0) for portability reason.
6114  * see http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm
6115  */
6116  if (new_size == 0) {
6117  objspace_xfree(objspace, ptr, old_size);
6118  return 0;
6119  }
6120 
6121 #if CALC_EXACT_MALLOC_SIZE
6122  new_size += sizeof(size_t);
6123  ptr = (size_t *)ptr - 1;
6124  oldsize = ((size_t *)ptr)[0];
6125 #endif
6126 
6127  old_size = objspace_malloc_size(objspace, ptr, old_size);
6128  TRY_WITH_GC(mem = realloc(ptr, new_size));
6129  new_size = objspace_malloc_size(objspace, mem, new_size);
6130 
6131 #if CALC_EXACT_MALLOC_SIZE
6132  ((size_t *)mem)[0] = new_size;
6133  mem = (size_t *)mem + 1;
6134 #endif
6135 
6136  objspace_malloc_increase(objspace, mem, new_size, old_size, MEMOP_TYPE_REALLOC);
6137 
6138  return mem;
6139 }
6140 
6141 static void
6142 objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size)
6143 {
6144 #if CALC_EXACT_MALLOC_SIZE
6145  ptr = ((size_t *)ptr) - 1;
6146  oldsize = ((size_t*)ptr)[0];
6147 #endif
6148  old_size = objspace_malloc_size(objspace, ptr, old_size);
6149 
6150  free(ptr);
6151 
6152  objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE);
6153 }
6154 
6155 void *
6157 {
6158  return objspace_xmalloc(&rb_objspace, size);
6159 }
6160 
6161 static inline size_t
6162 xmalloc2_size(size_t n, size_t size)
6163 {
6164  size_t len = size * n;
6165  if (n != 0 && size != len / n) {
6166  rb_raise(rb_eArgError, "malloc: possible integer overflow");
6167  }
6168  return len;
6169 }
6170 
6171 void *
6172 ruby_xmalloc2(size_t n, size_t size)
6173 {
6174  return objspace_xmalloc(&rb_objspace, xmalloc2_size(n, size));
6175 }
6176 
6177 static void *
6178 objspace_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
6179 {
6180  void *mem;
6181  size_t size;
6182 
6183  size = xmalloc2_size(count, elsize);
6184  size = objspace_malloc_prepare(objspace, size);
6185 
6186  TRY_WITH_GC(mem = calloc(1, size));
6187  return objspace_malloc_fixup(objspace, mem, size);
6188 }
6189 
6190 void *
6191 ruby_xcalloc(size_t n, size_t size)
6192 {
6193  return objspace_xcalloc(&rb_objspace, n, size);
6194 }
6195 
6196 #ifdef ruby_sized_xrealloc
6197 #undef ruby_sized_xrealloc
6198 #endif
6199 void *
6200 ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
6201 {
6202  return objspace_xrealloc(&rb_objspace, ptr, new_size, old_size);
6203 }
6204 
6205 void *
6206 ruby_xrealloc(void *ptr, size_t new_size)
6207 {
6208  return ruby_sized_xrealloc(ptr, new_size, 0);
6209 }
6210 
6211 #ifdef ruby_sized_xrealloc2
6212 #undef ruby_sized_xrealloc2
6213 #endif
6214 void *
6215 ruby_sized_xrealloc2(void *ptr, size_t n, size_t size, size_t old_n)
6216 {
6217  size_t len = size * n;
6218  if (n != 0 && size != len / n) {
6219  rb_raise(rb_eArgError, "realloc: possible integer overflow");
6220  }
6221  return objspace_xrealloc(&rb_objspace, ptr, len, old_n * size);
6222 }
6223 
6224 void *
6225 ruby_xrealloc2(void *ptr, size_t n, size_t size)
6226 {
6227  return ruby_sized_xrealloc2(ptr, n, size, 0);
6228 }
6229 
6230 #ifdef ruby_sized_xfree
6231 #undef ruby_sized_xfree
6232 #endif
6233 void
6234 ruby_sized_xfree(void *x, size_t size)
6235 {
6236  if (x) {
6237  objspace_xfree(&rb_objspace, x, size);
6238  }
6239 }
6240 
6241 void
6242 ruby_xfree(void *x)
6243 {
6244  ruby_sized_xfree(x, 0);
6245 }
6246 
6247 /* Mimic ruby_xmalloc, but need not rb_objspace.
6248  * should return pointer suitable for ruby_xfree
6249  */
6250 void *
6252 {
6253  void *mem;
6254 #if CALC_EXACT_MALLOC_SIZE
6255  size += sizeof(size_t);
6256 #endif
6257  mem = malloc(size);
6258 #if CALC_EXACT_MALLOC_SIZE
6259  /* set 0 for consistency of allocated_size/allocations */
6260  ((size_t *)mem)[0] = 0;
6261  mem = (size_t *)mem + 1;
6262 #endif
6263  return mem;
6264 }
6265 
6266 void
6267 ruby_mimfree(void *ptr)
6268 {
6269  size_t *mem = (size_t *)ptr;
6270 #if CALC_EXACT_MALLOC_SIZE
6271  mem = mem - 1;
6272 #endif
6273  free(mem);
6274 }
6275 
6276 #if MALLOC_ALLOCATED_SIZE
6277 /*
6278  * call-seq:
6279  * GC.malloc_allocated_size -> Integer
6280  *
6281  * Returns the size of memory allocated by malloc().
6282  *
6283  * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
6284  */
6285 
6286 static VALUE
6287 gc_malloc_allocated_size(VALUE self)
6288 {
6289  return UINT2NUM(rb_objspace.malloc_params.allocated_size);
6290 }
6291 
6292 /*
6293  * call-seq:
6294  * GC.malloc_allocations -> Integer
6295  *
6296  * Returns the number of malloc() allocations.
6297  *
6298  * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
6299  */
6300 
6301 static VALUE
6302 gc_malloc_allocations(VALUE self)
6303 {
6304  return UINT2NUM(rb_objspace.malloc_params.allocations);
6305 }
6306 #endif
6307 
6308 /*
6309  ------------------------------ WeakMap ------------------------------
6310 */
6311 
6312 struct weakmap {
6313  st_table *obj2wmap; /* obj -> [ref,...] */
6314  st_table *wmap2obj; /* ref -> obj */
6315  VALUE final;
6316 };
6317 
6318 #define WMAP_DELETE_DEAD_OBJECT_IN_MARK 0
6319 
6320 #if WMAP_DELETE_DEAD_OBJECT_IN_MARK
6321 static int
6322 wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
6323 {
6324  rb_objspace_t *objspace = (rb_objspace_t *)arg;
6325  VALUE obj = (VALUE)val;
6326  if (!is_live_object(objspace, obj)) return ST_DELETE;
6327  return ST_CONTINUE;
6328 }
6329 #endif
6330 
6331 static void
6332 wmap_mark(void *ptr)
6333 {
6334  struct weakmap *w = ptr;
6335 #if WMAP_DELETE_DEAD_OBJECT_IN_MARK
6336  if (w->obj2wmap) st_foreach(w->obj2wmap, wmap_mark_map, (st_data_t)&rb_objspace);
6337 #endif
6338  rb_gc_mark(w->final);
6339 }
6340 
6341 static int
6343 {
6344  VALUE *ptr = (VALUE *)val;
6345  ruby_sized_xfree(ptr, (ptr[0] + 1) * sizeof(VALUE));
6346  return ST_CONTINUE;
6347 }
6348 
6349 static void
6350 wmap_free(void *ptr)
6351 {
6352  struct weakmap *w = ptr;
6354  st_free_table(w->obj2wmap);
6355  st_free_table(w->wmap2obj);
6356 }
6357 
6358 static int
6360 {
6361  VALUE *ptr = (VALUE *)val;
6362  *(size_t *)arg += (ptr[0] + 1) * sizeof(VALUE);
6363  return ST_CONTINUE;
6364 }
6365 
6366 static size_t
6367 wmap_memsize(const void *ptr)
6368 {
6369  size_t size;
6370  const struct weakmap *w = ptr;
6371  if (!w) return 0;
6372  size = sizeof(*w);
6373  size += st_memsize(w->obj2wmap);
6374  size += st_memsize(w->wmap2obj);
6376  return size;
6377 }
6378 
6380  "weakmap",
6381  {
6382  wmap_mark,
6383  wmap_free,
6384  wmap_memsize,
6385  },
6387 };
6388 
6389 static VALUE
6391 {
6392  struct weakmap *w;
6393  VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &weakmap_type, w);
6394  w->obj2wmap = st_init_numtable();
6395  w->wmap2obj = st_init_numtable();
6396  w->final = rb_obj_method(obj, ID2SYM(rb_intern("finalize")));
6397  return obj;
6398 }
6399 
6400 static int
6401 wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
6402 {
6403  VALUE wmap, *ptr, size, i, j;
6404  if (!existing) return ST_STOP;
6405  wmap = (VALUE)arg, ptr = (VALUE *)*value;
6406  for (i = j = 1, size = ptr[0]; i <= size; ++i) {
6407  if (ptr[i] != wmap) {
6408  ptr[j++] = ptr[i];
6409  }
6410  }
6411  if (j == 1) {
6412  ruby_sized_xfree(ptr, i * sizeof(VALUE));
6413  return ST_DELETE;
6414  }
6415  if (j < i) {
6416  ptr = ruby_sized_xrealloc2(ptr, j, sizeof(VALUE), i);
6417  ptr[0] = j;
6418  *value = (st_data_t)ptr;
6419  }
6420  return ST_CONTINUE;
6421 }
6422 
6423 static VALUE
6425 {
6426  st_data_t orig, wmap, data;
6427  VALUE obj, *rids, i, size;
6428  struct weakmap *w;
6429 
6430  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6431  /* Get reference from object id. */
6432  obj = obj_id_to_ref(objid);
6433 
6434  /* obj is original referenced object and/or weak reference. */
6435  orig = (st_data_t)obj;
6436  if (st_delete(w->obj2wmap, &orig, &data)) {
6437  rids = (VALUE *)data;
6438  size = *rids++;
6439  for (i = 0; i < size; ++i) {
6440  wmap = (st_data_t)rids[i];
6441  st_delete(w->wmap2obj, &wmap, NULL);
6442  }
6443  ruby_sized_xfree((VALUE *)data, (size + 1) * sizeof(VALUE));
6444  }
6445 
6446  wmap = (st_data_t)obj;
6447  if (st_delete(w->wmap2obj, &wmap, &orig)) {
6448  wmap = (st_data_t)obj;
6449  st_update(w->obj2wmap, orig, wmap_final_func, wmap);
6450  }
6451  return self;
6452 }
6453 
6457 };
6458 
6459 static int
6461 {
6462  VALUE str = (VALUE)arg;
6463  VALUE k = (VALUE)key, v = (VALUE)val;
6464 
6465  if (RSTRING_PTR(str)[0] == '#') {
6466  rb_str_cat2(str, ", ");
6467  }
6468  else {
6469  rb_str_cat2(str, ": ");
6470  RSTRING_PTR(str)[0] = '#';
6471  }
6472  k = SPECIAL_CONST_P(k) ? rb_inspect(k) : rb_any_to_s(k);
6473  rb_str_append(str, k);
6474  rb_str_cat2(str, " => ");
6475  v = SPECIAL_CONST_P(v) ? rb_inspect(v) : rb_any_to_s(v);
6476  rb_str_append(str, v);
6477  OBJ_INFECT(str, k);
6478  OBJ_INFECT(str, v);
6479 
6480  return ST_CONTINUE;
6481 }
6482 
6483 static VALUE
6485 {
6486  VALUE str;
6487  VALUE c = rb_class_name(CLASS_OF(self));
6488  struct weakmap *w;
6489 
6490  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6491  str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self);
6492  if (w->wmap2obj) {
6494  }
6495  RSTRING_PTR(str)[0] = '#';
6496  rb_str_cat2(str, ">");
6497  return str;
6498 }
6499 
6500 static int
6502 {
6503  rb_objspace_t *objspace = (rb_objspace_t *)arg;
6504  VALUE obj = (VALUE)val;
6505  if (is_id_value(objspace, obj) && is_live_object(objspace, obj)) {
6506  rb_yield_values(2, (VALUE)key, obj);
6507  }
6508  return ST_CONTINUE;
6509 }
6510 
6511 /* Iterates over keys and objects in a weakly referenced object */
6512 static VALUE
6514 {
6515  struct weakmap *w;
6516  rb_objspace_t *objspace = &rb_objspace;
6517 
6518  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6519  st_foreach(w->wmap2obj, wmap_each_i, (st_data_t)objspace);
6520  return self;
6521 }
6522 
6523 static int
6525 {
6526  rb_objspace_t *objspace = (rb_objspace_t *)arg;
6527  VALUE obj = (VALUE)val;
6528  if (is_id_value(objspace, obj) && is_live_object(objspace, obj)) {
6529  rb_yield((VALUE)key);
6530  }
6531  return ST_CONTINUE;
6532 }
6533 
6534 /* Iterates over keys and objects in a weakly referenced object */
6535 static VALUE
6537 {
6538  struct weakmap *w;
6539  rb_objspace_t *objspace = &rb_objspace;
6540 
6541  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6542  st_foreach(w->wmap2obj, wmap_each_key_i, (st_data_t)objspace);
6543  return self;
6544 }
6545 
6546 static int
6548 {
6549  rb_objspace_t *objspace = (rb_objspace_t *)arg;
6550  VALUE obj = (VALUE)val;
6551  if (is_id_value(objspace, obj) && is_live_object(objspace, obj)) {
6552  rb_yield(obj);
6553  }
6554  return ST_CONTINUE;
6555 }
6556 
6557 /* Iterates over keys and objects in a weakly referenced object */
6558 static VALUE
6560 {
6561  struct weakmap *w;
6562  rb_objspace_t *objspace = &rb_objspace;
6563 
6564  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6566  return self;
6567 }
6568 
6569 static int
6571 {
6572  struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
6573  rb_objspace_t *objspace = argp->objspace;
6574  VALUE ary = argp->value;
6575  VALUE obj = (VALUE)val;
6576  if (is_id_value(objspace, obj) && is_live_object(objspace, obj)) {
6577  rb_ary_push(ary, (VALUE)key);
6578  }
6579  return ST_CONTINUE;
6580 }
6581 
6582 /* Iterates over keys and objects in a weakly referenced object */
6583 static VALUE
6585 {
6586  struct weakmap *w;
6587  struct wmap_iter_arg args;
6588 
6589  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6590  args.objspace = &rb_objspace;
6591  args.value = rb_ary_new();
6593  return args.value;
6594 }
6595 
6596 static int
6598 {
6599  struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
6600  rb_objspace_t *objspace = argp->objspace;
6601  VALUE ary = argp->value;
6602  VALUE obj = (VALUE)val;
6603  if (is_id_value(objspace, obj) && is_live_object(objspace, obj)) {
6604  rb_ary_push(ary, obj);
6605  }
6606  return ST_CONTINUE;
6607 }
6608 
6609 /* Iterates over values and objects in a weakly referenced object */
6610 static VALUE
6612 {
6613  struct weakmap *w;
6614  struct wmap_iter_arg args;
6615 
6616  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6617  args.objspace = &rb_objspace;
6618  args.value = rb_ary_new();
6620  return args.value;
6621 }
6622 
6623 static int
6625 {
6626  VALUE size, *ptr, *optr;
6627  if (existing) {
6628  size = (ptr = optr = (VALUE *)*val)[0];
6629  ++size;
6630  ptr = ruby_sized_xrealloc2(ptr, size + 1, sizeof(VALUE), size);
6631  }
6632  else {
6633  optr = 0;
6634  size = 1;
6635  ptr = ruby_xmalloc2(2, sizeof(VALUE));
6636  }
6637  ptr[0] = size;
6638  ptr[size] = (VALUE)arg;
6639  if (ptr == optr) return ST_STOP;
6640  *val = (st_data_t)ptr;
6641  return ST_CONTINUE;
6642 }
6643 
6644 /* Creates a weak reference from the given key to the given value */
6645 static VALUE
6646 wmap_aset(VALUE self, VALUE wmap, VALUE orig)
6647 {
6648  struct weakmap *w;
6649 
6650  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6651  should_be_finalizable(orig);
6652  should_be_finalizable(wmap);
6653  define_final0(orig, w->final);
6654  define_final0(wmap, w->final);
6655  st_update(w->obj2wmap, (st_data_t)orig, wmap_aset_update, wmap);
6656  st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
6657  return nonspecial_obj_id(orig);
6658 }
6659 
6660 /* Retrieves a weakly referenced object with the given key */
6661 static VALUE
6662 wmap_aref(VALUE self, VALUE wmap)
6663 {
6664  st_data_t data;
6665  VALUE obj;
6666  struct weakmap *w;
6667  rb_objspace_t *objspace = &rb_objspace;
6668 
6669  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6670  if (!st_lookup(w->wmap2obj, (st_data_t)wmap, &data)) return Qnil;
6671  obj = (VALUE)data;
6672  if (!is_id_value(objspace, obj)) return Qnil;
6673  if (!is_live_object(objspace, obj)) return Qnil;
6674  return obj;
6675 }
6676 
6677 /* Returns +true+ if +key+ is registered */
6678 static VALUE
6680 {
6681  return NIL_P(wmap_aref(self, key)) ? Qfalse : Qtrue;
6682 }
6683 
6684 static VALUE
6686 {
6687  struct weakmap *w;
6688  st_index_t n;
6689 
6690  TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
6691  n = w->wmap2obj->num_entries;
6692 #if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
6693  return ULONG2NUM(n);
6694 #else
6695  return ULL2NUM(n);
6696 #endif
6697 }
6698 
6699 /*
6700  ------------------------------ GC profiler ------------------------------
6701 */
6702 
6703 #define GC_PROFILE_RECORD_DEFAULT_SIZE 100
6704 
6705 static double
6707 {
6708 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
6709  {
6710  static int try_clock_gettime = 1;
6711  struct timespec ts;
6712  if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
6713  return ts.tv_sec + ts.tv_nsec * 1e-9;
6714  }
6715  else {
6716  try_clock_gettime = 0;
6717  }
6718  }
6719 #endif
6720 
6721 #ifdef RUSAGE_SELF
6722  {
6723  struct rusage usage;
6724  struct timeval time;
6725  if (getrusage(RUSAGE_SELF, &usage) == 0) {
6726  time = usage.ru_utime;
6727  return time.tv_sec + time.tv_usec * 1e-6;
6728  }
6729  }
6730 #endif
6731 
6732 #ifdef _WIN32
6733  {
6734  FILETIME creation_time, exit_time, kernel_time, user_time;
6735  ULARGE_INTEGER ui;
6736  LONG_LONG q;
6737  double t;
6738 
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;
6744  q /= 1000000L;
6745 #ifdef __GNUC__
6746  t += q;
6747 #else
6748  t += (double)(DWORD)(q >> 16) * (1 << 16);
6749  t += (DWORD)q & ~(~0 << 16);
6750 #endif
6751  return t;
6752  }
6753  }
6754 #endif
6755 
6756  return 0.0;
6757 }
6758 
6759 static inline void
6761 {
6762  if (objspace->profile.run) {
6763  size_t index = objspace->profile.next_index;
6764  gc_profile_record *record;
6765 
6766  /* create new record */
6767  objspace->profile.next_index++;
6768 
6769  if (!objspace->profile.records) {
6771  objspace->profile.records = malloc(sizeof(gc_profile_record) * objspace->profile.size);
6772  }
6773  if (index >= objspace->profile.size) {
6774  objspace->profile.size += 1000;
6775  objspace->profile.records = realloc(objspace->profile.records, sizeof(gc_profile_record) * objspace->profile.size);
6776  }
6777  if (!objspace->profile.records) {
6778  rb_bug("gc_profile malloc or realloc miss");
6779  }
6780  record = objspace->profile.current_record = &objspace->profile.records[objspace->profile.next_index - 1];
6781  MEMZERO(record, gc_profile_record, 1);
6782 
6783  /* setup before-GC parameter */
6784  record->flags = reason | ((ruby_gc_stress && !ruby_disable_gc_stress) ? GPR_FLAG_STRESS : 0);
6785 #if MALLOC_ALLOCATED_SIZE
6786  record->allocated_size = malloc_allocated_size;
6787 #endif
6788 #if GC_PROFILE_DETAIL_MEMORY
6789 #ifdef RUSAGE_SELF
6790  {
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;
6796  }
6797  }
6798 #endif
6799 #endif
6800  }
6801 }
6802 
6803 static inline void
6805 {
6806  if (gc_prof_enabled(objspace)) {
6807  gc_profile_record *record = gc_prof_record(objspace);
6808 #if GC_PROFILE_MORE_DETAIL
6809  record->prepare_time = objspace->profile.prepare_time;
6810 #endif
6811  record->gc_time = 0;
6812  record->gc_invoke_time = getrusage_time();
6813  }
6814 }
6815 
6816 static double
6817 elapsed_time_from(double time)
6818 {
6819  double now = getrusage_time();
6820  if (now > time) {
6821  return now - time;
6822  }
6823  else {
6824  return 0;
6825  }
6826 }
6827 
6828 static inline void
6830 {
6831  if (gc_prof_enabled(objspace)) {
6832  gc_profile_record *record = gc_prof_record(objspace);
6833  record->gc_time = elapsed_time_from(record->gc_invoke_time);
6834  record->gc_invoke_time -= objspace->profile.invoke_time;
6835  }
6836 }
6837 
6838 static inline void
6840 {
6843  }
6844 #if GC_PROFILE_MORE_DETAIL
6845  if (gc_prof_enabled(objspace)) {
6846  gc_prof_record(objspace)->gc_mark_time = getrusage_time();
6847  }
6848 #endif
6849 }
6850 
6851 static inline void
6853 {
6856  }
6857 #if GC_PROFILE_MORE_DETAIL
6858  if (gc_prof_enabled(objspace)) {
6859  gc_profile_record *record = gc_prof_record(objspace);
6860  record->gc_mark_time = elapsed_time_from(record->gc_mark_time);
6861  }
6862 #endif
6863 }
6864 
6865 static inline void
6867 {
6870  }
6871  if (gc_prof_enabled(objspace)) {
6872  gc_profile_record *record = gc_prof_record(objspace);
6873 
6874  if (record->gc_time > 0 || GC_PROFILE_MORE_DETAIL) {
6876  }
6877  }
6878 }
6879 
6880 static inline void
6882 {
6885  }
6886 
6887  if (gc_prof_enabled(objspace)) {
6888  double sweep_time;
6889  gc_profile_record *record = gc_prof_record(objspace);
6890 
6891  if (record->gc_time > 0) {
6892  sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
6893  /* need to accumulate GC time for lazy sweep after gc() */
6894  record->gc_time += sweep_time;
6895  }
6896  else if (GC_PROFILE_MORE_DETAIL) {
6897  sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
6898  }
6899 
6900 #if GC_PROFILE_MORE_DETAIL
6901  record->gc_sweep_time += sweep_time;
6903 #endif
6905  }
6906 }
6907 
6908 static inline void
6910 {
6911 #if GC_PROFILE_MORE_DETAIL
6912  if (gc_prof_enabled(objspace)) {
6913  gc_profile_record *record = gc_prof_record(objspace);
6914  record->allocate_increase = malloc_increase;
6915  record->allocate_limit = malloc_limit;
6916  }
6917 #endif
6918 }
6919 
6920 static inline void
6922 {
6923  if (gc_prof_enabled(objspace)) {
6924  gc_profile_record *record = gc_prof_record(objspace);
6926  size_t total = objspace->profile.heap_used_at_gc_start * HEAP_OBJ_LIMIT;
6927 
6928 #if GC_PROFILE_MORE_DETAIL
6929  record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
6930  record->heap_live_objects = live;
6931  record->heap_free_objects = total - live;
6932 #endif
6933 
6934  record->heap_total_objects = total;
6935  record->heap_use_size = live * sizeof(RVALUE);
6936  record->heap_total_size = total * sizeof(RVALUE);
6937  }
6938 }
6939 
6940 /*
6941  * call-seq:
6942  * GC::Profiler.clear -> nil
6943  *
6944  * Clears the GC profiler data.
6945  *
6946  */
6947 
6948 static VALUE
6950 {
6951  rb_objspace_t *objspace = &rb_objspace;
6952  if (GC_PROFILE_RECORD_DEFAULT_SIZE * 2 < objspace->profile.size) {
6954  objspace->profile.records = realloc(objspace->profile.records, sizeof(gc_profile_record) * objspace->profile.size);
6955  if (!objspace->profile.records) {
6956  rb_memerror();
6957  }
6958  }
6959  MEMZERO(objspace->profile.records, gc_profile_record, objspace->profile.size);
6960  objspace->profile.next_index = 0;
6961  objspace->profile.current_record = 0;
6962  return Qnil;
6963 }
6964 
6965 /*
6966  * call-seq:
6967  * GC::Profiler.raw_data -> [Hash, ...]
6968  *
6969  * Returns an Array of individual raw profile data Hashes ordered
6970  * from earliest to latest by +:GC_INVOKE_TIME+.
6971  *
6972  * For example:
6973  *
6974  * [
6975  * {
6976  * :GC_TIME=>1.3000000000000858e-05,
6977  * :GC_INVOKE_TIME=>0.010634999999999999,
6978  * :HEAP_USE_SIZE=>289640,
6979  * :HEAP_TOTAL_SIZE=>588960,
6980  * :HEAP_TOTAL_OBJECTS=>14724,
6981  * :GC_IS_MARKED=>false
6982  * },
6983  * # ...
6984  * ]
6985  *
6986  * The keys mean:
6987  *
6988  * +:GC_TIME+::
6989  * Time elapsed in seconds for this GC run
6990  * +:GC_INVOKE_TIME+::
6991  * Time elapsed in seconds from startup to when the GC was invoked
6992  * +:HEAP_USE_SIZE+::
6993  * Total bytes of heap used
6994  * +:HEAP_TOTAL_SIZE+::
6995  * Total size of heap in bytes
6996  * +:HEAP_TOTAL_OBJECTS+::
6997  * Total number of objects
6998  * +:GC_IS_MARKED+::
6999  * Returns +true+ if the GC is in mark phase
7000  *
7001  * If ruby was built with +GC_PROFILE_MORE_DETAIL+, you will also have access
7002  * to the following hash keys:
7003  *
7004  * +:GC_MARK_TIME+::
7005  * +:GC_SWEEP_TIME+::
7006  * +:ALLOCATE_INCREASE+::
7007  * +:ALLOCATE_LIMIT+::
7008  * +:HEAP_USE_PAGES+::
7009  * +:HEAP_LIVE_OBJECTS+::
7010  * +:HEAP_FREE_OBJECTS+::
7011  * +:HAVE_FINALIZE+::
7012  *
7013  */
7014 
7015 static VALUE
7017 {
7018  VALUE prof;
7019  VALUE gc_profile = rb_ary_new();
7020  size_t i;
7021  rb_objspace_t *objspace = (&rb_objspace);
7022 
7023  if (!objspace->profile.run) {
7024  return Qnil;
7025  }
7026 
7027  for (i =0; i < objspace->profile.next_index; i++) {
7028  gc_profile_record *record = &objspace->profile.records[i];
7029 
7030  prof = rb_hash_new();
7031  rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(record->flags, rb_hash_new()));
7032  rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(record->gc_time));
7033  rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(record->gc_invoke_time));
7034  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(record->heap_use_size));
7035  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), SIZET2NUM(record->heap_total_size));
7036  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), SIZET2NUM(record->heap_total_objects));
7037  rb_hash_aset(prof, ID2SYM(rb_intern("GC_IS_MARKED")), Qtrue);
7038 #if GC_PROFILE_MORE_DETAIL
7039  rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(record->gc_mark_time));
7040  rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(record->gc_sweep_time));
7041  rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(record->allocate_increase));
7042  rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(record->allocate_limit));
7043  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_PAGES")), SIZET2NUM(record->heap_use_pages));
7044  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects));
7045  rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects));
7046 
7047  rb_hash_aset(prof, ID2SYM(rb_intern("REMOVING_OBJECTS")), SIZET2NUM(record->removing_objects));
7048  rb_hash_aset(prof, ID2SYM(rb_intern("EMPTY_OBJECTS")), SIZET2NUM(record->empty_objects));
7049 
7050  rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), (record->flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse);
7051 #endif
7052 
7053 #if RGENGC_PROFILE > 0
7054  rb_hash_aset(prof, ID2SYM(rb_intern("OLD_OBJECTS")), SIZET2NUM(record->old_objects));
7055  rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBED_NORMAL_OBJECTS")), SIZET2NUM(record->remembered_normal_objects));
7056  rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBED_SHADY_OBJECTS")), SIZET2NUM(record->remembered_shady_objects));
7057 #endif
7058  rb_ary_push(gc_profile, prof);
7059  }
7060 
7061  return gc_profile;
7062 }
7063 
7064 #if GC_PROFILE_MORE_DETAIL
7065 #define MAJOR_REASON_MAX 0x10
7066 
7067 static char *
7068 gc_profile_dump_major_reason(int flags, char *buff)
7069 {
7070  int reason = flags & GPR_FLAG_MAJOR_MASK;
7071  int i = 0;
7072 
7073  if (reason == GPR_FLAG_NONE) {
7074  buff[0] = '-';
7075  buff[1] = 0;
7076  }
7077  else {
7078 #define C(x, s) \
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"); \
7082  buff[i] = 0; \
7083  }
7084  C(NOFREE, N);
7085  C(OLDGEN, O);
7086  C(SHADY, S);
7087  C(RESCAN, R);
7088  C(STRESS, T);
7089 #if RGENGC_ESTIMATE_OLDMALLOC
7090  C(OLDMALLOC, M);
7091 #endif
7092 #undef C
7093  }
7094  return buff;
7095 }
7096 #endif
7097 
7098 static void
7100 {
7101  rb_objspace_t *objspace = &rb_objspace;
7102  size_t count = objspace->profile.next_index;
7103 #ifdef MAJOR_REASON_MAX
7104  char reason_str[MAJOR_REASON_MAX];
7105 #endif
7106 
7107  if (objspace->profile.run && count /* > 1 */) {
7108  size_t i;
7109  const gc_profile_record *record;
7110 
7111  append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->profile.count));
7112  append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
7113 
7114  for (i = 0; i < count; i++) {
7115  record = &objspace->profile.records[i];
7116  append(out, rb_sprintf("%5"PRIdSIZE" %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
7117  i+1, record->gc_invoke_time, record->heap_use_size,
7118  record->heap_total_size, record->heap_total_objects, record->gc_time*1000));
7119  }
7120 
7121 #if GC_PROFILE_MORE_DETAIL
7122  append(out, rb_str_new_cstr("\n\n" \
7123  "More detail.\n" \
7124  "Prepare Time = Previously GC's rest sweep time\n"
7125  "Index Flags Allocate Inc. Allocate Limit"
7127  " Allocated Size"
7128 #endif
7129  " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
7130 #if RGENGC_PROFILE
7131  " OldgenObj RemNormObj RemShadObj"
7132 #endif
7134  " MaxRSS(KB) MinorFLT MajorFLT"
7135 #endif
7136  "\n"));
7137 
7138  for (i = 0; i < count; i++) {
7139  record = &objspace->profile.records[i];
7140  append(out, rb_sprintf("%5"PRIdSIZE" %4s/%c/%6s%c %13"PRIuSIZE" %15"PRIuSIZE
7142  " %15"PRIuSIZE
7143 #endif
7144  " %9"PRIuSIZE" %17.12f %17.12f %17.12f %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
7145 #if RGENGC_PROFILE
7146  "%10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
7147 #endif
7149  "%11ld %8ld %8ld"
7150 #endif
7151 
7152  "\n",
7153  i+1,
7154  gc_profile_dump_major_reason(record->flags, reason_str),
7155  (record->flags & GPR_FLAG_HAVE_FINALIZE) ? 'F' : '.',
7156  (record->flags & GPR_FLAG_NEWOBJ) ? "NEWOBJ" :
7157  (record->flags & GPR_FLAG_MALLOC) ? "MALLOC" :
7158  (record->flags & GPR_FLAG_METHOD) ? "METHOD" :
7159  (record->flags & GPR_FLAG_CAPI) ? "CAPI__" : "??????",
7160  (record->flags & GPR_FLAG_STRESS) ? '!' : ' ',
7161  record->allocate_increase, record->allocate_limit,
7163  record->allocated_size,
7164 #endif
7165  record->heap_use_pages,
7166  record->gc_mark_time*1000,
7167  record->gc_sweep_time*1000,
7168  record->prepare_time*1000,
7169 
7170  record->heap_live_objects,
7171  record->heap_free_objects,
7172  record->removing_objects,
7173  record->empty_objects
7174 #if RGENGC_PROFILE
7175  ,
7176  record->old_objects,
7177  record->remembered_normal_objects,
7178  record->remembered_shady_objects
7179 #endif
7181  ,
7182  record->maxrss / 1024,
7183  record->minflt,
7184  record->majflt
7185 #endif
7186 
7187  ));
7188  }
7189 #endif
7190  }
7191 }
7192 
7193 /*
7194  * call-seq:
7195  * GC::Profiler.result -> String
7196  *
7197  * Returns a profile data report such as:
7198  *
7199  * GC 1 invokes.
7200  * Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC time(ms)
7201  * 1 0.012 159240 212940 10647 0.00000000000001530000
7202  */
7203 
7204 static VALUE
7206 {
7207  VALUE str = rb_str_buf_new(0);
7209  return str;
7210 }
7211 
7212 /*
7213  * call-seq:
7214  * GC::Profiler.report
7215  * GC::Profiler.report(io)
7216  *
7217  * Writes the GC::Profiler.result to <tt>$stdout</tt> or the given IO object.
7218  *
7219  */
7220 
7221 static VALUE
7223 {
7224  VALUE out;
7225 
7226  if (argc == 0) {
7227  out = rb_stdout;
7228  }
7229  else {
7230  rb_scan_args(argc, argv, "01", &out);
7231  }
7233 
7234  return Qnil;
7235 }
7236 
7237 /*
7238  * call-seq:
7239  * GC::Profiler.total_time -> float
7240  *
7241  * The total time used for garbage collection in seconds
7242  */
7243 
7244 static VALUE
7246 {
7247  double time = 0;
7248  rb_objspace_t *objspace = &rb_objspace;
7249 
7250  if (objspace->profile.run && objspace->profile.next_index > 0) {
7251  size_t i;
7252  size_t count = objspace->profile.next_index;
7253 
7254  for (i = 0; i < count; i++) {
7255  time += objspace->profile.records[i].gc_time;
7256  }
7257  }
7258  return DBL2NUM(time);
7259 }
7260 
7261 /*
7262  * call-seq:
7263  * GC::Profiler.enabled? -> true or false
7264  *
7265  * The current status of GC profile mode.
7266  */
7267 
7268 static VALUE
7270 {
7271  rb_objspace_t *objspace = &rb_objspace;
7272  return objspace->profile.run ? Qtrue : Qfalse;
7273 }
7274 
7275 /*
7276  * call-seq:
7277  * GC::Profiler.enable -> nil
7278  *
7279  * Starts the GC profiler.
7280  *
7281  */
7282 
7283 static VALUE
7285 {
7286  rb_objspace_t *objspace = &rb_objspace;
7287  objspace->profile.run = TRUE;
7288  objspace->profile.current_record = 0;
7289  return Qnil;
7290 }
7291 
7292 /*
7293  * call-seq:
7294  * GC::Profiler.disable -> nil
7295  *
7296  * Stops the GC profiler.
7297  *
7298  */
7299 
7300 static VALUE
7302 {
7303  rb_objspace_t *objspace = &rb_objspace;
7304 
7305  objspace->profile.run = FALSE;
7306  objspace->profile.current_record = 0;
7307  return Qnil;
7308 }
7309 
7310 /*
7311  ------------------------------ DEBUG ------------------------------
7312 */
7313 
7314 static const char *
7315 type_name(int type, VALUE obj)
7316 {
7317  switch (type) {
7318 #define TYPE_NAME(t) case (t): return #t;
7319  TYPE_NAME(T_NONE);
7321  TYPE_NAME(T_CLASS);
7323  TYPE_NAME(T_FLOAT);
7326  TYPE_NAME(T_ARRAY);
7327  TYPE_NAME(T_HASH);
7330  TYPE_NAME(T_FILE);
7331  TYPE_NAME(T_MATCH);
7334  TYPE_NAME(T_NIL);
7335  TYPE_NAME(T_TRUE);
7336  TYPE_NAME(T_FALSE);
7339  TYPE_NAME(T_UNDEF);
7340  TYPE_NAME(T_NODE);
7343  case T_DATA:
7344  if (obj && rb_objspace_data_type_name(obj)) {
7345  return rb_objspace_data_type_name(obj);
7346  }
7347  return "T_DATA";
7348 #undef TYPE_NAME
7349  }
7350  return "unknown";
7351 }
7352 
7353 static const char *
7355 {
7356  return type_name(TYPE(obj), obj);
7357 }
7358 
7359 #if GC_DEBUG
7360 
7361 void
7363 {
7364  rb_objspace_t *objspace = &rb_objspace;
7365 
7366  fprintf(stderr, "created at: %s:%d\n", RSTRING_PTR(RANY(obj)->file), FIX2INT(RANY(obj)->line));
7367 
7368  if (is_pointer_to_heap(objspace, (void *)obj)) {
7369  fprintf(stderr, "pointer to heap?: true\n");
7370  }
7371  else {
7372  fprintf(stderr, "pointer to heap?: false\n");
7373  return;
7374  }
7375 
7376  fprintf(stderr, "marked? : %s\n", MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) ? "true" : "false");
7377 #if USE_RGENGC
7378 #if RGENGC_THREEGEN
7379  fprintf(stderr, "young? : %s\n", RVALUE_YOUNG_P(obj) ? "true" : "false");
7380 #endif
7381  fprintf(stderr, "old? : %s\n", RVALUE_OLD_P(obj) ? "true" : "false");
7382  fprintf(stderr, "WB-protected?: %s\n", RVALUE_WB_PROTECTED(obj) ? "true" : "false");
7383  fprintf(stderr, "remembered? : %s\n", MARKED_IN_BITMAP(GET_HEAP_REMEMBERSET_BITS(obj), obj) ? "true" : "false");
7384 #endif
7385 
7386  if (is_lazy_sweeping(heap_eden)) {
7387  fprintf(stderr, "lazy sweeping?: true\n");
7388  fprintf(stderr, "swept?: %s\n", is_swept_object(objspace, obj) ? "done" : "not yet");
7389  }
7390  else {
7391  fprintf(stderr, "lazy sweeping?: false\n");
7392  }
7393 }
7394 
7395 static VALUE
7396 gcdebug_sential(VALUE obj, VALUE name)
7397 {
7398  fprintf(stderr, "WARNING: object %s(%p) is inadvertently collected\n", (char *)name, (void *)obj);
7399  return Qnil;
7400 }
7401 
7402 void
7403 rb_gcdebug_sentinel(VALUE obj, const char *name)
7404 {
7405  rb_define_finalizer(obj, rb_proc_new(gcdebug_sential, (VALUE)name));
7406 }
7407 #endif /* GC_DEBUG */
7408 
7409 /*
7410  * Document-module: ObjectSpace
7411  *
7412  * The ObjectSpace module contains a number of routines
7413  * that interact with the garbage collection facility and allow you to
7414  * traverse all living objects with an iterator.
7415  *
7416  * ObjectSpace also provides support for object finalizers, procs that will be
7417  * called when a specific object is about to be destroyed by garbage
7418  * collection.
7419  *
7420  * a = "A"
7421  * b = "B"
7422  *
7423  * ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
7424  * ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" })
7425  *
7426  * _produces:_
7427  *
7428  * Finalizer two on 537763470
7429  * Finalizer one on 537763480
7430  */
7431 
7432 /*
7433  * Document-class: ObjectSpace::WeakMap
7434  *
7435  * An ObjectSpace::WeakMap object holds references to
7436  * any objects, but those objects can get garbage collected.
7437  *
7438  * This class is mostly used internally by WeakRef, please use
7439  * +lib/weakref.rb+ for the public interface.
7440  */
7441 
7442 /* Document-class: GC::Profiler
7443  *
7444  * The GC profiler provides access to information on GC runs including time,
7445  * length and object space size.
7446  *
7447  * Example:
7448  *
7449  * GC::Profiler.enable
7450  *
7451  * require 'rdoc/rdoc'
7452  *
7453  * GC::Profiler.report
7454  *
7455  * GC::Profiler.disable
7456  *
7457  * See also GC.count, GC.malloc_allocated_size and GC.malloc_allocations
7458  */
7459 
7460 /*
7461  * The GC module provides an interface to Ruby's mark and
7462  * sweep garbage collection mechanism.
7463  *
7464  * Some of the underlying methods are also available via the ObjectSpace
7465  * module.
7466  *
7467  * You may obtain information about the operation of the GC through
7468  * GC::Profiler.
7469  */
7470 
7471 void
7472 Init_GC(void)
7473 {
7474  VALUE rb_mObjSpace;
7475  VALUE rb_mProfiler;
7476  VALUE gc_constants;
7477 
7478  rb_mGC = rb_define_module("GC");
7479  rb_define_singleton_method(rb_mGC, "start", gc_start_internal, -1);
7480  rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
7481  rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
7482  rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0);
7483  rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
7484  rb_define_singleton_method(rb_mGC, "count", gc_count, 0);
7485  rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1);
7486  rb_define_singleton_method(rb_mGC, "latest_gc_info", gc_latest_gc_info, -1);
7487  rb_define_method(rb_mGC, "garbage_collect", gc_start_internal, -1);
7488 
7489  gc_constants = rb_hash_new();
7490  rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE)));
7491  rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_OBJ_LIMIT")), SIZET2NUM(HEAP_OBJ_LIMIT));
7492  rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_BITMAP_SIZE")), SIZET2NUM(HEAP_BITMAP_SIZE));
7493  rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_BITMAP_PLANES")), SIZET2NUM(HEAP_BITMAP_PLANES));
7494  OBJ_FREEZE(gc_constants);
7495  rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
7496 
7497  rb_mProfiler = rb_define_module_under(rb_mGC, "Profiler");
7498  rb_define_singleton_method(rb_mProfiler, "enabled?", gc_profile_enable_get, 0);
7499  rb_define_singleton_method(rb_mProfiler, "enable", gc_profile_enable, 0);
7500  rb_define_singleton_method(rb_mProfiler, "raw_data", gc_profile_record_get, 0);
7501  rb_define_singleton_method(rb_mProfiler, "disable", gc_profile_disable, 0);
7502  rb_define_singleton_method(rb_mProfiler, "clear", gc_profile_clear, 0);
7503  rb_define_singleton_method(rb_mProfiler, "result", gc_profile_result, 0);
7504  rb_define_singleton_method(rb_mProfiler, "report", gc_profile_report, -1);
7505  rb_define_singleton_method(rb_mProfiler, "total_time", gc_profile_total_time, 0);
7506 
7507  rb_mObjSpace = rb_define_module("ObjectSpace");
7508  rb_define_module_function(rb_mObjSpace, "each_object", os_each_obj, -1);
7509  rb_define_module_function(rb_mObjSpace, "garbage_collect", gc_start_internal, -1);
7510 
7511  rb_define_module_function(rb_mObjSpace, "define_finalizer", define_final, -1);
7512  rb_define_module_function(rb_mObjSpace, "undefine_finalizer", undefine_final, 1);
7513 
7514  rb_define_module_function(rb_mObjSpace, "_id2ref", id2ref, 1);
7515 
7517  rb_obj_freeze(rb_str_new2("failed to allocate memory")));
7520 
7522  rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
7523 
7524  rb_define_module_function(rb_mObjSpace, "count_objects", count_objects, -1);
7525 
7526  {
7527  VALUE rb_cWeakMap = rb_define_class_under(rb_mObjSpace, "WeakMap", rb_cObject);
7528  rb_define_alloc_func(rb_cWeakMap, wmap_allocate);
7529  rb_define_method(rb_cWeakMap, "[]=", wmap_aset, 2);
7530  rb_define_method(rb_cWeakMap, "[]", wmap_aref, 1);
7531  rb_define_method(rb_cWeakMap, "include?", wmap_has_key, 1);
7532  rb_define_method(rb_cWeakMap, "member?", wmap_has_key, 1);
7533  rb_define_method(rb_cWeakMap, "key?", wmap_has_key, 1);
7534  rb_define_method(rb_cWeakMap, "inspect", wmap_inspect, 0);
7535  rb_define_method(rb_cWeakMap, "each", wmap_each, 0);
7536  rb_define_method(rb_cWeakMap, "each_pair", wmap_each, 0);
7537  rb_define_method(rb_cWeakMap, "each_key", wmap_each_key, 0);
7538  rb_define_method(rb_cWeakMap, "each_value", wmap_each_value, 0);
7539  rb_define_method(rb_cWeakMap, "keys", wmap_keys, 0);
7540  rb_define_method(rb_cWeakMap, "values", wmap_values, 0);
7541  rb_define_method(rb_cWeakMap, "size", wmap_size, 0);
7542  rb_define_method(rb_cWeakMap, "length", wmap_size, 0);
7543  rb_define_private_method(rb_cWeakMap, "finalize", wmap_finalize, 1);
7544  rb_include_module(rb_cWeakMap, rb_mEnumerable);
7545  }
7546 
7547  /* internal methods */
7548  rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency, 0);
7549 #if MALLOC_ALLOCATED_SIZE
7550  rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
7551  rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
7552 #endif
7553 
7554  /* ::GC::OPTS, which shows GC build options */
7555  {
7556  VALUE opts;
7557  rb_define_const(rb_mGC, "OPTS", opts = rb_ary_new());
7558 #define OPT(o) if (o) rb_ary_push(opts, rb_str_new2(#o))
7559  OPT(GC_DEBUG);
7560  OPT(USE_RGENGC);
7561  OPT(RGENGC_DEBUG);
7572 #undef OPT
7573  }
7574 }
#define ELTS_SHARED
Definition: ruby.h:817
VALUE of
Definition: gc.c:1783
rb_event_flag_t hook_events
Definition: gc.c:508
static int rgengc_unprotect_logging_exit_func_i(st_data_t key, st_data_t val)
Definition: gc.c:4791
#define rb_objspace
Definition: gc.c:599
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:607
VALUE value
Definition: gc.c:6456
static void * objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
Definition: gc.c:6070
void rb_gc(void)
Definition: gc.c:5190
static void mark_hash(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:3372
rb_control_frame_t * cfp
Definition: vm_core.h:531
void rb_gc_finalize_deferred(void)
Definition: gc.c:2112
void rb_class_remove_from_super_subclasses(VALUE klass)
Definition: class.c:80
char mark
Definition: method.h:99
struct RNode node
Definition: gc.c:349
#define T_SYMBOL
Definition: ruby.h:494
size_t heap_total_objects
Definition: gc.c:291
#define T_OBJECT
Definition: ruby.h:477
static void gc_marks(rb_objspace_t *objspace, int full_mark)
Definition: gc.c:4492
Definition: node.h:93
Definition: node.h:29
Definition: re.h:44
Definition: st.h:100
static st_index_t new_size(st_index_t size)
Definition: st.c:184
rb_vm_t * vm
Definition: vm_core.h:526
void rb_class_detach_subclasses(VALUE klass)
Definition: class.c:131
struct rb_objspace::@104 flags
static void gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:2817
Definition: ruby.h:805
bits_t oldgen_bits[HEAP_BITMAP_LIMIT]
Definition: gc.c:578
#define R(b, x)
Definition: sha2.c:203
int ruby_thread_has_gvl_p(void)
Definition: thread.c:1492
#define FL_EXIVAR
Definition: ruby.h:1139
struct RBignum bignum
Definition: gc.c:347
void rb_gc_writebarrier(VALUE a, VALUE b)
Definition: gc.c:4731
static void root_objects_from(VALUE obj, void *ptr)
Definition: gc.c:5800
static void gc_mark_roots(rb_objspace_t *objspace, int full_mark, const char **categoryp)
Definition: gc.c:4058
#define RARRAY_LEN(a)
Definition: ruby.h:878
void(* func)(const char *category, VALUE, void *)
Definition: gc.c:5795
void rb_bug(const char *fmt,...)
Definition: error.c:327
rb_method_type_t type
Definition: method.h:79
rb_objspace_t * objspace
Definition: gc.c:3319
#define heap_pages_final_slots
Definition: gc.c:619
static VALUE gc_profile_disable(void)
Definition: gc.c:7301
static void objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type)
Definition: gc.c:5978
#define FALSE
Definition: nkf.h:174
static int set_zero(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:2554
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
#define RUBY_DTRACE_GC_SWEEP_END_ENABLED()
Definition: probes.h:76
rb_method_attr_t attr
Definition: method.h:84
#define GC_PROFILE_MORE_DETAIL
Definition: gc.c:238
#define STACK_START
Definition: gc.c:3224
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:2373
size_t strlen(const char *)
#define rb_gc_mark_locations(start, end)
Definition: gc.c:3316
gc_profile_record_flag
Definition: gc.c:260
#define INT2NUM(x)
Definition: ruby.h:1288
RVALUE * start
Definition: gc.c:566
void(* dfree)(void *)
Definition: ruby.h:960
void rb_objspace_free(rb_objspace_t *objspace)
Definition: gc.c:890
int need_major_gc
Definition: gc.c:521
static void gc_prof_set_malloc_info(rb_objspace_t *)
Definition: gc.c:6909
#define RCLASS_CONST_TBL(c)
Definition: internal.h:293
Definition: constant.h:19
static VALUE wmap_each(VALUE self)
Definition: gc.c:6513
#define T_FIXNUM
Definition: ruby.h:489
Definition: st.h:69
#define RUBY_DEFAULT_FREE
Definition: ruby.h:1009
#define RSTRUCT(obj)
Definition: ruby.h:1127
VALUE rb_id2str(ID id)
Definition: ripper.c:17157
static void pop_mark_stack_chunk(mark_stack_t *stack)
Definition: gc.c:3151
size_t num
Definition: gc.c:1782
Definition: st.h:100
static VALUE wmap_each_value(VALUE self)
Definition: gc.c:6559
#define T_MATCH
Definition: ruby.h:493
double gc_sweep_start_time
Definition: gc.c:497
Definition: node.h:47
size_t unused_cache_size
Definition: gc.c:404
size_t rb_io_memsize(const rb_io_t *)
Definition: io.c:4280
static void gc_prof_timer_stop(rb_objspace_t *)
Definition: gc.c:6829
static int rgengc_remembered(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:4642
VALUE rb_yield_values(int n,...)
Definition: vm_eval.c:953
int count
Definition: encoding.c:48
static int max(int a, int b)
Definition: strftime.c:141
static VALUE id2ref(VALUE obj, VALUE objid)
Definition: gc.c:2301
struct RFile file
Definition: gc.c:348
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1655
#define FIXNUM_FLAG
Definition: ruby.h:430
void * ruby_sized_xrealloc2(void *ptr, size_t n, size_t size, size_t old_n)
Definition: gc.c:6215
static int mark_keyvalue(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:3363
size_t size
Definition: gc.c:461
#define GC_HEAP_GROWTH_FACTOR
Definition: gc.c:106
static VALUE RVALUE_PROMOTED_P(VALUE obj)
Definition: gc.c:781
static VALUE os_each_obj(int argc, VALUE *argv, VALUE os)
Definition: gc.c:1882
static int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
Definition: gc.c:1405
int run
Definition: gc.c:457
const VALUE location
Definition: method.h:73
int immediate_sweep
Definition: gc.c:5081
size_t ruby_stack_length(VALUE **p)
Definition: gc.c:3250
#define FLUSH_REGISTER_WINDOWS
Definition: defines.h:270
static VALUE run_single_final(VALUE arg)
Definition: gc.c:2013
#define malloc_allocated_size
Definition: gc.c:609
bits_t rememberset_bits[HEAP_BITMAP_LIMIT]
Definition: gc.c:577
#define FL_TAINT
Definition: ruby.h:1137
#define CLASS_OF(v)
Definition: ruby.h:440
#define GC_HEAP_OLDOBJECT_LIMIT_FACTOR
Definition: gc.c:112
static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
Definition: gc.c:989
#define T_MODULE
Definition: ruby.h:480
const VALUE file
Definition: constant.h:22
#define RCLASS_EXT(c)
Definition: classext.h:15
#define N
Definition: lgamma_r.c:20
void rb_class_remove_from_module_subclasses(VALUE klass)
Definition: class.c:98
static void RVALUE_PROMOTE_INFANT(VALUE obj)
Definition: gc.c:788
RVALUE * range[2]
Definition: gc.c:434
#define ATOMIC_EXCHANGE(var, val)
Definition: ruby_atomic.h:131
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1916
static int wmap_each_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6501
VALUE rb_obj_is_thread(VALUE obj)
Definition: vm.c:2120
int parent_object_is_old
Definition: gc.c:519
#define Qtrue
Definition: ruby.h:426
int st_insert(st_table *, st_data_t, st_data_t)
static void wmap_mark(void *ptr)
Definition: gc.c:6332
static VALUE gc_verify_internal_consistency(VALUE self)
Definition: gc.c:4224
size_t final_slots
Definition: gc.c:567
size_t increment
Definition: gc.c:437
size_t onig_memsize(const regex_t *reg)
Definition: regcomp.c:5592
static void mark_m_tbl_wrapper(rb_objspace_t *objspace, struct method_table_wrapper *wrapper)
Definition: gc.c:3431
Definition: io.h:61
static void gc_finalize_deferred(void *dmy)
Definition: gc.c:2102
#define FL_TEST2(x, f)
Definition: gc.c:704
struct rb_io_t * fptr
Definition: ruby.h:936
static size_t objspace_live_slot(rb_objspace_t *objspace)
Definition: gc.c:2686
static size_t objspace_malloc_prepare(rb_objspace_t *objspace, size_t size)
Definition: gc.c:6055
struct rb_method_entry_struct * orig_me
Definition: method.h:92
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1041
node_type
Definition: node.h:22
static VALUE check_gen_consistency(VALUE obj)
Definition: gc.c:717
void(* mark_func)(VALUE v, void *data)
Definition: gc.c:513
static int stack_check(int water_mark)
Definition: gc.c:3260
struct RFloat flonum
Definition: gc.c:339
void * ruby_xmalloc2(size_t n, size_t size)
Definition: gc.c:6172
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1500
long tv_sec
Definition: ossl_asn1.c:17
static VALUE gc_info_decode(int flags, VALUE hash_or_key)
Definition: gc.c:5241
void ruby_mimfree(void *ptr)
Definition: gc.c:6267
struct RStruct rstruct
Definition: gc.c:346
VALUE mark_object_ary
Definition: vm_core.h:366
#define dont_gc
Definition: gc.c:623
void rb_gcdebug_print_obj_condition(VALUE obj)
#define GC_ENABLE_LAZY_SWEEP
Definition: gc.c:244
static int wmap_keys_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6570
VALUE rb_eTypeError
Definition: error.c:548
size_t increase
Definition: gc.c:420
RVALUE * deferred_final
Definition: gc.c:445
#define finalizer_table
Definition: gc.c:626
#define T_RATIONAL
Definition: ruby.h:495
VALUE rb_newobj(void)
Definition: gc.c:1348
#define ULONG2NUM(x)
Definition: ruby.h:1319
Definition: node.h:39
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
#define SIZED_REALLOC_N(var, type, n, old_n)
Definition: internal.h:471
static void gc_prof_mark_timer_start(rb_objspace_t *)
Definition: gc.c:6839
rb_objspace_t * objspace
Definition: gc.c:4169
void st_free_table(st_table *)
Definition: st.c:334
#define RGENGC_DEBUG
Definition: gc.c:185
#define SYM2ID(x)
Definition: ruby.h:356
size_t oldmalloc_increase
Definition: gc.c:534
#define global_List
Definition: gc.c:627
#define RGENGC_ESTIMATE_OLDMALLOC
Definition: gc.c:224
void * ruby_xrealloc2(void *ptr, size_t n, size_t size)
Definition: gc.c:6225
#define RGENGC_PROFILE
Definition: gc.c:205
static struct heap_page * heap_page_create(rb_objspace_t *objspace)
Definition: gc.c:1116
static VALUE count_objects(int argc, VALUE *argv, VALUE os)
Definition: gc.c:2588
#define OBJ_PROMOTED(x)
Definition: ruby.h:1189
#define RGENGC_CHECK_MODE
Definition: gc.c:196
void ruby_sized_xfree(void *x, size_t size)
Definition: gc.c:6234
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *passing_data)
Definition: gc.c:5807
size_t next_index
Definition: gc.c:460
struct gc_list * next
Definition: gc.c:388
#define STACK_UPPER(x, a, b)
Definition: gc.h:74
static double elapsed_time_from(double time)
Definition: gc.c:6817
static void * objspace_xmalloc(rb_objspace_t *objspace, size_t size)
Definition: gc.c:6089
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
static void gc_prof_sweep_timer_start(rb_objspace_t *)
Definition: gc.c:6866
#define PRIxVALUE
Definition: ruby.h:135
static void make_deferred(rb_objspace_t *objspace, RVALUE *p)
Definition: gc.c:1473
#define GC_MALLOC_LIMIT_MAX
Definition: gc.c:119
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
#define Check_Type(v, t)
Definition: ruby.h:532
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1854
int rb_io_fptr_finalize(rb_io_t *)
Definition: io.c:4257
static void ruby_memerror(void)
Definition: gc.c:5864
struct re_registers regs
Definition: re.h:37
static void rgengc_report_body(int level, rb_objspace_t *objspace, const char *fmt,...)
Definition: gc.c:4549
int ruby_get_stack_grow_direction(volatile VALUE *addr)
Definition: gc.c:3239
void rb_sweep_method_entry(void *vm)
Definition: vm_method.c:137
#define GC_PROFILE_DETAIL_MEMORY
Definition: gc.c:241
#define C
Definition: util.c:195
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:653
#define T_HASH
Definition: ruby.h:485
void Init_heap(void)
Definition: gc.c:1661
st_table * st_init_strtable(void)
Definition: st.c:284
#define RCLASS_M_TBL_WRAPPER(c)
Definition: internal.h:294
static int wmap_memsize_map(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6359
const VALUE value
Definition: constant.h:21
static int wmap_values_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6597
static void gc_heap_rest_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:3038
static VALUE gc_profile_total_time(VALUE self)
Definition: gc.c:7245
union rb_method_definition_struct::@126 body
static struct heap_page * heap_page_allocate(rb_objspace_t *objspace)
Definition: gc.c:1026
double oldobject_limit_factor
Definition: gc.c:140
static int obj_free(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:1490
static int mark_key(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:3340
static int heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr)
Definition: gc.c:2230
#define nd_set_type(n, t)
Definition: node.h:283
#define DATA_PTR(dta)
Definition: ruby.h:992
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:1761
#define RSTRUCT_EMBED_LEN_MASK
Definition: ruby.h:1056
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
#define GC_PROFILE_RECORD_DEFAULT_SIZE
Definition: gc.c:6703
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
size_t rb_gc_count(void)
Definition: gc.c:5219
static int rgengc_remembersetbits_get(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:4577
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:2281
#define T_ARRAY
Definition: ruby.h:484
st_data_t st_index_t
Definition: st.h:48
#define ATOMIC_PTR_EXCHANGE(var, val)
Definition: ruby_atomic.h:161
static struct heap_page * heap_prepare_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:1198
#define RUBY_INTERNAL_EVENT_GC_START
Definition: ruby.h:1734
#define BITMAP_BIT(p)
Definition: gc.c:591
#define TAG_RAISE
Definition: eval_intern.h:193
void rb_gc_register_address(VALUE *addr)
Definition: gc.c:4927
#define heap_pages_himem
Definition: gc.c:614
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:867
VALUE rb_io_write(VALUE, VALUE)
Definition: io.c:1427
Definition: ruby.h:1081
#define VALGRIND_MAKE_MEM_UNDEFINED(p, n)
Definition: zlib.c:25
#define RFILE(obj)
Definition: ruby.h:1129
#define ROBJECT_NUMIV(o)
Definition: ruby.h:774
size_t used
Definition: gc.c:432
memop_type
Definition: gc.c:5959
#define S(s)
st_table * tbl
Definition: internal.h:283
#define rb_setjmp(env)
Definition: gc.c:88
Definition: gc.c:386
static const char * obj_type_name(VALUE obj)
Definition: gc.c:7354
void rb_gc_writebarrier_unprotect_promoted(VALUE obj)
Definition: gc.c:4749
void callback(ffi_cif *cif, void *resp, void **args, void *ctx)
Definition: closure.c:59
size_t heap_used_at_gc_start
Definition: gc.c:499
static VALUE wmap_each_key(VALUE self)
Definition: gc.c:6536
int char_offset_num_allocated
Definition: re.h:40
#define gc_event_hook(objspace, event, data)
Definition: gc.c:1278
#define FIXNUM_P(f)
Definition: ruby.h:347
#define heap_pages_min_free_slots
Definition: gc.c:617
#define T_UNDEF
Definition: ruby.h:497
#define nd_type(n)
Definition: node.h:282
static size_t objspace_free_slot(rb_objspace_t *objspace)
Definition: gc.c:2698
size_t limit
Definition: gc.c:402
#define LIKELY(x)
Definition: vm_core.h:108
#define RDATA(obj)
Definition: ruby.h:1125
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2282
static int mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data)
Definition: gc.c:3447
static int heap_increment(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:1184
static size_t objspace_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint)
Definition: gc.c:5950
#define SET(name, attr)
static int garbage_collect_body(rb_objspace_t *, int full_mark, int immediate_sweep, int reason)
Definition: gc.c:4970
Definition: ruby.h:948
Definition: ruby.h:957
static int wmap_free_map(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6342
int ruby_stack_grow_direction
Definition: gc.c:3237
#define FL_SET2(x, f)
Definition: gc.c:705
static VALUE gc_stat_internal(VALUE hash_or_sym, size_t *out)
Definition: gc.c:5352
struct rb_thread_struct::@169 machine
int ruby_stack_check(void)
Definition: gc.c:3279
void rb_mark_method_entry(const rb_method_entry_t *me)
Definition: gc.c:3417
struct heap_page_header header
Definition: gc.c:381
static VALUE wmap_size(VALUE self)
Definition: gc.c:6685
VALUE rb_eRangeError
Definition: error.c:552
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
struct rb_objspace::mark_func_data_struct * mark_func_data
static void push_mark_stack(mark_stack_t *, VALUE)
Definition: gc.c:3178
void rb_gc_force_recycle(VALUE p)
Definition: gc.c:4897
#define MARK_CHECKPOINT(category)
stack_chunk_t * chunk
Definition: gc.c:399
#define ruby_gc_stress
Definition: gc.c:628
static size_t obj_memsize_of(VALUE obj, int use_tdata)
Definition: gc.c:2426
#define ATOMIC_SIZE_ADD(var, val)
Definition: ruby_atomic.h:134
#define ATOMIC_SIZE_CAS(var, oldval, val)
Definition: ruby_atomic.h:156
static VALUE objspace_each_objects(VALUE arg)
Definition: gc.c:1695
static void negative_size_allocation_error(const char *)
Definition: gc.c:5840
gc_profile_record * current_record
Definition: gc.c:459
Definition: node.h:27
#define ruby_initial_gc_stress
Definition: gc.c:600
rb_heap_t tomb_heap
Definition: gc.c:428
time_t tv_sec
Definition: missing.h:51
static VALUE define_final(int argc, VALUE *argv, VALUE os)
Definition: gc.c:1949
Definition: gc.c:556
#define RUBY_DTRACE_GC_SWEEP_END()
Definition: probes.h:77
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
static int force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:2132
#define heap_pages_deferred_final
Definition: gc.c:620
#define GET_HEAP_OLDGEN_BITS(x)
Definition: gc.c:587
static void RVALUE_DEMOTE_FROM_OLD(VALUE obj)
Definition: gc.c:854
Definition: node.h:239
#define obj_id_to_ref(objid)
Definition: gc.c:635
void rb_global_variable(VALUE *var)
Definition: gc.c:4962
static VALUE wmap_allocate(VALUE klass)
Definition: gc.c:6390
static void mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
Definition: gc.c:3475
static VALUE RVALUE_OLD_BITMAP_P(VALUE obj)
Definition: gc.c:763
#define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
Definition: gc.c:129
struct RObject object
Definition: gc.c:337
unsigned int malloc_limit_min
Definition: gc.c:141
void rb_gc_unprotect_logging(void *objptr, const char *filename, int line)
Definition: gc.c:4804
static int mark_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data)
Definition: gc.c:3423
VALUE data[STACK_CHUNK_SIZE]
Definition: gc.c:394
int during_gc
Definition: gc.c:451
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
void rb_objspace_set_event_hook(const rb_event_flag_t event)
Definition: gc.c:1265
static void finalize_list(rb_objspace_t *objspace, RVALUE *p)
Definition: gc.c:2074
rb_heap_t * heap
Definition: gc.c:572
size_t limit
Definition: gc.c:419
#define malloc_increase
Definition: gc.c:608
void rb_free_m_tbl_wrapper(struct method_table_wrapper *wrapper)
Definition: gc.c:1450
#define FL_SINGLETON
Definition: ruby.h:1133
int dont_lazy_sweep
Definition: gc.c:450
struct RVALUE RVALUE
VALUE rb_define_finalizer(VALUE obj, VALUE block)
Definition: gc.c:1990
#define strtod(s, e)
Definition: util.h:74
static void gc_marks_body(rb_objspace_t *objspace, int full_mark)
Definition: gc.c:4143
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:608
static size_t xmalloc2_size(size_t n, size_t size)
Definition: gc.c:6162
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:2548
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
void * ruby_xcalloc(size_t n, size_t size)
Definition: gc.c:6191
#define RHASH(obj)
Definition: ruby.h:1124
#define GET_STACK_BOUNDS(start, end, appendix)
Definition: gc.c:3469
Definition: gc.c:6312
struct heap_page * next
Definition: gc.c:569
static void gc_prof_timer_start(rb_objspace_t *)
Definition: gc.c:6804
#define ATOMIC_SET(var, val)
Definition: ruby_atomic.h:127
void Init_GC(void)
Definition: gc.c:7472
int st_lookup(st_table *, st_data_t, st_data_t *)
#define MEMZERO(p, type, n)
Definition: ruby.h:1351
VALUE rb_obj_method(VALUE, VALUE)
Definition: proc.c:1460
Definition: ruby.h:820
struct rb_objspace::@102 malloc_params
size_t oldmalloc_increase_limit
Definition: gc.c:535
#define heap_pages_max_free_slots
Definition: gc.c:618
void rb_free_generic_ivar(VALUE)
Definition: variable.c:1030
#define during_gc
Definition: gc.c:624
#define FL_TEST(x, f)
Definition: ruby.h:1169
static const char * type_name(int type, VALUE obj)
Definition: gc.c:7315
int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data)
Definition: vm_trace.c:1487
int latest_gc_info
Definition: gc.c:505
static VALUE wmap_has_key(VALUE self, VALUE key)
Definition: gc.c:6679
static void * aligned_malloc(size_t, size_t)
Definition: gc.c:5900
int ruby_disable_gc_stress
Definition: gc.c:650
void rb_ary_free(VALUE ary)
Definition: array.c:540
void rb_mark_end_proc(void)
Definition: eval_jump.c:80
static void gc_mark(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:3589
#define STACK_CHUNK_SIZE
Definition: gc.c:391
#define ROBJECT_IVPTR(o)
Definition: ruby.h:778
#define GC_HEAP_GROWTH_MAX_SLOTS
Definition: gc.c:109
VALUE rb_class_name(VALUE)
Definition: variable.c:391
VALUE rb_undefine_finalizer(VALUE obj)
Definition: gc.c:1911
size_t total_allocated_object_num
Definition: gc.c:503
#define ALLOC_N(type, n)
Definition: ruby.h:1333
void rb_vm_mark(void *ptr)
Definition: vm.c:1727
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
double gc_invoke_time
Definition: gc.c:289
static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_sweep, int reason)
Definition: gc.c:5053
static void * gc_with_gvl(void *ptr)
Definition: gc.c:5085
void rb_gc_copy_finalizer(VALUE dest, VALUE obj)
Definition: gc.c:1998
void rb_mark_generic_ivar_tbl(void)
Definition: variable.c:1022
#define nomem_error
Definition: gc.c:646
VALUE final
Definition: gc.c:6315
#define level
long tv_usec
Definition: ossl_asn1.c:18
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
static void finalize_deferred(rb_objspace_t *objspace)
Definition: gc.c:2092
static VALUE define_final0(VALUE obj, VALUE block)
Definition: gc.c:1966
IUnknown DWORD
Definition: win32ole.c:149
static void * negative_size_allocation_error_with_gvl(void *ptr)
Definition: gc.c:5833
void rb_gc_unregister_address(VALUE *addr)
Definition: gc.c:4939
static void gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page)
Definition: gc.c:2716
static int pop_mark_stack(mark_stack_t *, VALUE *)
Definition: gc.c:3187
static VALUE gc_stress_get(VALUE self)
Definition: gc.c:5575
#define VALGRIND_MAKE_MEM_DEFINED(p, n)
Definition: zlib.c:24
void rb_str_free(VALUE)
Definition: string.c:941
#define I(s)
#define T_NIL
Definition: ruby.h:476
VALUE * varptr
Definition: gc.c:387
static void gc_after_sweep(rb_objspace_t *objspace)
Definition: gc.c:2952
#define NUM2PTR(x)
rb_atomic_t finalizing
Definition: gc.c:452
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
static VALUE RVALUE_INFANT_P(VALUE obj)
Definition: gc.c:756
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ruby.h:1552
VALUE rb_ary_new(void)
Definition: array.c:495
static int gc_marked(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:3543
#define T_TRUE
Definition: ruby.h:490
struct gc_profile_record gc_profile_record
#define UINT2NUM(x)
Definition: ruby.h:1298
static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:3525
mark_stack_t mark_stack
Definition: gc.c:455
void rb_free_method_entry(rb_method_entry_t *me)
Definition: vm_method.c:178
Definition: ruby.h:747
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1541
#define RSTRUCT_LEN(st)
Definition: ruby.h:1058
#define RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()
Definition: probes.h:73
#define snprintf
Definition: subst.h:6
static VALUE heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:1249
Definition: ruby.h:860
#define JUMP_TAG(st)
Definition: eval_intern.h:173
Definition: gc.c:330
static void push_mark_stack_chunk(mark_stack_t *stack)
Definition: gc.c:3130
#define nonspecial_obj_id(obj)
Definition: gc.c:634
#define NIL_P(v)
Definition: ruby.h:438
st_table * obj2wmap
Definition: gc.c:6313
long tv_nsec
Definition: missing.h:52
#define RUBY_DTRACE_GC_MARK_END_ENABLED()
Definition: probes.h:70
void st_add_direct(st_table *, st_data_t, st_data_t)
Definition: st.c:629
static struct heap_page * heap_page_resurrect(rb_objspace_t *objspace)
Definition: gc.c:1104
VALUE rb_gc_latest_gc_info(VALUE key)
Definition: gc.c:5318
static VALUE os_obj_of(VALUE of)
Definition: gc.c:1835
#define UNLIKELY(x)
Definition: vm_core.h:109
#define add(x, y)
Definition: date_strftime.c:23
#define CEILDIV(i, mod)
Definition: gc.c:551
static char msg[50]
Definition: strerror.c:8
#define calloc
Definition: ripper.c:98
static size_t wmap_memsize(const void *ptr)
Definition: gc.c:6367
static int gc_heap_lazy_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:3004
int st_delete(st_table *, st_data_t *, st_data_t *)
double gc_time
Definition: gc.c:288
#define RCLASS_IV_TBL(c)
Definition: internal.h:292
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2225
size_t page_length
Definition: gc.c:413
VALUE rb_obj_is_mutex(VALUE obj)
Definition: thread.c:4216
#define MALLOC_ALLOCATED_SIZE
Definition: gc.c:254
VALUE rb_eNoMemError
Definition: error.c:559
static void heap_add_freepage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
Definition: gc.c:967
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:489
unsigned int oldmalloc_limit_max
Definition: gc.c:145
void onig_region_free(OnigRegion *r, int free_self)
Definition: regexec.c:315
bits_t mark_bits[HEAP_BITMAP_LIMIT]
Definition: gc.c:575
#define FLONUM_P(x)
Definition: ruby.h:367
#define T_FLOAT
Definition: ruby.h:481
VALUE rb_mGC
Definition: gc.c:649
#define TYPE(x)
Definition: ruby.h:505
int argc
Definition: ruby.c:131
Definition: node.h:59
#define heap_pages_increment
Definition: gc.c:616
#define RBIGNUM_LEN(b)
Definition: ruby.h:1103
struct heap_page * pages
Definition: gc.c:408
#define Qfalse
Definition: ruby.h:425
#define M
Definition: random.c:94
#define rb_sourcefile()
Definition: tcltklib.c:98
#define realloc
Definition: ripper.c:97
size_t onig_region_memsize(const OnigRegion *regs)
Definition: regcomp.c:5607
Definition: method.h:97
struct force_finalize_list * next
Definition: gc.c:2128
static int free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data)
Definition: gc.c:1459
#define T_BIGNUM
Definition: ruby.h:487
#define heap_eden
Definition: gc.c:621
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:4920
if((ID)(DISPID) nameid!=nameid)
Definition: win32ole.c:770
#define ATOMIC_SIZE_EXCHANGE(var, val)
Definition: ruby_atomic.h:136
#define T_NODE
Definition: ruby.h:498
#define GC_MALLOC_LIMIT_GROWTH_FACTOR
Definition: gc.c:122
#define FL_ANY(x, f)
Definition: ruby.h:1170
#define rb_str_new2
Definition: intern.h:840
size_t index
Definition: gc.c:401
#define RNODE(obj)
Definition: node.h:266
int err
Definition: win32.c:114
#define GC_NOTIFY
Definition: gc.c:4967
static void gc_before_sweep(rb_objspace_t *objspace)
Definition: gc.c:2850
#define STACK_END
Definition: gc.c:3225
#define OBJ_FREEZE(x)
Definition: ruby.h:1186
#define EXIT_FAILURE
Definition: eval_intern.h:24
#define is_lazy_sweeping(heap)
Definition: gc.c:632
#define RUBY_DTRACE_GC_MARK_END()
Definition: probes.h:71
#define T_COMPLEX
Definition: ruby.h:496
#define RSTRUCT_CONST_PTR(st)
Definition: ruby.h:1064
static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:4651
static RVALUE * heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:1230
size_t rb_objspace_data_type_memsize(VALUE obj)
Definition: gc.c:1383
#define RBIGNUM_DIGITS(b)
Definition: ruby.h:1109
VALUE klass
Definition: method.h:102
NODE * rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
Definition: gc.c:1360
struct rb_objspace::@105 profile
#define numberof(array)
Definition: etc.c:595
#define RGENGC_WB_PROTECTED_NODE_CREF
Definition: ruby.h:744
void rb_gc_mark_machine_stack(rb_thread_t *th)
Definition: gc.c:3506
union RVALUE::@99 as
volatile VALUE * rb_gc_guarded_ptr(volatile VALUE *ptr)
Definition: gc.c:93
#define ALLOC(type)
Definition: ruby.h:1334
static VALUE wmap_values(VALUE self)
Definition: gc.c:6611
static void run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
Definition: gc.c:2021
void * ruby_mimmalloc(size_t size)
Definition: gc.c:6251
#define PRIuVALUE
Definition: ruby.h:134
size_t heap_total_size
Definition: gc.c:293
st_table * finalizer_table
Definition: gc.c:454
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:226
#define RUBY_INTERNAL_EVENT_GC_END_MARK
Definition: ruby.h:1735
static void gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
Definition: gc.c:3301
static int internal_object_p(VALUE obj)
Definition: gc.c:1787
#define sub(x, y)
Definition: date_strftime.c:24
#define FL_FINALIZE
Definition: ruby.h:1136
#define RGENGC_THREEGEN
Definition: gc.c:214
#define FL_ABLE(x)
Definition: ruby.h:1167
#define COUNT_TYPE(t)
#define OBJ_WB_PROTECTED(x)
Definition: ruby.h:1190
static void gc_prof_set_heap_info(rb_objspace_t *)
Definition: gc.c:6921
size_t total_slots
Definition: gc.c:414
static int is_dead_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2248
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1670
size_t total_freed_object_num
Definition: gc.c:504
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
static void gc_profile_dump_on(VALUE out, VALUE(*append)(VALUE, VALUE))
Definition: gc.c:7099
#define RCLASS_M_TBL(c)
Definition: internal.h:295
#define heap_tomb
Definition: gc.c:622
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
struct RRational rational
Definition: gc.c:351
int rb_during_gc(void)
Definition: gc.c:5198
rb_iseq_t *const iseq
Definition: method.h:82
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static void rgengc_unprotect_logging_exit_func(void)
Definition: gc.c:4798
#define lo
Definition: siphash.c:21
static double getrusage_time(void)
Definition: gc.c:6706
#define TRUE
Definition: nkf.h:175
static VALUE gc_profile_report(int argc, VALUE *argv, VALUE self)
Definition: gc.c:7222
VALUE * ruby_initial_gc_stress_ptr
Definition: gc.c:601
#define T_DATA
Definition: ruby.h:492
double malloc_limit_growth_factor
Definition: gc.c:143
static void gc_set_initial_pages(void)
Definition: gc.c:5690
size_t cache_size
Definition: gc.c:403
static void gc_prof_sweep_timer_stop(rb_objspace_t *)
Definition: gc.c:6881
VALUE rb_mEnumerable
Definition: enum.c:20
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:1810
struct heap_page_body * body
Definition: gc.c:564
#define GET_HEAP_MARK_BITS(x)
Definition: gc.c:585
#define STACKFRAME_FOR_CALL_CFUNC
Definition: gc.c:3276
unsigned int oldmalloc_limit_min
Definition: gc.c:144
int rb_obj_respond_to(VALUE, ID, int)
Definition: vm_method.c:1599
#define GC_DEBUG
Definition: gc.c:173
static void gc_prof_mark_timer_stop(rb_objspace_t *)
Definition: gc.c:6852
static void aligned_free(void *)
Definition: gc.c:5936
const VALUE klass
Definition: ruby.h:749
size_t rb_obj_gc_flags(VALUE obj, ID *flags, size_t max)
Definition: gc.c:4848
static void add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
Definition: gc.c:3108
#define MARKED_IN_BITMAP(bits, p)
Definition: gc.c:593
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1353
#define malloc
Definition: ripper.c:96
struct RHash hash
Definition: gc.c:343
VALUE rb_hash_new(void)
Definition: hash.c:298
static void run_final(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:2048
void ruby_xfree(void *x)
Definition: gc.c:6242
Definition: ruby.h:1046
#define STACK_LENGTH
Definition: gc.c:3233
size_t old_object_count
Definition: gc.c:527
static VALUE wmap_aset(VALUE self, VALUE wmap, VALUE orig)
Definition: gc.c:6646
#define RVALUE_OLDGEN_BITMAP(obj)
Definition: gc.c:711
static int os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
Definition: gc.c:1816
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
RVALUE * freelist
Definition: gc.c:412
const char * category
Definition: gc.c:5794
static int rgengc_remember(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:4600
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:223
Definition: ruby.h:934
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
static int wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
Definition: gc.c:6401
#define PRIsVALUE
Definition: ruby.h:137
static void mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:3456
static void mark_tbl(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:3331
void Init_stack(volatile VALUE *addr)
Definition: gc.c:5124
static st_table * rgengc_unprotect_logging_table
Definition: gc.c:4788
unsigned long ID
Definition: ruby.h:89
static size_t objspace_total_slot(rb_objspace_t *objspace)
Definition: gc.c:2692
size_t final_slots
Definition: gc.c:444
static ruby_gc_params_t gc_params
Definition: gc.c:152
VALUE v2
Definition: gc.c:356
struct RVALUE::@99::@100 free
static VALUE lazy_sweep_enable(void)
Definition: gc.c:2677
#define ATOMIC_SIZE_INC(var)
Definition: ruby_atomic.h:147
static void verify_internal_consistency_reachable_i(VALUE child, void *ptr)
Definition: gc.c:4176
#define MALLOC_ALLOCATED_SIZE_CHECK
Definition: gc.c:257
static void atomic_sub_nounderflow(size_t *var, size_t sub)
Definition: gc.c:5966
void rb_gc_mark_symbols(int full_mark)
Definition: ripper.c:16776
static VALUE newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
Definition: gc.c:1285
#define Qnil
Definition: ruby.h:427
#define T_STRUCT
Definition: ruby.h:486
unsigned int uintptr_t
Definition: win32.h:103
static void heap_pages_free_unused_pages(rb_objspace_t *objspace)
Definition: gc.c:997
static int is_id_value(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2221
size_t major_gc_count
Definition: gc.c:470
int type
Definition: tcltklib.c:112
static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:4717
static void heap_add_pages(rb_objspace_t *objspace, rb_heap_t *heap, size_t add)
Definition: gc.c:1149
#define BITMAP_INDEX(p)
Definition: gc.c:589
VALUE rb_obj_rgengc_writebarrier_protected_p(VALUE obj)
Definition: gc.c:4836
#define BUILTIN_TYPE(x)
Definition: ruby.h:502
int dont_gc
Definition: gc.c:449
#define OBJ_TAINT(x)
Definition: ruby.h:1177
unsigned long VALUE
Definition: ruby.h:88
#define NUM_IN_PAGE(p)
Definition: gc.c:588
VALUE gc_stress
Definition: gc.c:509
static VALUE gc_profile_enable_get(VALUE self)
Definition: gc.c:7269
static void rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:3560
static VALUE result
Definition: nkf.c:40
static VALUE gc_start_internal(int argc, VALUE *argv, VALUE self)
Definition: gc.c:5151
static int mark_entry(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:3323
#define gc_prof_record(objspace)
Definition: gc.c:690
#define RBASIC(obj)
Definition: ruby.h:1116
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:1394
void rb_free_const_table(st_table *tbl)
Definition: gc.c:1466
static int is_markable_object(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:2267
#define USE_RGENGC
Definition: ruby.h:707
unsigned int malloc_limit_max
Definition: gc.c:142
#define FIX2INT(x)
Definition: ruby.h:632
static VALUE RVALUE_OLD_P(VALUE obj)
Definition: gc.c:770
static void * ruby_memerror_body(void *dummy)
Definition: gc.c:5857
void rb_mark_tbl(st_table *tbl)
Definition: gc.c:3519
#define rgengc_report
Definition: gc.c:693
Definition: gc.c:563
size_t heap_use_size
Definition: gc.c:292
#define heap_pages_swept_slots
Definition: gc.c:615
#define heap_pages_lomem
Definition: gc.c:613
#define rb_ary_new3
Definition: intern.h:91
VALUE rb_gc_disable(void)
Definition: gc.c:5638
#define OPT(o)
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4319
#define SET_MACHINE_STACK_END(p)
Definition: gc.h:11
void ruby_init_stack(volatile VALUE *)
static int get_envparam_double(const char *name, double *default_value, double lower_bound)
Definition: gc.c:5670
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:839
VALUE flags
Definition: ruby.h:748
VALUE rb_str_new_cstr(const char *)
Definition: string.c:560
struct heap_page * free_next
Definition: gc.c:571
int rb_sigaltstack_size(void)
void * ruby_xrealloc(void *ptr, size_t new_size)
Definition: gc.c:6206
struct heap_page * page
Definition: gc.c:377
#define RVALUE_WB_PROTECTED(obj)
Definition: gc.c:709
st_table * st_init_numtable(void)
Definition: st.c:272
static VALUE gc_stress_set(VALUE self, VALUE flag)
Definition: gc.c:5594
unsigned int heap_free_slots
Definition: gc.c:137
void ruby_gc_set_params(int safe_level)
Definition: gc.c:5733
void rb_class_detach_module_subclasses(VALUE klass)
Definition: class.c:137
static void wmap_free(void *ptr)
Definition: gc.c:6350
static int is_mark_stack_empty(mark_stack_t *stack)
Definition: gc.c:3102
int rb_garbage_collect(void)
Definition: gc.c:5116
void * data
Definition: gc.c:5796
struct RVALUE::@99::@101 values
static VALUE gc_latest_gc_info(int argc, VALUE *argv, VALUE self)
Definition: gc.c:5334
#define CHAR_BIT
Definition: ruby.h:198
Definition: re.h:36
#define RANY(o)
Definition: gc.c:644
#define FL_UNSET(x, f)
Definition: ruby.h:1173
size_t rb_ary_memsize(VALUE)
Definition: array.c:548
#define RTYPEDDATA_P(v)
Definition: ruby.h:994
rb_objspace_t * objspace
Definition: gc.c:5078
#define ROBJECT(obj)
Definition: ruby.h:1117
#define LONG2NUM(x)
Definition: ruby.h:1309
unsigned int growth_max_slots
Definition: gc.c:139
static const rb_data_type_t weakmap_type
Definition: gc.c:6379
void rb_memerror(void)
Definition: gc.c:5882
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:766
void rb_gc_set_params(void)
Definition: gc.c:5773
static void heap_assign_page(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:1141
static void heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
Definition: gc.c:976
#define getenv(name)
Definition: win32.c:66
void rb_free_m_tbl(st_table *tbl)
Definition: gc.c:1443
void * ruby_xmalloc(size_t size)
Definition: gc.c:6156
static VALUE gc_profile_result(void)
Definition: gc.c:7205
Definition: gc.c:553
static VALUE wmap_aref(VALUE self, VALUE wmap)
Definition: gc.c:6662
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
Definition: gc.c:1376
#define RSTRING_PTR(str)
Definition: ruby.h:845
#define MARK_IN_BITMAP(bits, p)
Definition: gc.c:594
size_t count
Definition: gc.c:502
#define rb_exc_new3
Definition: intern.h:248
struct heap_page * prev
Definition: gc.c:570
#define finalizing
Definition: gc.c:625
static VALUE wmap_keys(VALUE self)
Definition: gc.c:6584
#define STACK_LEVEL_MAX
Definition: gc.c:3226
void * ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
Definition: gc.c:6200
struct RMatch match
Definition: gc.c:350
#define GC_HEAP_FREE_SLOTS
Definition: gc.c:100
static int rgengc_remembersetbits_set(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:4584
void rb_gc_mark_parser(void)
Definition: ripper.c:16604
#define STR_ASSOC
static void free_stack_chunks(mark_stack_t *)
Definition: gc.c:3164
static VALUE gc_profile_record_get(void)
Definition: gc.c:7016
int size
Definition: encoding.c:49
void rb_mark_generic_ivar(VALUE)
Definition: variable.c:992
#define INT2FIX(i)
Definition: ruby.h:231
void * data
Definition: gc.c:1691
static void gc_rest_sweep(rb_objspace_t *objspace)
Definition: gc.c:3050
static int wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
Definition: gc.c:6624
#define RCLASS_SUPER(c)
Definition: classext.h:16
int rb_sourceline(void)
Definition: vm.c:966
static int ready_to_gc(rb_objspace_t *objspace)
Definition: gc.c:5047
VALUE v1
Definition: gc.c:355
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
Definition: node.h:45
double invoke_time
Definition: gc.c:466
static void mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
Definition: gc.c:3387
VALUE rb_block_proc(void)
Definition: proc.c:641
#define xmalloc
Definition: defines.h:108
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:5779
rb_method_definition_t * def
Definition: method.h:100
size_t st_memsize(const st_table *)
Definition: st.c:342
#define RUBY_INTERNAL_EVENT_NEWOBJ
Definition: ruby.h:1732
Definition: gc.c:372
#define RUBY_INTERNAL_EVENT_FREEOBJ
Definition: ruby.h:1733
VALUE rb_gc_start(void)
Definition: gc.c:5183
void rb_set_errinfo(VALUE err)
Definition: eval.c:1504
static int wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6460
#define RUBY_DTRACE_GC_SWEEP_BEGIN()
Definition: probes.h:74
void(* RUBY_DATA_FUNC)(void *)
Definition: ruby.h:1001
#define ANYARGS
Definition: defines.h:98
int getrusage(int who, struct rusage *usage)
Definition: missing-pips.c:58
unsigned long rb_event_flag_t
Definition: ruby.h:1740
size_t rb_gc_stat(VALUE key)
Definition: gc.c:5555
void rb_mark_set(st_table *tbl)
Definition: gc.c:3357
struct RVALUE * next
Definition: gc.c:334
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1450
Definition: node.h:207
struct RRegexp regexp
Definition: gc.c:342
static VALUE gc_count(VALUE self)
Definition: gc.c:5235
st_table * wmap2obj
Definition: gc.c:6314
static int is_swept_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2237
size_t minor_gc_count
Definition: gc.c:469
VALUE rb_newobj_of(VALUE klass, VALUE flags)
Definition: gc.c:1354
#define RCLASS_IV_INDEX_TBL(c)
Definition: internal.h:296
#define RHASH_TBL_RAW(h)
Definition: internal.h:478
static void heap_pages_expand_sorted(rb_objspace_t *objspace)
Definition: gc.c:927
#define FL_WB_PROTECTED
Definition: ruby.h:1134
struct gc_list * global_list
Definition: gc.c:507
static void * objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size)
Definition: gc.c:6101
static void heap_add_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
Definition: gc.c:1130
static VALUE wmap_inspect(VALUE self)
Definition: gc.c:6484
uint8_t key[16]
Definition: random.c:1250
VALUE rb_any_to_s(VALUE)
Definition: object.c:453
size_t max_free_slots
Definition: gc.c:441
static void gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
Definition: gc.c:3057
VALUE rb_obj_is_fiber(VALUE obj)
Definition: cont.c:370
static stack_chunk_t * stack_chunk_alloc(void)
Definition: gc.c:3090
static int rb_special_const_p(VALUE obj)
Definition: ruby.h:1687
int ruby_gc_debug_indent
Definition: gc.c:648
void rb_gc_writebarrier_remember_promoted(VALUE obj)
Definition: gc.c:4782
gc_profile_record * records
Definition: gc.c:458
#define RTEST(v)
Definition: ruby.h:437
VALUE rb_proc_new(VALUE(*)(ANYARGS), VALUE)
Definition: proc.c:2321
Definition: node.h:139
#define T_STRING
Definition: ruby.h:482
void rb_gc_resurrect(VALUE obj)
Definition: gc.c:3612
#define PRIuSIZE
Definition: ruby.h:179
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
#define RREGEXP(obj)
Definition: ruby.h:1122
static void rb_objspace_call_finalizer(rb_objspace_t *objspace)
Definition: gc.c:2150
size_t total_allocated_object_num_at_gc_start
Definition: gc.c:498
VALUE rb_obj_rgengc_promoted_p(VALUE obj)
Definition: gc.c:4842
struct rb_encoding_entry * list
Definition: encoding.c:47
static int get_envparam_int(const char *name, unsigned int *default_value, int lower_bound)
Definition: gc.c:5650
static int wmap_each_value_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6547
void rb_gc_mark_unlinked_live_method_entries(void *pvm)
Definition: vm_method.c:123
size_t last_major_gc
Definition: gc.c:523
#define heap_pages_length
Definition: gc.c:612
int each_obj_callback(void *, void *, size_t, void *)
Definition: gc.c:1687
#define T_FALSE
Definition: ruby.h:491
#define T_FILE
Definition: ruby.h:488
struct rb_heap_struct rb_heap_t
rb_objspace_t * rb_objspace_alloc(void)
Definition: gc.c:873
size_t length
Definition: gc.c:433
struct rb_classext_struct rb_classext_t
Definition: ruby.h:788
static int free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
Definition: gc.c:1434
double growth_factor
Definition: gc.c:138
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
VALUE rb_eval_cmd(VALUE, VALUE, int)
Definition: vm_eval.c:1463
RVALUE * freelist
Definition: gc.c:565
struct mark_stack mark_stack_t
#define rb_thread_raised_p(th, f)
Definition: eval_intern.h:225
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
size_t old_object_limit
Definition: gc.c:528
rb_heap_t eden_heap
Definition: gc.c:427
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
int rb_atomic_t
Definition: ruby_atomic.h:120
#define heap_pages_sorted
Definition: gc.c:610
#define T_CLASS
Definition: ruby.h:478
struct rmatch_offset * char_offset
Definition: re.h:41
#define heap_pages_used
Definition: gc.c:611
#define SET_STACK_END
Definition: gc.c:3221
#define rb_safe_level()
Definition: tcltklib.c:95
#define RVALUE_WB_PROTECTED_RAW(obj)
Definition: gc.c:708
static void gc_event_hook_body(rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data)
Definition: gc.c:1272
#define ROBJECT_EMBED
Definition: ruby.h:773
#define PRIdSIZE
Definition: ruby.h:176
static void init_mark_stack(mark_stack_t *stack)
Definition: gc.c:3203
void rb_gc_mark_maybe(VALUE obj)
Definition: gc.c:3537
VALUE self
Definition: vm_core.h:349
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, klass_, data_)
Definition: vm_core.h:1031
VALUE gc_stress
Definition: gc.c:148
#define assert(condition)
Definition: ossl.h:45
static void shrink_stack_chunk_cache(mark_stack_t *stack)
Definition: gc.c:3116
const char * name
Definition: nkf.c:208
#define FL_SET(x, f)
Definition: ruby.h:1172
struct RData data
Definition: gc.c:344
VALUE self
Definition: vm_core.h:303
#define ID2SYM(x)
Definition: ruby.h:355
Definition: node.h:61
#define GC_HEAP_INIT_SLOTS
Definition: gc.c:103
static int heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:5032
const char * rb_id2name(ID id)
Definition: ripper.c:17227
static void gc_prof_setup_new_record(rb_objspace_t *objspace, int reason)
Definition: gc.c:6760
void rb_gc_mark_global_tbl(void)
Definition: variable.c:562
#define ruby_native_thread_p()
Definition: tcltklib.c:83
struct rb_objspace::@103 heap_pages
Definition: ruby.h:762
static int is_live_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2256
#define GC_OLDMALLOC_LIMIT_MIN
Definition: gc.c:126
unsigned int heap_init_slots
Definition: gc.c:136
VALUE rb_inspect(VALUE)
Definition: object.c:471
#define hi
Definition: siphash.c:22
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
Definition: gc.c:64
#define RMATCH(obj)
Definition: re.h:51
static void make_io_deferred(rb_objspace_t *objspace, RVALUE *p)
Definition: gc.c:1481
uintptr_t bits_t
Definition: gc.c:370
static void gc_mark_stacked_objects(rb_objspace_t *)
Definition: gc.c:3968
static int garbage_collect_with_gvl(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
Definition: gc.c:5092
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:996
void rb_secure(int)
Definition: safe.c:88
Definition: node.h:31
Definition: ruby.h:920
struct heap_page * using_page
Definition: gc.c:410
#define rb_check_frozen(obj)
Definition: intern.h:277
#define RBIGNUM_EMBED_FLAG
Definition: ruby.h:1100
struct RTypedData typeddata
Definition: gc.c:345
RUBY_EXTERN VALUE rb_stdout
Definition: ruby.h:1627
#define RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()
Definition: probes.h:67
void rb_gc_call_finalizer_at_exit(void)
Definition: gc.c:2144
size_t rb_generic_ivar_memsize(VALUE)
Definition: variable.c:1040
VALUE rb_gc_enable(void)
Definition: gc.c:5616
size_t remembered_shady_object_count
Definition: gc.c:525
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1077
#define vsnprintf
Definition: subst.h:7
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1165
struct rb_objspace rb_objspace_t
struct RArray array
Definition: gc.c:341
static int verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, void *ptr)
Definition: gc.c:4194
#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK
Definition: ruby.h:1737
#define TYPE_NAME(t)
void void xfree(void *)
static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:3624
Definition: node.h:41
#define RUBY_INTERNAL_EVENT_GC_END_SWEEP
Definition: ruby.h:1736
static void gc_before_heap_sweep(rb_objspace_t *objspace, rb_heap_t *heap)
Definition: gc.c:2830
struct RBasic basic
Definition: gc.c:336
#define RHASH_EMPTY_P(h)
Definition: ruby.h:931
VALUE rb_define_module(const char *name)
Definition: class.c:746
#define RUBY_DTRACE_GC_MARK_BEGIN()
Definition: probes.h:68
#define gc_prof_enabled(objspace)
Definition: gc.c:691
static void heap_set_increment(rb_objspace_t *objspace, size_t minimum_limit)
Definition: gc.c:1162
void rb_mark_hash(st_table *tbl)
Definition: gc.c:3381
VALUE v3
Definition: gc.c:357
#define GC_MALLOC_LIMIT_MIN
Definition: gc.c:116
#define rb_intern(str)
each_obj_callback * callback
Definition: gc.c:1690
void * data
Definition: ruby.h:961
static VALUE undefine_final(VALUE os, VALUE obj)
Definition: gc.c:1905
VALUE rb_str_buf_new(long)
Definition: string.c:891
static VALUE gc_profile_clear(void)
Definition: gc.c:6949
#define T_ZOMBIE
Definition: ruby.h:499
void rb_gc_mark_encodings(void)
Definition: encoding.c:236
#define SYMBOL_P(x)
Definition: ruby.h:354
#define RCLASS(obj)
Definition: ruby.h:1118
#define T_NONE
Definition: ruby.h:475
static void * objspace_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
Definition: gc.c:6178
int during_minor_gc
Definition: gc.c:518
#define HEAP_ALIGN_LOG
Definition: gc.c:549
static int wmap_each_key_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:6524
struct RString string
Definition: gc.c:340
#define FL_UNSET2(x, f)
Definition: gc.c:706
#define GET_HEAP_REMEMBERSET_BITS(x)
Definition: gc.c:586
static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size)
Definition: gc.c:6142
#define NULL
Definition: _sdbm.c:103
stack_chunk_t * cache
Definition: gc.c:400
#define RTYPEDDATA_TYPE(v)
Definition: ruby.h:995
struct RClass klass
Definition: gc.c:338
Definition: ruby.h:790
#define Qundef
Definition: ruby.h:428
#define T_ICLASS
Definition: ruby.h:479
#define GC_OLDMALLOC_LIMIT_MAX
Definition: gc.c:132
VALUE flags
Definition: gc.c:333
static VALUE wmap_finalize(VALUE self, VALUE objid)
Definition: gc.c:6424
static VALUE gc_stat(int argc, VALUE *argv, VALUE self)
Definition: gc.c:5533
static void mark_set(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:3348
void onig_free(regex_t *reg)
Definition: regcomp.c:5583
#define GET_HEAP_PAGE(x)
Definition: gc.c:584
st_index_t num_entries
Definition: st.h:85
#define malloc_limit
Definition: gc.c:607
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:924
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
#define ruby_verbose
Definition: ruby.h:1475
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
#define CALC_EXACT_MALLOC_SIZE
Definition: gc.c:247
struct heap_page ** sorted
Definition: gc.c:431
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
static ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS void mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
Definition: gc.c:3290
double oldmalloc_limit_growth_factor
Definition: gc.c:146
struct RComplex complex
Definition: gc.c:352
size_t swept_slots
Definition: gc.c:439
#define RSTRING_NOEMBED
Definition: ruby.h:834
size_t rb_str_memsize(VALUE)
Definition: string.c:953
struct stack_chunk stack_chunk_t
void rb_warn(const char *fmt,...)
Definition: error.c:223
free(psz)
static VALUE gc_profile_enable(void)
Definition: gc.c:7284
int before_sweep
Definition: gc.c:573
#define SIZET2NUM(v)
Definition: ruby.h:262
VALUE rb_eArgError
Definition: error.c:549
#define T_REGEXP
Definition: ruby.h:483
size_t min_free_slots
Definition: gc.c:440
#define CLEAR_IN_BITMAP(bits, p)
Definition: gc.c:595
Definition: node.h:137
#define T_MASK
Definition: md5.c:131
rb_objspace_t * objspace
Definition: gc.c:6455
#define rb_jmp_buf
Definition: gc.c:89
struct rb_objspace::@106 rgengc
#define FL_PROMOTED
Definition: ruby.h:1135
size_t limit
Definition: gc.c:568
#define BDIGIT
Definition: bigdecimal.h:47
VALUE rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
Definition: gc.c:1369
static void should_be_finalizable(VALUE obj)
Definition: gc.c:1930
char ** argv
Definition: ruby.c:132
Definition: ruby.h:909
static void should_be_callable(VALUE block)
Definition: gc.c:1922
struct heap_page * free_pages
Definition: gc.c:409
#define DBL2NUM(dbl)
Definition: ruby.h:815
static void gc_setup_mark_bits(struct heap_page *page)
Definition: gc.c:2704
#define __asm__
static void heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
Definition: gc.c:957
static void gc_finalize_deferred_register(void)
Definition: gc.c:2118
#define TRY_WITH_GC(alloc)
Definition: gc.c:6080
#define SIGNED_VALUE
Definition: ruby.h:90
struct stack_chunk * next
Definition: gc.c:395
Definition: gc.c:398
#define GET_VM()
Definition: vm_core.h:917
struct heap_page * sweep_pages
Definition: gc.c:411
static int gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:3551
size_t remembered_shady_object_limit
Definition: gc.c:526