ruby-changes:35362
From: ko1 <ko1@a...>
Date: Mon, 8 Sep 2014 13:11:19 +0900 (JST)
Subject: [ruby-changes:35362] ko1:r47444 (trunk): * gc.c: add incremental GC algorithm. [Feature #10137]
ko1 2014-09-08 13:11:00 +0900 (Mon, 08 Sep 2014) New Revision: 47444 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47444 Log: * gc.c: add incremental GC algorithm. [Feature #10137] Please refer this ticket for details. This change also introduces the following changes. * Remove RGENGC_AGE2_PROMOTION and introduce object age (0 to 3). Age can be count with FL_PROMOTE0 and FL_PROMOTE1 flags in RBasic::flags (2 bit). Age == 3 objects become old objects. * WB_PROTECTED flag in RBasic to WB_UNPROTECTED bitmap. * LONG_LIVED bitmap to represent living objects while minor GCs It specifies (1) Old objects and (2) remembered shady objects. * Introduce rb_objspace_t::marked_objects which counts marked objects in current marking phase. marking count is needed to introduce incremental marking. * rename mark related function and sweep related function to gc_(marks|sweep)_(start|finish|step|rest|continue). * rename rgengc_report() to gc_report(). * Add obj_info() function to get cstr of object details. * Add MEASURE_LINE() macro to measure execution time of specific line. * and many small fixes. * include/ruby/ruby.h: add flag USE_RINCGC. Now USE_RINCGC can be set only with USE_RGENGC. * include/ruby/ruby.h: introduce FL_PROMOTED0 and add FL_PROMOTED1 to count object age. * include/ruby/ruby.h: rewrite write barriers for incremental marking. * debug.c: catch up flag name changes. * internal.h: add rb_gc_writebarrier_remember() instead of rb_gc_writebarrier_remember_promoted(). * array.c (ary_memcpy0): use rb_gc_writebarrier_remember(). * array.c (rb_ary_modify): ditto. * hash.c (rb_hash_keys): ditto. * hash.c (rb_hash_values): ditto. * object.c (init_copy): use rb_copy_wb_protected_attribute() because FL_WB_PROTECTED is moved from RBasic::flags. * test/objspace/test_objspace.rb: catch up ObjectSpace.dump() changes. Modified files: trunk/ChangeLog trunk/array.c trunk/debug.c trunk/gc.c trunk/hash.c trunk/include/ruby/ruby.h trunk/internal.h trunk/object.c trunk/test/objspace/test_objspace.rb Index: array.c =================================================================== --- array.c (revision 47443) +++ array.c (revision 47444) @@ -172,25 +172,18 @@ ary_memcpy0(VALUE ary, long beg, long ar https://github.com/ruby/ruby/blob/trunk/array.c#L172 #if 1 assert(!ARY_SHARED_P(buff_owner_ary)); - if (OBJ_PROMOTED(buff_owner_ary)) { - if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) { - rb_gc_writebarrier_remember_promoted(buff_owner_ary); - RARRAY_PTR_USE(ary, ptr, { - MEMCPY(ptr+beg, argv, VALUE, argc); - }); - } - else { - int i; - RARRAY_PTR_USE(ary, ptr, { - for (i=0; i<argc; i++) { - RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]); - } - }); - } + if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) { + rb_gc_writebarrier_remember(buff_owner_ary); + RARRAY_PTR_USE(ary, ptr, { + MEMCPY(ptr+beg, argv, VALUE, argc); + }); } else { + int i; RARRAY_PTR_USE(ary, ptr, { - MEMCPY(ptr+beg, argv, VALUE, argc); + for (i=0; i<argc; i++) { + RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]); + } }); } #else @@ -355,10 +348,7 @@ rb_ary_modify(VALUE ary) https://github.com/ruby/ruby/blob/trunk/array.c#L348 ARY_SET_PTR(ary, ptr); } - /* TODO: age2 promotion, OBJ_PROMOTED() checks not infant. */ - if (OBJ_PROMOTED(ary) && !OBJ_PROMOTED(shared)) { - rb_gc_writebarrier_remember_promoted(ary); - } + rb_gc_writebarrier_remember(ary); } } Index: debug.c =================================================================== --- debug.c (revision 47443) +++ debug.c (revision 47444) @@ -33,8 +33,8 @@ const union { https://github.com/ruby/ruby/blob/trunk/debug.c#L33 RUBY_ENC_CODERANGE_7BIT = ENC_CODERANGE_7BIT, RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID, RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN, - RUBY_FL_WB_PROTECTED = FL_WB_PROTECTED, - RUBY_FL_PROMOTED = FL_PROMOTED, + RUBY_FL_PROMOTED0 = FL_PROMOTED0, + RUBY_FL_PROMOTED1 = FL_PROMOTED1, RUBY_FL_FINALIZE = FL_FINALIZE, RUBY_FL_TAINT = FL_TAINT, RUBY_FL_EXIVAR = FL_EXIVAR, Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 47443) +++ include/ruby/ruby.h (revision 47444) @@ -710,6 +710,13 @@ VALUE rb_obj_setup(VALUE obj, VALUE klas https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L710 #ifndef USE_RGENGC #define USE_RGENGC 1 +#ifndef USE_RINCGC +#define USE_RINCGC 1 +#endif +#endif + +#if USE_RGENGC == 0 +#define USE_RINCGC 0 #endif #ifndef RGENGC_WB_PROTECTED_ARRAY @@ -1068,7 +1075,8 @@ struct RStruct { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1075 #define FL_SINGLETON FL_USER0 #define FL_WB_PROTECTED (((VALUE)1)<<5) -#define FL_PROMOTED (((VALUE)1)<<6) +#define FL_PROMOTED0 (((VALUE)1)<<5) +#define FL_PROMOTED1 (((VALUE)1)<<6) #define FL_FINALIZE (((VALUE)1)<<7) #define FL_TAINT (((VALUE)1)<<8) #define FL_UNTRUSTED FL_TAINT @@ -1122,16 +1130,20 @@ struct RStruct { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1130 #define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE) #if USE_RGENGC -#define OBJ_PROMOTED(x) (SPECIAL_CONST_P(x) ? 0 : FL_TEST_RAW((x), FL_PROMOTED)) -#define OBJ_WB_PROTECTED(x) (SPECIAL_CONST_P(x) ? 1 : FL_TEST_RAW((x), FL_WB_PROTECTED)) +#define OBJ_PROMOTED_RAW(x) ((RBASIC(x)->flags & (FL_PROMOTED0|FL_PROMOTED1)) == (FL_PROMOTED0|FL_PROMOTED1)) +#define OBJ_PROMOTED(x) (SPECIAL_CONST_P(x) ? 0 : OBJ_PROMOTED_RAW(x)) #define OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) -void rb_gc_writebarrier(VALUE a, VALUE b); -void rb_gc_writebarrier_unprotect_promoted(VALUE obj); +#if USE_RINCGC +int rb_gc_writebarrier_incremental(VALUE a, VALUE b); +#else +#define rb_gc_writebarrier_incremental(a, b) 0 +#endif +void rb_gc_writebarrier_generational(VALUE a, VALUE b); +void rb_gc_writebarrier_unprotect(VALUE obj); #else /* USE_RGENGC */ #define OBJ_PROMOTED(x) 0 -#define OBJ_WB_PROTECTED(x) 0 #define OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) #endif @@ -1164,15 +1176,8 @@ rb_obj_wb_unprotect(VALUE x, RB_UNUSED_V https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1176 #ifdef RGENGC_LOGGING_WB_UNPROTECT RGENGC_LOGGING_WB_UNPROTECT((void *)x, filename, line); #endif - #if USE_RGENGC - /* `x' should be an RVALUE object */ - if (FL_TEST_RAW((x), FL_WB_PROTECTED)) { - if (FL_TEST_RAW((x), FL_PROMOTED)) { - rb_gc_writebarrier_unprotect_promoted(x); - } - RBASIC(x)->flags &= ~FL_WB_PROTECTED; - } + rb_gc_writebarrier_unprotect(x); #endif return x; } @@ -1185,9 +1190,12 @@ rb_obj_written(VALUE a, RB_UNUSED_VAR(VA https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1190 #endif #if USE_RGENGC - /* `a' should be an RVALUE object */ - if (FL_TEST_RAW((a), FL_PROMOTED) && !SPECIAL_CONST_P(b)) { - rb_gc_writebarrier(a, b); + if (!SPECIAL_CONST_P(b)) { + if (rb_gc_writebarrier_incremental(a, b) == 0) { + if (OBJ_PROMOTED_RAW(a) && !OBJ_PROMOTED_RAW(b)) { + rb_gc_writebarrier_generational(a, b); + } + } } #endif Index: ChangeLog =================================================================== --- ChangeLog (revision 47443) +++ ChangeLog (revision 47444) @@ -1,3 +1,53 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Sep 8 12:01:39 2014 Koichi Sasada <ko1@a...> + + * gc.c: add incremental GC algorithm. [Feature #10137] + + Please refer this ticket for details. + + This change also introduces the following changes. + + * Remove RGENGC_AGE2_PROMOTION and introduce object age (0 to 3). + Age can be count with FL_PROMOTE0 and FL_PROMOTE1 flags in + RBasic::flags (2 bit). Age == 3 objects become old objects. + * WB_PROTECTED flag in RBasic to WB_UNPROTECTED bitmap. + * LONG_LIVED bitmap to represent living objects while minor GCs + It specifies (1) Old objects and (2) remembered shady objects. + * Introduce rb_objspace_t::marked_objects which counts marked + objects in current marking phase. marking count is needed to + introduce incremental marking. + * rename mark related function and sweep related function to + gc_(marks|sweep)_(start|finish|step|rest|continue). + * rename rgengc_report() to gc_report(). + * Add obj_info() function to get cstr of object details. + * Add MEASURE_LINE() macro to measure execution time of specific line. + * and many small fixes. + + * include/ruby/ruby.h: add flag USE_RINCGC. + Now USE_RINCGC can be set only with USE_RGENGC. + + * include/ruby/ruby.h: introduce FL_PROMOTED0 and add FL_PROMOTED1 + to count object age. + + * include/ruby/ruby.h: rewrite write barriers for incremental marking. + + * debug.c: catch up flag name changes. + + * internal.h: add rb_gc_writebarrier_remember() instead of + rb_gc_writebarrier_remember_promoted(). + + * array.c (ary_memcpy0): use rb_gc_writebarrier_remember(). + + * array.c (rb_ary_modify): ditto. + + * hash.c (rb_hash_keys): ditto. + + * hash.c (rb_hash_values): ditto. + + * object.c (init_copy): use rb_copy_wb_protected_attribute() because + FL_WB_PROTECTED is moved from RBasic::flags. + + * test/objspace/test_objspace.rb: catch up ObjectSpace.dump() changes. + Sun Sep 7 12:47:06 2014 Tanaka Akira <akr@f...> * process.c: PTHREAD_CANCEL_DISABLE is not defined on Android. Index: object.c =================================================================== --- object.c (revision 47443) +++ object.c (revision 47444) @@ -282,6 +282,8 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L282 } } +void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj); + static void init_copy(VALUE dest, VALUE obj) { @@ -290,6 +292,7 @@ init_copy(VALUE dest, VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L292 } RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR); RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT); + rb_copy_wb_protected_attribute(dest, obj); rb_copy_generic_ivar(dest, obj); rb_gc_copy_finalizer(dest, obj); if (RB_TYPE_P(obj, T_OBJECT)) { @@ -331,8 +334,8 @@ rb_obj_clone(VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L334 rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj)); } clone = rb_obj_alloc(rb_obj_class(obj)); - RBASIC(clone)->flags &= (FL_TAINT|FL_PROMOTED|FL_WB_PROTECTED); - RBASIC(clone)->flags |= RBASIC(obj)->flags & ~(FL_PROMOTED|FL_FREEZE|FL_FINALIZE|FL_WB_PROTECTED); + RBASIC(clone)->flags &= (FL_TAINT); + RBASIC(clone)->flags |= RBASIC(obj)->flags & ~(FL_PROMOTED0|FL_PROMOTED1|FL_FREEZE|FL_FINALIZE); singleton = rb_singleton_class_clone_and_attach(obj, clone); RBASIC_SET_CLASS(clone, singleton); Index: gc.c =================================================================== --- gc.c (revision 47443) +++ gc.c (revision 47444) @@ -143,6 +143,19 @@ rb_gc_guarded_ptr_val(volatile VALUE *pt https://github.com/ruby/ruby/blob/trunk/gc.c#L143 #define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 /* 128MB */) #endif +#ifndef PRINT_MEASURE_LINE +#define PRINT_MEASURE_LINE 0 +#endif +#ifndef PRINT_ENTER_EXIT_TICK +#define PRINT_ENTER_EXIT_TICK 0 +#endif +#ifndef PRINT_ROOT_TICKS +#define PRINT_ROOT_TICKS 0 +#endif + +#define USE_TICK_T (PRINT_ENTER_EXIT_TICK || PRINT_MEASURE_LINE) +#define TICK_TYPE 1 + typedef struct { size_t heap_init_slots; size_t heap_free_slots; @@ -199,9 +212,10 @@ static ruby_gc_params_t gc_params = { https://github.com/ruby/ruby/blob/trunk/gc.c#L212 /* RGENGC_CHECK_MODE * 0: disable all assertions * 1: enable assertions (to debug RGenGC) - * 2: enable generational bits check (for debugging) - * 3: enable livness check - * 4: show all references + * 2: enable internal consistency check at each GC (for debugging) + * 3: enable internal consistency check at each GC steps (for debugging) + * 4: enable livness check + * 5: show all references */ #ifndef RGENGC_CHECK_MODE #define RGENGC_CHECK_MODE 0 @@ -216,15 +230,6 @@ static ruby_gc_params_t gc_params = { https://github.com/ruby/ruby/blob/trunk/gc.c#L230 #define RGENGC_PROFILE 0 #endif -/* RGENGC_AGE2_PROMOTION - * Enable/disable age2 promotion strategy - * 0: Infant gen -> Old gen - * 1: Infant gen -> Young -> Old gen - */ -#ifndef RGENGC_AGE2_PROMOTION -#define RGENGC_AGE2_PROMOTION 1 -#endif - /* RGENGC_ESTIMATE_OLDMALLOC * Enable/disable to estimate increase size of malloc'ed size by old objects. * If estimation exceeds threshold, then will invoke full GC. @@ -235,13 +240,26 @@ static ruby_gc_params_t gc_params = { https://github.com/ruby/ruby/blob/trunk/gc.c#L240 #define RGENGC_ESTIMATE_OLDMALLOC 1 #endif +/* RGENGC_FORCE_MAJOR_GC + * Force major/full GC if this macro is not 0. + */ +#ifndef RGENGC_FORCE_MAJOR_GC +#define RGENGC_FORCE_MAJOR_GC 0 +#endif + #else /* USE_RGENGC */ +#ifdef RGENGC_DEBUG +#undef RGENGC_DEBUG +#endif #define RGENGC_DEBUG 0 +#ifdef RGENGC_CHECK_MODE +#undef RGENGC_CHECK_MODE +#endif #define RGENGC_CHECK_MODE 0 #define RGENGC_PROFILE 0 -#define RGENGC_AGE2_PROMOTION 0 #define RGENGC_ESTIMATE_OLDMALLOC 0 +#define RGENGC_FORCE_MAJOR_GC 0 #endif /* USE_RGENGC */ @@ -251,6 +269,9 @@ static ruby_gc_params_t gc_params = { https://github.com/ruby/ruby/blob/trunk/gc.c#L269 #ifndef GC_PROFILE_DETAIL_MEMORY #define GC_PROFILE_DETAIL_MEMORY 0 #endif +#ifndef GC_ENABLE_INCREMENTAL_MARK +#define GC_ENABLE_INCREMENTAL_MARK USE_RINCGC +#endif #ifndef GC_ENABLE_LAZY_SWEEP #define GC_ENABLE_LAZY_SWEEP 1 #endif @@ -409,8 +430,8 @@ typedef struct stack_chunk { https://github.com/ruby/ruby/blob/trunk/gc.c#L430 typedef struct mark_stack { stack_chunk_t *chunk; stack_chunk_t *cache; - size_t index; - size_t limit; + int index; + int limit; size_t cache_size; size_t unused_cache_size; } mark_stack_t; @@ -420,11 +441,19 @@ typedef struct rb_heap_struct { https://github.com/ruby/ruby/blob/trunk/gc.c#L441 struct heap_page *free_pages; struct heap_page *using_page; struct heap_page *sweep_pages; + struct heap_page *pooled_pages; + RVALUE *freelist; size_t page_length; /* total page count in a heap */ size_t total_slots; /* total slot count (page_length * HEAP_OBJ_LIMIT) */ } rb_heap_t; +enum gc_stat { + none, + marking, + sweeping +}; + typedef struct rb_objspace { struct { size_t limit; @@ -435,6 +464,11 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L464 #endif } malloc_params; + enum gc_stat stat; + size_t marked_objects; + + int immediate_sweep; + rb_heap_t eden_heap; rb_heap_t tomb_heap; /* heap for zombies and ghosts */ @@ -458,7 +492,7 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L492 struct { int dont_gc; - int dont_lazy_sweep; + int dont_incremental; int during_gc; rb_atomic_t finalizing; } flags; @@ -484,9 +518,6 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L518 size_t generated_shady_object_count; size_t shade_operation_count; size_t promote_infant_count; -#if RGENGC_AGE2_PROMOTION - size_t promote_young_count; -#endif size_t remembered_normal_object_count; size_t remembered_shady_object_count; @@ -495,9 +526,6 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L526 size_t generated_shady_object_count_types[RUBY_T_MASK]; size_t shade_operation_count_types[RUBY_T_MASK]; size_t promote_infant_types[RUBY_T_MASK]; -#if RGENGC_AGE2_PROMOTION - size_t promote_young_types[RUBY_T_MASK]; -#endif size_t remembered_normal_object_count_types[RUBY_T_MASK]; size_t remembered_shady_object_count_types[RUBY_T_MASK]; #endif @@ -534,10 +562,7 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L562 size_t remembered_shady_object_limit; size_t old_object_count; size_t old_object_limit; - -#if RGENGC_AGE2_PROMOTION - size_t young_object_count; -#endif + size_t old_object_count_at_gc_start; #if RGENGC_ESTIMATE_OLDMALLOC size_t oldmalloc_increase; @@ -550,6 +575,12 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L575 #endif } rgengc; #endif /* USE_RGENGC */ + +#if USE_RINCGC + struct { + int during_incremental_marking; + } rincgc; +#endif } rb_objspace_t; @@ -571,38 +602,56 @@ enum { https://github.com/ruby/ruby/blob/trunk/gc.c#L602 struct heap_page { struct heap_page_body *body; - RVALUE *freelist; - RVALUE *start; - size_t final_slots; - size_t limit; - struct heap_page *next; struct heap_page *prev; - struct heap_page *free_next; rb_heap_t *heap; - int before_sweep; + int total_slots; + int free_slots; + int final_slots; + + struct heap_page *free_next; + RVALUE *start; + RVALUE *freelist; + struct heap_page *next; + struct { + unsigned int before_sweep : 1; + unsigned int has_remembered_objects : 1; + unsigned int has_long_lived_shady_objects : 1; + } flags; + +#if USE_RGENGC + bits_t wb_unprotected_bits[HEAP_BITMAP_LIMIT]; +#endif + /* the following three bitmaps are cleared at the beggining of full GC */ bits_t mark_bits[HEAP_BITMAP_LIMIT]; #if USE_RGENGC - bits_t rememberset_bits[HEAP_BITMAP_LIMIT]; - bits_t oldgen_bits[HEAP_BITMAP_LIMIT]; + bits_t long_lived_bits[HEAP_BITMAP_LIMIT]; + bits_t marking_bits[HEAP_BITMAP_LIMIT]; #endif }; -#define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK))) -#define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header) -#define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page) -#define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0]) -#define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_PAGE(x)->rememberset_bits[0]) -#define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_PAGE(x)->oldgen_bits[0]) -#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE)) -#define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH ) -#define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1)) -#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p)) +#define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK))) +#define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header) +#define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page) + +#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE)) +#define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH ) +#define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1)) +#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p)) + /* Bitmap Operations */ #define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p)) #define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p)) #define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p)) +/* getting bitmap */ +#define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0]) +#if USE_RGENGC +#define GET_HEAP_LONG_LIVED_BITS(x) (&GET_HEAP_PAGE(x)->long_lived_bits[0]) +#define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0]) +#define GET_HEAP_MARKING_BITS(x) (&GET_HEAP_PAGE(x)->marking_bits[0]) +#endif + /* Aliases */ #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE #define rb_objspace (*GET_VM()->objspace) @@ -636,7 +685,21 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_ https://github.com/ruby/ruby/blob/trunk/gc.c#L685 #define global_list objspace->global_list #define ruby_gc_stress objspace->gc_stress -#define is_lazy_sweeping(heap) ((heap)->sweep_pages != 0) +#define is_marking(objspace) ((objspace)->stat == marking) +#define is_sweeping(objspace) ((objspace)->stat == sweeping) +#define is_full_marking(objspace) ((objspace)->rgengc.during_minor_gc == FALSE) +#if GC_ENABLE_INCREMENTAL_MARK +#define is_incremental_marking(objspace) ((objspace)->rincgc.during_incremental_marking != FALSE) +#else +#define is_incremental_marking(objspace) 0 +#endif +#define is_lazy_sweeping(heap) (GC_ENABLE_LAZY_SWEEP && (heap)->sweep_pages != 0) +#if GC_ENABLE_INCREMENTAL_MARK +#define will_be_incremental_marking(objspace) ((objspace)->rgengc.need_major_gc != GPR_FLAG_NONE) +#else +#define will_be_incremental_marking(objspace) 0 +#endif + #if SIZEOF_LONG == SIZEOF_VOIDP # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG) # define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */ @@ -676,22 +739,48 @@ static void aligned_free(void *); https://github.com/ruby/ruby/blob/trunk/gc.c#L739 static void init_mark_stack(mark_stack_t *stack); -static VALUE lazy_sweep_enable(void); static int ready_to_gc(rb_objspace_t *objspace); -static int heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap); -static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_sweep, int reason); -static int garbage_collect_body(rb_objspace_t *, int full_mark, int immediate_sweep, int reason); -static int gc_heap_lazy_sweep(rb_objspace_t *objspace, rb_heap_t *heap); -static void gc_rest_sweep(rb_objspace_t *objspace); -static void gc_heap_rest_sweep(rb_objspace_t *objspace, rb_heap_t *heap); -static void gc_mark_stacked_objects(rb_objspace_t *); +static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_mark, int immediate_sweep, int reason); + +static int gc_start(rb_objspace_t *objspace, const int full_mark, const int immediate_mar (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/