mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* 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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
			
			
This commit is contained in:
		
							parent
							
								
									e6368921ea
								
							
						
					
					
						commit
						123eeb1c1a
					
				
					 9 changed files with 2064 additions and 1135 deletions
				
			
		
							
								
								
									
										50
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,53 @@
 | 
			
		|||
Mon Sep  8 12:01:39 2014  Koichi Sasada  <ko1@atdot.net>
 | 
			
		||||
 | 
			
		||||
	* 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@fsij.org>
 | 
			
		||||
 | 
			
		||||
	* process.c: PTHREAD_CANCEL_DISABLE is not defined on Android.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								array.c
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								array.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -172,9 +172,8 @@ ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_
 | 
			
		|||
#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);
 | 
			
		||||
	rb_gc_writebarrier_remember(buff_owner_ary);
 | 
			
		||||
	RARRAY_PTR_USE(ary, ptr, {
 | 
			
		||||
	    MEMCPY(ptr+beg, argv, VALUE, argc);
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			@ -187,12 +186,6 @@ ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_
 | 
			
		|||
	    }
 | 
			
		||||
	});
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	RARRAY_PTR_USE(ary, ptr, {
 | 
			
		||||
	    MEMCPY(ptr+beg, argv, VALUE, argc);
 | 
			
		||||
	});
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    /* giveup write barrier (traditional way) */
 | 
			
		||||
    RARRAY_PTR(buff_owner_ary);
 | 
			
		||||
| 
						 | 
				
			
			@ -355,10 +348,7 @@ rb_ary_modify(VALUE ary)
 | 
			
		|||
            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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								debug.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								debug.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -33,8 +33,8 @@ const union {
 | 
			
		|||
        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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								hash.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								hash.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1781,7 +1781,7 @@ rb_hash_keys(VALUE hash)
 | 
			
		|||
    if (ST_DATA_COMPATIBLE_P(VALUE)) {
 | 
			
		||||
	st_table *table = RHASH(hash)->ntbl;
 | 
			
		||||
 | 
			
		||||
	if (OBJ_PROMOTED(keys)) rb_gc_writebarrier_remember_promoted(keys);
 | 
			
		||||
	rb_gc_writebarrier_remember(keys);
 | 
			
		||||
	RARRAY_PTR_USE(keys, ptr, {
 | 
			
		||||
	    size = st_keys_check(table, ptr, size, Qundef);
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			@ -1825,7 +1825,7 @@ rb_hash_values(VALUE hash)
 | 
			
		|||
    if (ST_DATA_COMPATIBLE_P(VALUE)) {
 | 
			
		||||
	st_table *table = RHASH(hash)->ntbl;
 | 
			
		||||
 | 
			
		||||
	if (OBJ_PROMOTED(values)) rb_gc_writebarrier_remember_promoted(values);
 | 
			
		||||
	rb_gc_writebarrier_remember(values);
 | 
			
		||||
	RARRAY_PTR_USE(values, ptr, {
 | 
			
		||||
	    size = st_values_check(table, ptr, size, Qundef);
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -710,6 +710,13 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
 | 
			
		|||
 | 
			
		||||
#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 {
 | 
			
		|||
 | 
			
		||||
#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 {
 | 
			
		|||
#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_VAR(const char *filename), RB_UNUSED_VAR(
 | 
			
		|||
#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(VALUE oldv), VALUE b, RB_UNUSED_VAR(const
 | 
			
		|||
#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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -639,7 +639,11 @@ void Init_heap(void);
 | 
			
		|||
void *ruby_mimmalloc(size_t size);
 | 
			
		||||
void ruby_mimfree(void *ptr);
 | 
			
		||||
void rb_objspace_set_event_hook(const rb_event_flag_t event);
 | 
			
		||||
void rb_gc_writebarrier_remember_promoted(VALUE obj);
 | 
			
		||||
#if USE_RGENGC
 | 
			
		||||
void rb_gc_writebarrier_remember(VALUE obj);
 | 
			
		||||
#else
 | 
			
		||||
#define rb_gc_writebarrier_remember(obj) 0
 | 
			
		||||
#endif
 | 
			
		||||
void ruby_gc_set_params(int safe_level);
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								object.c
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								object.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -282,6 +282,8 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		|||
    }
 | 
			
		||||
    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)
 | 
			
		|||
        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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -196,7 +196,7 @@ class TestObjSpace < Test::Unit::TestCase
 | 
			
		|||
 | 
			
		||||
  def test_dump_flags
 | 
			
		||||
    info = ObjectSpace.dump("foo".freeze)
 | 
			
		||||
    assert_match /"wb_protected":true, "old":true, "marked":true/, info
 | 
			
		||||
    assert_match /"wb_protected":true, "old":true, "long_lived":true, "marked":true/, info
 | 
			
		||||
    assert_match /"fstring":true/, info
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue