зеркало из https://github.com/github/ruby.git
* 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:
Родитель
e6368921ea
Коммит
123eeb1c1a
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.
|
||||
|
|
32
array.c
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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,
|
||||
|
|
3052
gc.c
3052
gc.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче