Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 "eval_intern.h"
21 #include "vm_core.h"
22 #include "internal.h"
23 #include "gc.h"
24 #include "constant.h"
25 #include "ruby_atomic.h"
26 #include "probes.h"
27 #include <stdio.h>
28 #include <setjmp.h>
29 #include <sys/types.h>
30 #include <assert.h>
31
32 #ifdef HAVE_SYS_TIME_H
33 #include <sys/time.h>
34 #endif
35
36 #ifdef HAVE_SYS_RESOURCE_H
37 #include <sys/resource.h>
38 #endif
39 #if defined(__native_client__) && defined(NACL_NEWLIB)
40 # include "nacl/resource.h"
41 # undef HAVE_POSIX_MEMALIGN
42 # undef HAVE_MEMALIGN
43
44 #endif
45
46 #if defined _WIN32 || defined __CYGWIN__
47 #include <windows.h>
48 #elif defined(HAVE_POSIX_MEMALIGN)
49 #elif defined(HAVE_MEMALIGN)
50 #include <malloc.h>
51 #endif
52
53 #ifdef HAVE_VALGRIND_MEMCHECK_H
54 # include <valgrind/memcheck.h>
55 # ifndef VALGRIND_MAKE_MEM_DEFINED
56 # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
57 # endif
58 # ifndef VALGRIND_MAKE_MEM_UNDEFINED
59 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
60 # endif
61 #else
62 # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
63 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
64 #endif
65
66 #define rb_setjmp(env) RUBY_SETJMP(env)
67 #define rb_jmp_buf rb_jmpbuf_t
68
69 #ifndef GC_MALLOC_LIMIT
70 #define GC_MALLOC_LIMIT 8000000
71 #endif
72 #define HEAP_MIN_SLOTS 10000
73 #define FREE_MIN 4096
74
75 typedef struct {
76 unsigned int initial_malloc_limit;
77 unsigned int initial_heap_min_slots;
78 unsigned int initial_free_min;
79 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
80 int gc_stress;
81 #endif
82 } ruby_gc_params_t;
83
84 static ruby_gc_params_t initial_params = {
85 GC_MALLOC_LIMIT,
86 HEAP_MIN_SLOTS,
87 FREE_MIN,
88 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
89 FALSE,
90 #endif
91 };
92
93 #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
94
95 #ifndef GC_PROFILE_MORE_DETAIL
96 #define GC_PROFILE_MORE_DETAIL 0
97 #endif
98
99 typedef struct gc_profile_record {
100 double gc_time;
101 double gc_invoke_time;
102
103 size_t heap_total_objects;
104 size_t heap_use_size;
105 size_t heap_total_size;
106
107 int is_marked;
108
109 #if GC_PROFILE_MORE_DETAIL
110 double gc_mark_time;
111 double gc_sweep_time;
112
113 size_t heap_use_slots;
114 size_t heap_live_objects;
115 size_t heap_free_objects;
116
117 int have_finalize;
118
119 size_t allocate_increase;
120 size_t allocate_limit;
121 #endif
122 } gc_profile_record;
123
124 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
125 #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
126 #endif
127
128 typedef struct RVALUE {
129 union {
130 struct {
131 VALUE flags; /* always 0 for freed obj */
132 struct RVALUE *next;
133 } free;
134 struct RBasic basic;
135 struct RObject object;
136 struct RClass klass;
137 struct RFloat flonum;
138 struct RString string;
139 struct RArray array;
140 struct RRegexp regexp;
141 struct RHash hash;
142 struct RData data;
143 struct RTypedData typeddata;
144 struct RStruct rstruct;
145 struct RBignum bignum;
146 struct RFile file;
147 struct RNode node;
148 struct RMatch match;
149 struct RRational rational;
150 struct RComplex complex;
151 } as;
152 #ifdef GC_DEBUG
153 const char *file;
154 int line;
155 #endif
156 } RVALUE;
157
158 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
159 #pragma pack(pop)
160 #endif
161
162 struct heaps_slot {
163 struct heaps_header *header;
164 uintptr_t *bits;
165 RVALUE *freelist;
166 struct heaps_slot *next;
167 struct heaps_slot *prev;
168 struct heaps_slot *free_next;
169 };
170
171 struct heaps_header {
172 struct heaps_slot *base;
173 uintptr_t *bits;
174 RVALUE *start;
175 RVALUE *end;
176 size_t limit;
177 };
178
179 struct heaps_free_bitmap {
180 struct heaps_free_bitmap *next;
181 };
182
183 struct gc_list {
184 VALUE *varptr;
185 struct gc_list *next;
186 };
187
188 #define STACK_CHUNK_SIZE 500
189
190 typedef struct stack_chunk {
191 VALUE data[STACK_CHUNK_SIZE];
192 struct stack_chunk *next;
193 } stack_chunk_t;
194
195 typedef struct mark_stack {
196 stack_chunk_t *chunk;
197 stack_chunk_t *cache;
198 size_t index;
199 size_t limit;
200 size_t cache_size;
201 size_t unused_cache_size;
202 } mark_stack_t;
203
204 #ifndef CALC_EXACT_MALLOC_SIZE
205 #define CALC_EXACT_MALLOC_SIZE 0
206 #endif
207
208 typedef struct rb_objspace {
209 struct {
210 size_t limit;
211 size_t increase;
212 #if CALC_EXACT_MALLOC_SIZE
213 size_t allocated_size;
214 size_t allocations;
215 #endif
216 } malloc_params;
217 struct {
218 size_t increment;
219 struct heaps_slot *ptr;
220 struct heaps_slot *sweep_slots;
221 struct heaps_slot *free_slots;
222 struct heaps_header **sorted;
223 size_t length;
224 size_t used;
225 struct heaps_free_bitmap *free_bitmap;
226 RVALUE *range[2];
227 struct heaps_header *freed;
228 size_t marked_num;
229 size_t free_num;
230 size_t free_min;
231 size_t final_num;
232 size_t do_heap_free;
233 } heap;
234 struct {
235 int dont_gc;
236 int dont_lazy_sweep;
237 int during_gc;
238 rb_atomic_t finalizing;
239 } flags;
240 struct {
241 st_table *table;
242 RVALUE *deferred;
243 } final;
244 mark_stack_t mark_stack;
245 struct {
246 int run;
247 gc_profile_record *record;
248 size_t count;
249 size_t size;
250 double invoke_time;
251 } profile;
252 struct gc_list *global_list;
253 size_t count;
254 size_t total_allocated_object_num;
255 size_t total_freed_object_num;
256 int gc_stress;
257
258 struct mark_func_data_struct {
259 void *data;
260 void (*mark_func)(VALUE v, void *data);
261 } *mark_func_data;
262 } rb_objspace_t;
263
264 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
265 #define rb_objspace (*GET_VM()->objspace)
266 #define ruby_initial_gc_stress initial_params.gc_stress
267 int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
268 #else
269 static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}};
270 int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
271 #endif
272 #define malloc_limit objspace->malloc_params.limit
273 #define malloc_increase objspace->malloc_params.increase
274 #define heaps objspace->heap.ptr
275 #define heaps_length objspace->heap.length
276 #define heaps_used objspace->heap.used
277 #define lomem objspace->heap.range[0]
278 #define himem objspace->heap.range[1]
279 #define heaps_inc objspace->heap.increment
280 #define heaps_freed objspace->heap.freed
281 #define dont_gc objspace->flags.dont_gc
282 #define during_gc objspace->flags.during_gc
283 #define finalizing objspace->flags.finalizing
284 #define finalizer_table objspace->final.table
285 #define deferred_final_list objspace->final.deferred
286 #define global_List objspace->global_list
287 #define ruby_gc_stress objspace->gc_stress
288 #define initial_malloc_limit initial_params.initial_malloc_limit
289 #define initial_heap_min_slots initial_params.initial_heap_min_slots
290 #define initial_free_min initial_params.initial_free_min
291
292 #define is_lazy_sweeping(objspace) ((objspace)->heap.sweep_slots != 0)
293
294 #if SIZEOF_LONG == SIZEOF_VOIDP
295 # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
296 # define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */
297 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
298 # define nonspecial_obj_id(obj) LL2NUM((SIGNED_VALUE)(obj) / 2)
299 # define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
300 ((objid) ^ FIXNUM_FLAG) : (NUM2PTR(objid) << 1))
301 #else
302 # error not supported
303 #endif
304
305 #define RANY(o) ((RVALUE*)(o))
306 #define has_free_object (objspace->heap.free_slots && objspace->heap.free_slots->freelist)
307
308 #define HEAP_HEADER(p) ((struct heaps_header *)(p))
309 #define GET_HEAP_HEADER(x) (HEAP_HEADER((uintptr_t)(x) & ~(HEAP_ALIGN_MASK)))
310 #define GET_HEAP_SLOT(x) (GET_HEAP_HEADER(x)->base)
311 #define GET_HEAP_BITMAP(x) (GET_HEAP_HEADER(x)->bits)
312 #define NUM_IN_SLOT(p) (((uintptr_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE))
313 #define BITMAP_INDEX(p) (NUM_IN_SLOT(p) / (sizeof(uintptr_t) * CHAR_BIT))
314 #define BITMAP_OFFSET(p) (NUM_IN_SLOT(p) & ((sizeof(uintptr_t) * CHAR_BIT)-1))
315 #define MARKED_IN_BITMAP(bits, p) (bits[BITMAP_INDEX(p)] & ((uintptr_t)1 << BITMAP_OFFSET(p)))
316
317 #ifndef HEAP_ALIGN_LOG
318 /* default tiny heap size: 16KB */
319 #define HEAP_ALIGN_LOG 14
320 #endif
321
322 #define CEILDIV(i, mod) (((i) + (mod) - 1)/(mod))
323
324 enum {
325 HEAP_ALIGN = (1UL << HEAP_ALIGN_LOG),
326 HEAP_ALIGN_MASK = (~(~0UL << HEAP_ALIGN_LOG)),
327 REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5),
328 HEAP_SIZE = (HEAP_ALIGN - REQUIRED_SIZE_BY_MALLOC),
329 HEAP_OBJ_LIMIT = (unsigned int)((HEAP_SIZE - sizeof(struct heaps_header))/sizeof(struct RVALUE)),
330 HEAP_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_SIZE, sizeof(struct RVALUE)), sizeof(uintptr_t) * CHAR_BIT)
331 };
332
333 int ruby_gc_debug_indent = 0;
334 VALUE rb_mGC;
335 extern st_table *rb_class_tbl;
336 int ruby_disable_gc_stress = 0;
337
338 static void rb_objspace_call_finalizer(rb_objspace_t *objspace);
339 static VALUE define_final0(VALUE obj, VALUE block);
340 VALUE rb_define_final(VALUE obj, VALUE block);
341 VALUE rb_undefine_final(VALUE obj);
342 static void run_final(rb_objspace_t *objspace, VALUE obj);
343 static void initial_expand_heap(rb_objspace_t *objspace);
344
345 static void negative_size_allocation_error(const char *);
346 static void *aligned_malloc(size_t, size_t);
347 static void aligned_free(void *);
348
349 static void init_mark_stack(mark_stack_t *stack);
350
351 static VALUE lazy_sweep_enable(void);
352 static int garbage_collect(rb_objspace_t *);
353 static int gc_prepare_free_objects(rb_objspace_t *);
354 static void mark_tbl(rb_objspace_t *, st_table *);
355 static void rest_sweep(rb_objspace_t *);
356 static void gc_mark_stacked_objects(rb_objspace_t *);
357
358 static double getrusage_time(void);
359 static inline void gc_prof_timer_start(rb_objspace_t *);
360 static inline void gc_prof_timer_stop(rb_objspace_t *, int);
361 static inline void gc_prof_mark_timer_start(rb_objspace_t *);
362 static inline void gc_prof_mark_timer_stop(rb_objspace_t *);
363 static inline void gc_prof_sweep_timer_start(rb_objspace_t *);
364 static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
365 static inline void gc_prof_set_malloc_info(rb_objspace_t *);
366
367
368 /*
369 --------------------------- ObjectSpace -----------------------------
370 */
371
372 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
373 rb_objspace_t *
374 rb_objspace_alloc(void)
375 {
376 rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t));
377 memset(objspace, 0, sizeof(*objspace));
378 malloc_limit = initial_malloc_limit;
379 ruby_gc_stress = ruby_initial_gc_stress;
380
381 return objspace;
382 }
383 #endif
384
385 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
386 static void free_stack_chunks(mark_stack_t *);
387
388 void
389 rb_objspace_free(rb_objspace_t *objspace)
390 {
391 rest_sweep(objspace);
392 if (objspace->profile.record) {
393 free(objspace->profile.record);
394 objspace->profile.record = 0;
395 }
396 if (global_List) {
397 struct gc_list *list, *next;
398 for (list = global_List; list; list = next) {
399 next = list->next;
400 xfree(list);
401 }
402 }
403 if (objspace->heap.free_bitmap) {
404 struct heaps_free_bitmap *list, *next;
405 for (list = objspace->heap.free_bitmap; list; list = next) {
406 next = list->next;
407 free(list);
408 }
409 }
410 if (objspace->heap.sorted) {
411 size_t i;
412 for (i = 0; i < heaps_used; ++i) {
413 free(objspace->heap.sorted[i]->bits);
414 aligned_free(objspace->heap.sorted[i]);
415 }
416 free(objspace->heap.sorted);
417 heaps_used = 0;
418 heaps = 0;
419 }
420 free_stack_chunks(&objspace->mark_stack);
421 free(objspace);
422 }
423 #endif
424
425 void
426 rb_global_variable(VALUE *var)
427 {
428 rb_gc_register_address(var);
429 }
430
431 static void
432 allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
433 {
434 struct heaps_header **p;
435 struct heaps_free_bitmap *bits;
436 size_t size, add, i;
437
438 size = next_heaps_length*sizeof(struct heaps_header *);
439 add = next_heaps_length - heaps_used;
440
441 if (heaps_used > 0) {
442 p = (struct heaps_header **)realloc(objspace->heap.sorted, size);
443 if (p) objspace->heap.sorted = p;
444 }
445 else {
446 p = objspace->heap.sorted = (struct heaps_header **)malloc(size);
447 }
448
449 if (p == 0) {
450 during_gc = 0;
451 rb_memerror();
452 }
453
454 for (i = 0; i < add; i++) {
455 bits = (struct heaps_free_bitmap *)malloc(HEAP_BITMAP_LIMIT * sizeof(uintptr_t));
456 if (bits == 0) {
457 during_gc = 0;
458 rb_memerror();
459 return;
460 }
461 bits->next = objspace->heap.free_bitmap;
462 objspace->heap.free_bitmap = bits;
463 }
464 }
465
466 static void
467 link_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
468 {
469 slot->free_next = objspace->heap.free_slots;
470 objspace->heap.free_slots = slot;
471 }
472
473 static void
474 unlink_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
475 {
476 objspace->heap.free_slots = slot->free_next;
477 slot->free_next = NULL;
478 }
479
480 static void
481 assign_heap_slot(rb_objspace_t *objspace)
482 {
483 RVALUE *p, *pend, *membase;
484 struct heaps_slot *slot;
485 size_t hi, lo, mid;
486 size_t objs;
487
488 objs = HEAP_OBJ_LIMIT;
489 p = (RVALUE*)aligned_malloc(HEAP_ALIGN, HEAP_SIZE);
490 if (p == 0) {
491 during_gc = 0;
492 rb_memerror();
493 }
494 slot = (struct heaps_slot *)malloc(sizeof(struct heaps_slot));
495 if (slot == 0) {
496 aligned_free(p);
497 during_gc = 0;
498 rb_memerror();
499 }
500 MEMZERO((void*)slot, struct heaps_slot, 1);
501
502 slot->next = heaps;
503 if (heaps) heaps->prev = slot;
504 heaps = slot;
505
506 membase = p;
507 p = (RVALUE*)((VALUE)p + sizeof(struct heaps_header));
508 if ((VALUE)p % sizeof(RVALUE) != 0) {
509 p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
510 objs = (HEAP_SIZE - (size_t)((VALUE)p - (VALUE)membase))/sizeof(RVALUE);
511 }
512
513 lo = 0;
514 hi = heaps_used;
515 while (lo < hi) {
516 register RVALUE *mid_membase;
517 mid = (lo + hi) / 2;
518 mid_membase = (RVALUE *)objspace->heap.sorted[mid];
519 if (mid_membase < membase) {
520 lo = mid + 1;
521 }
522 else if (mid_membase > membase) {
523 hi = mid;
524 }
525 else {
526 rb_bug("same heap slot is allocated: %p at %"PRIuVALUE, (void *)membase, (VALUE)mid);
527 }
528 }
529 if (hi < heaps_used) {
530 MEMMOVE(&objspace->heap.sorted[hi+1], &objspace->heap.sorted[hi], struct heaps_header*, heaps_used - hi);
531 }
532 heaps->header = (struct heaps_header *)membase;
533 objspace->heap.sorted[hi] = heaps->header;
534 objspace->heap.sorted[hi]->start = p;
535 objspace->heap.sorted[hi]->end = (p + objs);
536 objspace->heap.sorted[hi]->base = heaps;
537 objspace->heap.sorted[hi]->limit = objs;
538 assert(objspace->heap.free_bitmap != NULL);
539 heaps->bits = (uintptr_t *)objspace->heap.free_bitmap;
540 objspace->heap.sorted[hi]->bits = (uintptr_t *)objspace->heap.free_bitmap;
541 objspace->heap.free_bitmap = objspace->heap.free_bitmap->next;
542 memset(heaps->bits, 0, HEAP_BITMAP_LIMIT * sizeof(uintptr_t));
543 pend = p + objs;
544 if (lomem == 0 || lomem > p) lomem = p;
545 if (himem < pend) himem = pend;
546 heaps_used++;
547
548 while (p < pend) {
549 p->as.free.flags = 0;
550 p->as.free.next = heaps->freelist;
551 heaps->freelist = p;
552 p++;
553 }
554 link_free_heap_slot(objspace, heaps);
555 }
556
557 static void
558 add_heap_slots(rb_objspace_t *objspace, size_t add)
559 {
560 size_t i;
561 size_t next_heaps_length;
562
563 next_heaps_length = heaps_used + add;
564
565 if (next_heaps_length > heaps_length) {
566 allocate_sorted_heaps(objspace, next_heaps_length);
567 heaps_length = next_heaps_length;
568 }
569
570 for (i = 0; i < add; i++) {
571 assign_heap_slot(objspace);
572 }
573 heaps_inc = 0;
574 }
575
576 static void
577 init_heap(rb_objspace_t *objspace)
578 {
579 add_heap_slots(objspace, HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT);
580 init_mark_stack(&objspace->mark_stack);
581
582 #ifdef USE_SIGALTSTACK
583 {
584 /* altstack of another threads are allocated in another place */
585 rb_thread_t *th = GET_THREAD();
586 void *tmp = th->altstack;
587 th->altstack = malloc(rb_sigaltstack_size());
588 free(tmp); /* free previously allocated area */
589 }
590 #endif
591
592 objspace->profile.invoke_time = getrusage_time();
593 finalizer_table = st_init_numtable();
594 }
595
596 static void
597 initial_expand_heap(rb_objspace_t *objspace)
598 {
599 size_t min_size = initial_heap_min_slots / HEAP_OBJ_LIMIT;
600
601 if (min_size > heaps_used) {
602 add_heap_slots(objspace, min_size - heaps_used);
603 }
604 }
605
606 static void
607 set_heaps_increment(rb_objspace_t *objspace)
608 {
609 size_t next_heaps_length = (size_t)(heaps_used * 1.8);
610
611 if (next_heaps_length == heaps_used) {
612 next_heaps_length++;
613 }
614
615 heaps_inc = next_heaps_length - heaps_used;
616
617 if (next_heaps_length > heaps_length) {
618 allocate_sorted_heaps(objspace, next_heaps_length);
619 heaps_length = next_heaps_length;
620 }
621 }
622
623 static int
624 heaps_increment(rb_objspace_t *objspace)
625 {
626 if (heaps_inc > 0) {
627 assign_heap_slot(objspace);
628 heaps_inc--;
629 return TRUE;
630 }
631 return FALSE;
632 }
633
634 static VALUE
635 newobj(VALUE klass, VALUE flags)
636 {
637 rb_objspace_t *objspace = &rb_objspace;
638 VALUE obj;
639
640 if (UNLIKELY(during_gc)) {
641 dont_gc = 1;
642 during_gc = 0;
643 rb_bug("object allocation during garbage collection phase");
644 }
645
646 if (UNLIKELY(ruby_gc_stress && !ruby_disable_gc_stress)) {
647 if (!garbage_collect(objspace)) {
648 during_gc = 0;
649 rb_memerror();
650 }
651 }
652
653 if (UNLIKELY(!has_free_object)) {
654 if (!gc_prepare_free_objects(objspace)) {
655 during_gc = 0;
656 rb_memerror();
657 }
658 }
659
660 obj = (VALUE)objspace->heap.free_slots->freelist;
661 objspace->heap.free_slots->freelist = RANY(obj)->as.free.next;
662 if (objspace->heap.free_slots->freelist == NULL) {
663 unlink_free_heap_slot(objspace, objspace->heap.free_slots);
664 }
665
666 MEMZERO((void*)obj, RVALUE, 1);
667 #ifdef GC_DEBUG
668 RANY(obj)->file = rb_sourcefile();
669 RANY(obj)->line = rb_sourceline();
670 #endif
671 objspace->total_allocated_object_num++;
672
673 return obj;
674 }
675
676 VALUE
677 rb_newobj(void)
678 {
679 return newobj(0, T_NONE);
680 }
681
682 VALUE
683 rb_newobj_of(VALUE klass, VALUE flags)
684 {
685 VALUE obj;
686
687 obj = newobj(klass, flags);
688 OBJSETUP(obj, klass, flags);
689
690 return obj;
691 }
692
693 NODE*
694 rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
695 {
696 NODE *n = (NODE*)rb_newobj();
697
698 n->flags |= T_NODE;
699 nd_set_type(n, type);
700
701 n->u1.value = a0;
702 n->u2.value = a1;
703 n->u3.value = a2;
704
705 return n;
706 }
707
708 VALUE
709 rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
710 {
711 NEWOBJ(data, struct RData);
712 if (klass) Check_Type(klass, T_CLASS);
713 OBJSETUP(data, klass, T_DATA);
714 data->data = datap;
715 data->dfree = dfree;
716 data->dmark = dmark;
717
718 return (VALUE)data;
719 }
720
721 VALUE
722 rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
723 {
724 NEWOBJ(data, struct RTypedData);
725
726 if (klass) Check_Type(klass, T_CLASS);
727
728 OBJSETUP(data, klass, T_DATA);
729
730 data->data = datap;
731 data->typed_flag = 1;
732 data->type = type;
733
734 return (VALUE)data;
735 }
736
737 size_t
738 rb_objspace_data_type_memsize(VALUE obj)
739 {
740 if (RTYPEDDATA_P(obj) && RTYPEDDATA_TYPE(obj)->function.dsize) {
741 return RTYPEDDATA_TYPE(obj)->function.dsize(RTYPEDDATA_DATA(obj));
742 }
743 else {
744 return 0;
745 }
746 }
747
748 const char *
749 rb_objspace_data_type_name(VALUE obj)
750 {
751 if (RTYPEDDATA_P(obj)) {
752 return RTYPEDDATA_TYPE(obj)->wrap_struct_name;
753 }
754 else {
755 return 0;
756 }
757 }
758
759 static void gc_mark(rb_objspace_t *objspace, VALUE ptr);
760 static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr);
761
762 static inline int
763 is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
764 {
765 register RVALUE *p = RANY(ptr);
766 register struct heaps_header *heap;
767 register size_t hi, lo, mid;
768
769 if (p < lomem || p > himem) return FALSE;
770 if ((VALUE)p % sizeof(RVALUE) != 0) return FALSE;
771
772 /* check if p looks like a pointer using bsearch*/
773 lo = 0;
774 hi = heaps_used;
775 while (lo < hi) {
776 mid = (lo + hi) / 2;
777 heap = objspace->heap.sorted[mid];
778 if (heap->start <= p) {
779 if (p < heap->end)
780 return TRUE;
781 lo = mid + 1;
782 }
783 else {
784 hi = mid;
785 }
786 }
787 return FALSE;
788 }
789
790 static int
791 free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
792 {
793 if (!me->mark) {
794 rb_free_method_entry(me);
795 }
796 return ST_CONTINUE;
797 }
798
799 void
800 rb_free_m_table(st_table *tbl)
801 {
802 st_foreach(tbl, free_method_entry_i, 0);
803 st_free_table(tbl);
804 }
805
806 static int
807 free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data)
808 {
809 xfree(ce);
810 return ST_CONTINUE;
811 }
812
813 void
814 rb_free_const_table(st_table *tbl)
815 {
816 st_foreach(tbl, free_const_entry_i, 0);
817 st_free_table(tbl);
818 }
819
820 static int obj_free(rb_objspace_t *, VALUE);
821
822 static inline struct heaps_slot *
823 add_slot_local_freelist(rb_objspace_t *objspace, RVALUE *p)
824 {
825 struct heaps_slot *slot;
826
827 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
828 p->as.free.flags = 0;
829 slot = GET_HEAP_SLOT(p);
830 p->as.free.next = slot->freelist;
831 slot->freelist = p;
832
833 return slot;
834 }
835
836 static void
837 unlink_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
838 {
839 if (slot->prev)
840 slot->prev->next = slot->next;
841 if (slot->next)
842 slot->next->prev = slot->prev;
843 if (heaps == slot)
844 heaps = slot->next;
845 if (objspace->heap.sweep_slots == slot)
846 objspace->heap.sweep_slots = slot->next;
847 slot->prev = NULL;
848 slot->next = NULL;
849 }
850
851 static void
852 free_unused_heaps(rb_objspace_t *objspace)
853 {
854 size_t i, j;
855 struct heaps_header *last = 0;
856
857 for (i = j = 1; j < heaps_used; i++) {
858 if (objspace->heap.sorted[i]->limit == 0) {
859 struct heaps_header* h = objspace->heap.sorted[i];
860 ((struct heaps_free_bitmap *)(h->bits))->next =
861 objspace->heap.free_bitmap;
862 objspace->heap.free_bitmap = (struct heaps_free_bitmap *)h->bits;
863 if (!last) {
864 last = objspace->heap.sorted[i];
865 }
866 else {
867 aligned_free(objspace->heap.sorted[i]);
868 }
869 heaps_used--;
870 }
871 else {
872 if (i != j) {
873 objspace->heap.sorted[j] = objspace->heap.sorted[i];
874 }
875 j++;
876 }
877 }
878 if (last) {
879 if (last < heaps_freed) {
880 aligned_free(heaps_freed);
881 heaps_freed = last;
882 }
883 else {
884 aligned_free(last);
885 }
886 }
887 }
888 static inline void
889 make_deferred(RVALUE *p)
890 {
891 p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_ZOMBIE;
892 }
893
894 static inline void
895 make_io_deferred(RVALUE *p)
896 {
897 rb_io_t *fptr = p->as.file.fptr;
898 make_deferred(p);
899 p->as.data.dfree = (void (*)(void*))rb_io_fptr_finalize;
900 p->as.data.data = fptr;
901 }
902
903 static int
904 obj_free(rb_objspace_t *objspace, VALUE obj)
905 {
906 switch (BUILTIN_TYPE(obj)) {
907 case T_NIL:
908 case T_FIXNUM:
909 case T_TRUE:
910 case T_FALSE:
911 rb_bug("obj_free() called for broken object");
912 break;
913 }
914
915 if (FL_TEST(obj, FL_EXIVAR)) {
916 rb_free_generic_ivar((VALUE)obj);
917 FL_UNSET(obj, FL_EXIVAR);
918 }
919
920 switch (BUILTIN_TYPE(obj)) {
921 case T_OBJECT:
922 if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
923 RANY(obj)->as.object.as.heap.ivptr) {
924 xfree(RANY(obj)->as.object.as.heap.ivptr);
925 }
926 break;
927 case T_MODULE:
928 case T_CLASS:
929 rb_clear_cache_by_class((VALUE)obj);
930 if (RCLASS_M_TBL(obj)) {
931 rb_free_m_table(RCLASS_M_TBL(obj));
932 }
933 if (RCLASS_IV_TBL(obj)) {
934 st_free_table(RCLASS_IV_TBL(obj));
935 }
936 if (RCLASS_CONST_TBL(obj)) {
937 rb_free_const_table(RCLASS_CONST_TBL(obj));
938 }
939 if (RCLASS_IV_INDEX_TBL(obj)) {
940 st_free_table(RCLASS_IV_INDEX_TBL(obj));
941 }
942 xfree(RANY(obj)->as.klass.ptr);
943 break;
944 case T_STRING:
945 rb_str_free(obj);
946 break;
947 case T_ARRAY:
948 rb_ary_free(obj);
949 break;
950 case T_HASH:
951 if (RANY(obj)->as.hash.ntbl) {
952 st_free_table(RANY(obj)->as.hash.ntbl);
953 }
954 break;
955 case T_REGEXP:
956 if (RANY(obj)->as.regexp.ptr) {
957 onig_free(RANY(obj)->as.regexp.ptr);
958 }
959 break;
960 case T_DATA:
961 if (DATA_PTR(obj)) {
962 if (RTYPEDDATA_P(obj)) {
963 RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->function.dfree;
964 }
965 if (RANY(obj)->as.data.dfree == (RUBY_DATA_FUNC)-1) {
966 xfree(DATA_PTR(obj));
967 }
968 else if (RANY(obj)->as.data.dfree) {
969 make_deferred(RANY(obj));
970 return 1;
971 }
972 }
973 break;
974 case T_MATCH:
975 if (RANY(obj)->as.match.rmatch) {
976 struct rmatch *rm = RANY(obj)->as.match.rmatch;
977 onig_region_free(&rm->regs, 0);
978 if (rm->char_offset)
979 xfree(rm->char_offset);
980 xfree(rm);
981 }
982 break;
983 case T_FILE:
984 if (RANY(obj)->as.file.fptr) {
985 make_io_deferred(RANY(obj));
986 return 1;
987 }
988 break;
989 case T_RATIONAL:
990 case T_COMPLEX:
991 break;
992 case T_ICLASS:
993 /* iClass shares table with the module */
994 xfree(RANY(obj)->as.klass.ptr);
995 break;
996
997 case T_FLOAT:
998 break;
999
1000 case T_BIGNUM:
1001 if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
1002 xfree(RBIGNUM_DIGITS(obj));
1003 }
1004 break;
1005 case T_NODE:
1006 switch (nd_type(obj)) {
1007 case NODE_SCOPE:
1008 if (RANY(obj)->as.node.u1.tbl) {
1009 xfree(RANY(obj)->as.node.u1.tbl);
1010 }
1011 break;
1012 case NODE_ARGS:
1013 if (RANY(obj)->as.node.u3.args) {
1014 xfree(RANY(obj)->as.node.u3.args);
1015 }
1016 break;
1017 case NODE_ALLOCA:
1018 xfree(RANY(obj)->as.node.u1.node);
1019 break;
1020 }
1021 break; /* no need to free iv_tbl */
1022
1023 case T_STRUCT:
1024 if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
1025 RANY(obj)->as.rstruct.as.heap.ptr) {
1026 xfree(RANY(obj)->as.rstruct.as.heap.ptr);
1027 }
1028 break;
1029
1030 default:
1031 rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE,
1032 BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
1033 }
1034
1035 return 0;
1036 }
1037
1038 void
1039 Init_heap(void)
1040 {
1041 init_heap(&rb_objspace);
1042 }
1043
1044 typedef int each_obj_callback(void *, void *, size_t, void *);
1045
1046 struct each_obj_args {
1047 each_obj_callback *callback;
1048 void *data;
1049 };
1050
1051 static VALUE
1052 objspace_each_objects(VALUE arg)
1053 {
1054 size_t i;
1055 RVALUE *membase = 0;
1056 RVALUE *pstart, *pend;
1057 rb_objspace_t *objspace = &rb_objspace;
1058 struct each_obj_args *args = (struct each_obj_args *)arg;
1059 volatile VALUE v;
1060
1061 i = 0;
1062 while (i < heaps_used) {
1063 while (0 < i && (uintptr_t)membase < (uintptr_t)objspace->heap.sorted[i-1])
1064 i--;
1065 while (i < heaps_used && (uintptr_t)objspace->heap.sorted[i] <= (uintptr_t)membase)
1066 i++;
1067 if (heaps_used <= i)
1068 break;
1069 membase = (RVALUE *)objspace->heap.sorted[i];
1070
1071 pstart = objspace->heap.sorted[i]->start;
1072 pend = pstart + objspace->heap.sorted[i]->limit;
1073
1074 for (; pstart != pend; pstart++) {
1075 if (pstart->as.basic.flags) {
1076 v = (VALUE)pstart; /* acquire to save this object */
1077 break;
1078 }
1079 }
1080 if (pstart != pend) {
1081 if ((*args->callback)(pstart, pend, sizeof(RVALUE), args->data)) {
1082 break;
1083 }
1084 }
1085 }
1086 RB_GC_GUARD(v);
1087
1088 return Qnil;
1089 }
1090
1091 /*
1092 * rb_objspace_each_objects() is special C API to walk through
1093 * Ruby object space. This C API is too difficult to use it.
1094 * To be frank, you should not use it. Or you need to read the
1095 * source code of this function and understand what this function does.
1096 *
1097 * 'callback' will be called several times (the number of heap slot,
1098 * at current implementation) with:
1099 * vstart: a pointer to the first living object of the heap_slot.
1100 * vend: a pointer to next to the valid heap_slot area.
1101 * stride: a distance to next VALUE.
1102 *
1103 * If callback() returns non-zero, the iteration will be stopped.
1104 *
1105 * This is a sample callback code to iterate liveness objects:
1106 *
1107 * int
1108 * sample_callback(void *vstart, void *vend, int stride, void *data) {
1109 * VALUE v = (VALUE)vstart;
1110 * for (; v != (VALUE)vend; v += stride) {
1111 * if (RBASIC(v)->flags) { // liveness check
1112 * // do something with live object 'v'
1113 * }
1114 * return 0; // continue to iteration
1115 * }
1116 *
1117 * Note: 'vstart' is not a top of heap_slot. This point the first
1118 * living object to grasp at least one object to avoid GC issue.
1119 * This means that you can not walk through all Ruby object slot
1120 * including freed object slot.
1121 *
1122 * Note: On this implementation, 'stride' is same as sizeof(RVALUE).
1123 * However, there are possibilities to pass variable values with
1124 * 'stride' with some reasons. You must use stride instead of
1125 * use some constant value in the iteration.
1126 */
1127 void
1128 rb_objspace_each_objects(each_obj_callback *callback, void *data)
1129 {
1130 struct each_obj_args args;
1131 rb_objspace_t *objspace = &rb_objspace;
1132
1133 rest_sweep(objspace);
1134 objspace->flags.dont_lazy_sweep = TRUE;
1135
1136 args.callback = callback;
1137 args.data = data;
1138 rb_ensure(objspace_each_objects, (VALUE)&args, lazy_sweep_enable, Qnil);
1139 }
1140
1141 struct os_each_struct {
1142 size_t num;
1143 VALUE of;
1144 };
1145
1146 static int
1147 internal_object_p(VALUE obj)
1148 {
1149 RVALUE *p = (RVALUE *)obj;
1150
1151 if (p->as.basic.flags) {
1152 switch (BUILTIN_TYPE(p)) {
1153 case T_NONE:
1154 case T_ICLASS:
1155 case T_NODE:
1156 case T_ZOMBIE:
1157 break;
1158 case T_CLASS:
1159 if (FL_TEST(p, FL_SINGLETON))
1160 break;
1161 default:
1162 if (!p->as.basic.klass) break;
1163 return 0;
1164 }
1165 }
1166 return 1;
1167 }
1168
1169 int
1170 rb_objspace_internal_object_p(VALUE obj)
1171 {
1172 return internal_object_p(obj);
1173 }
1174
1175 static int
1176 os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
1177 {
1178 struct os_each_struct *oes = (struct os_each_struct *)data;
1179 RVALUE *p = (RVALUE *)vstart, *pend = (RVALUE *)vend;
1180
1181 for (; p != pend; p++) {
1182 volatile VALUE v = (VALUE)p;
1183 if (!internal_object_p(v)) {
1184 if (!oes->of || rb_obj_is_kind_of(v, oes->of)) {
1185 rb_yield(v);
1186 oes->num++;
1187 }
1188 }
1189 }
1190
1191 return 0;
1192 }
1193
1194 static VALUE
1195 os_obj_of(VALUE of)
1196 {
1197 struct os_each_struct oes;
1198
1199 oes.num = 0;
1200 oes.of = of;
1201 rb_objspace_each_objects(os_obj_of_i, &oes);
1202 return SIZET2NUM(oes.num);
1203 }
1204
1205 /*
1206 * call-seq:
1207 * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum
1208 * ObjectSpace.each_object([module]) -> an_enumerator
1209 *
1210 * Calls the block once for each living, nonimmediate object in this
1211 * Ruby process. If <i>module</i> is specified, calls the block
1212 * for only those classes or modules that match (or are a subclass of)
1213 * <i>module</i>. Returns the number of objects found. Immediate
1214 * objects (<code>Fixnum</code>s, <code>Symbol</code>s
1215 * <code>true</code>, <code>false</code>, and <code>nil</code>) are
1216 * never returned. In the example below, <code>each_object</code>
1217 * returns both the numbers we defined and several constants defined in
1218 * the <code>Math</code> module.
1219 *
1220 * If no block is given, an enumerator is returned instead.
1221 *
1222 * a = 102.7
1223 * b = 95 # Won't be returned
1224 * c = 12345678987654321
1225 * count = ObjectSpace.each_object(Numeric) {|x| p x }
1226 * puts "Total count: #{count}"
1227 *
1228 * <em>produces:</em>
1229 *
1230 * 12345678987654321
1231 * 102.7
1232 * 2.71828182845905
1233 * 3.14159265358979
1234 * 2.22044604925031e-16
1235 * 1.7976931348623157e+308
1236 * 2.2250738585072e-308
1237 * Total count: 7
1238 *
1239 */
1240
1241 static VALUE
1242 os_each_obj(int argc, VALUE *argv, VALUE os)
1243 {
1244 VALUE of;
1245
1246 rb_secure(4);
1247 if (argc == 0) {
1248 of = 0;
1249 }
1250 else {
1251 rb_scan_args(argc, argv, "01", &of);
1252 }
1253 RETURN_ENUMERATOR(os, 1, &of);
1254 return os_obj_of(of);
1255 }
1256
1257 /*
1258 * call-seq:
1259 * ObjectSpace.undefine_finalizer(obj)
1260 *
1261 * Removes all finalizers for <i>obj</i>.
1262 *
1263 */
1264
1265 static VALUE
1266 undefine_final(VALUE os, VALUE obj)
1267 {
1268 return rb_undefine_final(obj);
1269 }
1270
1271 VALUE
1272 rb_undefine_final(VALUE obj)
1273 {
1274 rb_objspace_t *objspace = &rb_objspace;
1275 st_data_t data = obj;
1276 rb_check_frozen(obj);
1277 st_delete(finalizer_table, &data, 0);
1278 FL_UNSET(obj, FL_FINALIZE);
1279 return obj;
1280 }
1281
1282 /*
1283 * call-seq:
1284 * ObjectSpace.define_finalizer(obj, aProc=proc())
1285 *
1286 * Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
1287 * was destroyed.
1288 *
1289 */
1290
1291 static VALUE
1292 define_final(int argc, VALUE *argv, VALUE os)
1293 {
1294 VALUE obj, block;
1295
1296 rb_scan_args(argc, argv, "11", &obj, &block);
1297 rb_check_frozen(obj);
1298 if (argc == 1) {
1299 block = rb_block_proc();
1300 }
1301 else if (!rb_respond_to(block, rb_intern("call"))) {
1302 rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
1303 rb_obj_classname(block));
1304 }
1305
1306 return define_final0(obj, block);
1307 }
1308
1309 static VALUE
1310 define_final0(VALUE obj, VALUE block)
1311 {
1312 rb_objspace_t *objspace = &rb_objspace;
1313 VALUE table;
1314 st_data_t data;
1315
1316 if (!FL_ABLE(obj)) {
1317 rb_raise(rb_eArgError, "cannot define finalizer for %s",
1318 rb_obj_classname(obj));
1319 }
1320 RBASIC(obj)->flags |= FL_FINALIZE;
1321
1322 block = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
1323 OBJ_FREEZE(block);
1324
1325 if (st_lookup(finalizer_table, obj, &data)) {
1326 table = (VALUE)data;
1327 rb_ary_push(table, block);
1328 }
1329 else {
1330 table = rb_ary_new3(1, block);
1331 RBASIC(table)->klass = 0;
1332 st_add_direct(finalizer_table, obj, table);
1333 }
1334 return block;
1335 }
1336
1337 VALUE
1338 rb_define_final(VALUE obj, VALUE block)
1339 {
1340 rb_check_frozen(obj);
1341 if (!rb_respond_to(block, rb_intern("call"))) {
1342 rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
1343 rb_obj_classname(block));
1344 }
1345 return define_final0(obj, block);
1346 }
1347
1348 void
1349 rb_gc_copy_finalizer(VALUE dest, VALUE obj)
1350 {
1351 rb_objspace_t *objspace = &rb_objspace;
1352 VALUE table;
1353 st_data_t data;
1354
1355 if (!FL_TEST(obj, FL_FINALIZE)) return;
1356 if (st_lookup(finalizer_table, obj, &data)) {
1357 table = (VALUE)data;
1358 st_insert(finalizer_table, dest, table);
1359 }
1360 FL_SET(dest, FL_FINALIZE);
1361 }
1362
1363 static VALUE
1364 run_single_final(VALUE arg)
1365 {
1366 VALUE *args = (VALUE *)arg;
1367 rb_eval_cmd(args[0], args[1], (int)args[2]);
1368 return Qnil;
1369 }
1370
1371 static void
1372 run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
1373 {
1374 long i;
1375 int status;
1376 VALUE args[3];
1377 VALUE objid = nonspecial_obj_id(obj);
1378
1379 if (RARRAY_LEN(table) > 0) {
1380 args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
1381 }
1382 else {
1383 args[1] = 0;
1384 }
1385
1386 args[2] = (VALUE)rb_safe_level();
1387 for (i=0; i<RARRAY_LEN(table); i++) {
1388 VALUE final = RARRAY_PTR(table)[i];
1389 args[0] = RARRAY_PTR(final)[1];
1390 args[2] = FIX2INT(RARRAY_PTR(final)[0]);
1391 status = 0;
1392 rb_protect(run_single_final, (VALUE)args, &status);
1393 if (status)
1394 rb_set_errinfo(Qnil);
1395 }
1396 }
1397
1398 static void
1399 run_final(rb_objspace_t *objspace, VALUE obj)
1400 {
1401 RUBY_DATA_FUNC free_func = 0;
1402 st_data_t key, table;
1403
1404 objspace->heap.final_num--;
1405
1406 RBASIC(obj)->klass = 0;
1407
1408 if (RTYPEDDATA_P(obj)) {
1409 free_func = RTYPEDDATA_TYPE(obj)->function.dfree;
1410 }
1411 else {
1412 free_func = RDATA(obj)->dfree;
1413 }
1414 if (free_func) {
1415 (*free_func)(DATA_PTR(obj));
1416 }
1417
1418 key = (st_data_t)obj;
1419 if (st_delete(finalizer_table, &key, &table)) {
1420 run_finalizer(objspace, obj, (VALUE)table);
1421 }
1422 }
1423
1424 static void
1425 finalize_list(rb_objspace_t *objspace, RVALUE *p)
1426 {
1427 while (p) {
1428 RVALUE *tmp = p->as.free.next;
1429 run_final(objspace, (VALUE)p);
1430 objspace->total_freed_object_num++;
1431 if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
1432 add_slot_local_freelist(objspace, p);
1433 objspace->heap.free_num++;
1434 }
1435 else {
1436 struct heaps_slot *slot = (struct heaps_slot *)(VALUE)RDATA(p)->dmark;
1437 slot->header->limit--;
1438 }
1439 p = tmp;
1440 }
1441 }
1442
1443 static void
1444 finalize_deferred(rb_objspace_t *objspace)
1445 {
1446 RVALUE *p = deferred_final_list;
1447 deferred_final_list = 0;
1448
1449 if (p) {
1450 finalize_list(objspace, p);
1451 }
1452 }
1453
1454 void
1455 rb_gc_finalize_deferred(void)
1456 {
1457 rb_objspace_t *objspace = &rb_objspace;
1458 if (ATOMIC_EXCHANGE(finalizing, 1)) return;
1459 finalize_deferred(objspace);
1460 ATOMIC_SET(finalizing, 0);
1461 }
1462
1463 struct force_finalize_list {
1464 VALUE obj;
1465 VALUE table;
1466 struct force_finalize_list *next;
1467 };
1468
1469 static int
1470 force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
1471 {
1472 struct force_finalize_list **prev = (struct force_finalize_list **)arg;
1473 struct force_finalize_list *curr = ALLOC(struct force_finalize_list);
1474 curr->obj = key;
1475 curr->table = val;
1476 curr->next = *prev;
1477 *prev = curr;
1478 return ST_CONTINUE;
1479 }
1480
1481 void
1482 rb_gc_call_finalizer_at_exit(void)
1483 {
1484 rb_objspace_call_finalizer(&rb_objspace);
1485 }
1486
1487 static void
1488 rb_objspace_call_finalizer(rb_objspace_t *objspace)
1489 {
1490 RVALUE *p, *pend;
1491 RVALUE *final_list = 0;
1492 size_t i;
1493
1494 rest_sweep(objspace);
1495
1496 if (ATOMIC_EXCHANGE(finalizing, 1)) return;
1497
1498 /* run finalizers */
1499 finalize_deferred(objspace);
1500 assert(deferred_final_list == 0);
1501
1502 /* force to run finalizer */
1503 while (finalizer_table->num_entries) {
1504 struct force_finalize_list *list = 0;
1505 st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
1506 while (list) {
1507 struct force_finalize_list *curr = list;
1508 st_data_t obj = (st_data_t)curr->obj;
1509 run_finalizer(objspace, curr->obj, curr->table);
1510 st_delete(finalizer_table, &obj, 0);
1511 list = curr->next;
1512 xfree(curr);
1513 }
1514 }
1515
1516 /* finalizers are part of garbage collection */
1517 during_gc++;
1518
1519 /* run data object's finalizers */
1520 for (i = 0; i < heaps_used; i++) {
1521 p = objspace->heap.sorted[i]->start; pend = p + objspace->heap.sorted[i]->limit;
1522 while (p < pend) {
1523 if (BUILTIN_TYPE(p) == T_DATA &&
1524 DATA_PTR(p) && RANY(p)->as.data.dfree &&
1525 !rb_obj_is_thread((VALUE)p) && !rb_obj_is_mutex((VALUE)p) &&
1526 !rb_obj_is_fiber((VALUE)p)) {
1527 p->as.free.flags = 0;
1528 if (RTYPEDDATA_P(p)) {
1529 RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree;
1530 }
1531 if (RANY(p)->as.data.dfree == (RUBY_DATA_FUNC)-1) {
1532 xfree(DATA_PTR(p));
1533 }
1534 else if (RANY(p)->as.data.dfree) {
1535 make_deferred(RANY(p));
1536 RANY(p)->as.free.next = final_list;
1537 final_list = p;
1538 }
1539 }
1540 else if (BUILTIN_TYPE(p) == T_FILE) {
1541 if (RANY(p)->as.file.fptr) {
1542 make_io_deferred(RANY(p));
1543 RANY(p)->as.free.next = final_list;
1544 final_list = p;
1545 }
1546 }
1547 p++;
1548 }
1549 }
1550 during_gc = 0;
1551 if (final_list) {
1552 finalize_list(objspace, final_list);
1553 }
1554
1555 st_free_table(finalizer_table);
1556 finalizer_table = 0;
1557 ATOMIC_SET(finalizing, 0);
1558 }
1559
1560 static inline int
1561 is_id_value(rb_objspace_t *objspace, VALUE ptr)
1562 {
1563 if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE;
1564 if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE;
1565 if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE;
1566 return TRUE;
1567 }
1568
1569 static inline int
1570 is_swept_object(rb_objspace_t *objspace, VALUE ptr)
1571 {
1572 struct heaps_slot *slot = objspace->heap.sweep_slots;
1573
1574 while (slot) {
1575 if ((VALUE)slot->header->start <= ptr && ptr < (VALUE)(slot->header->end))
1576 return FALSE;
1577 slot = slot->next;
1578 }
1579 return TRUE;
1580 }
1581
1582 static inline int
1583 is_dead_object(rb_objspace_t *objspace, VALUE ptr)
1584 {
1585 if (!is_lazy_sweeping(objspace) || MARKED_IN_BITMAP(GET_HEAP_BITMAP(ptr), ptr))
1586 return FALSE;
1587 if (!is_swept_object(objspace, ptr))
1588 return TRUE;
1589 return FALSE;
1590 }
1591
1592 static inline int
1593 is_live_object(rb_objspace_t *objspace, VALUE ptr)
1594 {
1595 if (BUILTIN_TYPE(ptr) == 0) return FALSE;
1596 if (RBASIC(ptr)->klass == 0) return FALSE;
1597 if (is_dead_object(objspace, ptr)) return FALSE;
1598 return TRUE;
1599 }
1600
1601 /*
1602 * call-seq:
1603 * ObjectSpace._id2ref(object_id) -> an_object
1604 *
1605 * Converts an object id to a reference to the object. May not be
1606 * called on an object id passed as a parameter to a finalizer.
1607 *
1608 * s = "I am a string" #=> "I am a string"
1609 * r = ObjectSpace._id2ref(s.object_id) #=> "I am a string"
1610 * r == s #=> true
1611 *
1612 */
1613
1614 static VALUE
1615 id2ref(VALUE obj, VALUE objid)
1616 {
1617 #if SIZEOF_LONG == SIZEOF_VOIDP
1618 #define NUM2PTR(x) NUM2ULONG(x)
1619 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
1620 #define NUM2PTR(x) NUM2ULL(x)
1621 #endif
1622 rb_objspace_t *objspace = &rb_objspace;
1623 VALUE ptr;
1624 void *p0;
1625
1626 rb_secure(4);
1627 ptr = NUM2PTR(objid);
1628 p0 = (void *)ptr;
1629
1630 if (ptr == Qtrue) return Qtrue;
1631 if (ptr == Qfalse) return Qfalse;
1632 if (ptr == Qnil) return Qnil;
1633 if (FIXNUM_P(ptr)) return (VALUE)ptr;
1634 if (FLONUM_P(ptr)) return (VALUE)ptr;
1635 ptr = obj_id_to_ref(objid);
1636
1637 if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
1638 ID symid = ptr / sizeof(RVALUE);
1639 if (rb_id2name(symid) == 0)
1640 rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
1641 return ID2SYM(symid);
1642 }
1643
1644 if (!is_id_value(objspace, ptr)) {
1645 rb_raise(rb_eRangeError, "%p is not id value", p0);
1646 }
1647 if (!is_live_object(objspace, ptr)) {
1648 rb_raise(rb_eRangeError, "%p is recycled object", p0);
1649 }
1650 return (VALUE)ptr;
1651 }
1652
1653 /*
1654 * Document-method: __id__
1655 * Document-method: object_id
1656 *
1657 * call-seq:
1658 * obj.__id__ -> integer
1659 * obj.object_id -> integer
1660 *
1661 * Returns an integer identifier for +obj+.
1662 *
1663 * The same number will be returned on all calls to +id+ for a given object,
1664 * and no two active objects will share an id.
1665 *
1666 * Object#object_id is a different concept from the +:name+ notation, which
1667 * returns the symbol id of +name+.
1668 *
1669 * Replaces the deprecated Object#id.
1670 */
1671
1672 /*
1673 * call-seq:
1674 * obj.hash -> fixnum
1675 *
1676 * Generates a Fixnum hash value for this object.
1677 *
1678 * This function must have the property that <code>a.eql?(b)</code> implies
1679 * <code>a.hash == b.hash</code>.
1680 *
1681 * The hash value is used by Hash class.
1682 *
1683 * Any hash value that exceeds the capacity of a Fixnum will be truncated
1684 * before being used.
1685 */
1686
1687 VALUE
1688 rb_obj_id(VALUE obj)
1689 {
1690 /*
1691 * 32-bit VALUE space
1692 * MSB ------------------------ LSB
1693 * false 00000000000000000000000000000000
1694 * true 00000000000000000000000000000010
1695 * nil 00000000000000000000000000000100
1696 * undef 00000000000000000000000000000110
1697 * symbol ssssssssssssssssssssssss00001110
1698 * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
1699 * fixnum fffffffffffffffffffffffffffffff1
1700 *
1701 * object_id space
1702 * LSB
1703 * false 00000000000000000000000000000000
1704 * true 00000000000000000000000000000010
1705 * nil 00000000000000000000000000000100
1706 * undef 00000000000000000000000000000110
1707 * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
1708 * object oooooooooooooooooooooooooooooo0 o...o % A = 0
1709 * fixnum fffffffffffffffffffffffffffffff1 bignum if required
1710 *
1711 * where A = sizeof(RVALUE)/4
1712 *
1713 * sizeof(RVALUE) is
1714 * 20 if 32-bit, double is 4-byte aligned
1715 * 24 if 32-bit, double is 8-byte aligned
1716 * 40 if 64-bit
1717 */
1718 if (SYMBOL_P(obj)) {
1719 return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
1720 }
1721 else if (FLONUM_P(obj)) {
1722 #if SIZEOF_LONG == SIZEOF_VOIDP
1723 return LONG2NUM((SIGNED_VALUE)obj);
1724 #else
1725 return LL2NUM((SIGNED_VALUE)obj);
1726 #endif
1727 }
1728 else if (SPECIAL_CONST_P(obj)) {
1729 return LONG2NUM((SIGNED_VALUE)obj);
1730 }
1731 return nonspecial_obj_id(obj);
1732 }
1733
1734 static int
1735 set_zero(st_data_t key, st_data_t val, st_data_t arg)
1736 {
1737 VALUE k = (VALUE)key;
1738 VALUE hash = (VALUE)arg;
1739 rb_hash_aset(hash, k, INT2FIX(0));
1740 return ST_CONTINUE;
1741 }
1742
1743 /*
1744 * call-seq:
1745 * ObjectSpace.count_objects([result_hash]) -> hash
1746 *
1747 * Counts objects for each type.
1748 *
1749 * It returns a hash, such as:
1750 * {
1751 * :TOTAL=>10000,
1752 * :FREE=>3011,
1753 * :T_OBJECT=>6,
1754 * :T_CLASS=>404,
1755 * # ...
1756 * }
1757 *
1758 * The contents of the returned hash are implementation specific.
1759 * It may be changed in future.
1760 *
1761 * If the optional argument +result_hash+ is given,
1762 * it is overwritten and returned. This is intended to avoid probe effect.
1763 *
1764 * This method is only expected to work on C Ruby.
1765 *
1766 */
1767
1768 static VALUE
1769 count_objects(int argc, VALUE *argv, VALUE os)
1770 {
1771 rb_objspace_t *objspace = &rb_objspace;
1772 size_t counts[T_MASK+1];
1773 size_t freed = 0;
1774 size_t total = 0;
1775 size_t i;
1776 VALUE hash;
1777
1778 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
1779 if (!RB_TYPE_P(hash, T_HASH))
1780 rb_raise(rb_eTypeError, "non-hash given");
1781 }
1782
1783 for (i = 0; i <= T_MASK; i++) {
1784 counts[i] = 0;
1785 }
1786
1787 for (i = 0; i < heaps_used; i++) {
1788 RVALUE *p, *pend;
1789
1790 p = objspace->heap.sorted[i]->start; pend = p + objspace->heap.sorted[i]->limit;
1791 for (;p < pend; p++) {
1792 if (p->as.basic.flags) {
1793 counts[BUILTIN_TYPE(p)]++;
1794 }
1795 else {
1796 freed++;
1797 }
1798 }
1799 total += objspace->heap.sorted[i]->limit;
1800 }
1801
1802 if (hash == Qnil) {
1803 hash = rb_hash_new();
1804 }
1805 else if (!RHASH_EMPTY_P(hash)) {
1806 st_foreach(RHASH_TBL(hash), set_zero, hash);
1807 }
1808 rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
1809 rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(freed));
1810
1811 for (i = 0; i <= T_MASK; i++) {
1812 VALUE type;
1813 switch (i) {
1814 #define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t)); break;
1815 COUNT_TYPE(T_NONE);
1816 COUNT_TYPE(T_OBJECT);
1817 COUNT_TYPE(T_CLASS);
1818 COUNT_TYPE(T_MODULE);
1819 COUNT_TYPE(T_FLOAT);
1820 COUNT_TYPE(T_STRING);
1821 COUNT_TYPE(T_REGEXP);
1822 COUNT_TYPE(T_ARRAY);
1823 COUNT_TYPE(T_HASH);
1824 COUNT_TYPE(T_STRUCT);
1825 COUNT_TYPE(T_BIGNUM);
1826 COUNT_TYPE(T_FILE);
1827 COUNT_TYPE(T_DATA);
1828 COUNT_TYPE(T_MATCH);
1829 COUNT_TYPE(T_COMPLEX);
1830 COUNT_TYPE(T_RATIONAL);
1831 COUNT_TYPE(T_NIL);
1832 COUNT_TYPE(T_TRUE);
1833 COUNT_TYPE(T_FALSE);
1834 COUNT_TYPE(T_SYMBOL);
1835 COUNT_TYPE(T_FIXNUM);
1836 COUNT_TYPE(T_UNDEF);
1837 COUNT_TYPE(T_NODE);
1838 COUNT_TYPE(T_ICLASS);
1839 COUNT_TYPE(T_ZOMBIE);
1840 #undef COUNT_TYPE
1841 default: type = INT2NUM(i); break;
1842 }
1843 if (counts[i])
1844 rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
1845 }
1846
1847 return hash;
1848 }
1849
1850
1851
1852 /*
1853 ------------------------ Garbage Collection ------------------------
1854 */
1855
1856 /* Sweeping */
1857
1858 static VALUE
1859 lazy_sweep_enable(void)
1860 {
1861 rb_objspace_t *objspace = &rb_objspace;
1862
1863 objspace->flags.dont_lazy_sweep = FALSE;
1864 return Qnil;
1865 }
1866
1867 static void
1868 gc_clear_slot_bits(struct heaps_slot *slot)
1869 {
1870 memset(slot->bits, 0, HEAP_BITMAP_LIMIT * sizeof(uintptr_t));
1871 }
1872
1873 static size_t
1874 objspace_live_num(rb_objspace_t *objspace)
1875 {
1876 return objspace->total_allocated_object_num - objspace->total_freed_object_num;
1877 }
1878
1879 static void
1880 slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
1881 {
1882 size_t empty_num = 0, freed_num = 0, final_num = 0;
1883 RVALUE *p, *pend;
1884 RVALUE *final = deferred_final_list;
1885 int deferred;
1886 uintptr_t *bits;
1887
1888 p = sweep_slot->header->start; pend = p + sweep_slot->header->limit;
1889 bits = GET_HEAP_BITMAP(p);
1890 while (p < pend) {
1891 if ((!(MARKED_IN_BITMAP(bits, p))) && BUILTIN_TYPE(p) != T_ZOMBIE) {
1892 if (p->as.basic.flags) {
1893 if ((deferred = obj_free(objspace, (VALUE)p)) ||
1894 (FL_TEST(p, FL_FINALIZE))) {
1895 if (!deferred) {
1896 p->as.free.flags = T_ZOMBIE;
1897 RDATA(p)->dfree = 0;
1898 }
1899 p->as.free.next = deferred_final_list;
1900 deferred_final_list = p;
1901 assert(BUILTIN_TYPE(p) == T_ZOMBIE);
1902 final_num++;
1903 }
1904 else {
1905 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1906 p->as.free.flags = 0;
1907 p->as.free.next = sweep_slot->freelist;
1908 sweep_slot->freelist = p;
1909 freed_num++;
1910 }
1911 }
1912 else {
1913 empty_num++;
1914 }
1915 }
1916 p++;
1917 }
1918 gc_clear_slot_bits(sweep_slot);
1919 if (final_num + freed_num + empty_num == sweep_slot->header->limit &&
1920 objspace->heap.free_num > objspace->heap.do_heap_free) {
1921 RVALUE *pp;
1922
1923 for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) {
1924 RDATA(pp)->dmark = (void (*)(void *))(VALUE)sweep_slot;
1925 pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
1926 }
1927 sweep_slot->header->limit = final_num;
1928 unlink_heap_slot(objspace, sweep_slot);
1929 }
1930 else {
1931 if (freed_num + empty_num > 0) {
1932 link_free_heap_slot(objspace, sweep_slot);
1933 }
1934 else {
1935 sweep_slot->free_next = NULL;
1936 }
1937 objspace->heap.free_num += freed_num + empty_num;
1938 }
1939 objspace->total_freed_object_num += freed_num;
1940 objspace->heap.final_num += final_num;
1941
1942 if (deferred_final_list && !finalizing) {
1943 rb_thread_t *th = GET_THREAD();
1944 if (th) {
1945 RUBY_VM_SET_FINALIZER_INTERRUPT(th);
1946 }
1947 }
1948 }
1949
1950 static int
1951 ready_to_gc(rb_objspace_t *objspace)
1952 {
1953 if (dont_gc || during_gc) {
1954 if (!has_free_object) {
1955 if (!heaps_increment(objspace)) {
1956 set_heaps_increment(objspace);
1957 heaps_increment(objspace);
1958 }
1959 }
1960 return FALSE;
1961 }
1962 return TRUE;
1963 }
1964
1965 static void
1966 before_gc_sweep(rb_objspace_t *objspace)
1967 {
1968 objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65);
1969 objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2);
1970 if (objspace->heap.free_min < initial_free_min) {
1971 objspace->heap.free_min = initial_free_min;
1972 if (objspace->heap.do_heap_free < initial_free_min)
1973 objspace->heap.do_heap_free = initial_free_min;
1974 }
1975 objspace->heap.sweep_slots = heaps;
1976 objspace->heap.free_num = 0;
1977 objspace->heap.free_slots = NULL;
1978
1979 /* sweep unlinked method entries */
1980 if (GET_VM()->unlinked_method_entry_list) {
1981 rb_sweep_method_entry(GET_VM());
1982 }
1983 }
1984
1985 static void
1986 after_gc_sweep(rb_objspace_t *objspace)
1987 {
1988 size_t inc;
1989
1990 gc_prof_set_malloc_info(objspace);
1991 if (objspace->heap.free_num < objspace->heap.free_min) {
1992 set_heaps_increment(objspace);
1993 heaps_increment(objspace);
1994 }
1995
1996 inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
1997 if (inc > malloc_limit) {
1998 malloc_limit +=
1999 (size_t)((inc - malloc_limit) * (double)objspace->heap.marked_num / (heaps_used * HEAP_OBJ_LIMIT));
2000 if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
2001 }
2002
2003 free_unused_heaps(objspace);
2004 }
2005
2006 static int
2007 lazy_sweep(rb_objspace_t *objspace)
2008 {
2009 struct heaps_slot *next;
2010
2011 heaps_increment(objspace);
2012 while (objspace->heap.sweep_slots) {
2013 next = objspace->heap.sweep_slots->next;
2014 slot_sweep(objspace, objspace->heap.sweep_slots);
2015 objspace->heap.sweep_slots = next;
2016 if (has_free_object) {
2017 during_gc = 0;
2018 return TRUE;
2019 }
2020 }
2021 return FALSE;
2022 }
2023
2024 static void
2025 rest_sweep(rb_objspace_t *objspace)
2026 {
2027 if (objspace->heap.sweep_slots) {
2028 while (objspace->heap.sweep_slots) {
2029 lazy_sweep(objspace);
2030 }
2031 after_gc_sweep(objspace);
2032 }
2033 }
2034
2035 static void gc_marks(rb_objspace_t *objspace);
2036
2037 static int
2038 gc_prepare_free_objects(rb_objspace_t *objspace)
2039 {
2040 int res;
2041
2042 if (objspace->flags.dont_lazy_sweep)
2043 return garbage_collect(objspace);
2044
2045
2046 if (!ready_to_gc(objspace)) return TRUE;
2047
2048 during_gc++;
2049 gc_prof_timer_start(objspace);
2050 gc_prof_sweep_timer_start(objspace);
2051
2052 if (objspace->heap.sweep_slots) {
2053 res = lazy_sweep(objspace);
2054 if (res) {
2055 gc_prof_sweep_timer_stop(objspace);
2056 gc_prof_set_malloc_info(objspace);
2057 gc_prof_timer_stop(objspace, Qfalse);
2058 return res;
2059 }
2060 after_gc_sweep(objspace);
2061 }
2062 else {
2063 if (heaps_increment(objspace)) {
2064 during_gc = 0;
2065 return TRUE;
2066 }
2067 }
2068
2069 gc_marks(objspace);
2070
2071 before_gc_sweep(objspace);
2072 if (objspace->heap.free_min > (heaps_used * HEAP_OBJ_LIMIT - objspace->heap.marked_num)) {
2073 set_heaps_increment(objspace);
2074 }
2075
2076 gc_prof_sweep_timer_start(objspace);
2077 if (!(res = lazy_sweep(objspace))) {
2078 after_gc_sweep(objspace);
2079 if (has_free_object) {
2080 res = TRUE;
2081 during_gc = 0;
2082 }
2083 }
2084 gc_prof_sweep_timer_stop(objspace);
2085
2086 gc_prof_timer_stop(objspace, Qtrue);
2087 return res;
2088 }
2089
2090 static void
2091 gc_sweep(rb_objspace_t *objspace)
2092 {
2093 struct heaps_slot *next;
2094
2095 before_gc_sweep(objspace);
2096
2097 while (objspace->heap.sweep_slots) {
2098 next = objspace->heap.sweep_slots->next;
2099 slot_sweep(objspace, objspace->heap.sweep_slots);
2100 objspace->heap.sweep_slots = next;
2101 }
2102
2103 after_gc_sweep(objspace);
2104
2105 during_gc = 0;
2106 }
2107
2108 /* Marking stack */
2109
2110 static void push_mark_stack(mark_stack_t *, VALUE);
2111 static int pop_mark_stack(mark_stack_t *, VALUE *);
2112 static void shrink_stack_chunk_cache(mark_stack_t *stack);
2113
2114 static stack_chunk_t *
2115 stack_chunk_alloc(void)
2116 {
2117 stack_chunk_t *res;
2118
2119 res = malloc(sizeof(stack_chunk_t));
2120 if (!res)
2121 rb_memerror();
2122
2123 return res;
2124 }
2125
2126 static inline int
2127 is_mark_stask_empty(mark_stack_t *stack)
2128 {
2129 return stack->chunk == NULL;
2130 }
2131
2132 static void
2133 add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
2134 {
2135 chunk->next = stack->cache;
2136 stack->cache = chunk;
2137 stack->cache_size++;
2138 }
2139
2140 static void
2141 shrink_stack_chunk_cache(mark_stack_t *stack)
2142 {
2143 stack_chunk_t *chunk;
2144
2145 if (stack->unused_cache_size > (stack->cache_size/2)) {
2146 chunk = stack->cache;
2147 stack->cache = stack->cache->next;
2148 stack->cache_size--;
2149 free(chunk);
2150 }
2151 stack->unused_cache_size = stack->cache_size;
2152 }
2153
2154 static void
2155 push_mark_stack_chunk(mark_stack_t *stack)
2156 {
2157 stack_chunk_t *next;
2158
2159 assert(stack->index == stack->limit);
2160 if (stack->cache_size > 0) {
2161 next = stack->cache;
2162 stack->cache = stack->cache->next;
2163 stack->cache_size--;
2164 if (stack->unused_cache_size > stack->cache_size)
2165 stack->unused_cache_size = stack->cache_size;
2166 }
2167 else {
2168 next = stack_chunk_alloc();
2169 }
2170 next->next = stack->chunk;
2171 stack->chunk = next;
2172 stack->index = 0;
2173 }
2174
2175 static void
2176 pop_mark_stack_chunk(mark_stack_t *stack)
2177 {
2178 stack_chunk_t *prev;
2179
2180 prev = stack->chunk->next;
2181 assert(stack->index == 0);
2182 add_stack_chunk_cache(stack, stack->chunk);
2183 stack->chunk = prev;
2184 stack->index = stack->limit;
2185 }
2186
2187 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2188 static void
2189 free_stack_chunks(mark_stack_t *stack)
2190 {
2191 stack_chunk_t *chunk = stack->chunk;
2192 stack_chunk_t *next = NULL;
2193
2194 while (chunk != NULL) {
2195 next = chunk->next;
2196 free(chunk);
2197 chunk = next;
2198 }
2199 }
2200 #endif
2201
2202 static void
2203 push_mark_stack(mark_stack_t *stack, VALUE data)
2204 {
2205 if (stack->index == stack->limit) {
2206 push_mark_stack_chunk(stack);
2207 }
2208 stack->chunk->data[stack->index++] = data;
2209 }
2210
2211 static int
2212 pop_mark_stack(mark_stack_t *stack, VALUE *data)
2213 {
2214 if (is_mark_stask_empty(stack)) {
2215 return FALSE;
2216 }
2217 if (stack->index == 1) {
2218 *data = stack->chunk->data[--stack->index];
2219 pop_mark_stack_chunk(stack);
2220 return TRUE;
2221 }
2222 *data = stack->chunk->data[--stack->index];
2223 return TRUE;
2224 }
2225
2226 static void
2227 init_mark_stack(mark_stack_t *stack)
2228 {
2229 int i;
2230
2231 push_mark_stack_chunk(stack);
2232 stack->limit = STACK_CHUNK_SIZE;
2233
2234 for (i=0; i < 4; i++) {
2235 add_stack_chunk_cache(stack, stack_chunk_alloc());
2236 }
2237 stack->unused_cache_size = stack->cache_size;
2238 }
2239
2240
2241 /* Marking */
2242
2243 #define MARK_IN_BITMAP(bits, p) (bits[BITMAP_INDEX(p)] = bits[BITMAP_INDEX(p)] | ((uintptr_t)1 << BITMAP_OFFSET(p)))
2244
2245
2246 #ifdef __ia64
2247 #define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
2248 #else
2249 #define SET_STACK_END SET_MACHINE_STACK_END(&th->machine_stack_end)
2250 #endif
2251
2252 #define STACK_START (th->machine_stack_start)
2253 #define STACK_END (th->machine_stack_end)
2254 #define STACK_LEVEL_MAX (th->machine_stack_maxsize/sizeof(VALUE))
2255
2256 #if STACK_GROW_DIRECTION < 0
2257 # define STACK_LENGTH (size_t)(STACK_START - STACK_END)
2258 #elif STACK_GROW_DIRECTION > 0
2259 # define STACK_LENGTH (size_t)(STACK_END - STACK_START + 1)
2260 #else
2261 # define STACK_LENGTH ((STACK_END < STACK_START) ? (size_t)(STACK_START - STACK_END) \
2262 : (size_t)(STACK_END - STACK_START + 1))
2263 #endif
2264 #if !STACK_GROW_DIRECTION
2265 int ruby_stack_grow_direction;
2266 int
2267 ruby_get_stack_grow_direction(volatile VALUE *addr)
2268 {
2269 VALUE *end;
2270 SET_MACHINE_STACK_END(&end);
2271
2272 if (end > addr) return ruby_stack_grow_direction = 1;
2273 return ruby_stack_grow_direction = -1;
2274 }
2275 #endif
2276
2277 size_t
2278 ruby_stack_length(VALUE **p)
2279 {
2280 rb_thread_t *th = GET_THREAD();
2281 SET_STACK_END;
2282 if (p) *p = STACK_UPPER(STACK_END, STACK_START, STACK_END);
2283 return STACK_LENGTH;
2284 }
2285
2286 #if !(defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK))
2287 static int
2288 stack_check(int water_mark)
2289 {
2290 int ret;
2291 rb_thread_t *th = GET_THREAD();
2292 SET_STACK_END;
2293 ret = STACK_LENGTH > STACK_LEVEL_MAX - water_mark;
2294 #ifdef __ia64
2295 if (!ret) {
2296 ret = (VALUE*)rb_ia64_bsp() - th->machine_register_stack_start >
2297 th->machine_register_stack_maxsize/sizeof(VALUE) - water_mark;
2298 }
2299 #endif
2300 return ret;
2301 }
2302 #endif
2303
2304 #define STACKFRAME_FOR_CALL_CFUNC 512
2305
2306 int
2307 ruby_stack_check(void)
2308 {
2309 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
2310 return 0;
2311 #else
2312 return stack_check(STACKFRAME_FOR_CALL_CFUNC);
2313 #endif
2314 }
2315
2316 static void
2317 mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
2318 {
2319 VALUE v;
2320 while (n--) {
2321 v = *x;
2322 (void)VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
2323 if (is_pointer_to_heap(objspace, (void *)v)) {
2324 gc_mark(objspace, v);
2325 }
2326 x++;
2327 }
2328 }
2329
2330 static void
2331 gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
2332 {
2333 long n;
2334
2335 if (end <= start) return;
2336 n = end - start;
2337 mark_locations_array(objspace, start, n);
2338 }
2339
2340 void
2341 rb_gc_mark_locations(VALUE *start, VALUE *end)
2342 {
2343 gc_mark_locations(&rb_objspace, start, end);
2344 }
2345
2346 #define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, (start), (end))
2347
2348 struct mark_tbl_arg {
2349 rb_objspace_t *objspace;
2350 };
2351
2352 static int
2353 mark_entry(st_data_t key, st_data_t value, st_data_t data)
2354 {
2355 struct mark_tbl_arg *arg = (void*)data;
2356 gc_mark(arg->objspace, (VALUE)value);
2357 return ST_CONTINUE;
2358 }
2359
2360 static void
2361 mark_tbl(rb_objspace_t *objspace, st_table *tbl)
2362 {
2363 struct mark_tbl_arg arg;
2364 if (!tbl || tbl->num_entries == 0) return;
2365 arg.objspace = objspace;
2366 st_foreach(tbl, mark_entry, (st_data_t)&arg);
2367 }
2368
2369 static int
2370 mark_key(st_data_t key, st_data_t value, st_data_t data)
2371 {
2372 struct mark_tbl_arg *arg = (void*)data;
2373 gc_mark(arg->objspace, (VALUE)key);
2374 return ST_CONTINUE;
2375 }
2376
2377 static void
2378 mark_set(rb_objspace_t *objspace, st_table *tbl)
2379 {
2380 struct mark_tbl_arg arg;
2381 if (!tbl) return;
2382 arg.objspace = objspace;
2383 st_foreach(tbl, mark_key, (st_data_t)&arg);
2384 }
2385
2386 void
2387 rb_mark_set(st_table *tbl)
2388 {
2389 mark_set(&rb_objspace, tbl);
2390 }
2391
2392 static int
2393 mark_keyvalue(st_data_t key, st_data_t value, st_data_t data)
2394 {
2395 struct mark_tbl_arg *arg = (void*)data;
2396 gc_mark(arg->objspace, (VALUE)key);
2397 gc_mark(arg->objspace, (VALUE)value);
2398 return ST_CONTINUE;
2399 }
2400
2401 static void
2402 mark_hash(rb_objspace_t *objspace, st_table *tbl)
2403 {
2404 struct mark_tbl_arg arg;
2405 if (!tbl) return;
2406 arg.objspace = objspace;
2407 st_foreach(tbl, mark_keyvalue, (st_data_t)&arg);
2408 }
2409
2410 void
2411 rb_mark_hash(st_table *tbl)
2412 {
2413 mark_hash(&rb_objspace, tbl);
2414 }
2415
2416 static void
2417 mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
2418 {
2419 const rb_method_definition_t *def = me->def;
2420
2421 gc_mark(objspace, me->klass);
2422 again:
2423 if (!def) return;
2424 switch (def->type) {
2425 case VM_METHOD_TYPE_ISEQ:
2426 gc_mark(objspace, def->body.iseq->self);
2427 break;
2428 case VM_METHOD_TYPE_BMETHOD:
2429 gc_mark(objspace, def->body.proc);
2430 break;
2431 case VM_METHOD_TYPE_ATTRSET:
2432 case VM_METHOD_TYPE_IVAR:
2433 gc_mark(objspace, def->body.attr.location);
2434 break;
2435 case VM_METHOD_TYPE_REFINED:
2436 if (def->body.orig_me) {
2437 def = def->body.orig_me->def;
2438 goto again;
2439 }
2440 break;
2441 default:
2442 break; /* ignore */
2443 }
2444 }
2445
2446 void
2447 rb_mark_method_entry(const rb_method_entry_t *me)
2448 {
2449 mark_method_entry(&rb_objspace, me);
2450 }
2451
2452 static int
2453 mark_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data)
2454 {
2455 struct mark_tbl_arg *arg = (void*)data;
2456 mark_method_entry(arg->objspace, me);
2457 return ST_CONTINUE;
2458 }
2459
2460 static void
2461 mark_m_tbl(rb_objspace_t *objspace, st_table *tbl)
2462 {
2463 struct mark_tbl_arg arg;
2464 if (!tbl) return;
2465 arg.objspace = objspace;
2466 st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg);
2467 }
2468
2469 static int
2470 mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data)
2471 {
2472 struct mark_tbl_arg *arg = (void*)data;
2473 gc_mark(arg->objspace, ce->value);
2474 gc_mark(arg->objspace, ce->file);
2475 return ST_CONTINUE;
2476 }
2477
2478 static void
2479 mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
2480 {
2481 struct mark_tbl_arg arg;
2482 if (!tbl) return;
2483 arg.objspace = objspace;
2484 st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg);
2485 }
2486
2487 #if STACK_GROW_DIRECTION < 0
2488 #define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_END, (end) = STACK_START)
2489 #elif STACK_GROW_DIRECTION > 0
2490 #define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_START, (end) = STACK_END+(appendix))
2491 #else
2492 #define GET_STACK_BOUNDS(start, end, appendix) \
2493 ((STACK_END < STACK_START) ? \
2494 ((start) = STACK_END, (end) = STACK_START) : ((start) = STACK_START, (end) = STACK_END+(appendix)))
2495 #endif
2496
2497 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
2498
2499 static void
2500 mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
2501 {
2502 union {
2503 rb_jmp_buf j;
2504 VALUE v[sizeof(rb_jmp_buf) / sizeof(VALUE)];
2505 } save_regs_gc_mark;
2506 VALUE *stack_start, *stack_end;
2507
2508 FLUSH_REGISTER_WINDOWS;
2509 /* This assumes that all registers are saved into the jmp_buf (and stack) */
2510 rb_setjmp(save_regs_gc_mark.j);
2511
2512 SET_STACK_END;
2513 GET_STACK_BOUNDS(stack_start, stack_end, 1);
2514
2515 mark_locations_array(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v));
2516
2517 rb_gc_mark_locations(stack_start, stack_end);
2518 #ifdef __ia64
2519 rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
2520 #endif
2521 #if defined(__mc68000__)
2522 mark_locations_array(objspace, (VALUE*)((char*)STACK_END + 2),
2523 (STACK_START - STACK_END));
2524 #endif
2525 }
2526
2527 void
2528 rb_gc_mark_machine_stack(rb_thread_t *th)
2529 {
2530 rb_objspace_t *objspace = &rb_objspace;
2531 VALUE *stack_start, *stack_end;
2532
2533 GET_STACK_BOUNDS(stack_start, stack_end, 0);
2534 rb_gc_mark_locations(stack_start, stack_end);
2535 #ifdef __ia64
2536 rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
2537 #endif
2538 }
2539
2540 void
2541 rb_mark_tbl(st_table *tbl)
2542 {
2543 mark_tbl(&rb_objspace, tbl);
2544 }
2545
2546 void
2547 rb_gc_mark_maybe(VALUE obj)
2548 {
2549 if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
2550 gc_mark(&rb_objspace, obj);
2551 }
2552 }
2553
2554 static int
2555 gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr)
2556 {
2557 register uintptr_t *bits = GET_HEAP_BITMAP(ptr);
2558 if (MARKED_IN_BITMAP(bits, ptr)) return 0;
2559 MARK_IN_BITMAP(bits, ptr);
2560 objspace->heap.marked_num++;
2561 return 1;
2562 }
2563
2564 static int
2565 markable_object_p(rb_objspace_t *objspace, VALUE ptr)
2566 {
2567 register RVALUE *obj = RANY(ptr);
2568
2569 if (rb_special_const_p(ptr)) return 0; /* special const not marked */
2570 if (obj->as.basic.flags == 0) return 0 ; /* free cell */
2571
2572 return 1;
2573 }
2574
2575 int
2576 rb_objspace_markable_object_p(VALUE obj)
2577 {
2578 return markable_object_p(/* now it doesn't use &rb_objspace */ 0, obj);
2579 }
2580
2581 static void
2582 gc_mark(rb_objspace_t *objspace, VALUE ptr)
2583 {
2584 if (!markable_object_p(objspace, ptr)) {
2585 return;
2586 }
2587
2588 if (LIKELY(objspace->mark_func_data == 0)) {
2589 if (!gc_mark_ptr(objspace, ptr)) return; /* already marked */
2590 push_mark_stack(&objspace->mark_stack, ptr);
2591 }
2592 else {
2593 objspace->mark_func_data->mark_func(ptr, objspace->mark_func_data->data);
2594 }
2595 }
2596
2597 void
2598 rb_gc_mark(VALUE ptr)
2599 {
2600 gc_mark(&rb_objspace, ptr);
2601 }
2602
2603 static void
2604 gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
2605 {
2606 register RVALUE *obj = RANY(ptr);
2607
2608 goto marking; /* skip */
2609
2610 again:
2611 if (LIKELY(objspace->mark_func_data == 0)) {
2612 obj = RANY(ptr);
2613 if (!markable_object_p(objspace, ptr)) return;
2614 if (!gc_mark_ptr(objspace, ptr)) return; /* already marked */
2615 }
2616 else {
2617 gc_mark(objspace, ptr);
2618 return;
2619 }
2620
2621 marking:
2622 if (FL_TEST(obj, FL_EXIVAR)) {
2623 rb_mark_generic_ivar(ptr);
2624 }
2625
2626 switch (BUILTIN_TYPE(obj)) {
2627 case T_NIL:
2628 case T_FIXNUM:
2629 rb_bug("rb_gc_mark() called for broken object");
2630 break;
2631
2632 case T_NODE:
2633 switch (nd_type(obj)) {
2634 case NODE_IF: /* 1,2,3 */
2635 case NODE_FOR:
2636 case NODE_ITER:
2637 case NODE_WHEN:
2638 case NODE_MASGN:
2639 case NODE_RESCUE:
2640 case NODE_RESBODY:
2641 case NODE_CLASS:
2642 case NODE_BLOCK_PASS:
2643 gc_mark(objspace, (VALUE)obj->as.node.u2.node);
2644 /* fall through */
2645 case NODE_BLOCK: /* 1,3 */
2646 case NODE_ARRAY:
2647 case NODE_DSTR:
2648 case NODE_DXSTR:
2649 case NODE_DREGX:
2650 case NODE_DREGX_ONCE:
2651 case NODE_ENSURE:
2652 case NODE_CALL:
2653 case NODE_DEFS:
2654 case NODE_OP_ASGN1:
2655 gc_mark(objspace, (VALUE)obj->as.node.u1.node);
2656 /* fall through */
2657 case NODE_SUPER: /* 3 */
2658 case NODE_FCALL:
2659 case NODE_DEFN:
2660 case NODE_ARGS_AUX:
2661 ptr = (VALUE)obj->as.node.u3.node;
2662 goto again;
2663
2664 case NODE_WHILE: /* 1,2 */
2665 case NODE_UNTIL:
2666 case NODE_AND:
2667 case NODE_OR:
2668 case NODE_CASE:
2669 case NODE_SCLASS:
2670 case NODE_DOT2:
2671 case NODE_DOT3:
2672 case NODE_FLIP2:
2673 case NODE_FLIP3:
2674 case NODE_MATCH2:
2675 case NODE_MATCH3:
2676 case NODE_OP_ASGN_OR:
2677 case NODE_OP_ASGN_AND:
2678 case NODE_MODULE:
2679 case NODE_ALIAS:
2680 case NODE_VALIAS:
2681 case NODE_ARGSCAT:
2682 gc_mark(objspace, (VALUE)obj->as.node.u1.node);
2683 /* fall through */
2684 case NODE_GASGN: /* 2 */
2685 case NODE_LASGN:
2686 case NODE_DASGN:
2687 case NODE_DASGN_CURR:
2688 case NODE_IASGN:
2689 case NODE_IASGN2:
2690 case NODE_CVASGN:
2691 case NODE_COLON3:
2692 case NODE_OPT_N:
2693 case NODE_EVSTR:
2694 case NODE_UNDEF:
2695 case NODE_POSTEXE:
2696 ptr = (VALUE)obj->as.node.u2.node;
2697 goto again;
2698
2699 case NODE_HASH: /* 1 */
2700 case NODE_LIT:
2701 case NODE_STR:
2702 case NODE_XSTR:
2703 case NODE_DEFINED:
2704 case NODE_MATCH:
2705 case NODE_RETURN:
2706 case NODE_BREAK:
2707 case NODE_NEXT:
2708 case NODE_YIELD:
2709 case NODE_COLON2:
2710 case NODE_SPLAT:
2711 case NODE_TO_ARY:
2712 ptr = (VALUE)obj->as.node.u1.node;
2713 goto again;
2714
2715 case NODE_SCOPE: /* 2,3 */
2716 case NODE_CDECL:
2717 case NODE_OPT_ARG:
2718 gc_mark(objspace, (VALUE)obj->as.node.u3.node);
2719 ptr = (VALUE)obj->as.node.u2.node;
2720 goto again;
2721
2722 case NODE_ARGS: /* custom */
2723 {
2724 struct rb_args_info *args = obj->as.node.u3.args;
2725 if (args) {
2726 if (args->pre_init) gc_mark(objspace, (VALUE)args->pre_init);
2727 if (args->post_init) gc_mark(objspace, (VALUE)args->post_init);
2728 if (args->opt_args) gc_mark(objspace, (VALUE)args->opt_args);
2729 if (args->kw_args) gc_mark(objspace, (VALUE)args->kw_args);
2730 if (args->kw_rest_arg) gc_mark(objspace, (VALUE)args->kw_rest_arg);
2731 }
2732 }
2733 ptr = (VALUE)obj->as.node.u2.node;
2734 goto again;
2735
2736 case NODE_ZARRAY: /* - */
2737 case NODE_ZSUPER:
2738 case NODE_VCALL:
2739 case NODE_GVAR:
2740 case NODE_LVAR:
2741 case NODE_DVAR:
2742 case NODE_IVAR:
2743 case NODE_CVAR:
2744 case NODE_NTH_REF:
2745 case NODE_BACK_REF:
2746 case NODE_REDO:
2747 case NODE_RETRY:
2748 case NODE_SELF:
2749 case NODE_NIL:
2750 case NODE_TRUE:
2751 case NODE_FALSE:
2752 case NODE_ERRINFO:
2753 case NODE_BLOCK_ARG:
2754 break;
2755 case NODE_ALLOCA:
2756 mark_locations_array(objspace,
2757 (VALUE*)obj->as.node.u1.value,
2758 obj->as.node.u3.cnt);
2759 gc_mark(objspace, (VALUE)obj->as.node.u2.node);
2760 break;
2761
2762 case NODE_CREF:
2763 gc_mark(objspace, obj->as.node.nd_refinements);
2764 gc_mark(objspace, (VALUE)obj->as.node.u1.node);
2765 ptr = (VALUE)obj->as.node.u3.node;
2766 goto again;
2767
2768 default: /* unlisted NODE */
2769 if (is_pointer_to_heap(objspace, obj->as.node.u1.node)) {
2770 gc_mark(objspace, (VALUE)obj->as.node.u1.node);
2771 }
2772 if (is_pointer_to_heap(objspace, obj->as.node.u2.node)) {
2773 gc_mark(objspace, (VALUE)obj->as.node.u2.node);
2774 }
2775 if (is_pointer_to_heap(objspace, obj->as.node.u3.node)) {
2776 gc_mark(objspace, (VALUE)obj->as.node.u3.node);
2777 }
2778 }
2779 return; /* no need to mark class. */
2780 }
2781
2782 gc_mark(objspace, obj->as.basic.klass);
2783 switch (BUILTIN_TYPE(obj)) {
2784 case T_ICLASS:
2785 case T_CLASS:
2786 case T_MODULE:
2787 mark_m_tbl(objspace, RCLASS_M_TBL(obj));
2788 if (!RCLASS_EXT(obj)) break;
2789 mark_tbl(objspace, RCLASS_IV_TBL(obj));
2790 mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
2791 ptr = RCLASS_SUPER(obj);
2792 goto again;
2793
2794 case T_ARRAY:
2795 if (FL_TEST(obj, ELTS_SHARED)) {
2796 ptr = obj->as.array.as.heap.aux.shared;
2797 goto again;
2798 }
2799 else {
2800 long i, len = RARRAY_LEN(obj);
2801 VALUE *ptr = RARRAY_PTR(obj);
2802 for (i=0; i < len; i++) {
2803 gc_mark(objspace, *ptr++);
2804 }
2805 }
2806 break;
2807
2808 case T_HASH:
2809 mark_hash(objspace, obj->as.hash.ntbl);
2810 ptr = obj->as.hash.ifnone;
2811 goto again;
2812
2813 case T_STRING:
2814 #define STR_ASSOC FL_USER3 /* copied from string.c */
2815 if (FL_TEST(obj, RSTRING_NOEMBED) && FL_ANY(obj, ELTS_SHARED|STR_ASSOC)) {
2816 ptr = obj->as.string.as.heap.aux.shared;
2817 goto again;
2818 }
2819 break;
2820
2821 case T_DATA:
2822 if (RTYPEDDATA_P(obj)) {
2823 RUBY_DATA_FUNC mark_func = obj->as.typeddata.type->function.dmark;
2824 if (mark_func) (*mark_func)(DATA_PTR(obj));
2825 }
2826 else {
2827 if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
2828 }
2829 break;
2830
2831 case T_OBJECT:
2832 {
2833 long i, len = ROBJECT_NUMIV(obj);
2834 VALUE *ptr = ROBJECT_IVPTR(obj);
2835 for (i = 0; i < len; i++) {
2836 gc_mark(objspace, *ptr++);
2837 }
2838 }
2839 break;
2840
2841 case T_FILE:
2842 if (obj->as.file.fptr) {
2843 gc_mark(objspace, obj->as.file.fptr->pathv);
2844 gc_mark(objspace, obj->as.file.fptr->tied_io_for_writing);
2845 gc_mark(objspace, obj->as.file.fptr->writeconv_asciicompat);
2846 gc_mark(objspace, obj->as.file.fptr->writeconv_pre_ecopts);
2847 gc_mark(objspace, obj->as.file.fptr->encs.ecopts);
2848 gc_mark(objspace, obj->as.file.fptr->write_lock);
2849 }
2850 break;
2851
2852 case T_REGEXP:
2853 ptr = obj->as.regexp.src;
2854 goto again;
2855
2856 case T_FLOAT:
2857 case T_BIGNUM:
2858 case T_ZOMBIE:
2859 break;
2860
2861 case T_MATCH:
2862 gc_mark(objspace, obj->as.match.regexp);
2863 if (obj->as.match.str) {
2864 ptr = obj->as.match.str;
2865 goto again;
2866 }
2867 break;
2868
2869 case T_RATIONAL:
2870 gc_mark(objspace, obj->as.rational.num);
2871 ptr = obj->as.rational.den;
2872 goto again;
2873
2874 case T_COMPLEX:
2875 gc_mark(objspace, obj->as.complex.real);
2876 ptr = obj->as.complex.imag;
2877 goto again;
2878
2879 case T_STRUCT:
2880 {
2881 long len = RSTRUCT_LEN(obj);
2882 VALUE *ptr = RSTRUCT_PTR(obj);
2883
2884 while (len--) {
2885 gc_mark(objspace, *ptr++);
2886 }
2887 }
2888 break;
2889
2890 default:
2891 rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
2892 BUILTIN_TYPE(obj), (void *)obj,
2893 is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
2894 }
2895 }
2896
2897 static void
2898 gc_mark_stacked_objects(rb_objspace_t *objspace)
2899 {
2900 mark_stack_t *mstack = &objspace->mark_stack;
2901 VALUE obj = 0;
2902
2903 if (!mstack->index) return;
2904 while (pop_mark_stack(mstack, &obj)) {
2905 gc_mark_children(objspace, obj);
2906 }
2907 shrink_stack_chunk_cache(mstack);
2908 }
2909
2910 static void
2911 gc_marks(rb_objspace_t *objspace)
2912 {
2913 struct gc_list *list;
2914 rb_thread_t *th = GET_THREAD();
2915 struct mark_func_data_struct *prev_mark_func_data;
2916
2917 prev_mark_func_data = objspace->mark_func_data;
2918 objspace->mark_func_data = 0;
2919
2920 gc_prof_mark_timer_start(objspace);
2921 objspace->heap.marked_num = 0;
2922 objspace->count++;
2923
2924 SET_STACK_END;
2925
2926 th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
2927
2928 mark_tbl(objspace, finalizer_table);
2929 mark_current_machine_context(objspace, th);
2930
2931 rb_gc_mark_symbols();
2932 rb_gc_mark_encodings();
2933
2934 /* mark protected global variables */
2935 for (list = global_List; list; list = list->next) {
2936 rb_gc_mark_maybe(*list->varptr);
2937 }
2938 rb_mark_end_proc();
2939 rb_gc_mark_global_tbl();
2940
2941 mark_tbl(objspace, rb_class_tbl);
2942
2943 /* mark generic instance variables for special constants */
2944 rb_mark_generic_ivar_tbl();
2945
2946 rb_gc_mark_parser();
2947
2948 rb_gc_mark_unlinked_live_method_entries(th->vm);
2949
2950 /* marking-loop */
2951 gc_mark_stacked_objects(objspace);
2952
2953 gc_prof_mark_timer_stop(objspace);
2954
2955 objspace->mark_func_data = prev_mark_func_data;
2956 }
2957
2958 /* GC */
2959
2960 void
2961 rb_gc_force_recycle(VALUE p)
2962 {
2963 rb_objspace_t *objspace = &rb_objspace;
2964 struct heaps_slot *slot;
2965
2966 objspace->total_freed_object_num++;
2967 if (MARKED_IN_BITMAP(GET_HEAP_BITMAP(p), p)) {
2968 add_slot_local_freelist(objspace, (RVALUE *)p);
2969 }
2970 else {
2971 objspace->heap.free_num++;
2972 slot = add_slot_local_freelist(objspace, (RVALUE *)p);
2973 if (slot->free_next == NULL) {
2974 link_free_heap_slot(objspace, slot);
2975 }
2976 }
2977 }
2978
2979 void
2980 rb_gc_register_mark_object(VALUE obj)
2981 {
2982 VALUE ary = GET_THREAD()->vm->mark_object_ary;
2983 rb_ary_push(ary, obj);
2984 }
2985
2986 void
2987 rb_gc_register_address(VALUE *addr)
2988 {
2989 rb_objspace_t *objspace = &rb_objspace;
2990 struct gc_list *tmp;
2991
2992 tmp = ALLOC(struct gc_list);
2993 tmp->next = global_List;
2994 tmp->varptr = addr;
2995 global_List = tmp;
2996 }
2997
2998 void
2999 rb_gc_unregister_address(VALUE *addr)
3000 {
3001 rb_objspace_t *objspace = &rb_objspace;
3002 struct gc_list *tmp = global_List;
3003
3004 if (tmp->varptr == addr) {
3005 global_List = tmp->next;
3006 xfree(tmp);
3007 return;
3008 }
3009 while (tmp->next) {
3010 if (tmp->next->varptr == addr) {
3011 struct gc_list *t = tmp->next;
3012
3013 tmp->next = tmp->next->next;
3014 xfree(t);
3015 break;
3016 }
3017 tmp = tmp->next;
3018 }
3019 }
3020
3021 #define GC_NOTIFY 0
3022
3023 static int
3024 garbage_collect(rb_objspace_t *objspace)
3025 {
3026 if (GC_NOTIFY) printf("start garbage_collect()\n");
3027
3028 if (!heaps) {
3029 return FALSE;
3030 }
3031 if (!ready_to_gc(objspace)) {
3032 return TRUE;
3033 }
3034
3035 gc_prof_timer_start(objspace);
3036
3037 rest_sweep(objspace);
3038
3039 during_gc++;
3040 gc_marks(objspace);
3041
3042 gc_prof_sweep_timer_start(objspace);
3043 gc_sweep(objspace);
3044 gc_prof_sweep_timer_stop(objspace);
3045
3046 gc_prof_timer_stop(objspace, Qtrue);
3047 if (GC_NOTIFY) printf("end garbage_collect()\n");
3048 return TRUE;
3049 }
3050
3051 static void *
3052 gc_with_gvl(void *ptr)
3053 {
3054 return (void *)(VALUE)garbage_collect((rb_objspace_t *)ptr);
3055 }
3056
3057 static int
3058 garbage_collect_with_gvl(rb_objspace_t *objspace)
3059 {
3060 if (dont_gc) return TRUE;
3061 if (ruby_thread_has_gvl_p()) {
3062 return garbage_collect(objspace);
3063 }
3064 else {
3065 if (ruby_native_thread_p()) {
3066 return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)objspace);
3067 }
3068 else {
3069 /* no ruby thread */
3070 fprintf(stderr, "[FATAL] failed to allocate memory\n");
3071 exit(EXIT_FAILURE);
3072 }
3073 }
3074 }
3075
3076 int
3077 rb_garbage_collect(void)
3078 {
3079 return garbage_collect(&rb_objspace);
3080 }
3081
3082 #undef Init_stack
3083
3084 void
3085 Init_stack(volatile VALUE *addr)
3086 {
3087 ruby_init_stack(addr);
3088 }
3089
3090 /*
3091 * call-seq:
3092 * GC.start -> nil
3093 * gc.garbage_collect -> nil
3094 * ObjectSpace.garbage_collect -> nil
3095 *
3096 * Initiates garbage collection, unless manually disabled.
3097 *
3098 */
3099
3100 VALUE
3101 rb_gc_start(void)
3102 {
3103 rb_gc();
3104 return Qnil;
3105 }
3106
3107 void
3108 rb_gc(void)
3109 {
3110 rb_objspace_t *objspace = &rb_objspace;
3111 garbage_collect(objspace);
3112 if (!finalizing) finalize_deferred(objspace);
3113 free_unused_heaps(objspace);
3114 }
3115
3116 int
3117 rb_during_gc(void)
3118 {
3119 rb_objspace_t *objspace = &rb_objspace;
3120 return during_gc;
3121 }
3122
3123 /*
3124 * call-seq:
3125 * GC.count -> Integer
3126 *
3127 * The number of times GC occurred.
3128 *
3129 * It returns the number of times GC occurred since the process started.
3130 *
3131 */
3132
3133 static VALUE
3134 gc_count(VALUE self)
3135 {
3136 return UINT2NUM(rb_objspace.count);
3137 }
3138
3139 /*
3140 * call-seq:
3141 * GC.stat -> Hash
3142 *
3143 * Returns a Hash containing information about the GC.
3144 *
3145 * The hash includes information about internal statistics about GC such as:
3146 *
3147 * {
3148 * :count=>0,
3149 * :heap_used=>12,
3150 * :heap_length=>12,
3151 * :heap_increment=>0,
3152 * :heap_live_num=>7539,
3153 * :heap_free_num=>88,
3154 * :heap_final_num=>0,
3155 * :total_allocated_object=>7630,
3156 * :total_freed_object=>88
3157 * }
3158 *
3159 * The contents of the hash are implementation specific and may be changed in
3160 * the future.
3161 *
3162 * This method is only expected to work on C Ruby.
3163 *
3164 */
3165
3166 static VALUE
3167 gc_stat(int argc, VALUE *argv, VALUE self)
3168 {
3169 rb_objspace_t *objspace = &rb_objspace;
3170 VALUE hash;
3171 static VALUE sym_count;
3172 static VALUE sym_heap_used, sym_heap_length, sym_heap_increment;
3173 static VALUE sym_heap_live_num, sym_heap_free_num, sym_heap_final_num;
3174 static VALUE sym_total_allocated_object, sym_total_freed_object;
3175 if (sym_count == 0) {
3176 sym_count = ID2SYM(rb_intern_const("count"));
3177 sym_heap_used = ID2SYM(rb_intern_const("heap_used"));
3178 sym_heap_length = ID2SYM(rb_intern_const("heap_length"));
3179 sym_heap_increment = ID2SYM(rb_intern_const("heap_increment"));
3180 sym_heap_live_num = ID2SYM(rb_intern_const("heap_live_num"));
3181 sym_heap_free_num = ID2SYM(rb_intern_const("heap_free_num"));
3182 sym_heap_final_num = ID2SYM(rb_intern_const("heap_final_num"));
3183 sym_total_allocated_object = ID2SYM(rb_intern_const("total_allocated_object"));
3184 sym_total_freed_object = ID2SYM(rb_intern_const("total_freed_object"));
3185 }
3186
3187 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
3188 if (!RB_TYPE_P(hash, T_HASH))
3189 rb_raise(rb_eTypeError, "non-hash given");
3190 }
3191
3192 if (hash == Qnil) {
3193 hash = rb_hash_new();
3194 }
3195
3196 rest_sweep(objspace);
3197
3198 rb_hash_aset(hash, sym_count, SIZET2NUM(objspace->count));
3199 /* implementation dependent counters */
3200 rb_hash_aset(hash, sym_heap_used, SIZET2NUM(objspace->heap.used));
3201 rb_hash_aset(hash, sym_heap_length, SIZET2NUM(objspace->heap.length));
3202 rb_hash_aset(hash, sym_heap_increment, SIZET2NUM(objspace->heap.increment));
3203 rb_hash_aset(hash, sym_heap_live_num, SIZET2NUM(objspace_live_num(objspace)));
3204 rb_hash_aset(hash, sym_heap_free_num, SIZET2NUM(objspace->heap.free_num));
3205 rb_hash_aset(hash, sym_heap_final_num, SIZET2NUM(objspace->heap.final_num));
3206 rb_hash_aset(hash, sym_total_allocated_object, SIZET2NUM(objspace->total_allocated_object_num));
3207 rb_hash_aset(hash, sym_total_freed_object, SIZET2NUM(objspace->total_freed_object_num));
3208
3209 return hash;
3210 }
3211
3212 /*
3213 * call-seq:
3214 * GC.stress -> true or false
3215 *
3216 * Returns current status of GC stress mode.
3217 */
3218
3219 static VALUE
3220 gc_stress_get(VALUE self)
3221 {
3222 rb_objspace_t *objspace = &rb_objspace;
3223 return ruby_gc_stress ? Qtrue : Qfalse;
3224 }
3225
3226 /*
3227 * call-seq:
3228 * GC.stress = bool -> bool
3229 *
3230 * Updates the GC stress mode.
3231 *
3232 * When stress mode is enabled, the GC is invoked at every GC opportunity:
3233 * all memory and object allocations.
3234 *
3235 * Enabling stress mode will degrade performance, it is only for debugging.
3236 */
3237
3238 static VALUE
3239 gc_stress_set(VALUE self, VALUE flag)
3240 {
3241 rb_objspace_t *objspace = &rb_objspace;
3242 rb_secure(2);
3243 ruby_gc_stress = RTEST(flag);
3244 return flag;
3245 }
3246
3247 /*
3248 * call-seq:
3249 * GC.enable -> true or false
3250 *
3251 * Enables garbage collection, returning +true+ if garbage
3252 * collection was previously disabled.
3253 *
3254 * GC.disable #=> false
3255 * GC.enable #=> true
3256 * GC.enable #=> false
3257 *
3258 */
3259
3260 VALUE
3261 rb_gc_enable(void)
3262 {
3263 rb_objspace_t *objspace = &rb_objspace;
3264 int old = dont_gc;
3265
3266 dont_gc = FALSE;
3267 return old ? Qtrue : Qfalse;
3268 }
3269
3270 /*
3271 * call-seq:
3272 * GC.disable -> true or false
3273 *
3274 * Disables garbage collection, returning +true+ if garbage
3275 * collection was already disabled.
3276 *
3277 * GC.disable #=> false
3278 * GC.disable #=> true
3279 *
3280 */
3281
3282 VALUE
3283 rb_gc_disable(void)
3284 {
3285 rb_objspace_t *objspace = &rb_objspace;
3286 int old = dont_gc;
3287
3288 rest_sweep(objspace);
3289
3290 dont_gc = TRUE;
3291 return old ? Qtrue : Qfalse;
3292 }
3293
3294 void
3295 rb_gc_set_params(void)
3296 {
3297 char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr;
3298
3299 if (rb_safe_level() > 0) return;
3300
3301 malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
3302 if (malloc_limit_ptr != NULL) {
3303 int malloc_limit_i = atoi(malloc_limit_ptr);
3304 if (RTEST(ruby_verbose))
3305 fprintf(stderr, "malloc_limit=%d (%d)\n",
3306 malloc_limit_i, initial_malloc_limit);
3307 if (malloc_limit_i > 0) {
3308 initial_malloc_limit = malloc_limit_i;
3309 }
3310 }
3311
3312 heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");
3313 if (heap_min_slots_ptr != NULL) {
3314 int heap_min_slots_i = atoi(heap_min_slots_ptr);
3315 if (RTEST(ruby_verbose))
3316 fprintf(stderr, "heap_min_slots=%d (%d)\n",
3317 heap_min_slots_i, initial_heap_min_slots);
3318 if (heap_min_slots_i > 0) {
3319 initial_heap_min_slots = heap_min_slots_i;
3320 initial_expand_heap(&rb_objspace);
3321 }
3322 }
3323
3324 free_min_ptr = getenv("RUBY_FREE_MIN");
3325 if (free_min_ptr != NULL) {
3326 int free_min_i = atoi(free_min_ptr);
3327 if (RTEST(ruby_verbose))
3328 fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min);
3329 if (free_min_i > 0) {
3330 initial_free_min = free_min_i;
3331 }
3332 }
3333 }
3334
3335 void
3336 rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data)
3337 {
3338 rb_objspace_t *objspace = &rb_objspace;
3339
3340 if (markable_object_p(objspace, obj)) {
3341 struct mark_func_data_struct mfd;
3342 mfd.mark_func = func;
3343 mfd.data = data;
3344 objspace->mark_func_data = &mfd;
3345 gc_mark_children(objspace, obj);
3346 objspace->mark_func_data = 0;
3347 }
3348 }
3349
3350 /*
3351 ------------------------ Extended allocator ------------------------
3352 */
3353
3354 static void vm_xfree(rb_objspace_t *objspace, void *ptr);
3355
3356 static void *
3357 negative_size_allocation_error_with_gvl(void *ptr)
3358 {
3359 rb_raise(rb_eNoMemError, "%s", (const char *)ptr);
3360 return 0; /* should not be reached */
3361 }
3362
3363 static void
3364 negative_size_allocation_error(const char *msg)
3365 {
3366 if (ruby_thread_has_gvl_p()) {
3367 rb_raise(rb_eNoMemError, "%s", msg);
3368 }
3369 else {
3370 if (ruby_native_thread_p()) {
3371 rb_thread_call_with_gvl(negative_size_allocation_error_with_gvl, (void *)msg);
3372 }
3373 else {
3374 fprintf(stderr, "[FATAL] %s\n", msg);
3375 exit(EXIT_FAILURE);
3376 }
3377 }
3378 }
3379
3380 static void *
3381 ruby_memerror_body(void *dummy)
3382 {
3383 rb_memerror();
3384 return 0;
3385 }
3386
3387 static void
3388 ruby_memerror(void)
3389 {
3390 if (ruby_thread_has_gvl_p()) {
3391 rb_memerror();
3392 }
3393 else {
3394 if (ruby_native_thread_p()) {
3395 rb_thread_call_with_gvl(ruby_memerror_body, 0);
3396 }
3397 else {
3398 /* no ruby thread */
3399 fprintf(stderr, "[FATAL] failed to allocate memory\n");
3400 exit(EXIT_FAILURE);
3401 }
3402 }
3403 }
3404
3405 void
3406 rb_memerror(void)
3407 {
3408 rb_thread_t *th = GET_THREAD();
3409 if (!nomem_error ||
3410 (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) {
3411 fprintf(stderr, "[FATAL] failed to allocate memory\n");
3412 exit(EXIT_FAILURE);
3413 }
3414 if (rb_thread_raised_p(th, RAISED_NOMEMORY)) {
3415 rb_thread_raised_clear(th);
3416 GET_THREAD()->errinfo = nomem_error;
3417 JUMP_TAG(TAG_RAISE);
3418 }
3419 rb_thread_raised_set(th, RAISED_NOMEMORY);
3420 rb_exc_raise(nomem_error);
3421 }
3422
3423 static void *
3424 aligned_malloc(size_t alignment, size_t size)
3425 {
3426 void *res;
3427
3428 #if defined __MINGW32__
3429 res = __mingw_aligned_malloc(size, alignment);
3430 #elif defined _WIN32 && !defined __CYGWIN__
3431 res = _aligned_malloc(size, alignment);
3432 #elif defined(HAVE_POSIX_MEMALIGN)
3433 if (posix_memalign(&res, alignment, size) == 0) {
3434 return res;
3435 }
3436 else {
3437 return NULL;
3438 }
3439 #elif defined(HAVE_MEMALIGN)
3440 res = memalign(alignment, size);
3441 #else
3442 char* aligned;
3443 res = malloc(alignment + size + sizeof(void*));
3444 aligned = (char*)res + alignment + sizeof(void*);
3445 aligned -= ((VALUE)aligned & (alignment - 1));
3446 ((void**)aligned)[-1] = res;
3447 res = (void*)aligned;
3448 #endif
3449
3450 #if defined(_DEBUG) || defined(GC_DEBUG)
3451 /* alignment must be a power of 2 */
3452 assert((alignment - 1) & alignment == 0);
3453 assert(alignment % sizeof(void*) == 0);
3454 #endif
3455 return res;
3456 }
3457
3458 static void
3459 aligned_free(void *ptr)
3460 {
3461 #if defined __MINGW32__
3462 __mingw_aligned_free(ptr);
3463 #elif defined _WIN32 && !defined __CYGWIN__
3464 _aligned_free(ptr);
3465 #elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)
3466 free(ptr);
3467 #else
3468 free(((void**)ptr)[-1]);
3469 #endif
3470 }
3471
3472 static inline size_t
3473 vm_malloc_prepare(rb_objspace_t *objspace, size_t size)
3474 {
3475 if ((ssize_t)size < 0) {
3476 negative_size_allocation_error("negative allocation size (or too big)");
3477 }
3478 if (size == 0) size = 1;
3479
3480 #if CALC_EXACT_MALLOC_SIZE
3481 size += sizeof(size_t);
3482 #endif
3483
3484 if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
3485 (malloc_increase+size) > malloc_limit) {
3486 garbage_collect_with_gvl(objspace);
3487 }
3488
3489 return size;
3490 }
3491
3492 static inline void *
3493 vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
3494 {
3495 ATOMIC_SIZE_ADD(malloc_increase, size);
3496
3497 #if CALC_EXACT_MALLOC_SIZE
3498 ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, size);
3499 ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
3500 ((size_t *)mem)[0] = size;
3501 mem = (size_t *)mem + 1;
3502 #endif
3503
3504 return mem;
3505 }
3506
3507 #define TRY_WITH_GC(alloc) do { \
3508 if (!(alloc) && \
3509 (!garbage_collect_with_gvl(objspace) || \
3510 !(alloc))) { \
3511 ruby_memerror(); \
3512 } \
3513 } while (0)
3514
3515 static void *
3516 vm_xmalloc(rb_objspace_t *objspace, size_t size)
3517 {
3518 void *mem;
3519
3520 size = vm_malloc_prepare(objspace, size);
3521 TRY_WITH_GC(mem = malloc(size));
3522 return vm_malloc_fixup(objspace, mem, size);
3523 }
3524
3525 static void *
3526 vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
3527 {
3528 void *mem;
3529 #if CALC_EXACT_MALLOC_SIZE
3530 size_t oldsize;
3531 #endif
3532
3533 if ((ssize_t)size < 0) {
3534 negative_size_allocation_error("negative re-allocation size");
3535 }
3536
3537 if (!ptr) return vm_xmalloc(objspace, size);
3538
3539 /*
3540 * The behavior of realloc(ptr, 0) is implementation defined.
3541 * Therefore we don't use realloc(ptr, 0) for portability reason.
3542 * see http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm
3543 */
3544 if (size == 0) {
3545 vm_xfree(objspace, ptr);
3546 return 0;
3547 }
3548 if (ruby_gc_stress && !ruby_disable_gc_stress)
3549 garbage_collect_with_gvl(objspace);
3550
3551 #if CALC_EXACT_MALLOC_SIZE
3552 size += sizeof(size_t);
3553 ptr = (size_t *)ptr - 1;
3554 oldsize = ((size_t *)ptr)[0];
3555 #endif
3556
3557 mem = realloc(ptr, size);
3558 if (!mem) {
3559 if (garbage_collect_with_gvl(objspace)) {
3560 mem = realloc(ptr, size);
3561 }
3562 if (!mem) {
3563 ruby_memerror();
3564 }
3565 }
3566 ATOMIC_SIZE_ADD(malloc_increase, size);
3567
3568 #if CALC_EXACT_MALLOC_SIZE
3569 ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, size - oldsize);
3570 ((size_t *)mem)[0] = size;
3571 mem = (size_t *)mem + 1;
3572 #endif
3573
3574 return mem;
3575 }
3576
3577 static void
3578 vm_xfree(rb_objspace_t *objspace, void *ptr)
3579 {
3580 #if CALC_EXACT_MALLOC_SIZE
3581 size_t size;
3582 ptr = ((size_t *)ptr) - 1;
3583 size = ((size_t*)ptr)[0];
3584 if (size) {
3585 ATOMIC_SIZE_SUB(objspace->malloc_params.allocated_size, size);
3586 ATOMIC_SIZE_DEC(objspace->malloc_params.allocations);
3587 }
3588 #endif
3589
3590 free(ptr);
3591 }
3592
3593 void *
3594 ruby_xmalloc(size_t size)
3595 {
3596 return vm_xmalloc(&rb_objspace, size);
3597 }
3598
3599 static inline size_t
3600 xmalloc2_size(size_t n, size_t size)
3601 {
3602 size_t len = size * n;
3603 if (n != 0 && size != len / n) {
3604 rb_raise(rb_eArgError, "malloc: possible integer overflow");
3605 }
3606 return len;
3607 }
3608
3609 void *
3610 ruby_xmalloc2(size_t n, size_t size)
3611 {
3612 return vm_xmalloc(&rb_objspace, xmalloc2_size(n, size));
3613 }
3614
3615 static void *
3616 vm_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
3617 {
3618 void *mem;
3619 size_t size;
3620
3621 size = xmalloc2_size(count, elsize);
3622 size = vm_malloc_prepare(objspace, size);
3623
3624 TRY_WITH_GC(mem = calloc(1, size));
3625 return vm_malloc_fixup(objspace, mem, size);
3626 }
3627
3628 void *
3629 ruby_xcalloc(size_t n, size_t size)
3630 {
3631 return vm_xcalloc(&rb_objspace, n, size);
3632 }
3633
3634 void *
3635 ruby_xrealloc(void *ptr, size_t size)
3636 {
3637 return vm_xrealloc(&rb_objspace, ptr, size);
3638 }
3639
3640 void *
3641 ruby_xrealloc2(void *ptr, size_t n, size_t size)
3642 {
3643 size_t len = size * n;
3644 if (n != 0 && size != len / n) {
3645 rb_raise(rb_eArgError, "realloc: possible integer overflow");
3646 }
3647 return ruby_xrealloc(ptr, len);
3648 }
3649
3650 void
3651 ruby_xfree(void *x)
3652 {
3653 if (x)
3654 vm_xfree(&rb_objspace, x);
3655 }
3656
3657
3658 /* Mimic ruby_xmalloc, but need not rb_objspace.
3659 * should return pointer suitable for ruby_xfree
3660 */
3661 void *
3662 ruby_mimmalloc(size_t size)
3663 {
3664 void *mem;
3665 #if CALC_EXACT_MALLOC_SIZE
3666 size += sizeof(size_t);
3667 #endif
3668 mem = malloc(size);
3669 #if CALC_EXACT_MALLOC_SIZE
3670 /* set 0 for consistency of allocated_size/allocations */
3671 ((size_t *)mem)[0] = 0;
3672 mem = (size_t *)mem + 1;
3673 #endif
3674 return mem;
3675 }
3676
3677 #if CALC_EXACT_MALLOC_SIZE
3678 /*
3679 * call-seq:
3680 * GC.malloc_allocated_size -> Integer
3681 *
3682 * Returns the size of memory allocated by malloc().
3683 *
3684 * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
3685 */
3686
3687 static VALUE
3688 gc_malloc_allocated_size(VALUE self)
3689 {
3690 return UINT2NUM(rb_objspace.malloc_params.allocated_size);
3691 }
3692
3693 /*
3694 * call-seq:
3695 * GC.malloc_allocations -> Integer
3696 *
3697 * Returns the number of malloc() allocations.
3698 *
3699 * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
3700 */
3701
3702 static VALUE
3703 gc_malloc_allocations(VALUE self)
3704 {
3705 return UINT2NUM(rb_objspace.malloc_params.allocations);
3706 }
3707 #endif
3708
3709 /*
3710 ------------------------------ WeakMap ------------------------------
3711 */
3712
3713 struct weakmap {
3714 st_table *obj2wmap; /* obj -> [ref,...] */
3715 st_table *wmap2obj; /* ref -> obj */
3716 VALUE final;
3717 };
3718
3719 static int
3720 wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
3721 {
3722 gc_mark_ptr((rb_objspace_t *)arg, (VALUE)val);
3723 return ST_CONTINUE;
3724 }
3725
3726 static void
3727 wmap_mark(void *ptr)
3728 {
3729 struct weakmap *w = ptr;
3730 st_foreach(w->obj2wmap, wmap_mark_map, (st_data_t)&rb_objspace);
3731 rb_gc_mark(w->final);
3732 }
3733
3734 static int
3735 wmap_free_map(st_data_t key, st_data_t val, st_data_t arg)
3736 {
3737 rb_ary_resize((VALUE)val, 0);
3738 return ST_CONTINUE;
3739 }
3740
3741 static void
3742 wmap_free(void *ptr)
3743 {
3744 struct weakmap *w = ptr;
3745 st_foreach(w->obj2wmap, wmap_free_map, 0);
3746 st_free_table(w->obj2wmap);
3747 st_free_table(w->wmap2obj);
3748 }
3749
3750 size_t rb_ary_memsize(VALUE ary);
3751 static int
3752 wmap_memsize_map(st_data_t key, st_data_t val, st_data_t arg)
3753 {
3754 *(size_t *)arg += rb_ary_memsize((VALUE)val);
3755 return ST_CONTINUE;
3756 }
3757
3758 static size_t
3759 wmap_memsize(const void *ptr)
3760 {
3761 size_t size;
3762 const struct weakmap *w = ptr;
3763 if (!w) return 0;
3764 size = sizeof(*w);
3765 size += st_memsize(w->obj2wmap);
3766 size += st_memsize(w->wmap2obj);
3767 st_foreach(w->obj2wmap, wmap_memsize_map, (st_data_t)&size);
3768 return size;
3769 }
3770
3771 static const rb_data_type_t weakmap_type = {
3772 "weakmap",
3773 {
3774 wmap_mark,
3775 wmap_free,
3776 wmap_memsize,
3777 }
3778 };
3779
3780 static VALUE
3781 wmap_allocate(VALUE klass)
3782 {
3783 struct weakmap *w;
3784 VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &weakmap_type, w);
3785 w->obj2wmap = st_init_numtable();
3786 w->wmap2obj = st_init_numtable();
3787 w->final = rb_obj_method(obj, ID2SYM(rb_intern("finalize")));
3788 return obj;
3789 }
3790
3791 static int
3792 wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
3793 {
3794 VALUE wmap, ary;
3795 if (!existing) return ST_STOP;
3796 wmap = (VALUE)arg, ary = (VALUE)*value;
3797 rb_ary_delete_same(ary, wmap);
3798 if (!RARRAY_LEN(ary)) return ST_DELETE;
3799 return ST_CONTINUE;
3800 }
3801
3802 static VALUE
3803 wmap_finalize(VALUE self, VALUE objid)
3804 {
3805 st_data_t orig, wmap, data;
3806 VALUE obj, rids;
3807 long i;
3808 struct weakmap *w;
3809
3810 TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
3811 /* Get reference from object id. */
3812 obj = obj_id_to_ref(objid);
3813
3814 /* obj is original referenced object and/or weak reference. */
3815 orig = (st_data_t)obj;
3816 if (st_delete(w->obj2wmap, &orig, &data)) {
3817 rids = (VALUE)data;
3818 for (i = 0; i < RARRAY_LEN(rids); ++i) {
3819 wmap = (st_data_t)RARRAY_PTR(rids)[i];
3820 st_delete(w->wmap2obj, &wmap, NULL);
3821 }
3822 }
3823
3824 wmap = (st_data_t)obj;
3825 if (st_delete(w->wmap2obj, &wmap, &orig)) {
3826 wmap = (st_data_t)obj;
3827 st_update(w->obj2wmap, orig, wmap_final_func, wmap);
3828 }
3829 return self;
3830 }
3831
3832 /* Creates a weak reference from the given key to the given value */
3833 static VALUE
3834 wmap_aset(VALUE self, VALUE wmap, VALUE orig)
3835 {
3836 st_data_t data;
3837 VALUE rids;
3838 struct weakmap *w;
3839
3840 TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
3841 rb_define_final(orig, w->final);
3842 rb_define_final(wmap, w->final);
3843 if (st_lookup(w->obj2wmap, (st_data_t)orig, &data)) {
3844 rids = (VALUE)data;
3845 }
3846 else {
3847 rids = rb_ary_tmp_new(1);
3848 st_insert(w->obj2wmap, (st_data_t)orig, (st_data_t)rids);
3849 }
3850 rb_ary_push(rids, wmap);
3851 st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
3852 return nonspecial_obj_id(orig);
3853 }
3854
3855 /* Retrieves a weakly referenced object with the given key */
3856 static VALUE
3857 wmap_aref(VALUE self, VALUE wmap)
3858 {
3859 st_data_t data;
3860 VALUE obj;
3861 struct weakmap *w;
3862 rb_objspace_t *objspace = &rb_objspace;
3863
3864 TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
3865 if (!st_lookup(w->wmap2obj, (st_data_t)wmap, &data)) return Qnil;
3866 obj = (VALUE)data;
3867 if (!is_id_value(objspace, obj)) return Qnil;
3868 if (!is_live_object(objspace, obj)) return Qnil;
3869 return obj;
3870 }
3871
3872
3873 /*
3874 ------------------------------ GC profiler ------------------------------
3875 */
3876
3877 static inline void gc_prof_set_heap_info(rb_objspace_t *, gc_profile_record *);
3878 #define GC_PROFILE_RECORD_DEFAULT_SIZE 100
3879
3880 static double
3881 getrusage_time(void)
3882 {
3883 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
3884 {
3885 static int try_clock_gettime = 1;
3886 struct timespec ts;
3887 if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
3888 return ts.tv_sec + ts.tv_nsec * 1e-9;
3889 }
3890 else {
3891 try_clock_gettime = 0;
3892 }
3893 }
3894 #endif
3895
3896 #ifdef RUSAGE_SELF
3897 {
3898 struct rusage usage;
3899 struct timeval time;
3900 if (getrusage(RUSAGE_SELF, &usage) == 0) {
3901 time = usage.ru_utime;
3902 return time.tv_sec + time.tv_usec * 1e-6;
3903 }
3904 }
3905 #endif
3906
3907 #ifdef _WIN32
3908 {
3909 FILETIME creation_time, exit_time, kernel_time, user_time;
3910 ULARGE_INTEGER ui;
3911 LONG_LONG q;
3912 double t;
3913
3914 if (GetProcessTimes(GetCurrentProcess(),
3915 &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
3916 memcpy(&ui, &user_time, sizeof(FILETIME));
3917 q = ui.QuadPart / 10L;
3918 t = (DWORD)(q % 1000000L) * 1e-6;
3919 q /= 1000000L;
3920 #ifdef __GNUC__
3921 t += q;
3922 #else
3923 t += (double)(DWORD)(q >> 16) * (1 << 16);
3924 t += (DWORD)q & ~(~0 << 16);
3925 #endif
3926 return t;
3927 }
3928 }
3929 #endif
3930
3931 return 0.0;
3932 }
3933
3934 static inline void
3935 gc_prof_timer_start(rb_objspace_t *objspace)
3936 {
3937 if (objspace->profile.run) {
3938 size_t count = objspace->profile.count;
3939
3940 if (!objspace->profile.record) {
3941 objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE;
3942 objspace->profile.record = malloc(sizeof(gc_profile_record) * objspace->profile.size);
3943 }
3944 if (count >= objspace->profile.size) {
3945 objspace->profile.size += 1000;
3946 objspace->profile.record = realloc(objspace->profile.record, sizeof(gc_profile_record) * objspace->profile.size);
3947 }
3948 if (!objspace->profile.record) {
3949 rb_bug("gc_profile malloc or realloc miss");
3950 }
3951 MEMZERO(&objspace->profile.record[count], gc_profile_record, 1);
3952 objspace->profile.record[count].gc_time = getrusage_time();
3953 objspace->profile.record[objspace->profile.count].gc_invoke_time =
3954 objspace->profile.record[count].gc_time - objspace->profile.invoke_time;
3955 }
3956 }
3957
3958 static inline void
3959 gc_prof_timer_stop(rb_objspace_t *objspace, int marked)
3960 {
3961 if (objspace->profile.run) {
3962 double gc_time = 0;
3963 size_t count = objspace->profile.count;
3964 gc_profile_record *record = &objspace->profile.record[count];
3965
3966 gc_time = getrusage_time() - record->gc_time;
3967 if (gc_time < 0) gc_time = 0;
3968 record->gc_time = gc_time;
3969 record->is_marked = !!(marked);
3970 gc_prof_set_heap_info(objspace, record);
3971 objspace->profile.count++;
3972 }
3973 }
3974
3975 #if !GC_PROFILE_MORE_DETAIL
3976
3977 static inline void
3978 gc_prof_mark_timer_start(rb_objspace_t *objspace)
3979 {
3980 if (RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()) {
3981 RUBY_DTRACE_GC_MARK_BEGIN();
3982 }
3983 }
3984
3985 static inline void
3986 gc_prof_mark_timer_stop(rb_objspace_t *objspace)
3987 {
3988 if (RUBY_DTRACE_GC_MARK_END_ENABLED()) {
3989 RUBY_DTRACE_GC_MARK_END();
3990 }
3991 }
3992
3993 static inline void
3994 gc_prof_sweep_timer_start(rb_objspace_t *objspace)
3995 {
3996 if (RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()) {
3997 RUBY_DTRACE_GC_SWEEP_BEGIN();
3998 }
3999 }
4000
4001 static inline void
4002 gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
4003 {
4004 if (RUBY_DTRACE_GC_SWEEP_END_ENABLED()) {
4005 RUBY_DTRACE_GC_SWEEP_END();
4006 }
4007 }
4008
4009 static inline void
4010 gc_prof_set_malloc_info(rb_objspace_t *objspace)
4011 {
4012 }
4013
4014 static inline void
4015 gc_prof_set_heap_info(rb_objspace_t *objspace, gc_profile_record *record)
4016 {
4017 size_t live = objspace_live_num(objspace);
4018 size_t total = heaps_used * HEAP_OBJ_LIMIT;
4019
4020 record->heap_total_objects = total;
4021 record->heap_use_size = live * sizeof(RVALUE);
4022 record->heap_total_size = total * sizeof(RVALUE);
4023 }
4024
4025 #else
4026
4027 static inline void
4028 gc_prof_mark_timer_start(rb_objspace_t *objspace)
4029 {
4030 if (RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()) {
4031 RUBY_DTRACE_GC_MARK_BEGIN();
4032 }
4033 if (objspace->profile.run) {
4034 size_t count = objspace->profile.count;
4035
4036 objspace->profile.record[count].gc_mark_time = getrusage_time();
4037 }
4038 }
4039
4040 static inline void
4041 gc_prof_mark_timer_stop(rb_objspace_t *objspace)
4042 {
4043 if (RUBY_DTRACE_GC_MARK_END_ENABLED()) {
4044 RUBY_DTRACE_GC_MARK_END();
4045 }
4046 if (objspace->profile.run) {
4047 double mark_time = 0;
4048 size_t count = objspace->profile.count;
4049 gc_profile_record *record = &objspace->profile.record[count];
4050
4051 mark_time = getrusage_time() - record->gc_mark_time;
4052 if (mark_time < 0) mark_time = 0;
4053 record->gc_mark_time = mark_time;
4054 }
4055 }
4056
4057 static inline void
4058 gc_prof_sweep_timer_start(rb_objspace_t *objspace)
4059 {
4060 if (RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()) {
4061 RUBY_DTRACE_GC_SWEEP_BEGIN();
4062 }
4063 if (objspace->profile.run) {
4064 size_t count = objspace->profile.count;
4065
4066 objspace->profile.record[count].gc_sweep_time = getrusage_time();
4067 }
4068 }
4069
4070 static inline void
4071 gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
4072 {
4073 if (RUBY_DTRACE_GC_SWEEP_END_ENABLED()) {
4074 RUBY_DTRACE_GC_SWEEP_END();
4075 }
4076 if (objspace->profile.run) {
4077 double sweep_time = 0;
4078 size_t count = objspace->profile.count;
4079 gc_profile_record *record = &objspace->profile.record[count];
4080
4081 sweep_time = getrusage_time() - record->gc_sweep_time;\
4082 if (sweep_time < 0) sweep_time = 0;\
4083 record->gc_sweep_time = sweep_time;
4084 }
4085 }
4086
4087 static inline void
4088 gc_prof_set_malloc_info(rb_objspace_t *objspace)
4089 {
4090 if (objspace->profile.run) {
4091 gc_profile_record *record = &objspace->profile.record[objspace->profile.count];
4092 if (record) {
4093 record->allocate_increase = malloc_increase;
4094 record->allocate_limit = malloc_limit;
4095 }
4096 }
4097 }
4098
4099 static inline void
4100 gc_prof_set_heap_info(rb_objspace_t *objspace, gc_profile_record *record)
4101 {
4102 size_t live = objspace_live_num(objspace);
4103 size_t total = heaps_used * HEAP_OBJ_LIMIT;
4104
4105 record->heap_use_slots = heaps_used;
4106 record->heap_live_objects = live;
4107 record->heap_free_objects = total - live;
4108 record->heap_total_objects = total;
4109 record->have_finalize = deferred_final_list ? Qtrue : Qfalse;
4110 record->heap_use_size = live * sizeof(RVALUE);
4111 record->heap_total_size = total * sizeof(RVALUE);
4112 }
4113
4114 #endif /* !GC_PROFILE_MORE_DETAIL */
4115
4116
4117 /*
4118 * call-seq:
4119 * GC::Profiler.clear -> nil
4120 *
4121 * Clears the GC profiler data.
4122 *
4123 */
4124
4125 static VALUE
4126 gc_profile_clear(void)
4127 {
4128 rb_objspace_t *objspace = &rb_objspace;
4129
4130 if (GC_PROFILE_RECORD_DEFAULT_SIZE * 2 < objspace->profile.size) {
4131 objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE * 2;
4132 objspace->profile.record = realloc(objspace->profile.record, sizeof(gc_profile_record) * objspace->profile.size);
4133 if (!objspace->profile.record) {
4134 rb_memerror();
4135 }
4136 }
4137 MEMZERO(objspace->profile.record, gc_profile_record, objspace->profile.size);
4138 objspace->profile.count = 0;
4139 return Qnil;
4140 }
4141
4142 /*
4143 * call-seq:
4144 * GC::Profiler.raw_data -> [Hash, ...]
4145 *
4146 * Returns an Array of individual raw profile data Hashes ordered
4147 * from earliest to latest by +:GC_INVOKE_TIME+.
4148 *
4149 * For example:
4150 *
4151 * [
4152 * {
4153 * :GC_TIME=>1.3000000000000858e-05,
4154 * :GC_INVOKE_TIME=>0.010634999999999999,
4155 * :HEAP_USE_SIZE=>289640,
4156 * :HEAP_TOTAL_SIZE=>588960,
4157 * :HEAP_TOTAL_OBJECTS=>14724,
4158 * :GC_IS_MARKED=>false
4159 * },
4160 * # ...
4161 * ]
4162 *
4163 * The keys mean:
4164 *
4165 * +:GC_TIME+::
4166 * Time elapsed in seconds for this GC run
4167 * +:GC_INVOKE_TIME+::
4168 * Time elapsed in seconds from startup to when the GC was invoked
4169 * +:HEAP_USE_SIZE+::
4170 * Total bytes of heap used
4171 * +:HEAP_TOTAL_SIZE+::
4172 * Total size of heap in bytes
4173 * +:HEAP_TOTAL_OBJECTS+::
4174 * Total number of objects
4175 * +:GC_IS_MARKED+::
4176 * Returns +true+ if the GC is in mark phase
4177 *
4178 * If ruby was built with +GC_PROFILE_MORE_DETAIL+, you will also have access
4179 * to the following hash keys:
4180 *
4181 * +:GC_MARK_TIME+::
4182 * +:GC_SWEEP_TIME+::
4183 * +:ALLOCATE_INCREASE+::
4184 * +:ALLOCATE_LIMIT+::
4185 * +:HEAP_USE_SLOTS+::
4186 * +:HEAP_LIVE_OBJECTS+::
4187 * +:HEAP_FREE_OBJECTS+::
4188 * +:HAVE_FINALIZE+::
4189 *
4190 */
4191
4192 static VALUE
4193 gc_profile_record_get(void)
4194 {
4195 VALUE prof;
4196 VALUE gc_profile = rb_ary_new();
4197 size_t i;
4198 rb_objspace_t *objspace = (&rb_objspace);
4199
4200 if (!objspace->profile.run) {
4201 return Qnil;
4202 }
4203
4204 for (i =0; i < objspace->profile.count; i++) {
4205 prof = rb_hash_new();
4206 rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(objspace->profile.record[i].gc_time));
4207 rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(objspace->profile.record[i].gc_invoke_time));
4208 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(objspace->profile.record[i].heap_use_size));
4209 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), SIZET2NUM(objspace->profile.record[i].heap_total_size));
4210 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_total_objects));
4211 rb_hash_aset(prof, ID2SYM(rb_intern("GC_IS_MARKED")), objspace->profile.record[i].is_marked);
4212 #if GC_PROFILE_MORE_DETAIL
4213 rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(objspace->profile.record[i].gc_mark_time));
4214 rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(objspace->profile.record[i].gc_sweep_time));
4215 rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(objspace->profile.record[i].allocate_increase));
4216 rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(objspace->profile.record[i].allocate_limit));
4217 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SLOTS")), SIZET2NUM(objspace->profile.record[i].heap_use_slots));
4218 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_live_objects));
4219 rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(objspace->profile.record[i].heap_free_objects));
4220 rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), objspace->profile.record[i].have_finalize);
4221 #endif
4222 rb_ary_push(gc_profile, prof);
4223 }
4224
4225 return gc_profile;
4226 }
4227
4228 static void
4229 gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
4230 {
4231 rb_objspace_t *objspace = &rb_objspace;
4232 size_t count = objspace->profile.count;
4233
4234 if (objspace->profile.run && count) {
4235 int index = 1;
4236 size_t i;
4237 gc_profile_record r;
4238 append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->count));
4239 append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
4240 for (i = 0; i < count; i++) {
4241 r = objspace->profile.record[i];
4242 #if !GC_PROFILE_MORE_DETAIL
4243 if (r.is_marked) {
4244 #endif
4245 append(out, rb_sprintf("%5d %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
4246 index++, r.gc_invoke_time, r.heap_use_size,
4247 r.heap_total_size, r.heap_total_objects, r.gc_time*1000));
4248 #if !GC_PROFILE_MORE_DETAIL
4249 }
4250 #endif
4251 }
4252 #if GC_PROFILE_MORE_DETAIL
4253 append(out, rb_str_new_cstr("\n\n" \
4254 "More detail.\n" \
4255 "Index Allocate Increase Allocate Limit Use Slot Have Finalize Mark Time(ms) Sweep Time(ms)\n"));
4256 index = 1;
4257 for (i = 0; i < count; i++) {
4258 r = objspace->profile.record[i];
4259 append(out, rb_sprintf("%5d %17"PRIuSIZE" %17"PRIuSIZE" %9"PRIuSIZE" %14s %25.20f %25.20f\n",
4260 index++, r.allocate_increase, r.allocate_limit,
4261 r.heap_use_slots, (r.have_finalize ? "true" : "false"),
4262 r.gc_mark_time*1000, r.gc_sweep_time*1000));
4263 }
4264 #endif
4265 }
4266 }
4267
4268 /*
4269 * call-seq:
4270 * GC::Profiler.result -> String
4271 *
4272 * Returns a profile data report such as:
4273 *
4274 * GC 1 invokes.
4275 * Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC time(ms)
4276 * 1 0.012 159240 212940 10647 0.00000000000001530000
4277 */
4278
4279 static VALUE
4280 gc_profile_result(void)
4281 {
4282 VALUE str = rb_str_buf_new(0);
4283 gc_profile_dump_on(str, rb_str_buf_append);
4284 return str;
4285 }
4286
4287 /*
4288 * call-seq:
4289 * GC::Profiler.report
4290 * GC::Profiler.report(io)
4291 *
4292 * Writes the GC::Profiler.result to <tt>$stdout</tt> or the given IO object.
4293 *
4294 */
4295
4296 static VALUE
4297 gc_profile_report(int argc, VALUE *argv, VALUE self)
4298 {
4299 VALUE out;
4300
4301 if (argc == 0) {
4302 out = rb_stdout;
4303 }
4304 else {
4305 rb_scan_args(argc, argv, "01", &out);
4306 }
4307 gc_profile_dump_on(out, rb_io_write);
4308
4309 return Qnil;
4310 }
4311
4312 /*
4313 * call-seq:
4314 * GC::Profiler.total_time -> float
4315 *
4316 * The total time used for garbage collection in seconds
4317 */
4318
4319 static VALUE
4320 gc_profile_total_time(VALUE self)
4321 {
4322 double time = 0;
4323 rb_objspace_t *objspace = &rb_objspace;
4324 size_t i;
4325
4326 if (objspace->profile.run && objspace->profile.count) {
4327 for (i = 0; i < objspace->profile.count; i++) {
4328 time += objspace->profile.record[i].gc_time;
4329 }
4330 }
4331 return DBL2NUM(time);
4332 }
4333
4334 /*
4335 * call-seq:
4336 * GC::Profiler.enabled? -> true or false
4337 *
4338 * The current status of GC profile mode.
4339 */
4340
4341 static VALUE
4342 gc_profile_enable_get(VALUE self)
4343 {
4344 rb_objspace_t *objspace = &rb_objspace;
4345 return objspace->profile.run ? Qtrue : Qfalse;
4346 }
4347
4348 /*
4349 * call-seq:
4350 * GC::Profiler.enable -> nil
4351 *
4352 * Starts the GC profiler.
4353 *
4354 */
4355
4356 static VALUE
4357 gc_profile_enable(void)
4358 {
4359 rb_objspace_t *objspace = &rb_objspace;
4360
4361 objspace->profile.run = TRUE;
4362 return Qnil;
4363 }
4364
4365 /*
4366 * call-seq:
4367 * GC::Profiler.disable -> nil
4368 *
4369 * Stops the GC profiler.
4370 *
4371 */
4372
4373 static VALUE
4374 gc_profile_disable(void)
4375 {
4376 rb_objspace_t *objspace = &rb_objspace;
4377
4378 objspace->profile.run = FALSE;
4379 return Qnil;
4380 }
4381
4382 #ifdef GC_DEBUG
4383
4384 /*
4385 ------------------------------ DEBUG ------------------------------
4386 */
4387
4388 void
4389 rb_gcdebug_print_obj_condition(VALUE obj)
4390 {
4391 rb_objspace_t *objspace = &rb_objspace;
4392
4393 if (is_pointer_to_heap(objspace, (void *)obj)) {
4394 fprintf(stderr, "pointer to heap?: true\n");
4395 }
4396 else {
4397 fprintf(stderr, "pointer to heap?: false\n");
4398 return;
4399 }
4400 fprintf(stderr, "marked?: %s\n",
4401 MARKED_IN_BITMAP(GET_HEAP_BITMAP(obj), obj) ? "true" : "false");
4402 if (is_lazy_sweeping(objspace)) {
4403 fprintf(stderr, "lazy sweeping?: true\n");
4404 fprintf(stderr, "swept?: %s\n",
4405 is_swept_object(objspace, obj) ? "done" : "not yet");
4406 }
4407 else {
4408 fprintf(stderr, "lazy sweeping?: false\n");
4409 }
4410 }
4411
4412 static VALUE
4413 gcdebug_sential(VALUE obj, VALUE name)
4414 {
4415 fprintf(stderr, "WARNING: object %s(%p) is inadvertently collected\n", (char *)name, (void *)obj);
4416 return Qnil;
4417 }
4418
4419 void
4420 rb_gcdebug_sentinel(VALUE obj, const char *name)
4421 {
4422 rb_define_final(obj, rb_proc_new(gcdebug_sential, (VALUE)name));
4423 }
4424 #endif /* GC_DEBUG */
4425
4426
4427 /*
4428 * Document-class: ObjectSpace
4429 *
4430 * The ObjectSpace module contains a number of routines
4431 * that interact with the garbage collection facility and allow you to
4432 * traverse all living objects with an iterator.
4433 *
4434 * ObjectSpace also provides support for object finalizers, procs that will be
4435 * called when a specific object is about to be destroyed by garbage
4436 * collection.
4437 *
4438 * include ObjectSpace
4439 *
4440 * a = "A"
4441 * b = "B"
4442 * c = "C"
4443 *
4444 * define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
4445 * define_finalizer(a, proc {|id| puts "Finalizer two on #{id}" })
4446 * define_finalizer(b, proc {|id| puts "Finalizer three on #{id}" })
4447 *
4448 * _produces:_
4449 *
4450 * Finalizer three on 537763470
4451 * Finalizer one on 537763480
4452 * Finalizer two on 537763480
4453 *
4454 */
4455
4456 /*
4457 * Document-class: ObjectSpace::WeakMap
4458 *
4459 * An ObjectSpace::WeakMap object holds references to
4460 * any objects, but those objects can get garbage collected.
4461 *
4462 * This class is mostly used internally by WeakRef, please use
4463 * +lib/weakref.rb+ for the public interface.
4464 */
4465
4466 /* Document-class: GC::Profiler
4467 *
4468 * The GC profiler provides access to information on GC runs including time,
4469 * length and object space size.
4470 *
4471 * Example:
4472 *
4473 * GC::Profiler.enable
4474 *
4475 * require 'rdoc/rdoc'
4476 *
4477 * GC::Profiler.report
4478 *
4479 * GC::Profiler.disable
4480 *
4481 * See also GC.count, GC.malloc_allocated_size and GC.malloc_allocations
4482 */
4483
4484 /*
4485 * The GC module provides an interface to Ruby's mark and
4486 * sweep garbage collection mechanism.
4487 *
4488 * Some of the underlying methods are also available via the ObjectSpace
4489 * module.
4490 *
4491 * You may obtain information about the operation of the GC through
4492 * GC::Profiler.
4493 */
4494
4495 void
4496 Init_GC(void)
4497 {
4498 VALUE rb_mObSpace;
4499 VALUE rb_mProfiler;
4500
4501 rb_mGC = rb_define_module("GC");
4502 rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
4503 rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
4504 rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
4505 rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0);
4506 rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
4507 rb_define_singleton_method(rb_mGC, "count", gc_count, 0);
4508 rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1);
4509 rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
4510
4511 rb_mProfiler = rb_define_module_under(rb_mGC, "Profiler");
4512 rb_define_singleton_method(rb_mProfiler, "enabled?", gc_profile_enable_get, 0);
4513 rb_define_singleton_method(rb_mProfiler, "enable", gc_profile_enable, 0);
4514 rb_define_singleton_method(rb_mProfiler, "raw_data", gc_profile_record_get, 0);
4515 rb_define_singleton_method(rb_mProfiler, "disable", gc_profile_disable, 0);
4516 rb_define_singleton_method(rb_mProfiler, "clear", gc_profile_clear, 0);
4517 rb_define_singleton_method(rb_mProfiler, "result", gc_profile_result, 0);
4518 rb_define_singleton_method(rb_mProfiler, "report", gc_profile_report, -1);
4519 rb_define_singleton_method(rb_mProfiler, "total_time", gc_profile_total_time, 0);
4520
4521 rb_mObSpace = rb_define_module("ObjectSpace");
4522 rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
4523 rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
4524
4525 rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
4526 rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);
4527
4528 rb_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
4529
4530 nomem_error = rb_exc_new3(rb_eNoMemError,
4531 rb_obj_freeze(rb_str_new2("failed to allocate memory")));
4532 OBJ_TAINT(nomem_error);
4533 OBJ_FREEZE(nomem_error);
4534
4535 rb_define_method(rb_cBasicObject, "__id__", rb_obj_id, 0);
4536 rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
4537
4538 rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
4539
4540 {
4541 VALUE rb_cWeakMap = rb_define_class_under(rb_mObSpace, "WeakMap", rb_cObject);
4542 rb_define_alloc_func(rb_cWeakMap, wmap_allocate);
4543 rb_define_method(rb_cWeakMap, "[]=", wmap_aset, 2);
4544 rb_define_method(rb_cWeakMap, "[]", wmap_aref, 1);
4545 rb_define_private_method(rb_cWeakMap, "finalize", wmap_finalize, 1);
4546 }
4547
4548 #if CALC_EXACT_MALLOC_SIZE
4549 rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
4550 rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
4551 #endif
4552 }
data
VALUE data
Definition: tcltklib.c:3368
os_each_struct::of
VALUE of
Definition: gc.c:1143
rb_objspace
#define rb_objspace
Definition: gc.c:265
RB_TYPE_P
#define RB_TYPE_P(obj, type)
rb_objspace::mark_func_data_struct
Definition: gc.c:258
nd_type
#define nd_type(n)
mark_hash
static void mark_hash(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:2402
RARRAY_PTR
RARRAY_PTR(q->result)[0]
NODE_DREGX_ONCE
#define NODE_DREGX_ONCE
rb_method_entry_struct::mark
char mark
Definition: method.h:97
RVALUE::node
struct RNode node
Definition: gc.c:147
gc_profile_record::heap_total_objects
size_t heap_total_objects
Definition: gc.c:103
each_obj_args
Definition: gc.c:1046
ALLOC
#define ALLOC(type)
tmp
volatile VALUE tmp
Definition: tcltklib.c:10209
slot_sweep
static void slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
Definition: gc.c:1880
NODE_IF
#define NODE_IF
rb_gc_disable
VALUE rb_gc_disable(void)
Definition: gc.c:3283
NODE_RESCUE
#define NODE_RESCUE
RMatch
Definition: re.h:46
NODE_RETRY
#define NODE_RETRY
rb_thread_struct::vm
rb_vm_t * vm
Definition: vm_core.h:495
NODE_DEFN
#define NODE_DEFN
ruby_initial_gc_stress_ptr
int * ruby_initial_gc_stress_ptr
Definition: gc.c:267
ROBJECT_EMBED
#define ROBJECT_EMBED
rb_method_definition_struct
Definition: method.h:76
n
ssize_t n
Definition: bigdecimal.c:5655
stack_chunk
Definition: gc.c:190
block
int register char * block
Definition: crypt.c:949
FIXNUM_FLAG
#define FIXNUM_FLAG
VALGRIND_MAKE_MEM_UNDEFINED
#define VALGRIND_MAKE_MEM_UNDEFINED(p, n)
Definition: gc.c:63
ary
volatile VALUE ary
Definition: tcltklib.c:9713
NODE_FALSE
#define NODE_FALSE
RFloat
Definition: ripper.y:752
rb_cBasicObject
RUBY_EXTERN VALUE rb_cBasicObject
Definition: ripper.y:1425
FLONUM_P
#define FLONUM_P(x)
ruby_thread_has_gvl_p
int ruby_thread_has_gvl_p(void)
Definition: thread.c:1443
int
VP_EXPORT int
Definition: bigdecimal.c:5050
vm_xcalloc
static void * vm_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
Definition: gc.c:3616
NODE_OR
#define NODE_OR
RVALUE::bignum
struct RBignum bignum
Definition: gc.c:145
RSTRUCT_LEN
#define RSTRUCT_LEN(st)
rb_special_const_p
static int rb_special_const_p(VALUE obj)
Definition: ripper.y:1560
ruby_gc_params_t::initial_free_min
unsigned int initial_free_min
Definition: gc.c:78
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
rb_method_definition_struct::type
rb_method_type_t type
Definition: method.h:77
mark_tbl_arg::objspace
rb_objspace_t * objspace
Definition: gc.c:2349
gc_profile_disable
static VALUE gc_profile_disable(void)
Definition: gc.c:4374
malloc
void * malloc()
FALSE
#define FALSE
Definition: nkf.h:174
set_zero
static int set_zero(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:1735
T_STRUCT
#define T_STRUCT
RUBY_DTRACE_GC_SWEEP_END_ENABLED
#define RUBY_DTRACE_GC_SWEEP_END_ENABLED()
Definition: probes.h:94
rb_method_definition_struct::attr
rb_method_attr_t attr
Definition: method.h:82
rb_mark_tbl
void rb_mark_tbl(struct st_table *)
Definition: gc.c:2541
th
static VALUE VALUE th
Definition: tcltklib.c:2948
STACK_START
#define STACK_START
Definition: gc.c:2252
rb_gc_mark_locations
#define rb_gc_mark_locations(start, end)
Definition: gc.c:2346
RData::dfree
void(* dfree)(void *)
Definition: ripper.y:954
rb_objspace_free
void rb_objspace_free(rb_objspace_t *objspace)
Definition: gc.c:389
gc_prof_set_malloc_info
static void gc_prof_set_malloc_info(rb_objspace_t *)
Definition: gc.c:4010
ST_DELETE
Definition: ripper.y:108
T_MATCH
#define T_MATCH
rb_const_entry_struct
Definition: constant.h:19
st_table
Definition: ripper.y:77
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
pop_mark_stack_chunk
static void pop_mark_stack_chunk(mark_stack_t *stack)
Definition: gc.c:2176
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
os_each_struct::num
size_t num
Definition: gc.c:1142
mark_stack::unused_cache_size
size_t unused_cache_size
Definition: gc.c:201
rb_eval_cmd
VALUE rb_eval_cmd(VALUE, VALUE, int)
Definition: vm_eval.c:1447
vm_malloc_prepare
static size_t vm_malloc_prepare(rb_objspace_t *objspace, size_t size)
Definition: gc.c:3473
FL_TEST
#define FL_TEST(x, f)
NODE_DEFS
#define NODE_DEFS
count
int count
Definition: encoding.c:51
RAISED_NOMEMORY
Definition: eval_intern.h:166
heaps_header::bits
uintptr_t * bits
Definition: gc.c:173
id2ref
static VALUE id2ref(VALUE obj, VALUE objid)
Definition: gc.c:1615
st_lookup
int st_lookup(st_table *, st_data_t, st_data_t *)
RUBY_DATA_FUNC
void(* RUBY_DATA_FUNC)(void *)
Definition: ripper.y:994
st_add_direct
void st_add_direct(st_table *, st_data_t, st_data_t)
Definition: st.c:624
RVALUE::file
struct RFile file
Definition: gc.c:146
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
rb_str_buf_append
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2105
link_free_heap_slot
static void link_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
Definition: gc.c:467
mark_keyvalue
static int mark_keyvalue(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:2393
NODE_HASH
#define NODE_HASH
rb_mark_generic_ivar
void rb_mark_generic_ivar(VALUE)
Definition: variable.c:990
rb_objspace::size
size_t size
Definition: gc.c:249
os_each_obj
static VALUE os_each_obj(int argc, VALUE *argv, VALUE os)
Definition: gc.c:1242
rb_objspace::ptr
struct heaps_slot * ptr
Definition: gc.c:219
NODE_DOT3
#define NODE_DOT3
is_pointer_to_heap
static int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
Definition: gc.c:763
ruby.h
rb_objspace::run
int run
Definition: gc.c:246
vm_xmalloc
static void * vm_xmalloc(rb_objspace_t *objspace, size_t size)
Definition: gc.c:3516
out
C_block * out
Definition: crypt.c:308
FL_EXIVAR
#define FL_EXIVAR
rb_stdout
RUBY_EXTERN VALUE rb_stdout
Definition: ripper.y:1500
ruby_stack_length
size_t ruby_stack_length(VALUE **)
Definition: gc.c:2278
gc_profile_record::is_marked
int is_marked
Definition: gc.c:107
run_single_final
static VALUE run_single_final(VALUE arg)
Definition: gc.c:1364
FL_SET
#define FL_SET(x, f)
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:272
heaps_slot::freelist
RVALUE * freelist
Definition: gc.c:165
T_ICLASS
#define T_ICLASS
rb_objspace::range
RVALUE * range[2]
Definition: gc.c:226
ATOMIC_EXCHANGE
#define ATOMIC_EXCHANGE(var, val)
Definition: ruby_atomic.h:104
table
static int VALUE table
Definition: tcltklib.c:10138
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
rb_secure
void rb_secure(int)
Definition: safe.c:79
SIZET2NUM
#define SIZET2NUM(v)
wmap_mark
static void wmap_mark(void *ptr)
Definition: gc.c:3727
NODE_VCALL
#define NODE_VCALL
rb_objspace::increment
size_t increment
Definition: gc.c:218
rb_objspace::mark_func_data_struct::data
void * data
Definition: gc.c:259
NODE_NTH_REF
#define NODE_NTH_REF
ruby_mimmalloc
void * ruby_mimmalloc(size_t size)
Definition: gc.c:3662
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE)
Definition: gc.c:2961
i
ssize_t i
Definition: bigdecimal.c:5655
NODE_TRUE
#define NODE_TRUE
rb_io_t
Definition: io.h:63
rb_objspace::profile
struct rb_objspace::@92 profile
rb_check_frozen
#define rb_check_frozen(obj)
T_NODE
#define T_NODE
probes.h
rb_method_definition_struct::orig_me
struct rb_method_entry_struct * orig_me
Definition: method.h:90
rb_objspace::sorted
struct heaps_header ** sorted
Definition: gc.c:222
RSTRUCT_EMBED_LEN_MASK
#define RSTRUCT_EMBED_LEN_MASK
NODE_ITER
#define NODE_ITER
NODE_ARGS
#define NODE_ARGS
eval_intern.h
NODE_MATCH3
#define NODE_MATCH3
HEAP_SIZE
Definition: gc.c:328
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:447
rb_objspace::mark_func_data_struct::mark_func
void(* mark_func)(VALUE v, void *data)
Definition: gc.c:260
rb_gc_mark_global_tbl
void rb_gc_mark_global_tbl(void)
Definition: variable.c:552
stack_check
static int stack_check(int water_mark)
Definition: gc.c:2288
ret
int ret
Definition: tcltklib.c:280
RVALUE::flonum
struct RFloat flonum
Definition: gc.c:137
ruby_xmalloc2
void * ruby_xmalloc2(size_t n, size_t size)
Definition: gc.c:3610
NODE_UNDEF
#define NODE_UNDEF
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1356
GET_HEAP_SLOT
#define GET_HEAP_SLOT(x)
Definition: gc.c:310
unlink_free_heap_slot
static void unlink_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
Definition: gc.c:474
status
int status
Definition: tcltklib.c:2197
RVALUE::rstruct
struct RStruct rstruct
Definition: gc.c:144
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:989
rb_vm_struct::mark_object_ary
VALUE mark_object_ary
Definition: vm_core.h:355
dont_gc
#define dont_gc
Definition: gc.c:281
NODE_ENSURE
#define NODE_ENSURE
VM_METHOD_TYPE_ISEQ
Definition: method.h:46
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:511
rb_objspace::increase
size_t increase
Definition: gc.c:211
OBJ_FREEZE
#define OBJ_FREEZE(x)
finalizer_table
#define finalizer_table
Definition: gc.c:284
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
gc_prof_mark_timer_start
static void gc_prof_mark_timer_start(rb_objspace_t *)
Definition: gc.c:3978
constant.h
global_List
#define global_List
Definition: gc.c:286
has_free_object
#define has_free_object
Definition: gc.c:306
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:465
ruby_xrealloc2
void * ruby_xrealloc2(void *ptr, size_t n, size_t size)
Definition: gc.c:3641
RHASH_TBL
#define RHASH_TBL(h)
count_objects
static VALUE count_objects(int argc, VALUE *argv, VALUE os)
Definition: gc.c:1769
ROBJECT_IVPTR
#define ROBJECT_IVPTR(o)
rb_gc_copy_finalizer
void rb_gc_copy_finalizer(VALUE, VALUE)
Definition: gc.c:1349
T_ARRAY
#define T_ARRAY
initial_heap_min_slots
#define initial_heap_min_slots
Definition: gc.c:289
gc_list::next
struct gc_list * next
Definition: gc.c:185
STACK_UPPER
#define STACK_UPPER(x, a, b)
Definition: gc.h:74
rb_mark_generic_ivar_tbl
void rb_mark_generic_ivar_tbl(void)
Definition: variable.c:1020
NODE_SUPER
#define NODE_SUPER
ruby_gc_params_t::gc_stress
int gc_stress
Definition: gc.c:80
var
VALUE var
Definition: tcltklib.c:5517
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:771
NODE_EVSTR
#define NODE_EVSTR
xfree
#define xfree
gc_prof_sweep_timer_start
static void gc_prof_sweep_timer_start(rb_objspace_t *)
Definition: gc.c:3994
NODE_RESBODY
#define NODE_RESBODY
rb_objspace::free_bitmap
struct heaps_free_bitmap * free_bitmap
Definition: gc.c:225
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:545
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
realloc
void * realloc()
NODE_DXSTR
#define NODE_DXSTR
NODE_CASE
#define NODE_CASE
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
rb_io_fptr_finalize
int rb_io_fptr_finalize(rb_io_t *)
Definition: io.c:4186
rb_proc_new
VALUE rb_proc_new(VALUE(*)(ANYARGS), VALUE)
Definition: proc.c:2018
ruby_memerror
static void ruby_memerror(void)
Definition: gc.c:3388
T_HASH
#define T_HASH
Qtrue
return Qtrue
Definition: tcltklib.c:9610
rmatch::regs
struct re_registers regs
Definition: re.h:39
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
rb_obj_id
VALUE rb_obj_id(VALUE)
Definition: gc.c:1688
gc.h
heaps_used
#define heaps_used
Definition: gc.c:276
rb_objspace::free_num
size_t free_num
Definition: gc.c:229
ruby_get_stack_grow_direction
int ruby_get_stack_grow_direction(volatile VALUE *addr)
Definition: gc.c:2267
rb_sweep_method_entry
void rb_sweep_method_entry(void *vm)
Definition: vm_method.c:122
T_FILE
#define T_FILE
st_memsize
size_t st_memsize(const st_table *)
Definition: st.c:342
index
int index
Definition: tcltklib.c:4478
wmap_memsize_map
static int wmap_memsize_map(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:3752
rb_objspace::malloc_params
struct rb_objspace::@88 malloc_params
rb_ary_new3
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
rb_method_definition_struct::body
union rb_method_definition_struct::@112 body
gc_profile_total_time
static VALUE gc_profile_total_time(VALUE self)
Definition: gc.c:4320
mark_key
static int mark_key(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:2370
NODE_STR
#define NODE_STR
rb_mark_set
void rb_mark_set(struct st_table *)
Definition: gc.c:2387
T_NIL
#define T_NIL
rb_objspace_each_objects
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:1128
NODE_REDO
#define NODE_REDO
NODE_NEXT
#define NODE_NEXT
GC_PROFILE_RECORD_DEFAULT_SIZE
#define GC_PROFILE_RECORD_DEFAULT_SIZE
Definition: gc.c:3878
before_gc_sweep
static void before_gc_sweep(rb_objspace_t *objspace)
Definition: gc.c:1966
rb_objspace_markable_object_p
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:2576
r
r
Definition: bigdecimal.c:1196
TAG_RAISE
#define TAG_RAISE
Definition: eval_intern.h:140
rb_str_new2
#define rb_str_new2
RBignum
Definition: ripper.y:1059
init_heap
static void init_heap(rb_objspace_t *objspace)
Definition: gc.c:577
rb_objspace::used
size_t used
Definition: gc.c:224
NODE_XSTR
#define NODE_XSTR
rb_setjmp
#define rb_setjmp(env)
Definition: gc.c:66
timeval::tv_sec
long tv_sec
Definition: ossl_asn1.c:17
NODE_BLOCK_PASS
#define NODE_BLOCK_PASS
gc_list
Definition: gc.c:183
last
unsigned int last
Definition: nkf.c:4310
after_gc_sweep
static void after_gc_sweep(rb_objspace_t *objspace)
Definition: gc.c:1986
callback
void callback(ffi_cif *cif, void *resp, void **args, void *ctx)
Definition: closure.c:53
lomem
#define lomem
Definition: gc.c:277
RNode::node
struct RNode * node
Definition: ripper.y:244
NODE_MATCH2
#define NODE_MATCH2
rb_thread_struct
Definition: vm_core.h:493
ID2SYM
#define ID2SYM(x)
NODE_FOR
#define NODE_FOR
VM_METHOD_TYPE_BMETHOD
Definition: method.h:50
GC_MALLOC_LIMIT
#define GC_MALLOC_LIMIT
Definition: gc.c:70
T_FLOAT
#define T_FLOAT
tbl
VALUE tbl
Definition: tkutil.c:1280
args
VALUE VALUE args
Definition: tcltklib.c:2561
mark_stack::limit
size_t limit
Definition: gc.c:199
RBasic::klass
VALUE klass
Definition: ripper.y:701
LIKELY
#define LIKELY(x)
Definition: vm_core.h:114
T_OBJECT
#define T_OBJECT
mark_const_entry_i
static int mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data)
Definition: gc.c:2470
RComplex
Definition: ripper.y:945
RData
Definition: ripper.y:951
LONG2NUM
#define LONG2NUM(x)
wmap_free_map
static int wmap_free_map(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:3735
ruby_stack_grow_direction
int ruby_stack_grow_direction
Definition: gc.c:2265
io.h
NODE_UNTIL
#define NODE_UNTIL
ruby_stack_check
int ruby_stack_check(void)
Definition: gc.c:2307
os_each_struct
Definition: gc.c:1141
rb_obj_is_thread
VALUE rb_obj_is_thread(VALUE obj)
Definition: vm.c:1928
NODE_GASGN
#define NODE_GASGN
NODE_ARGS_AUX
#define NODE_ARGS_AUX
rb_mark_method_entry
void rb_mark_method_entry(const rb_method_entry_t *me)
Definition: gc.c:2447
rb_objspace_data_type_name
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:749
VM_METHOD_TYPE_REFINED
Definition: method.h:56
flag
flag
Definition: tcltklib.c:2048
heaps
#define heaps
Definition: gc.c:274
RTypedData
Definition: ripper.y:978
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:515
rb_objspace::mark_func_data
struct rb_objspace::mark_func_data_struct * mark_func_data
push_mark_stack
static void push_mark_stack(mark_stack_t *, VALUE)
Definition: gc.c:2203
mark_stack::chunk
stack_chunk_t * chunk
Definition: gc.c:196
rest_sweep
static void rest_sweep(rb_objspace_t *)
Definition: gc.c:2025
ruby_gc_stress
#define ruby_gc_stress
Definition: gc.c:287
himem
#define himem
Definition: gc.c:278
ATOMIC_SIZE_ADD
#define ATOMIC_SIZE_ADD(var, val)
Definition: ruby_atomic.h:107
add_slot_local_freelist
static struct heaps_slot * add_slot_local_freelist(rb_objspace_t *objspace, RVALUE *p)
Definition: gc.c:823
lazy_sweep
static int lazy_sweep(rb_objspace_t *objspace)
Definition: gc.c:2007
RCLASS_EXT
#define RCLASS_EXT(c)
objspace_each_objects
static VALUE objspace_each_objects(VALUE arg)
Definition: gc.c:1052
negative_size_allocation_error
static void negative_size_allocation_error(const char *)
Definition: gc.c:3364
NODE_POSTEXE
#define NODE_POSTEXE
ruby_initial_gc_stress
#define ruby_initial_gc_stress
Definition: gc.c:266
heaps_slot::prev
struct heaps_slot * prev
Definition: gc.c:167
timespec::tv_sec
time_t tv_sec
Definition: ripper.y:47
define_final
static VALUE define_final(int argc, VALUE *argv, VALUE os)
Definition: gc.c:1292
RUBY_DTRACE_GC_SWEEP_END
#define RUBY_DTRACE_GC_SWEEP_END()
Definition: probes.h:95
force_chain_object
static int force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:1470
RNode
Definition: ripper.y:240
obj_id_to_ref
#define obj_id_to_ref(objid)
Definition: gc.c:296
nd_set_type
#define nd_set_type(n, t)
wmap_allocate
static VALUE wmap_allocate(VALUE klass)
Definition: gc.c:3781
mark_current_machine_context
static void mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
Definition: gc.c:2500
RVALUE::object
struct RObject object
Definition: gc.c:135
T_COMPLEX
#define T_COMPLEX
mark_method_entry_i
static int mark_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data)
Definition: gc.c:2453
stack_chunk::data
VALUE data[STACK_CHUNK_SIZE]
Definition: gc.c:191
MEMZERO
#define MEMZERO(p, type, n)
heaps_inc
#define heaps_inc
Definition: gc.c:279
rb_objspace::during_gc
int during_gc
Definition: gc.c:237
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:527
finalize_list
static void finalize_list(rb_objspace_t *objspace, RVALUE *p)
Definition: gc.c:1425
rb_objspace::limit
size_t limit
Definition: gc.c:210
malloc_increase
#define malloc_increase
Definition: gc.c:273
rb_objspace::dont_lazy_sweep
int dont_lazy_sweep
Definition: gc.c:236
RVALUE
struct RVALUE RVALUE
st_update
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:834
st_data_t
unsigned long st_data_t
Definition: ripper.y:35
heaps_freed
#define heaps_freed
Definition: gc.c:280
NODE_CLASS
#define NODE_CLASS
st_delete
int st_delete(st_table *, st_data_t *, st_data_t *)
FLUSH_REGISTER_WINDOWS
#define FLUSH_REGISTER_WINDOWS
Definition: ripper.y:299
xmalloc2_size
static size_t xmalloc2_size(size_t n, size_t size)
Definition: gc.c:3600
set_heaps_increment
static void set_heaps_increment(rb_objspace_t *objspace)
Definition: gc.c:607
rb_objspace::flags
struct rb_objspace::@90 flags
ruby_xcalloc
void * ruby_xcalloc(size_t n, size_t size)
Definition: gc.c:3629
GET_STACK_BOUNDS
#define GET_STACK_BOUNDS(start, end, appendix)
Definition: gc.c:2492
RSTRUCT_PTR
#define RSTRUCT_PTR(st)
is_lazy_sweeping
#define is_lazy_sweeping(objspace)
Definition: gc.c:292
FL_FINALIZE
#define FL_FINALIZE
rb_args_info
Definition: ripper.y:505
NODE_WHILE
#define NODE_WHILE
weakmap
Definition: gc.c:3713
gc_prof_timer_start
static void gc_prof_timer_start(rb_objspace_t *)
Definition: gc.c:3935
hash
VALUE hash
Definition: tkutil.c:267
rb_newobj
VALUE rb_newobj(void)
Definition: gc.c:677
ATOMIC_SET
#define ATOMIC_SET(var, val)
Definition: ruby_atomic.h:100
Init_GC
void Init_GC(void)
Definition: gc.c:4496
gc_clear_slot_bits
static void gc_clear_slot_bits(struct heaps_slot *slot)
Definition: gc.c:1868
RString
Definition: ripper.y:842
initial_free_min
#define initial_free_min
Definition: gc.c:290
rb_gc
void rb_gc(void)
Definition: gc.c:3108
NODE_LVAR
#define NODE_LVAR
rb_gc_start
VALUE rb_gc_start(void)
Definition: gc.c:3101
during_gc
#define during_gc
Definition: gc.c:282
PRIuVALUE
#define PRIuVALUE
memset
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
NODE_LASGN
#define NODE_LASGN
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:479
RUBY_VM_SET_FINALIZER_INTERRUPT
#define RUBY_VM_SET_FINALIZER_INTERRUPT(th)
Definition: vm_core.h:917
ruby_gc_params_t::initial_heap_min_slots
unsigned int initial_heap_min_slots
Definition: gc.c:77
aligned_malloc
static void * aligned_malloc(size_t, size_t)
Definition: gc.c:3424
ruby_disable_gc_stress
int ruby_disable_gc_stress
Definition: gc.c:336
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:471
thread.h
rb_mark_end_proc
void rb_mark_end_proc(void)
Definition: eval_jump.c:80
gc_mark
static void gc_mark(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2582
mark_m_tbl
static void mark_m_tbl(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:2461
STACK_CHUNK_SIZE
#define STACK_CHUNK_SIZE
Definition: gc.c:188
FIXNUM_P
#define FIXNUM_P(f)
Qfalse
return Qfalse
Definition: tcltklib.c:6779
NODE_OP_ASGN_AND
#define NODE_OP_ASGN_AND
rb_objspace::total_allocated_object_num
size_t total_allocated_object_num
Definition: gc.c:254
rb_method_definition_struct::proc
VALUE proc
Definition: method.h:83
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
gc_profile_record::gc_invoke_time
double gc_invoke_time
Definition: gc.c:101
ruby_atomic.h
RARRAY_LEN
#define RARRAY_LEN(a)
gc_with_gvl
static void * gc_with_gvl(void *ptr)
Definition: gc.c:3052
ROBJECT_NUMIV
#define ROBJECT_NUMIV(o)
NODE_WHEN
#define NODE_WHEN
Init_heap
void Init_heap(void)
Definition: gc.c:1039
Qnil
#define Qnil
Definition: tcltklib.c:1896
nomem_error
#define nomem_error
Definition: gc.c:93
weakmap::final
VALUE final
Definition: gc.c:3716
val
#define val
Definition: tcltklib.c:1949
timeval::tv_usec
long tv_usec
Definition: ossl_asn1.c:18
finalize_deferred
static void finalize_deferred(rb_objspace_t *objspace)
Definition: gc.c:1444
define_final0
static VALUE define_final0(VALUE obj, VALUE block)
Definition: gc.c:1310
rb_gc_finalize_deferred
void rb_gc_finalize_deferred(void)
Definition: gc.c:1455
DWORD
IUnknown DWORD
Definition: win32ole.c:149
ruby_gc_params_t::initial_malloc_limit
unsigned int initial_malloc_limit
Definition: gc.c:76
negative_size_allocation_error_with_gvl
static void * negative_size_allocation_error_with_gvl(void *ptr)
Definition: gc.c:3357
gc_prof_timer_stop
static void gc_prof_timer_stop(rb_objspace_t *, int)
Definition: gc.c:3959
pop_mark_stack
static int pop_mark_stack(mark_stack_t *, VALUE *)
Definition: gc.c:2212
gc_stress_get
static VALUE gc_stress_get(VALUE self)
Definition: gc.c:3220
RNode::u2
union RNode::@81 u2
RCLASS_IV_TBL
#define RCLASS_IV_TBL(c)
NODE_YIELD
#define NODE_YIELD
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ripper.y:1414
str
static VALUE char * str
Definition: tcltklib.c:3547
NODE_FLIP2
#define NODE_FLIP2
gc_list::varptr
VALUE * varptr
Definition: gc.c:184
NODE_BLOCK
#define NODE_BLOCK
NUM2PTR
#define NUM2PTR(x)
initial_expand_heap
static void initial_expand_heap(rb_objspace_t *objspace)
Definition: gc.c:597
rb_objspace::finalizing
rb_atomic_t finalizing
Definition: gc.c:238
NODE_DASGN_CURR
#define NODE_DASGN_CURR
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:424
force_finalize_list::table
VALUE table
Definition: gc.c:1465
Check_Type
#define Check_Type(v, t)
NODE_AND
#define NODE_AND
gc_profile_record
struct gc_profile_record gc_profile_record
flags
int flags
Definition: tcltklib.c:3023
PRIuSIZE
#define PRIuSIZE
ID
unsigned long ID
Definition: ripper.y:105
rb_objspace::mark_stack
mark_stack_t mark_stack
Definition: gc.c:244
REQUIRED_SIZE_BY_MALLOC
Definition: gc.c:327
T_RATIONAL
#define T_RATIONAL
rb_gc_mark
void rb_gc_mark(VALUE)
Definition: gc.c:2598
RCLASS_SUPER
#define RCLASS_SUPER(c)
rb_free_method_entry
void rb_free_method_entry(rb_method_entry_t *me)
Definition: vm_method.c:169
RBasic
Definition: ripper.y:699
RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED
#define RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()
Definition: probes.h:90
vm_xfree
static void vm_xfree(rb_objspace_t *objspace, void *ptr)
Definition: gc.c:3578
RArray
Definition: ripper.y:881
mark_locations_array
static void mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
Definition: gc.c:2317
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:120
RVALUE
Definition: gc.c:128
push_mark_stack_chunk
static void push_mark_stack_chunk(mark_stack_t *stack)
Definition: gc.c:2155
nonspecial_obj_id
#define nonspecial_obj_id(obj)
Definition: gc.c:295
weakmap::obj2wmap
st_table * obj2wmap
Definition: gc.c:3714
timespec::tv_nsec
long tv_nsec
Definition: ripper.y:48
RUBY_DTRACE_GC_MARK_END_ENABLED
#define RUBY_DTRACE_GC_MARK_END_ENABLED()
Definition: probes.h:86
rb_const_entry_struct::value
VALUE value
Definition: constant.h:21
os_obj_of
static VALUE os_obj_of(VALUE of)
Definition: gc.c:1195
UNLIKELY
#define UNLIKELY(x)
Definition: vm_core.h:115
add
#define add(x, y)
Definition: date_strftime.c:23
CEILDIV
#define CEILDIV(i, mod)
Definition: gc.c:322
PRIxVALUE
#define PRIxVALUE
calloc
#define calloc
Definition: ripper.c:100
wmap_memsize
static size_t wmap_memsize(const void *ptr)
Definition: gc.c:3759
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
FIX2INT
#define FIX2INT(x)
INT2FIX
#define INT2FIX(i)
rb_vm_mark
void rb_vm_mark(void *ptr)
Definition: vm.c:1549
gc_profile_record::gc_time
double gc_time
Definition: gc.c:100
HEAP_OBJ_LIMIT
Definition: gc.c:329
RNode::value
VALUE value
Definition: ripper.y:246
rb_eNoMemError
VALUE rb_eNoMemError
Definition: error.c:522
T_STRING
#define T_STRING
onig_region_free
void onig_region_free(OnigRegion *r, int free_self)
Definition: regexec.c:315
rb_gc_set_params
void rb_gc_set_params(void)
Definition: gc.c:3295
NODE_ARGSCAT
#define NODE_ARGSCAT
NODE_COLON2
#define NODE_COLON2
rb_gc_unregister_address
void rb_gc_unregister_address(VALUE *)
Definition: gc.c:2999
ATOMIC_SIZE_DEC
#define ATOMIC_SIZE_DEC(var)
Definition: ruby_atomic.h:110
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:97
rb_method_entry_struct
Definition: method.h:95
force_finalize_list::next
struct force_finalize_list * next
Definition: gc.c:1466
free_const_entry_i
static int free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data)
Definition: gc.c:807
RSTRING_NOEMBED
#define RSTRING_NOEMBED
RRational
Definition: ripper.y:939
NODE_ZSUPER
#define NODE_ZSUPER
RVALUE::free
struct RVALUE::@86::@87 free
rb_objspace::deferred
RVALUE * deferred
Definition: gc.c:242
rb_objspace
Definition: gc.c:208
rb_method_definition_struct::iseq
rb_iseq_t * iseq
Definition: method.h:80
for
for(v/=shifter=1)
Definition: bigdecimal.c:5677
ATOMIC_SIZE_EXCHANGE
#define ATOMIC_SIZE_EXCHANGE(var, val)
Definition: ruby_atomic.h:111
mark_stack::index
size_t index
Definition: gc.c:198
GC_NOTIFY
#define GC_NOTIFY
Definition: gc.c:3021
STACK_END
#define STACK_END
Definition: gc.c:2253
EXIT_FAILURE
#define EXIT_FAILURE
Definition: eval_intern.h:24
rb_objspace::record
gc_profile_record * record
Definition: gc.c:247
RUBY_DTRACE_GC_MARK_END
#define RUBY_DTRACE_GC_MARK_END()
Definition: probes.h:87
DBL2NUM
#define DBL2NUM(dbl)
NODE_MODULE
#define NODE_MODULE
assign_heap_slot
static void assign_heap_slot(rb_objspace_t *objspace)
Definition: gc.c:481
rb_objspace::free_slots
struct heaps_slot * free_slots
Definition: gc.c:221
rb_gc_mark_symbols
void rb_gc_mark_symbols(void)
Definition: ripper.c:16590
RNode::cnt
long cnt
Definition: ripper.y:262
key
static int VALUE key
Definition: tkutil.c:265
RFile::fptr
struct rb_io_t * fptr
Definition: ripper.y:936
rb_method_entry_struct::klass
VALUE klass
Definition: method.h:100
RBIGNUM_DIGITS
#define RBIGNUM_DIGITS(b)
rb_gc_mark_machine_stack
void rb_gc_mark_machine_stack(rb_thread_t *th)
Definition: gc.c:2528
run_finalizer
static void run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
Definition: gc.c:1372
RData::data
void * data
Definition: ripper.y:955
gc_profile_record::heap_total_size
size_t heap_total_size
Definition: gc.c:105
rb_thread_raised_clear
#define rb_thread_raised_clear(th)
Definition: eval_intern.h:173
vm_malloc_fixup
static void * vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
Definition: gc.c:3493
gc_mark_locations
static void gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
Definition: gc.c:2331
node_type
node_type
Definition: ripper.y:23
rb_data_object_alloc
VALUE rb_data_object_alloc(VALUE, void *, RUBY_DATA_FUNC, RUBY_DATA_FUNC)
Definition: gc.c:709
allocate_sorted_heaps
static void allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
Definition: gc.c:432
argv
VALUE * argv
Definition: tcltklib.c:1971
internal_object_p
static int internal_object_p(VALUE obj)
Definition: gc.c:1147
VM_METHOD_TYPE_ATTRSET
Definition: method.h:48
rb_hash_aset
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
rb_objspace::table
st_table * table
Definition: gc.c:241
rb_newobj_of
VALUE rb_newobj_of(VALUE, VALUE)
Definition: gc.c:683
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
COUNT_TYPE
#define COUNT_TYPE(t)
initial_malloc_limit
#define initial_malloc_limit
Definition: gc.c:288
memcpy
memcpy(buf+1, str, len)
is_dead_object
static int is_dead_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:1583
resource.h
RTEST
#define RTEST(v)
rb_define_module_function
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1512
rb_objspace::total_freed_object_num
size_t total_freed_object_num
Definition: gc.c:255
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1000
gc_profile_dump_on
static void gc_profile_dump_on(VALUE out, VALUE(*append)(VALUE, VALUE))
Definition: gc.c:4229
garbage_collect
static int garbage_collect(rb_objspace_t *)
Definition: gc.c:3024
rb_method_attr_struct::location
VALUE location
Definition: method.h:71
RVALUE::rational
struct RRational rational
Definition: gc.c:149
timeval
Definition: ossl_asn1.c:16
lo
#define lo
Definition: siphash.c:21
util.h
getrusage_time
static double getrusage_time(void)
Definition: gc.c:3881
TRUE
#define TRUE
Definition: nkf.h:175
gc_profile_report
static VALUE gc_profile_report(int argc, VALUE *argv, VALUE self)
Definition: gc.c:4297
NODE_NIL
#define NODE_NIL
mark_stack::cache_size
size_t cache_size
Definition: gc.c:200
gc_prof_sweep_timer_stop
static void gc_prof_sweep_timer_stop(rb_objspace_t *)
Definition: gc.c:4002
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
rb_objspace_internal_object_p
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:1170
value
volatile VALUE value
Definition: tcltklib.c:9442
NODE_COLON3
#define NODE_COLON3
NODE_DEFINED
#define NODE_DEFINED
RDATA
#define RDATA(obj)
STACKFRAME_FOR_CALL_CFUNC
#define STACKFRAME_FOR_CALL_CFUNC
Definition: gc.c:2304
rb_node_newnode
#define rb_node_newnode(type, a1, a2, a3)
Definition: ripper.c:419
NODE_MASGN
#define NODE_MASGN
RTYPEDDATA_P
#define RTYPEDDATA_P(v)
T_REGEXP
#define T_REGEXP
gc_prof_mark_timer_stop
static void gc_prof_mark_timer_stop(rb_objspace_t *)
Definition: gc.c:3986
aligned_free
static void aligned_free(void *)
Definition: gc.c:3459
make_deferred
static void make_deferred(RVALUE *p)
Definition: gc.c:889
gc_sweep
static void gc_sweep(rb_objspace_t *objspace)
Definition: gc.c:2091
make_io_deferred
static void make_io_deferred(RVALUE *p)
Definition: gc.c:895
add_stack_chunk_cache
static void add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
Definition: gc.c:2133
MARKED_IN_BITMAP
#define MARKED_IN_BITMAP(bits, p)
Definition: gc.c:315
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2980
gc_profile_record
Definition: gc.c:99
RVALUE::hash
struct RHash hash
Definition: gc.c:141
run_final
static void run_final(rb_objspace_t *objspace, VALUE obj)
Definition: gc.c:1399
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:3651
void
VP_EXPORT void
Definition: bigdecimal.c:5083
RStruct
Definition: ripper.y:1035
STACK_LENGTH
#define STACK_LENGTH
Definition: gc.c:2261
wmap_aset
static VALUE wmap_aset(VALUE self, VALUE wmap, VALUE orig)
Definition: gc.c:3834
os_obj_of_i
static int os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
Definition: gc.c:1176
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
rb_thread_raised_set
#define rb_thread_raised_set(th, f)
Definition: eval_intern.h:170
rb_obj_is_mutex
VALUE rb_obj_is_mutex(VALUE obj)
Definition: thread.c:4134
RFile
Definition: ripper.y:934
wmap_final_func
static int wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
Definition: gc.c:3792
numberof
#define numberof(array)
Definition: gc.c:2497
internal.h
mark_const_tbl
static void mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:2479
NODE_VALIAS
#define NODE_VALIAS
Init_stack
void Init_stack(volatile VALUE *addr)
Definition: gc.c:3085
NODE_GVAR
#define NODE_GVAR
NODE_CDECL
#define NODE_CDECL
lazy_sweep_enable
static VALUE lazy_sweep_enable(void)
Definition: gc.c:1859
ATOMIC_SIZE_INC
#define ATOMIC_SIZE_INC(var)
Definition: ruby_atomic.h:109
RNode::u3
union RNode::@82 u3
heaps_header::limit
size_t limit
Definition: gc.c:176
uintptr_t
unsigned int uintptr_t
Definition: win32.h:94
RB_GC_GUARD
#define RB_GC_GUARD(v)
is_id_value
static int is_id_value(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:1561
NODE_LIT
#define NODE_LIT
type
int type
Definition: tcltklib.c:111
vm_core.h
T_FIXNUM
#define T_FIXNUM
rb_objspace::dont_gc
int dont_gc
Definition: gc.c:235
argc
int argc
Definition: tcltklib.c:1970
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:777
gc_profile_enable_get
static VALUE gc_profile_enable_get(VALUE self)
Definition: gc.c:4342
mark_entry
static int mark_entry(st_data_t key, st_data_t value, st_data_t data)
Definition: gc.c:2353
ELTS_SHARED
#define ELTS_SHARED
ruby_memerror_body
static void * ruby_memerror_body(void *dummy)
Definition: gc.c:3381
NODE_ERRINFO
#define NODE_ERRINFO
gc_profile_record::heap_use_size
size_t heap_use_size
Definition: gc.c:104
rb_ary_memsize
RUBY_FUNC_EXPORTED size_t rb_ary_memsize(VALUE ary)
Definition: array.c:479
getenv
char * getenv()
heaps_free_bitmap
Definition: gc.c:179
ST_CONTINUE
Definition: ripper.y:108
SET_MACHINE_STACK_END
#define SET_MACHINE_STACK_END(p)
Definition: gc.h:11
ruby_init_stack
void ruby_init_stack(volatile VALUE *)
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
RBasic::flags
VALUE flags
Definition: ripper.y:700
force_finalize_list::obj
VALUE obj
Definition: gc.c:1464
rb_obj_method
VALUE rb_obj_method(VALUE, VALUE)
Definition: proc.c:1232
NODE_BACK_REF
#define NODE_BACK_REF
NODE_MATCH
#define NODE_MATCH
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:816
re.h
RNode::flags
VALUE flags
Definition: ripper.y:241
gc_stress_set
static VALUE gc_stress_set(VALUE self, VALUE flag)
Definition: gc.c:3239
heaps_slot::header
struct heaps_header * header
Definition: gc.c:163
ruby_verbose
ruby_verbose
Definition: tcltklib.c:5818
wmap_free
static void wmap_free(void *ptr)
Definition: gc.c:3742
NODE_ALIAS
#define NODE_ALIAS
rb_garbage_collect
int rb_garbage_collect(void)
Definition: gc.c:3077
ptr
return ptr
Definition: tcltklib.c:784
free
#define free(x)
Definition: dln.c:50
FL_ABLE
#define FL_ABLE(x)
CHAR_BIT
#define CHAR_BIT
Definition: ruby.h:208
rmatch
Definition: re.h:38
rb_intern_const
#define rb_intern_const(str)
RANY
#define RANY(o)
Definition: gc.c:305
rb_gc_mark_maybe
void rb_gc_mark_maybe(VALUE)
Definition: gc.c:2547
NODE_DASGN
#define NODE_DASGN
msg
volatile VALUE msg
Definition: tcltklib.c:3100
rb_free_const_table
void rb_free_const_table(st_table *tbl)
Definition: gc.c:814
weakmap_type
static const rb_data_type_t weakmap_type
Definition: gc.c:3771
T_BIGNUM
#define T_BIGNUM
RCLASS_CONST_TBL
#define RCLASS_CONST_TBL(c)
rb_memerror
void rb_memerror(void)
Definition: gc.c:3406
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:637
T_TRUE
#define T_TRUE
NODE_TO_ARY
#define NODE_TO_ARY
end
gz end
Definition: zlib.c:2272
heaps_slot
Definition: gc.c:162
ruby_xmalloc
void * ruby_xmalloc(size_t size)
Definition: gc.c:3594
gc_profile_result
static VALUE gc_profile_result(void)
Definition: gc.c:4280
wmap_aref
static VALUE wmap_aref(VALUE self, VALUE wmap)
Definition: gc.c:3857
heaps_slot::free_next
struct heaps_slot * free_next
Definition: gc.c:168
MARK_IN_BITMAP
#define MARK_IN_BITMAP(bits, p)
Definition: gc.c:2243
rb_objspace::count
size_t count
Definition: gc.c:248
ruby_xrealloc
void * ruby_xrealloc(void *ptr, size_t size)
Definition: gc.c:3635
arg
arg
Definition: ripper.y:1315
HEAP_ALIGN
Definition: gc.c:325
free_unused_heaps
static void free_unused_heaps(rb_objspace_t *objspace)
Definition: gc.c:852
finalizing
#define finalizing
Definition: gc.c:283
rb_ary_resize
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1513
rb_gc_register_address
void rb_gc_register_address(VALUE *)
Definition: gc.c:2987
T_SYMBOL
#define T_SYMBOL
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
mark_tbl
static void mark_tbl(rb_objspace_t *, st_table *)
Definition: gc.c:2361
STACK_LEVEL_MAX
#define STACK_LEVEL_MAX
Definition: gc.c:2254
RVALUE::match
struct RMatch match
Definition: gc.c:148
rb_objspace::final_num
size_t final_num
Definition: gc.c:231
rb_gc_mark_parser
void rb_gc_mark_parser(void)
Definition: ripper.c:16419
STR_ASSOC
#define STR_ASSOC
free_stack_chunks
static void free_stack_chunks(mark_stack_t *)
Definition: gc.c:2189
gc_profile_record_get
static VALUE gc_profile_record_get(void)
Definition: gc.c:4193
size
int size
Definition: encoding.c:52
ruby_gc_params_t
Definition: gc.c:75
ATOMIC_SIZE_SUB
#define ATOMIC_SIZE_SUB(var, val)
Definition: ruby_atomic.h:108
FREE_MIN
#define FREE_MIN
Definition: gc.c:73
NODE_FCALL
#define NODE_FCALL
each_obj_args::data
void * data
Definition: gc.c:1048
heaps_header::start
RVALUE * start
Definition: gc.c:174
SYMBOL_P
#define SYMBOL_P(x)
rb_objspace::do_heap_free
size_t do_heap_free
Definition: gc.c:232
FL_SINGLETON
#define FL_SINGLETON
NODE_FLIP3
#define NODE_FLIP3
ready_to_gc
static int ready_to_gc(rb_objspace_t *objspace)
Definition: gc.c:1951
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:582
rb_exc_new3
VALUE rb_exc_new3(VALUE etype, VALUE str)
Definition: error.c:548
T_CLASS
#define T_CLASS
if
if(RB_TYPE_P(r, T_FLOAT))
Definition: bigdecimal.c:1186
NODE_DVAR
#define NODE_DVAR
rb_objspace::invoke_time
double invoke_time
Definition: gc.c:250
mark_method_entry
static void mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
Definition: gc.c:2417
NODE_CREF
#define NODE_CREF
rb_objspace_reachable_objects_from
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:3336
rb_method_entry_struct::def
rb_method_definition_t * def
Definition: method.h:98
t
int t
Definition: ripper.c:14699
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Definition: eval.c:1436
RUBY_DTRACE_GC_SWEEP_BEGIN
#define RUBY_DTRACE_GC_SWEEP_BEGIN()
Definition: probes.h:91
getrusage
int getrusage(int who, struct rusage *usage)
Definition: missing-pips.c:58
rb_data_type_struct
Definition: ripper.y:960
rb_objspace::heap
struct rb_objspace::@89 heap
RVALUE::next
struct RVALUE * next
Definition: gc.c:132
NODE_ZARRAY
#define NODE_ZARRAY
RVALUE::regexp
struct RRegexp regexp
Definition: gc.c:140
DATA_PTR
DATA_PTR(self)
objspace_live_num
static size_t objspace_live_num(rb_objspace_t *objspace)
Definition: gc.c:1874
gc_count
static VALUE gc_count(VALUE self)
Definition: gc.c:3134
weakmap::wmap2obj
st_table * wmap2obj
Definition: gc.c:3715
is_swept_object
static int is_swept_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:1570
NODE_CVAR
#define NODE_CVAR
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
obj_free
static int obj_free(rb_objspace_t *, VALUE)
Definition: gc.c:904
rb_thread_call_with_gvl
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1401
NODE_BREAK
#define NODE_BREAK
rb_objspace::global_list
struct gc_list * global_list
Definition: gc.c:252
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
garbage_collect_with_gvl
static int garbage_collect_with_gvl(rb_objspace_t *objspace)
Definition: gc.c:3058
VALGRIND_MAKE_MEM_DEFINED
#define VALGRIND_MAKE_MEM_DEFINED(p, n)
Definition: gc.c:62
RBASIC
#define RBASIC(obj)
ST_STOP
Definition: ripper.y:108
rb_obj_is_fiber
VALUE rb_obj_is_fiber(VALUE obj)
Definition: cont.c:363
stack_chunk_alloc
static stack_chunk_t * stack_chunk_alloc(void)
Definition: gc.c:2115
ruby_gc_debug_indent
int ruby_gc_debug_indent
Definition: gc.c:333
unlink_heap_slot
static void unlink_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
Definition: gc.c:837
HEAP_MIN_SLOTS
#define HEAP_MIN_SLOTS
Definition: gc.c:72
OBJSETUP
#define OBJSETUP(obj, c, t)
klass
klass
Definition: tcltklib.c:3504
UINT2NUM
#define UINT2NUM(x)
INT2NUM
#define INT2NUM(x)
rb_objspace::freed
struct heaps_header * freed
Definition: gc.c:227
NODE_DSTR
#define NODE_DSTR
rb_objspace_call_finalizer
static void rb_objspace_call_finalizer(rb_objspace_t *objspace)
Definition: gc.c:1488
list
struct rb_encoding_entry * list
Definition: encoding.c:50
rb_objspace::marked_num
size_t marked_num
Definition: gc.c:228
is_mark_stask_empty
static int is_mark_stask_empty(mark_stack_t *stack)
Definition: gc.c:2127
rb_gc_mark_unlinked_live_method_entries
void rb_gc_mark_unlinked_live_method_entries(void *pvm)
Definition: vm_method.c:108
each_obj_callback
int each_obj_callback(void *, void *, size_t, void *)
Definition: gc.c:1044
rb_objspace_alloc
rb_objspace_t * rb_objspace_alloc(void)
Definition: gc.c:374
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1564
rb_objspace::length
size_t length
Definition: gc.c:223
gc_prof_set_heap_info
static void gc_prof_set_heap_info(rb_objspace_t *, gc_profile_record *)
Definition: gc.c:4015
NEWOBJ
#define NEWOBJ(obj, type)
timespec
Definition: ripper.y:46
NODE_ALLOCA
#define NODE_ALLOCA
NODE_SCLASS
#define NODE_SCLASS
free_method_entry_i
static int free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
Definition: gc.c:791
add_heap_slots
static void add_heap_slots(rb_objspace_t *objspace, size_t add)
Definition: gc.c:558
rb_const_entry_struct::file
VALUE file
Definition: constant.h:22
st_insert
int st_insert(st_table *, st_data_t, st_data_t)
FL_ANY
#define FL_ANY(x, f)
st.h
mark_stack_t
struct mark_stack mark_stack_t
rb_thread_raised_p
#define rb_thread_raised_p(th, f)
Definition: eval_intern.h:172
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:93
RNode::u1
union RNode::@80 u1
rmatch::char_offset
struct rmatch_offset * char_offset
Definition: re.h:43
HEAP_BITMAP_LIMIT
Definition: gc.c:330
SET_STACK_END
#define SET_STACK_END
Definition: gc.c:2249
NODE_OP_ASGN1
#define NODE_OP_ASGN1
rb_safe_level
#define rb_safe_level()
Definition: tcltklib.c:94
NODE_CVASGN
#define NODE_CVASGN
T_MODULE
#define T_MODULE
init_mark_stack
static void init_mark_stack(mark_stack_t *stack)
Definition: gc.c:2227
rb_vm_struct::self
VALUE self
Definition: vm_core.h:338
res
Real * res
Definition: bigdecimal.c:1233
RCLASS_IV_INDEX_TBL
#define RCLASS_IV_INDEX_TBL(c)
mark_tbl_arg
Definition: gc.c:2348
gc_marks
static void gc_marks(rb_objspace_t *objspace)
Definition: gc.c:2911
assert
#define assert(condition)
Definition: ossl.h:45
shrink_stack_chunk_cache
static void shrink_stack_chunk_cache(mark_stack_t *stack)
Definition: gc.c:2141
RVALUE::data
struct RData data
Definition: gc.c:142
rb_iseq_struct::self
VALUE self
Definition: vm_core.h:292
wmap_mark_map
static int wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
Definition: gc.c:3720
SIGNED_VALUE
#define SIGNED_VALUE
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:234
T_UNDEF
#define T_UNDEF
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
heaps_length
#define heaps_length
Definition: gc.c:275
NODE_CALL
#define NODE_CALL
rb_gc_call_finalizer_at_exit
void rb_gc_call_finalizer_at_exit(void)
Definition: gc.c:1482
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
NODE_OPT_N
#define NODE_OPT_N
ruby_native_thread_p
#define ruby_native_thread_p()
Definition: tcltklib.c:82
rb_class_tbl
st_table * rb_class_tbl
Definition: variable.c:23
rb_global_variable
void rb_global_variable(VALUE *)
Definition: gc.c:426
RObject
Definition: ripper.y:709
is_live_object
static int is_live_object(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:1593
heaps_free_bitmap::next
struct heaps_free_bitmap * next
Definition: gc.c:180
e
BDIGIT e
Definition: bigdecimal.c:5085
rb_mark_hash
void rb_mark_hash(struct st_table *)
Definition: gc.c:2411
hi
#define hi
Definition: siphash.c:22
gc_mark_stacked_objects
static void gc_mark_stacked_objects(rb_objspace_t *)
Definition: gc.c:2898
VALUE
unsigned long VALUE
Definition: ripper.y:104
vm_xrealloc
static void * vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
Definition: gc.c:3526
NODE_IVAR
#define NODE_IVAR
initial_params
static ruby_gc_params_t initial_params
Definition: gc.c:84
RNode::args
struct rb_args_info * args
Definition: ripper.y:261
RHash
Definition: ripper.y:921
rb_data_typed_object_alloc
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *)
Definition: gc.c:722
rb_undefine_final
VALUE rb_undefine_final(VALUE obj)
Definition: gc.c:1272
RVALUE::typeddata
struct RTypedData typeddata
Definition: gc.c:143
RUBY_DTRACE_GC_MARK_BEGIN_ENABLED
#define RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()
Definition: probes.h:82
NODE_DOT2
#define NODE_DOT2
deferred_final_list
#define deferred_final_list
Definition: gc.c:285
rb_objspace_t
struct rb_objspace rb_objspace_t
RVALUE::array
struct RArray array
Definition: gc.c:139
rb_sigaltstack_size
int rb_sigaltstack_size(void)
NODE_DREGX
#define NODE_DREGX
NODE_IASGN
#define NODE_IASGN
NODE_OP_ASGN_OR
#define NODE_OP_ASGN_OR
heaps_increment
static int heaps_increment(rb_objspace_t *objspace)
Definition: gc.c:624
gc_mark_children
static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2604
RVALUE::as
union RVALUE::@86 as
markable_object_p
static int markable_object_p(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2565
NODE_RETURN
#define NODE_RETURN
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
heaps_header::end
RVALUE * end
Definition: gc.c:175
RVALUE::basic
struct RBasic basic
Definition: gc.c:134
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
OBJ_TAINT
#define OBJ_TAINT(x)
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:617
RUBY_DTRACE_GC_MARK_BEGIN
#define RUBY_DTRACE_GC_MARK_BEGIN()
Definition: probes.h:83
heaps_slot::next
struct heaps_slot * next
Definition: gc.c:166
NODE_ARRAY
#define NODE_ARRAY
NODE_SPLAT
#define NODE_SPLAT
rb_intern
#define rb_intern(str)
each_obj_args::callback
each_obj_callback * callback
Definition: gc.c:1047
undefine_final
static VALUE undefine_final(VALUE os, VALUE obj)
Definition: gc.c:1266
v
BDIGIT v
Definition: bigdecimal.c:5656
gc_profile_clear
static VALUE gc_profile_clear(void)
Definition: gc.c:4126
rb_gc_mark_encodings
void rb_gc_mark_encodings(void)
Definition: encoding.c:211
HEAP_ALIGN_LOG
#define HEAP_ALIGN_LOG
Definition: gc.c:319
RVALUE::string
struct RString string
Definition: gc.c:138
RCLASS_M_TBL
#define RCLASS_M_TBL(c)
NULL
#define NULL
Definition: _sdbm.c:103
mark_stack::cache
stack_chunk_t * cache
Definition: gc.c:197
RVALUE::klass
struct RClass klass
Definition: gc.c:136
RClass
Definition: ripper.y:737
time
VALUE time
Definition: tcltklib.c:1866
q
q
Definition: tcltklib.c:2968
T_DATA
#define T_DATA
rb_define_final
VALUE rb_define_final(VALUE obj, VALUE block)
Definition: gc.c:1338
heaps_header
Definition: gc.c:171
name
const char * name
Definition: nkf.c:208
rb_objspace::sweep_slots
struct heaps_slot * sweep_slots
Definition: gc.c:220
RVALUE::flags
VALUE flags
Definition: gc.c:131
rb_mGC
RUBY_EXTERN VALUE rb_mGC
Definition: ripper.y:1419
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:542
wmap_finalize
static VALUE wmap_finalize(VALUE self, VALUE objid)
Definition: gc.c:3803
gc_stat
static VALUE gc_stat(int argc, VALUE *argv, VALUE self)
Definition: gc.c:3167
NODE_SCOPE
#define NODE_SCOPE
mark_set
static void mark_set(rb_objspace_t *objspace, st_table *tbl)
Definition: gc.c:2378
onig_free
void onig_free(regex_t *reg)
Definition: regcomp.c:5583
rb_free_generic_ivar
void rb_free_generic_ivar(VALUE)
Definition: variable.c:1028
VM_METHOD_TYPE_IVAR
Definition: method.h:49
rb_objspace::free_min
size_t free_min
Definition: gc.c:230
st_table::num_entries
st_index_t num_entries
Definition: ripper.y:93
malloc_limit
#define malloc_limit
Definition: gc.c:272
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
RVALUE::complex
struct RComplex complex
Definition: gc.c:150
NODE_IASGN2
#define NODE_IASGN2
NODE_SELF
#define NODE_SELF
HEAP_ALIGN_MASK
Definition: gc.c:326
rb_clear_cache_by_class
void rb_clear_cache_by_class(VALUE)
Definition: vm_method.c:64
rb_ary_delete_same
void rb_ary_delete_same(VALUE ary, VALUE item)
Definition: array.c:2790
heaps_slot::bits
uintptr_t * bits
Definition: gc.c:164
stack_chunk_t
struct stack_chunk stack_chunk_t
GET_HEAP_BITMAP
#define GET_HEAP_BITMAP(x)
Definition: gc.c:311
RBIGNUM_EMBED_FLAG
#define RBIGNUM_EMBED_FLAG
gc_profile_enable
static VALUE gc_profile_enable(void)
Definition: gc.c:4357
SYM2ID
#define SYM2ID(x)
rb_objspace::gc_stress
int gc_stress
Definition: gc.c:256
NODE_BLOCK_ARG
#define NODE_BLOCK_ARG
force_finalize_list
Definition: gc.c:1463
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
rb_during_gc
int rb_during_gc(void)
Definition: gc.c:3117
rb_objspace_data_type_memsize
size_t rb_objspace_data_type_memsize(VALUE obj)
Definition: gc.c:738
rb_free_m_table
void rb_free_m_table(st_table *tbl)
Definition: gc.c:800
T_NONE
#define T_NONE
rb_str_free
void rb_str_free(VALUE)
Definition: string.c:830
T_MASK
#define T_MASK
Definition: md5.c:131
rb_jmp_buf
#define rb_jmp_buf
Definition: gc.c:67
st_free_table
void st_free_table(st_table *)
Definition: st.c:334
gc_prepare_free_objects
static int gc_prepare_free_objects(rb_objspace_t *)
Definition: gc.c:2038
RTYPEDDATA_TYPE
#define RTYPEDDATA_TYPE(v)
T_FALSE
#define T_FALSE
dummy
int dummy
Definition: tcltklib.c:4483
newobj
static VALUE newobj(VALUE klass, VALUE flags)
Definition: gc.c:635
rb_gc_enable
VALUE rb_gc_enable(void)
Definition: gc.c:3261
RRegexp
Definition: ripper.y:910
FL_UNSET
#define FL_UNSET(x, f)
rb_io_write
VALUE rb_io_write(VALUE, VALUE)
Definition: io.c:1415
T_ZOMBIE
#define T_ZOMBIE
TRY_WITH_GC
#define TRY_WITH_GC(alloc)
Definition: gc.c:3507
heaps_header::base
struct heaps_slot * base
Definition: gc.c:172
NODE_OPT_ARG
#define NODE_OPT_ARG
stack_chunk::next
struct stack_chunk * next
Definition: gc.c:192
mark_stack
Definition: gc.c:195
GET_VM
#define GET_VM()
Definition: vm_core.h:876
len
size_t len
Definition: tcltklib.c:3568
gc_mark_ptr
static int gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr)
Definition: gc.c:2555