mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* gc.c: revert. before lazy sweep.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17887 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1890ae7aa9
commit
52f780c07f
2 changed files with 134 additions and 251 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
Sat Jul 5 16:12:54 2008 Narihiro Nakamura <authorNari@gmail.com>
|
||||||
|
|
||||||
|
* gc.c: revert. before lazy sweep.
|
||||||
|
|
||||||
Sat Jul 5 09:55:44 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
Sat Jul 5 09:55:44 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
||||||
|
|
||||||
* ext/win32ole/win32ole.c: add WIN32OLE#ole_respond_to?
|
* ext/win32ole/win32ole.c: add WIN32OLE#ole_respond_to?
|
||||||
|
@ -56,7 +60,7 @@ Fri Jul 4 14:17:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557]
|
* lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557]
|
||||||
|
|
||||||
Fri Jul 4 11:08:37 2008 nari <authorNari@gmail.com>
|
Fri Jul 4 11:08:37 2008 Narihiro Nakamura <authorNari@gmail.com>
|
||||||
|
|
||||||
* gc.c (garbage_collect_force): sweep is completely ended.
|
* gc.c (garbage_collect_force): sweep is completely ended.
|
||||||
|
|
||||||
|
|
379
gc.c
379
gc.c
|
@ -129,17 +129,10 @@ typedef struct RVALUE {
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum slot_color {
|
|
||||||
WHITE = 0x00, /* garbage */
|
|
||||||
BLACK = 0x01, /* used */
|
|
||||||
GRAY = 0x02, /* not sweep */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct heaps_slot {
|
struct heaps_slot {
|
||||||
void *membase;
|
void *membase;
|
||||||
RVALUE *slot;
|
RVALUE *slot;
|
||||||
int limit;
|
int limit;
|
||||||
enum slot_color color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HEAP_MIN_SLOTS 10000
|
#define HEAP_MIN_SLOTS 10000
|
||||||
|
@ -169,11 +162,6 @@ typedef struct rb_objspace {
|
||||||
RVALUE *freelist;
|
RVALUE *freelist;
|
||||||
RVALUE *range[2];
|
RVALUE *range[2];
|
||||||
RVALUE *freed;
|
RVALUE *freed;
|
||||||
size_t live;
|
|
||||||
size_t dead;
|
|
||||||
size_t do_heap_free;
|
|
||||||
size_t sweep_index;
|
|
||||||
size_t sweep_increment;
|
|
||||||
} heap;
|
} heap;
|
||||||
struct {
|
struct {
|
||||||
int dont_gc;
|
int dont_gc;
|
||||||
|
@ -191,7 +179,6 @@ typedef struct rb_objspace {
|
||||||
struct gc_list *global_list;
|
struct gc_list *global_list;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
int gc_stress;
|
int gc_stress;
|
||||||
int gc_not_lazy_sweep;
|
|
||||||
} rb_objspace_t;
|
} rb_objspace_t;
|
||||||
|
|
||||||
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
|
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
|
||||||
|
@ -213,11 +200,6 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
|
||||||
#define himem objspace->heap.range[1]
|
#define himem objspace->heap.range[1]
|
||||||
#define heaps_inc objspace->heap.increment
|
#define heaps_inc objspace->heap.increment
|
||||||
#define heaps_freed objspace->heap.freed
|
#define heaps_freed objspace->heap.freed
|
||||||
#define live objspace->heap.live
|
|
||||||
#define dead objspace->heap.dead
|
|
||||||
#define do_heap_free objspace->heap.do_heap_free
|
|
||||||
#define heaps_sweep_index objspace->heap.sweep_index
|
|
||||||
#define heaps_sweep_inc objspace->heap.sweep_increment
|
|
||||||
#define dont_gc objspace->flags.dont_gc
|
#define dont_gc objspace->flags.dont_gc
|
||||||
#define during_gc objspace->flags.during_gc
|
#define during_gc objspace->flags.during_gc
|
||||||
#define finalizer_table objspace->final.table
|
#define finalizer_table objspace->final.table
|
||||||
|
@ -227,7 +209,6 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
|
||||||
#define mark_stack_overflow objspace->markstack.overflow
|
#define mark_stack_overflow objspace->markstack.overflow
|
||||||
#define global_List objspace->global_list
|
#define global_List objspace->global_list
|
||||||
#define ruby_gc_stress objspace->gc_stress
|
#define ruby_gc_stress objspace->gc_stress
|
||||||
#define ruby_gc_not_lazy_sweep objspace->gc_not_lazy_sweep
|
|
||||||
|
|
||||||
#define need_call_final (finalizer_table && finalizer_table->num_entries)
|
#define need_call_final (finalizer_table && finalizer_table->num_entries)
|
||||||
|
|
||||||
|
@ -268,7 +249,6 @@ int ruby_disable_gc_stress = 0;
|
||||||
|
|
||||||
static void run_final(rb_objspace_t *objspace, VALUE obj);
|
static void run_final(rb_objspace_t *objspace, VALUE obj);
|
||||||
static int garbage_collect(rb_objspace_t *objspace);
|
static int garbage_collect(rb_objspace_t *objspace);
|
||||||
static int garbage_collect_force(rb_objspace_t *objspace);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_global_variable(VALUE *var)
|
rb_global_variable(VALUE *var)
|
||||||
|
@ -345,11 +325,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size)
|
||||||
|
|
||||||
if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
|
if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
|
||||||
(malloc_increase+size) > malloc_limit) {
|
(malloc_increase+size) > malloc_limit) {
|
||||||
garbage_collect_force(objspace);
|
garbage_collect(objspace);
|
||||||
}
|
}
|
||||||
RUBY_CRITICAL(mem = malloc(size));
|
RUBY_CRITICAL(mem = malloc(size));
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
if (garbage_collect_force(objspace)) {
|
if (garbage_collect(objspace)) {
|
||||||
RUBY_CRITICAL(mem = malloc(size));
|
RUBY_CRITICAL(mem = malloc(size));
|
||||||
}
|
}
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
|
@ -385,9 +365,10 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
|
||||||
objspace->malloc_params.allocated_size -= size;
|
objspace->malloc_params.allocated_size -= size;
|
||||||
ptr = (size_t *)ptr - 1;
|
ptr = (size_t *)ptr - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RUBY_CRITICAL(mem = realloc(ptr, size));
|
RUBY_CRITICAL(mem = realloc(ptr, size));
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
if (garbage_collect_force(objspace)) {
|
if (garbage_collect(objspace)) {
|
||||||
RUBY_CRITICAL(mem = realloc(ptr, size));
|
RUBY_CRITICAL(mem = realloc(ptr, size));
|
||||||
}
|
}
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
|
@ -578,8 +559,6 @@ allocate_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
|
||||||
heaps_length = next_heaps_length;
|
heaps_length = next_heaps_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RANY(o) ((RVALUE*)(o))
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assign_heap_slot(rb_objspace_t *objspace)
|
assign_heap_slot(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
|
@ -623,7 +602,6 @@ assign_heap_slot(rb_objspace_t *objspace)
|
||||||
heaps[hi].membase = membase;
|
heaps[hi].membase = membase;
|
||||||
heaps[hi].slot = p;
|
heaps[hi].slot = p;
|
||||||
heaps[hi].limit = objs;
|
heaps[hi].limit = objs;
|
||||||
heaps[hi].color = BLACK;
|
|
||||||
pend = p + objs;
|
pend = p + objs;
|
||||||
if (lomem == 0 || lomem > p) lomem = p;
|
if (lomem == 0 || lomem > p) lomem = p;
|
||||||
if (himem < pend) himem = pend;
|
if (himem < pend) himem = pend;
|
||||||
|
@ -635,9 +613,6 @@ assign_heap_slot(rb_objspace_t *objspace)
|
||||||
freelist = p;
|
freelist = p;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
if (hi < heaps_sweep_index) {
|
|
||||||
heaps_sweep_index++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -680,13 +655,15 @@ heaps_increment(rb_objspace_t *objspace)
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RANY(o) ((RVALUE*)(o))
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_newobj_from_heap(rb_objspace_t *objspace)
|
rb_newobj_from_heap(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
|
|
||||||
if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) {
|
if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) {
|
||||||
if (!garbage_collect(objspace)) {
|
if (!heaps_increment(objspace) && !garbage_collect(objspace)) {
|
||||||
rb_memerror();
|
rb_memerror();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1063,7 +1040,6 @@ gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev)
|
||||||
if (obj->as.basic.flags == 0) return; /* free cell */
|
if (obj->as.basic.flags == 0) return; /* free cell */
|
||||||
if (obj->as.basic.flags & FL_MARK) return; /* already marked */
|
if (obj->as.basic.flags & FL_MARK) return; /* already marked */
|
||||||
obj->as.basic.flags |= FL_MARK;
|
obj->as.basic.flags |= FL_MARK;
|
||||||
live++;
|
|
||||||
|
|
||||||
if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
|
if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
|
||||||
if (!mark_stack_overflow) {
|
if (!mark_stack_overflow) {
|
||||||
|
@ -1099,7 +1075,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
|
||||||
if (obj->as.basic.flags == 0) return; /* free cell */
|
if (obj->as.basic.flags == 0) return; /* free cell */
|
||||||
if (obj->as.basic.flags & FL_MARK) return; /* already marked */
|
if (obj->as.basic.flags & FL_MARK) return; /* already marked */
|
||||||
obj->as.basic.flags |= FL_MARK;
|
obj->as.basic.flags |= FL_MARK;
|
||||||
live++;
|
|
||||||
|
|
||||||
marking:
|
marking:
|
||||||
if (FL_TEST(obj, FL_EXIVAR)) {
|
if (FL_TEST(obj, FL_EXIVAR)) {
|
||||||
|
@ -1359,131 +1334,139 @@ finalize_list(rb_objspace_t *objspace, RVALUE *p)
|
||||||
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
|
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
||||||
p->as.free.flags = 0;
|
p->as.free.flags = 0;
|
||||||
|
p->as.free.next = freelist;
|
||||||
|
freelist = p;
|
||||||
}
|
}
|
||||||
p = tmp;
|
p = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rb_gc_abort_threads(void);
|
static void
|
||||||
|
free_unused_heaps(rb_objspace_t *objspace)
|
||||||
static int
|
|
||||||
slot_sweep(rb_objspace_t *objspace, struct heaps_slot *target)
|
|
||||||
{
|
{
|
||||||
RVALUE *p, *pend, *free;
|
size_t i, j;
|
||||||
RVALUE *final;
|
RVALUE *last = 0;
|
||||||
int freed = 0;
|
|
||||||
|
|
||||||
if (target->color == BLACK || target->color == WHITE) {
|
for (i = j = 1; j < heaps_used; i++) {
|
||||||
return Qfalse;
|
if (heaps[i].limit == 0) {
|
||||||
}
|
if (!last) {
|
||||||
|
last = heaps[i].membase;
|
||||||
final = deferred_final_list;
|
|
||||||
free = freelist;
|
|
||||||
p = target->slot; pend = p + target->limit;
|
|
||||||
while (p < pend) {
|
|
||||||
if (!(p->as.basic.flags & FL_MARK)) {
|
|
||||||
if (p->as.basic.flags) {
|
|
||||||
obj_free(objspace, (VALUE)p);
|
|
||||||
}
|
|
||||||
if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
|
|
||||||
p->as.free.flags = FL_MARK; /* remain marked */
|
|
||||||
p->as.free.next = deferred_final_list;
|
|
||||||
deferred_final_list = p;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
free(heaps[i].membase);
|
||||||
p->as.free.flags = 0;
|
|
||||||
p->as.free.next = freelist;
|
|
||||||
freelist = p;
|
|
||||||
}
|
}
|
||||||
freed++;
|
heaps_used--;
|
||||||
}
|
|
||||||
else if (RBASIC(p)->flags == FL_MARK) {
|
|
||||||
/* objects to be finalized */
|
|
||||||
/* do nothing remain marked */
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p->as.basic.flags &= ~FL_MARK;
|
if (i != j) {
|
||||||
|
heaps[j] = heaps[i];
|
||||||
|
}
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
dead += freed;
|
if (last) {
|
||||||
if (freed == target->limit && dead > do_heap_free) {
|
if (last < heaps_freed) {
|
||||||
RVALUE *pp;
|
free(heaps_freed);
|
||||||
|
heaps_freed = last;
|
||||||
target->limit = 0;
|
|
||||||
target->color = WHITE;
|
|
||||||
for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) {
|
|
||||||
pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
|
|
||||||
}
|
}
|
||||||
freelist = free; /* cancel this page from freelist */
|
else {
|
||||||
}
|
free(last);
|
||||||
else {
|
|
||||||
target->color = BLACK;
|
|
||||||
}
|
|
||||||
return Qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
heap_sweep_increment(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (i < heaps_sweep_inc && heaps_sweep_index < heaps_used) {
|
|
||||||
if (slot_sweep(objspace, &heaps[heaps_sweep_index])) {
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
heaps_sweep_index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
heap_sweep(rb_objspace_t *objspace)
|
gc_sweep(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
while (!freelist && heaps_sweep_index < heaps_used) {
|
RVALUE *p, *pend, *final_list;
|
||||||
slot_sweep(objspace, &heaps[heaps_sweep_index]);
|
size_t freed = 0;
|
||||||
heaps_sweep_index++;
|
size_t i;
|
||||||
}
|
size_t live = 0, free_min = 0, do_heap_free = 0;
|
||||||
}
|
|
||||||
|
|
||||||
#define GC_NOT_LAZY_SWEEP 0
|
do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
|
||||||
|
free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2;
|
||||||
static void
|
if (free_min < FREE_MIN) {
|
||||||
heap_all_sweep(rb_objspace_t *objspace)
|
do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
|
||||||
{
|
free_min = FREE_MIN;
|
||||||
while (heaps_sweep_index < heaps_used) {
|
|
||||||
slot_sweep(objspace, &heaps[heaps_sweep_index]);
|
|
||||||
heaps_sweep_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
gc_lazy_sweep(rb_objspace_t *objspace, rb_thread_t *th)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (heaps_increment(objspace)) {
|
|
||||||
heap_sweep_increment(objspace);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
heap_sweep(objspace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ruby_gc_not_lazy_sweep || GC_NOT_LAZY_SWEEP) {
|
freelist = 0;
|
||||||
heap_all_sweep(objspace);
|
final_list = deferred_final_list;
|
||||||
}
|
deferred_final_list = 0;
|
||||||
|
for (i = 0; i < heaps_used; i++) {
|
||||||
|
int n = 0;
|
||||||
|
RVALUE *free = freelist;
|
||||||
|
RVALUE *final = final_list;
|
||||||
|
|
||||||
if (!freelist) {
|
p = heaps[i].slot; pend = p + heaps[i].limit;
|
||||||
return Qfalse;
|
while (p < pend) {
|
||||||
}
|
if (!(p->as.basic.flags & FL_MARK)) {
|
||||||
|
if (p->as.basic.flags) {
|
||||||
|
obj_free(objspace, (VALUE)p);
|
||||||
|
}
|
||||||
|
if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
|
||||||
|
p->as.free.flags = FL_MARK; /* remain marked */
|
||||||
|
p->as.free.next = final_list;
|
||||||
|
final_list = p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
||||||
|
p->as.free.flags = 0;
|
||||||
|
p->as.free.next = freelist;
|
||||||
|
freelist = p;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
else if (RBASIC(p)->flags == FL_MARK) {
|
||||||
|
/* objects to be finalized */
|
||||||
|
/* do nothing remain marked */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RBASIC(p)->flags &= ~FL_MARK;
|
||||||
|
live++;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (n == heaps[i].limit && freed > do_heap_free) {
|
||||||
|
RVALUE *pp;
|
||||||
|
|
||||||
return Qtrue;
|
heaps[i].limit = 0;
|
||||||
|
for (pp = final_list; pp != final; pp = pp->as.free.next) {
|
||||||
|
p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
|
||||||
|
}
|
||||||
|
freelist = free; /* cancel this page from freelist */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
freed += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (malloc_increase > malloc_limit) {
|
||||||
|
malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
|
||||||
|
if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
|
||||||
|
}
|
||||||
|
malloc_increase = 0;
|
||||||
|
if (freed < free_min) {
|
||||||
|
set_heaps_increment(objspace);
|
||||||
|
heaps_increment(objspace);
|
||||||
|
}
|
||||||
|
during_gc = 0;
|
||||||
|
|
||||||
|
/* clear finalization list */
|
||||||
|
if (final_list) {
|
||||||
|
deferred_final_list = final_list;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free_unused_heaps(objspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_gc_force_recycle(VALUE p)
|
rb_gc_force_recycle(VALUE p)
|
||||||
{
|
{
|
||||||
|
rb_objspace_t *objspace = &rb_objspace;
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
||||||
RANY(p)->as.free.flags = 0;
|
RANY(p)->as.free.flags = 0;
|
||||||
|
RANY(p)->as.free.next = freelist;
|
||||||
|
freelist = RANY(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1684,86 +1667,29 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
|
||||||
|
|
||||||
void rb_gc_mark_encodings(void);
|
void rb_gc_mark_encodings(void);
|
||||||
|
|
||||||
static void
|
static int
|
||||||
gc_mark_all_clear(rb_objspace_t *objspace)
|
garbage_collect(rb_objspace_t *objspace)
|
||||||
{
|
|
||||||
RVALUE *last = 0;
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
for (i = j = 0; j < heaps_used; i++) {
|
|
||||||
if (heaps[i].color == WHITE && !deferred_final_list) {
|
|
||||||
if (!last) {
|
|
||||||
last = heaps[i].membase;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
free(heaps[i].membase);
|
|
||||||
}
|
|
||||||
heaps_used--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (heaps[i].color == GRAY) {
|
|
||||||
RVALUE *p, *pend;
|
|
||||||
p = heaps[i].slot; pend = p + heaps[i].limit;
|
|
||||||
while (p < pend) {
|
|
||||||
if (!(RBASIC(p)->flags & FL_MARK)) {
|
|
||||||
if (p->as.basic.flags && !FL_TEST(p, FL_FINALIZE)) {
|
|
||||||
obj_free(objspace, (VALUE)p);
|
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
|
|
||||||
p->as.free.flags = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (RBASIC(p)->flags != FL_MARK) {
|
|
||||||
p->as.basic.flags &= ~FL_MARK;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
heaps[i].color = GRAY;
|
|
||||||
}
|
|
||||||
if (i != j) {
|
|
||||||
heaps[j] = heaps[i];
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (last) {
|
|
||||||
if (last < heaps_freed) {
|
|
||||||
free(heaps_freed);
|
|
||||||
heaps_freed = last;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
free(last);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_lazy_sweep_params(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
size_t free_min = 0;
|
|
||||||
|
|
||||||
dead = 0;
|
|
||||||
heaps_sweep_index = 0;
|
|
||||||
heaps_sweep_inc = (heaps_used / 10) + 1;
|
|
||||||
do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
|
|
||||||
free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2;
|
|
||||||
if (free_min < FREE_MIN) free_min = FREE_MIN;
|
|
||||||
if (free_min > (heaps_used * HEAP_OBJ_LIMIT - live)) {
|
|
||||||
set_heaps_increment(objspace);
|
|
||||||
heaps_sweep_inc = (heaps_used + heaps_sweep_inc) / heaps_sweep_inc + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gc_marks(rb_objspace_t *objspace, rb_thread_t *th)
|
|
||||||
{
|
{
|
||||||
struct gc_list *list;
|
struct gc_list *list;
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
live = 0;
|
if (GC_NOTIFY) printf("start garbage_collect()\n");
|
||||||
freelist = 0;
|
|
||||||
|
|
||||||
gc_mark_all_clear(objspace);
|
if (!heaps) {
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dont_gc || during_gc) {
|
||||||
|
if (!freelist) {
|
||||||
|
if (!heaps_increment(objspace)) {
|
||||||
|
set_heaps_increment(objspace);
|
||||||
|
heaps_increment(objspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
during_gc++;
|
||||||
|
objspace->count++;
|
||||||
|
|
||||||
SET_STACK_END;
|
SET_STACK_END;
|
||||||
|
|
||||||
|
@ -1781,7 +1707,6 @@ gc_marks(rb_objspace_t *objspace, rb_thread_t *th)
|
||||||
rb_gc_mark_symbols();
|
rb_gc_mark_symbols();
|
||||||
rb_gc_mark_encodings();
|
rb_gc_mark_encodings();
|
||||||
|
|
||||||
|
|
||||||
/* mark protected global variables */
|
/* mark protected global variables */
|
||||||
for (list = global_List; list; list = list->next) {
|
for (list = global_List; list; list = list->next) {
|
||||||
rb_gc_mark_maybe(*list->varptr);
|
rb_gc_mark_maybe(*list->varptr);
|
||||||
|
@ -1807,55 +1732,9 @@ gc_marks(rb_objspace_t *objspace, rb_thread_t *th)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_lazy_sweep_params(objspace);
|
gc_sweep(objspace);
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
garbage_collect_force(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
int is_gc_success;
|
|
||||||
|
|
||||||
if (malloc_increase > malloc_limit) {
|
|
||||||
malloc_limit += (malloc_increase - malloc_limit) * (double)live / (heaps_used * HEAP_OBJ_LIMIT);
|
|
||||||
if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
|
|
||||||
}
|
|
||||||
malloc_increase = 0;
|
|
||||||
ruby_gc_not_lazy_sweep = Qtrue;
|
|
||||||
is_gc_success = garbage_collect(objspace);
|
|
||||||
ruby_gc_not_lazy_sweep = Qfalse;
|
|
||||||
return is_gc_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
garbage_collect(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
|
|
||||||
if (GC_NOTIFY) printf("start garbage_collect()\n");
|
|
||||||
|
|
||||||
if (!heaps) {
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dont_gc || during_gc) {
|
|
||||||
if (!freelist) {
|
|
||||||
if (!heaps_increment(objspace)) {
|
|
||||||
set_heaps_increment(objspace);
|
|
||||||
heaps_increment(objspace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Qtrue;
|
|
||||||
}
|
|
||||||
during_gc++;
|
|
||||||
objspace->count++;
|
|
||||||
|
|
||||||
while (!gc_lazy_sweep(objspace, th)) {
|
|
||||||
gc_marks(objspace, th);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GC_NOTIFY) printf("end garbage_collect()\n");
|
if (GC_NOTIFY) printf("end garbage_collect()\n");
|
||||||
during_gc = 0;
|
|
||||||
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1970,7 +1849,6 @@ os_obj_of(rb_objspace_t *objspace, VALUE of)
|
||||||
|
|
||||||
p = heaps[i].slot; pend = p + heaps[i].limit;
|
p = heaps[i].slot; pend = p + heaps[i].limit;
|
||||||
for (;p < pend; p++) {
|
for (;p < pend; p++) {
|
||||||
if (!freelist) garbage_collect_force(objspace);
|
|
||||||
if (p->as.basic.flags) {
|
if (p->as.basic.flags) {
|
||||||
switch (BUILTIN_TYPE(p)) {
|
switch (BUILTIN_TYPE(p)) {
|
||||||
case T_NONE:
|
case T_NONE:
|
||||||
|
@ -2156,6 +2034,7 @@ gc_finalize_deferred(rb_objspace_t *objspace)
|
||||||
if (p) {
|
if (p) {
|
||||||
finalize_list(objspace, p);
|
finalize_list(objspace, p);
|
||||||
}
|
}
|
||||||
|
free_unused_heaps(objspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2227,8 +2106,8 @@ void
|
||||||
rb_gc(void)
|
rb_gc(void)
|
||||||
{
|
{
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
rb_objspace_t *objspace = &rb_objspace;
|
||||||
gc_finalize_deferred(objspace);
|
|
||||||
garbage_collect(objspace);
|
garbage_collect(objspace);
|
||||||
|
gc_finalize_deferred(objspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue