* 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:
ko1 2014-09-08 04:11:00 +00:00
Родитель e6368921ea
Коммит 123eeb1c1a
9 изменённых файлов: 2064 добавлений и 1135 удалений

Просмотреть файл

@ -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.

32
array.c
Просмотреть файл

@ -172,27 +172,20 @@ 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);
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]);
}
});
}
}
else {
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, {
for (i=0; i<argc; i++) {
RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
}
});
}
#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);
}
}

Просмотреть файл

@ -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,

3052
gc.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)

Просмотреть файл

@ -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