зеркало из https://github.com/github/ruby.git
* gc.c (garbage_collect): all GC is start from garbage_collect()
(or garbage_collect_body()). `garbage_collect()' accept additional two parameters `full_mark' and `immediate_sweep'. If `full_mark' is TRUE, then force it full gc (major gc), otherwise, it depends on status of object space. Now, it will be minor gc. If `immediate_sweep' is TRUE, then disable lazy sweep. To allocate free memory, `full_mark' and `immediate_sweep' should be TRUE. Otherwise, they should be FALSE. * gc.c (gc_prepare_free_objects): use `garbage_collect_body()'. * gc.c (slot_sweep, before_gc_sweep, after_gc_sweep): add logging code. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40884 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
e12df5ef40
Коммит
9e64703ec8
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
Wed May 22 07:36:08 2013 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* gc.c (garbage_collect): all GC is start from garbage_collect()
|
||||
(or garbage_collect_body()). `garbage_collect()' accept additional
|
||||
two parameters `full_mark' and `immediate_sweep'.
|
||||
If `full_mark' is TRUE, then force it full gc (major gc), otherwise,
|
||||
it depends on status of object space. Now, it will be minor gc.
|
||||
If `immediate_sweep' is TRUE, then disable lazy sweep.
|
||||
To allocate free memory, `full_mark' and `immediate_sweep' should be
|
||||
TRUE. Otherwise, they should be FALSE.
|
||||
|
||||
* gc.c (gc_prepare_free_objects): use `garbage_collect_body()'.
|
||||
|
||||
* gc.c (slot_sweep, before_gc_sweep, after_gc_sweep): add logging code.
|
||||
|
||||
Tue May 21 22:47:06 2013 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* ext/strscan/strscan.c (strscan_aref): support named captures.
|
||||
|
|
149
gc.c
149
gc.c
|
@ -106,7 +106,7 @@ static ruby_gc_params_t initial_params = {
|
|||
|
||||
#if USE_RGENGC
|
||||
/* RGENGC_DEBUG:
|
||||
* 1:
|
||||
* 1: basic information
|
||||
* 2: remember set operation
|
||||
* 3: mark
|
||||
* 4:
|
||||
|
@ -450,7 +450,8 @@ static void aligned_free(void *);
|
|||
static void init_mark_stack(mark_stack_t *stack);
|
||||
|
||||
static VALUE lazy_sweep_enable(void);
|
||||
static int garbage_collect(rb_objspace_t *, int reason);
|
||||
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_prepare_free_objects(rb_objspace_t *);
|
||||
static void mark_tbl(rb_objspace_t *, st_table *);
|
||||
static void rest_sweep(rb_objspace_t *);
|
||||
|
@ -813,8 +814,7 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
|
|||
}
|
||||
|
||||
if (UNLIKELY(ruby_gc_stress && !ruby_disable_gc_stress)) {
|
||||
/* if (!garbage_collect(objspace)) { */
|
||||
if (!gc_prepare_free_objects(objspace)) {
|
||||
if (!garbage_collect(objspace, FALSE, FALSE, GPR_FLAG_NEWOBJ)) {
|
||||
during_gc = 0;
|
||||
rb_memerror();
|
||||
}
|
||||
|
@ -860,7 +860,6 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
|
|||
rgengc_report(5, objspace, "newobj: %p (%s)\n", (void *)obj, obj_type_name(obj));
|
||||
|
||||
#if USE_RGENGC && RGENGC_CHECK_MODE
|
||||
if (RBASIC(obj)->flags) rb_bug("newobj: flags of %p (%s) is not zero (%-8lx).\n", (void *)obj, obj_type_name(obj), RBASIC(obj)->flags);
|
||||
if (RVALUE_PROMOTED(obj)) rb_bug("newobj: %p (%s) is promoted.\n", (void *)obj, obj_type_name(obj));
|
||||
if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %p (%s) is remembered.\n", (void *)obj, obj_type_name(obj));
|
||||
#endif
|
||||
|
@ -2018,8 +2017,6 @@ count_objects(int argc, VALUE *argv, VALUE os)
|
|||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
------------------------ Garbage Collection ------------------------
|
||||
*/
|
||||
|
@ -2182,6 +2179,7 @@ slot_sweep_major(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
|
|||
static void
|
||||
slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
|
||||
{
|
||||
rgengc_report(1, objspace, "slot_sweep: start\n");
|
||||
gc_prof_sweep_slot_timer_start(objspace);
|
||||
{
|
||||
#if USE_RGENGC
|
||||
|
@ -2196,6 +2194,7 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
|
|||
#endif
|
||||
}
|
||||
gc_prof_sweep_slot_timer_stop(objspace);
|
||||
rgengc_report(1, objspace, "slot_sweep: end\n");
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2216,6 +2215,8 @@ ready_to_gc(rb_objspace_t *objspace)
|
|||
static void
|
||||
before_gc_sweep(rb_objspace_t *objspace)
|
||||
{
|
||||
rgengc_report(1, objspace, "before_gc_sweep\n");
|
||||
|
||||
objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65);
|
||||
objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2);
|
||||
if (objspace->heap.free_min < initial_free_min) {
|
||||
|
@ -2238,15 +2239,19 @@ after_gc_sweep(rb_objspace_t *objspace)
|
|||
{
|
||||
size_t inc;
|
||||
|
||||
rgengc_report(1, objspace, "after_gc_sweep\n");
|
||||
|
||||
gc_prof_set_malloc_info(objspace);
|
||||
rgengc_report(5, objspace, "after_gc_sweep: objspace->heap.free_num: %d, objspace->heap.free_min: %d\n",
|
||||
objspace->heap.free_num, objspace->heap.free_min);
|
||||
|
||||
if (objspace->heap.free_num < objspace->heap.free_min) {
|
||||
set_heaps_increment(objspace);
|
||||
heaps_increment(objspace);
|
||||
}
|
||||
|
||||
inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
|
||||
|
||||
if (inc > malloc_limit) {
|
||||
malloc_limit +=
|
||||
(size_t)((inc - malloc_limit) * (double)objspace_live_num(objspace) / (heaps_used * HEAP_OBJ_LIMIT));
|
||||
|
@ -2287,13 +2292,11 @@ rest_sweep(rb_objspace_t *objspace)
|
|||
}
|
||||
}
|
||||
|
||||
static void gc_marks(rb_objspace_t *objspace, int minor_gc);
|
||||
|
||||
static void
|
||||
gc_sweep(rb_objspace_t *objspace)
|
||||
gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
|
||||
{
|
||||
if (immediate_sweep) {
|
||||
struct heaps_slot *next;
|
||||
|
||||
before_gc_sweep(objspace);
|
||||
|
||||
while (objspace->heap.sweep_slots) {
|
||||
|
@ -2303,21 +2306,32 @@ gc_sweep(rb_objspace_t *objspace)
|
|||
}
|
||||
|
||||
after_gc_sweep(objspace);
|
||||
}
|
||||
else {
|
||||
before_gc_sweep(objspace);
|
||||
lazy_sweep(objspace);
|
||||
}
|
||||
|
||||
if (!has_free_object) {
|
||||
/* there is no freespace after slot_sweep() */
|
||||
/* TODO: [RGENGC] Should do major GC before adding hepas */
|
||||
set_heaps_increment(objspace);
|
||||
if (!heaps_increment(objspace)) {
|
||||
during_gc = 0;
|
||||
rb_memerror();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gc_prepare_free_objects(rb_objspace_t *objspace)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_lazy_sweep) {
|
||||
if (heaps_increment(objspace)) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return garbage_collect(objspace, GPR_FLAG_NEWOBJ);
|
||||
return garbage_collect(objspace, FALSE, TRUE, GPR_FLAG_NEWOBJ);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2326,9 +2340,8 @@ gc_prepare_free_objects(rb_objspace_t *objspace)
|
|||
during_gc++;
|
||||
|
||||
if (objspace->heap.sweep_slots) {
|
||||
res = lazy_sweep(objspace);
|
||||
if (res) {
|
||||
return res;
|
||||
if (lazy_sweep(objspace)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -2338,30 +2351,7 @@ gc_prepare_free_objects(rb_objspace_t *objspace)
|
|||
}
|
||||
}
|
||||
|
||||
gc_prof_timer_start(objspace, GPR_FLAG_NEWOBJ | GPR_FLAG_MINOR);
|
||||
{
|
||||
gc_marks(objspace, TRUE);
|
||||
|
||||
before_gc_sweep(objspace);
|
||||
if (!(res = lazy_sweep(objspace))) {
|
||||
/* there is no freespace after slot_sweep() */
|
||||
while (1) {
|
||||
/* There is no empty RVALUE spaces */
|
||||
/* TODO: [RGENGC] Should do major GC before adding hepas */
|
||||
|
||||
set_heaps_increment(objspace);
|
||||
heaps_increment(objspace);
|
||||
|
||||
if (has_free_object) {
|
||||
res = TRUE;
|
||||
during_gc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gc_prof_timer_stop(objspace);
|
||||
return res;
|
||||
return garbage_collect_body(objspace, 0, 0, GPR_FLAG_NEWOBJ);
|
||||
}
|
||||
|
||||
/* Marking stack */
|
||||
|
@ -2967,6 +2957,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
|
|||
marking:
|
||||
|
||||
#if USE_RGENGC
|
||||
if (LIKELY(objspace->mark_func_data == 0)) {
|
||||
if (RGENGC_CHECK_MODE && RVALUE_SHADY(obj) && RVALUE_PROMOTED(obj)) {
|
||||
rb_bug("gc_mark_children: (1) %p (%s) is shady and promoted.\n", (void *)obj, obj_type_name((VALUE)obj));
|
||||
}
|
||||
|
@ -2993,6 +2984,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
|
|||
if (RGENGC_CHECK_MODE && RVALUE_SHADY(obj) && RVALUE_PROMOTED(obj)) {
|
||||
rb_bug("gc_mark_children: (2) %p (%s) is shady and promoted.\n", (void *)obj, obj_type_name((VALUE)obj));
|
||||
}
|
||||
}
|
||||
#endif /* USE_RGENGC */
|
||||
|
||||
if (FL_TEST(obj, FL_EXIVAR)) {
|
||||
|
@ -3689,24 +3681,34 @@ rb_gc_unregister_address(VALUE *addr)
|
|||
#define GC_NOTIFY 0
|
||||
|
||||
static int
|
||||
garbage_collect(rb_objspace_t *objspace, int reason)
|
||||
garbage_collect_body(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
|
||||
{
|
||||
if (GC_NOTIFY) printf("start garbage_collect()\n");
|
||||
int minor_gc;
|
||||
|
||||
if (!heaps) {
|
||||
return FALSE;
|
||||
if (ruby_gc_stress && !ruby_disable_gc_stress) {
|
||||
minor_gc = TRUE;
|
||||
immediate_sweep = TRUE;
|
||||
}
|
||||
else {
|
||||
if (full_mark) {
|
||||
minor_gc = FALSE;
|
||||
}
|
||||
else {
|
||||
/* TODO: count old object size and so on */
|
||||
minor_gc = TRUE;
|
||||
}
|
||||
if (!ready_to_gc(objspace)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rest_sweep(objspace);
|
||||
if (GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_lazy_sweep) {
|
||||
immediate_sweep = TRUE;
|
||||
}
|
||||
|
||||
gc_prof_timer_start(objspace, reason);
|
||||
gc_prof_timer_start(objspace, reason | (minor_gc ? GPR_FLAG_MINOR : 0));
|
||||
{
|
||||
during_gc++;
|
||||
gc_marks(objspace, FALSE);
|
||||
gc_sweep(objspace);
|
||||
assert(during_gc > 0);
|
||||
gc_marks(objspace, minor_gc);
|
||||
gc_sweep(objspace, immediate_sweep);
|
||||
during_gc = 0;
|
||||
}
|
||||
gc_prof_timer_stop(objspace);
|
||||
|
||||
|
@ -3714,30 +3716,55 @@ garbage_collect(rb_objspace_t *objspace, int reason)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
garbage_collect(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
|
||||
{
|
||||
if (GC_NOTIFY) printf("start garbage_collect(%d, %d, %d)\n", full_mark, immediate_sweep, reason);
|
||||
|
||||
if (!heaps) {
|
||||
during_gc = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (!ready_to_gc(objspace)) {
|
||||
during_gc = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rest_sweep(objspace);
|
||||
|
||||
during_gc++;
|
||||
|
||||
return garbage_collect_body(objspace, full_mark, immediate_sweep, reason);
|
||||
}
|
||||
|
||||
struct objspace_and_reason {
|
||||
rb_objspace_t *objspace;
|
||||
int reason;
|
||||
int full_mark;
|
||||
int immediate_sweep;
|
||||
};
|
||||
|
||||
static void *
|
||||
gc_with_gvl(void *ptr)
|
||||
{
|
||||
struct objspace_and_reason *oar = (struct objspace_and_reason *)ptr;
|
||||
return (void *)(VALUE)garbage_collect(oar->objspace, oar->reason);
|
||||
return (void *)(VALUE)garbage_collect(oar->objspace, oar->full_mark, oar->immediate_sweep, oar->reason);
|
||||
}
|
||||
|
||||
static int
|
||||
garbage_collect_with_gvl(rb_objspace_t *objspace, int reason)
|
||||
garbage_collect_with_gvl(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
|
||||
{
|
||||
if (dont_gc) return TRUE;
|
||||
if (ruby_thread_has_gvl_p()) {
|
||||
return garbage_collect(objspace, reason);
|
||||
return garbage_collect(objspace, full_mark, immediate_sweep, reason);
|
||||
}
|
||||
else {
|
||||
if (ruby_native_thread_p()) {
|
||||
struct objspace_and_reason oar;
|
||||
oar.objspace = objspace;
|
||||
oar.reason = reason;
|
||||
oar.full_mark = full_mark;
|
||||
oar.immediate_sweep = immediate_sweep;
|
||||
return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
|
||||
}
|
||||
else {
|
||||
|
@ -3751,7 +3778,7 @@ garbage_collect_with_gvl(rb_objspace_t *objspace, int reason)
|
|||
int
|
||||
rb_garbage_collect(void)
|
||||
{
|
||||
return garbage_collect(&rb_objspace, GPR_FLAG_CAPI);
|
||||
return garbage_collect(&rb_objspace, TRUE, TRUE, GPR_FLAG_CAPI);
|
||||
}
|
||||
|
||||
#undef Init_stack
|
||||
|
@ -3783,7 +3810,7 @@ void
|
|||
rb_gc(void)
|
||||
{
|
||||
rb_objspace_t *objspace = &rb_objspace;
|
||||
garbage_collect(objspace, GPR_FLAG_METHOD);
|
||||
garbage_collect(objspace, TRUE, TRUE, GPR_FLAG_METHOD);
|
||||
if (!finalizing) finalize_deferred(objspace);
|
||||
free_unused_heaps(objspace);
|
||||
}
|
||||
|
@ -4213,7 +4240,7 @@ vm_malloc_prepare(rb_objspace_t *objspace, size_t size)
|
|||
|
||||
if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
|
||||
(malloc_increase+size) > malloc_limit) {
|
||||
garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
|
||||
garbage_collect_with_gvl(objspace, 0, 0, GPR_FLAG_MALLOC);
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -4236,7 +4263,7 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
|
|||
|
||||
#define TRY_WITH_GC(alloc) do { \
|
||||
if (!(alloc) && \
|
||||
(!garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC) || \
|
||||
(!garbage_collect_with_gvl(objspace, 1, 1, GPR_FLAG_MALLOC) || /* full mark && immediate sweep */ \
|
||||
!(alloc))) { \
|
||||
ruby_memerror(); \
|
||||
} \
|
||||
|
@ -4276,7 +4303,7 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
|
|||
return 0;
|
||||
}
|
||||
if (ruby_gc_stress && !ruby_disable_gc_stress)
|
||||
garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
|
||||
garbage_collect_with_gvl(objspace, 0, 0, GPR_FLAG_MALLOC);
|
||||
|
||||
#if CALC_EXACT_MALLOC_SIZE
|
||||
size += sizeof(size_t);
|
||||
|
@ -4286,7 +4313,7 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
|
|||
|
||||
mem = realloc(ptr, size);
|
||||
if (!mem) {
|
||||
if (garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC)) {
|
||||
if (garbage_collect_with_gvl(objspace, 1, 1, GPR_FLAG_MALLOC)) {
|
||||
mem = realloc(ptr, size);
|
||||
}
|
||||
if (!mem) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче