зеркало из https://github.com/github/ruby.git
* gc.c: reject unused longlife gc.
* debug.c: ditto. * include/ruby/intern.h: ditto. * include/ruby/ruby.h: ditto. * iseq.c: ditto. * node.h: ditto. * vm_insnhelper.c: ditto. * vm_insnhelper.h: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24490 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
a8cf451714
Коммит
de5f15bbe4
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
Mon Aug 10 10:57:59 2009 Narihiro Nakamura <authorNari@gmail.com>
|
||||||
|
|
||||||
|
* gc.c: reject unused longlife gc.
|
||||||
|
|
||||||
|
* debug.c: ditto.
|
||||||
|
|
||||||
|
* include/ruby/intern.h: ditto.
|
||||||
|
|
||||||
|
* include/ruby/ruby.h: ditto.
|
||||||
|
|
||||||
|
* iseq.c: ditto.
|
||||||
|
|
||||||
|
* node.h: ditto.
|
||||||
|
|
||||||
|
* vm_insnhelper.c: ditto.
|
||||||
|
|
||||||
|
* vm_insnhelper.h: ditto.
|
||||||
|
|
||||||
Mon Aug 10 06:55:45 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Aug 10 06:55:45 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* marshal.c (class2path, w_unique, w_extended, w_class, w_uclass):
|
* marshal.c (class2path, w_unique, w_extended, w_class, w_uclass):
|
||||||
|
|
2
debug.c
2
debug.c
|
@ -34,7 +34,7 @@ const union {
|
||||||
RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID,
|
RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID,
|
||||||
RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN,
|
RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN,
|
||||||
RUBY_FL_MARK = FL_MARK,
|
RUBY_FL_MARK = FL_MARK,
|
||||||
RUBY_FL_REMENBERED_SET = FL_REMEMBERED_SET,
|
RUBY_FL_RESERVED = FL_RESERVED,
|
||||||
RUBY_FL_FINALIZE = FL_FINALIZE,
|
RUBY_FL_FINALIZE = FL_FINALIZE,
|
||||||
RUBY_FL_TAINT = FL_TAINT,
|
RUBY_FL_TAINT = FL_TAINT,
|
||||||
RUBY_FL_UNTRUSTED = FL_UNTRUSTED,
|
RUBY_FL_UNTRUSTED = FL_UNTRUSTED,
|
||||||
|
|
261
gc.c
261
gc.c
|
@ -93,7 +93,6 @@ typedef struct gc_profile_record {
|
||||||
double gc_invoke_time;
|
double gc_invoke_time;
|
||||||
|
|
||||||
size_t heap_use_slots;
|
size_t heap_use_slots;
|
||||||
size_t heap_longlife_use_slots;
|
|
||||||
size_t heap_live_objects;
|
size_t heap_live_objects;
|
||||||
size_t heap_free_objects;
|
size_t heap_free_objects;
|
||||||
size_t heap_total_objects;
|
size_t heap_total_objects;
|
||||||
|
@ -101,7 +100,6 @@ typedef struct gc_profile_record {
|
||||||
size_t heap_total_size;
|
size_t heap_total_size;
|
||||||
|
|
||||||
int have_finalize;
|
int have_finalize;
|
||||||
int longlife_collection;
|
|
||||||
|
|
||||||
size_t allocate_increase;
|
size_t allocate_increase;
|
||||||
size_t allocate_limit;
|
size_t allocate_limit;
|
||||||
|
@ -159,7 +157,6 @@ getrusage_time(void)
|
||||||
MEMZERO(&objspace->profile.record[count], gc_profile_record, 1);\
|
MEMZERO(&objspace->profile.record[count], gc_profile_record, 1);\
|
||||||
gc_time = getrusage_time();\
|
gc_time = getrusage_time();\
|
||||||
objspace->profile.record[count].gc_invoke_time = gc_time - objspace->profile.invoke_time;\
|
objspace->profile.record[count].gc_invoke_time = gc_time - objspace->profile.invoke_time;\
|
||||||
objspace->profile.record[count].longlife_collection = objspace->flags.longlife_collection;\
|
|
||||||
}\
|
}\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
@ -214,12 +211,11 @@ getrusage_time(void)
|
||||||
if (objspace->profile.run) {\
|
if (objspace->profile.run) {\
|
||||||
gc_profile_record *record = &objspace->profile.record[objspace->profile.count];\
|
gc_profile_record *record = &objspace->profile.record[objspace->profile.count];\
|
||||||
record->heap_use_slots = heaps_used;\
|
record->heap_use_slots = heaps_used;\
|
||||||
record->heap_longlife_use_slots = objspace->heap.longlife_used;\
|
record->heap_live_objects = live;\
|
||||||
record->heap_live_objects = live + objspace->profile.longlife_objects;\
|
record->heap_free_objects = freed; \
|
||||||
record->heap_free_objects = freed + (objspace->heap.longlife_used * HEAP_OBJ_LIMIT - objspace->profile.longlife_objects); \
|
|
||||||
record->heap_total_objects = heaps_used * HEAP_OBJ_LIMIT;\
|
record->heap_total_objects = heaps_used * HEAP_OBJ_LIMIT;\
|
||||||
record->have_finalize = final_list ? Qtrue : Qfalse;\
|
record->have_finalize = final_list ? Qtrue : Qfalse;\
|
||||||
record->heap_use_size = (live + objspace->profile.longlife_objects) * sizeof(RVALUE); \
|
record->heap_use_size = live * sizeof(RVALUE); \
|
||||||
record->heap_total_size = heaps_used * (HEAP_OBJ_LIMIT * sizeof(RVALUE));\
|
record->heap_total_size = heaps_used * (HEAP_OBJ_LIMIT * sizeof(RVALUE));\
|
||||||
}\
|
}\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
@ -235,7 +231,7 @@ getrusage_time(void)
|
||||||
if (objspace->profile.run) {\
|
if (objspace->profile.run) {\
|
||||||
gc_profile_record *record = &objspace->profile.record[objspace->profile.count];\
|
gc_profile_record *record = &objspace->profile.record[objspace->profile.count];\
|
||||||
record->heap_total_objects = heaps_used * HEAP_OBJ_LIMIT;\
|
record->heap_total_objects = heaps_used * HEAP_OBJ_LIMIT;\
|
||||||
record->heap_use_size = (live + objspace->profile.longlife_objects) * sizeof(RVALUE); \
|
record->heap_use_size = live * sizeof(RVALUE); \
|
||||||
record->heap_total_size = heaps_used * HEAP_SIZE;\
|
record->heap_total_size = heaps_used * HEAP_SIZE;\
|
||||||
}\
|
}\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
@ -280,16 +276,10 @@ typedef struct RVALUE {
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum lifetime {
|
|
||||||
lifetime_normal,
|
|
||||||
lifetime_longlife
|
|
||||||
};
|
|
||||||
|
|
||||||
struct heaps_slot {
|
struct heaps_slot {
|
||||||
void *membase;
|
void *membase;
|
||||||
RVALUE *slot;
|
RVALUE *slot;
|
||||||
size_t limit;
|
size_t limit;
|
||||||
enum lifetime lifetime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HEAP_MIN_SLOTS 10000
|
#define HEAP_MIN_SLOTS 10000
|
||||||
|
@ -302,11 +292,6 @@ struct gc_list {
|
||||||
|
|
||||||
#define CALC_EXACT_MALLOC_SIZE 0
|
#define CALC_EXACT_MALLOC_SIZE 0
|
||||||
|
|
||||||
typedef struct remembered_set {
|
|
||||||
RVALUE *obj;
|
|
||||||
struct remembered_set *next;
|
|
||||||
} remembered_set_t;
|
|
||||||
|
|
||||||
typedef struct rb_objspace {
|
typedef struct rb_objspace {
|
||||||
struct {
|
struct {
|
||||||
size_t limit;
|
size_t limit;
|
||||||
|
@ -321,20 +306,13 @@ typedef struct rb_objspace {
|
||||||
struct heaps_slot *ptr;
|
struct heaps_slot *ptr;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t longlife_used;
|
|
||||||
RVALUE *freelist;
|
RVALUE *freelist;
|
||||||
RVALUE *longlife_freelist;
|
|
||||||
RVALUE *range[2];
|
RVALUE *range[2];
|
||||||
RVALUE *freed;
|
RVALUE *freed;
|
||||||
} heap;
|
} heap;
|
||||||
struct {
|
|
||||||
remembered_set_t *ptr;
|
|
||||||
remembered_set_t *freed;
|
|
||||||
} remembered_set;
|
|
||||||
struct {
|
struct {
|
||||||
int dont_gc;
|
int dont_gc;
|
||||||
int during_gc;
|
int during_gc;
|
||||||
int longlife_collection;
|
|
||||||
} flags;
|
} flags;
|
||||||
struct {
|
struct {
|
||||||
st_table *table;
|
st_table *table;
|
||||||
|
@ -350,7 +328,6 @@ typedef struct rb_objspace {
|
||||||
gc_profile_record *record;
|
gc_profile_record *record;
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t longlife_objects;
|
|
||||||
double invoke_time;
|
double invoke_time;
|
||||||
} profile;
|
} profile;
|
||||||
struct gc_list *global_list;
|
struct gc_list *global_list;
|
||||||
|
@ -419,7 +396,6 @@ rb_objspace_alloc(void)
|
||||||
/*#define HEAP_SIZE 0x800 */
|
/*#define HEAP_SIZE 0x800 */
|
||||||
|
|
||||||
#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
|
#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
|
||||||
#define NORMAL_HEAPS_USED (objspace->heap.used - objspace->heap.longlife_used)
|
|
||||||
|
|
||||||
extern VALUE rb_cMutex;
|
extern VALUE rb_cMutex;
|
||||||
extern st_table *rb_class_tbl;
|
extern st_table *rb_class_tbl;
|
||||||
|
@ -883,7 +859,7 @@ allocate_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assign_heap_slot(rb_objspace_t *objspace, RVALUE **list, enum lifetime lifetime)
|
assign_heap_slot(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
RVALUE *p, *pend, *membase;
|
RVALUE *p, *pend, *membase;
|
||||||
size_t hi, lo, mid;
|
size_t hi, lo, mid;
|
||||||
|
@ -927,17 +903,15 @@ assign_heap_slot(rb_objspace_t *objspace, RVALUE **list, enum lifetime lifetime)
|
||||||
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].lifetime = lifetime;
|
|
||||||
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;
|
||||||
if (lifetime == lifetime_longlife) objspace->heap.longlife_used++;
|
|
||||||
heaps_used++;
|
heaps_used++;
|
||||||
|
|
||||||
while (p < pend) {
|
while (p < pend) {
|
||||||
p->as.free.flags = 0;
|
p->as.free.flags = 0;
|
||||||
p->as.free.next = *list;
|
p->as.free.next = freelist;
|
||||||
*list = p;
|
freelist = p;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,7 +932,7 @@ init_heap(rb_objspace_t *objspace)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < add; i++) {
|
for (i = 0; i < add; i++) {
|
||||||
assign_heap_slot(objspace, &freelist, lifetime_normal);
|
assign_heap_slot(objspace);
|
||||||
}
|
}
|
||||||
heaps_inc = 0;
|
heaps_inc = 0;
|
||||||
objspace->profile.invoke_time = getrusage_time();
|
objspace->profile.invoke_time = getrusage_time();
|
||||||
|
@ -985,44 +959,15 @@ static int
|
||||||
heaps_increment(rb_objspace_t *objspace)
|
heaps_increment(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
if (heaps_inc > 0) {
|
if (heaps_inc > 0) {
|
||||||
assign_heap_slot(objspace, &freelist, lifetime_normal);
|
assign_heap_slot(objspace);
|
||||||
heaps_inc--;
|
heaps_inc--;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LONGLIFE_ALLOCATE_HEAPS_MIN 10
|
|
||||||
|
|
||||||
static void
|
|
||||||
add_longlife_heaps_slot(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
if ((heaps_used + heaps_inc) >= heaps_length) {
|
|
||||||
allocate_heaps(objspace, (heaps_length + LONGLIFE_ALLOCATE_HEAPS_MIN));
|
|
||||||
}
|
|
||||||
assign_heap_slot(objspace, &objspace->heap.longlife_freelist, lifetime_longlife);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RANY(o) ((RVALUE*)(o))
|
#define RANY(o) ((RVALUE*)(o))
|
||||||
|
|
||||||
static VALUE
|
|
||||||
rb_newobj_from_longlife_heap(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
VALUE obj;
|
|
||||||
if (!objspace->heap.longlife_freelist) {
|
|
||||||
add_longlife_heaps_slot(objspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
obj = (VALUE)objspace->heap.longlife_freelist;
|
|
||||||
objspace->heap.longlife_freelist = objspace->heap.longlife_freelist->as.free.next;
|
|
||||||
|
|
||||||
MEMZERO((void*)obj, RVALUE, 1);
|
|
||||||
FL_SET(RANY(obj), FL_MARK);
|
|
||||||
objspace->profile.longlife_objects++;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_newobj_from_heap(rb_objspace_t *objspace)
|
rb_newobj_from_heap(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
|
@ -1116,22 +1061,6 @@ rb_newobj(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
|
||||||
rb_newobj_longlife(void)
|
|
||||||
{
|
|
||||||
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
|
|
||||||
rb_objspace_t *objspace = th->vm->objspace;
|
|
||||||
#else
|
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
|
||||||
#endif
|
|
||||||
if (during_gc) {
|
|
||||||
dont_gc = 1;
|
|
||||||
during_gc = 0;
|
|
||||||
rb_bug("object allocation during garbage collection phase");
|
|
||||||
}
|
|
||||||
return rb_newobj_from_longlife_heap(objspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE*
|
NODE*
|
||||||
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
|
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
|
||||||
{
|
{
|
||||||
|
@ -1147,21 +1076,6 @@ rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE*
|
|
||||||
rb_node_newnode_longlife(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
|
|
||||||
{
|
|
||||||
NODE *n = (NODE*)rb_newobj_longlife();
|
|
||||||
|
|
||||||
n->flags |= T_NODE;
|
|
||||||
nd_set_type(n, type);
|
|
||||||
|
|
||||||
n->u1.value = a0;
|
|
||||||
n->u2.value = a1;
|
|
||||||
n->u3.value = a2;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
|
rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
|
||||||
{
|
{
|
||||||
|
@ -1356,30 +1270,6 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
|
||||||
rb_gc_write_barrier(VALUE ptr)
|
|
||||||
{
|
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
|
||||||
remembered_set_t *tmp;
|
|
||||||
RVALUE *obj = RANY(ptr);
|
|
||||||
|
|
||||||
if (!SPECIAL_CONST_P(ptr) &&
|
|
||||||
!(RBASIC(ptr)->flags & FL_MARK || RBASIC(ptr)->flags & FL_REMEMBERED_SET)) {
|
|
||||||
if (objspace->remembered_set.freed) {
|
|
||||||
tmp = objspace->remembered_set.freed;
|
|
||||||
objspace->remembered_set.freed = objspace->remembered_set.freed->next;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tmp = ALLOC(remembered_set_t);
|
|
||||||
}
|
|
||||||
tmp->next = objspace->remembered_set.ptr;
|
|
||||||
tmp->obj = obj;
|
|
||||||
obj->as.basic.flags |= FL_REMEMBERED_SET;
|
|
||||||
objspace->remembered_set.ptr = tmp;
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
|
mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
|
||||||
{
|
{
|
||||||
|
@ -1856,12 +1746,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
|
||||||
static int obj_free(rb_objspace_t *, VALUE);
|
static int obj_free(rb_objspace_t *, VALUE);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
add_freelist(rb_objspace_t *objspace, RVALUE **list, RVALUE *p)
|
add_freelist(rb_objspace_t *objspace, RVALUE *p)
|
||||||
{
|
{
|
||||||
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 = *list;
|
p->as.free.next = freelist;
|
||||||
*list = p;
|
freelist = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1871,7 +1761,7 @@ finalize_list(rb_objspace_t *objspace, RVALUE *p)
|
||||||
RVALUE *tmp = p->as.free.next;
|
RVALUE *tmp = p->as.free.next;
|
||||||
run_final(objspace, (VALUE)p);
|
run_final(objspace, (VALUE)p);
|
||||||
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
|
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
|
||||||
add_freelist(objspace, &freelist, p);
|
add_freelist(objspace, p);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct heaps_slot *slot = (struct heaps_slot *)RDATA(p)->dmark;
|
struct heaps_slot *slot = (struct heaps_slot *)RDATA(p)->dmark;
|
||||||
|
@ -1895,9 +1785,6 @@ free_unused_heaps(rb_objspace_t *objspace)
|
||||||
else {
|
else {
|
||||||
free(heaps[i].membase);
|
free(heaps[i].membase);
|
||||||
}
|
}
|
||||||
if (heaps[i].lifetime == lifetime_longlife) {
|
|
||||||
objspace->heap.longlife_used--;
|
|
||||||
}
|
|
||||||
heaps_used--;
|
heaps_used--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1943,7 +1830,6 @@ gc_sweep(rb_objspace_t *objspace)
|
||||||
RVALUE *final = final_list;
|
RVALUE *final = final_list;
|
||||||
int deferred;
|
int deferred;
|
||||||
|
|
||||||
if (heaps[i].lifetime == lifetime_longlife) continue;
|
|
||||||
p = heaps[i].slot; pend = p + heaps[i].limit;
|
p = heaps[i].slot; pend = p + heaps[i].limit;
|
||||||
while (p < pend) {
|
while (p < pend) {
|
||||||
if (!(p->as.basic.flags & FL_MARK)) {
|
if (!(p->as.basic.flags & FL_MARK)) {
|
||||||
|
@ -1960,7 +1846,7 @@ gc_sweep(rb_objspace_t *objspace)
|
||||||
final_num++;
|
final_num++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
add_freelist(objspace, &freelist, p);
|
add_freelist(objspace, p);
|
||||||
free_num++;
|
free_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1996,8 +1882,6 @@ gc_sweep(rb_objspace_t *objspace)
|
||||||
}
|
}
|
||||||
malloc_increase = 0;
|
malloc_increase = 0;
|
||||||
if (freed < free_min) {
|
if (freed < free_min) {
|
||||||
if (!heaps_inc && objspace->heap.longlife_used)
|
|
||||||
objspace->flags.longlife_collection = TRUE;
|
|
||||||
set_heaps_increment(objspace);
|
set_heaps_increment(objspace);
|
||||||
heaps_increment(objspace);
|
heaps_increment(objspace);
|
||||||
}
|
}
|
||||||
|
@ -2015,67 +1899,11 @@ gc_sweep(rb_objspace_t *objspace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
remembered_set_recycle(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
remembered_set_t *top = 0, *rem, *next;
|
|
||||||
|
|
||||||
rem = objspace->remembered_set.ptr;
|
|
||||||
while (rem) {
|
|
||||||
next = rem->next;
|
|
||||||
if (RBASIC(rem->obj)->flags & FL_MARK) {
|
|
||||||
top = rem;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (top) {
|
|
||||||
top->next = next;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
objspace->remembered_set.ptr = next;
|
|
||||||
}
|
|
||||||
rem->obj = 0;
|
|
||||||
rem->next = objspace->remembered_set.freed;
|
|
||||||
objspace->remembered_set.freed = rem;
|
|
||||||
}
|
|
||||||
rem = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gc_sweep_for_longlife(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
RVALUE *p, *pend;
|
|
||||||
size_t i, freed = 0;
|
|
||||||
|
|
||||||
objspace->heap.longlife_freelist = 0;
|
|
||||||
for (i = 0; i < heaps_used; i++) {
|
|
||||||
|
|
||||||
if (heaps[i].lifetime == lifetime_normal) continue;
|
|
||||||
p = heaps[i].slot; pend = p + heaps[i].limit;
|
|
||||||
while (p < pend) {
|
|
||||||
if (!(p->as.basic.flags & FL_MARK)) {
|
|
||||||
if (p->as.basic.flags) {
|
|
||||||
obj_free(objspace, (VALUE)p);
|
|
||||||
}
|
|
||||||
add_freelist(objspace, &objspace->heap.longlife_freelist, p);
|
|
||||||
freed++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remembered_set_recycle(objspace);
|
|
||||||
objspace->flags.longlife_collection = FALSE;
|
|
||||||
objspace->profile.longlife_objects = objspace->profile.longlife_objects - freed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_gc_force_recycle(VALUE p)
|
rb_gc_force_recycle(VALUE p)
|
||||||
{
|
{
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
rb_objspace_t *objspace = &rb_objspace;
|
||||||
if (!(RBASIC(p)->flags & FL_MARK || RBASIC(p)->flags & FL_REMEMBERED_SET)) {
|
add_freelist(objspace, (RVALUE *)p);
|
||||||
add_freelist(objspace, &freelist, (RVALUE *)p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -2264,37 +2092,6 @@ 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
|
|
||||||
rb_gc_mark_remembered_set(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
remembered_set_t *rem;
|
|
||||||
|
|
||||||
rem = objspace->remembered_set.ptr;
|
|
||||||
while (rem) {
|
|
||||||
rb_gc_mark((VALUE)rem->obj);
|
|
||||||
rem = rem->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_mark_longlife_heaps(rb_objspace_t *objspace)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < heaps_used; i++) {
|
|
||||||
RVALUE *p, *pend;
|
|
||||||
|
|
||||||
if (heaps[i].lifetime == lifetime_longlife) {
|
|
||||||
p = heaps[i].slot; pend = p + heaps[i].limit;
|
|
||||||
for (;p < pend; p++) {
|
|
||||||
if (p->as.basic.flags & FL_MARK) {
|
|
||||||
RBASIC(p)->flags &= ~FL_MARK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
garbage_collect(rb_objspace_t *objspace)
|
garbage_collect(rb_objspace_t *objspace)
|
||||||
{
|
{
|
||||||
|
@ -2326,13 +2123,6 @@ garbage_collect(rb_objspace_t *objspace)
|
||||||
|
|
||||||
init_mark_stack(objspace);
|
init_mark_stack(objspace);
|
||||||
|
|
||||||
if (objspace->flags.longlife_collection) {
|
|
||||||
clear_mark_longlife_heaps(objspace);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_gc_mark_remembered_set(objspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
|
th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
|
||||||
|
|
||||||
if (finalizer_table) {
|
if (finalizer_table) {
|
||||||
|
@ -2371,9 +2161,6 @@ garbage_collect(rb_objspace_t *objspace)
|
||||||
GC_PROF_MARK_TIMER_STOP;
|
GC_PROF_MARK_TIMER_STOP;
|
||||||
|
|
||||||
GC_PROF_SWEEP_TIMER_START;
|
GC_PROF_SWEEP_TIMER_START;
|
||||||
if (objspace->flags.longlife_collection) {
|
|
||||||
gc_sweep_for_longlife(objspace);
|
|
||||||
}
|
|
||||||
gc_sweep(objspace);
|
gc_sweep(objspace);
|
||||||
GC_PROF_SWEEP_TIMER_STOP;
|
GC_PROF_SWEEP_TIMER_STOP;
|
||||||
|
|
||||||
|
@ -2423,10 +2210,6 @@ rb_gc_mark_machine_stack(rb_thread_t *th)
|
||||||
VALUE
|
VALUE
|
||||||
rb_gc_start(void)
|
rb_gc_start(void)
|
||||||
{
|
{
|
||||||
rb_objspace_t *objspace = &rb_objspace;
|
|
||||||
if (objspace->heap.longlife_used) {
|
|
||||||
objspace->flags.longlife_collection = TRUE;
|
|
||||||
}
|
|
||||||
rb_gc();
|
rb_gc();
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
@ -3184,13 +2967,11 @@ gc_profile_record_get(void)
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), rb_uint2inum(objspace->profile.record[i].heap_total_size));
|
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), rb_uint2inum(objspace->profile.record[i].heap_total_size));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_total_objects));
|
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_total_objects));
|
||||||
#if GC_PROFILE_MORE_DETAIL
|
#if GC_PROFILE_MORE_DETAIL
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("LONGLIFE_COLLECTION")), objspace->profile.record[i].longlife_collection);
|
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(objspace->profile.record[i].gc_mark_time));
|
rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(objspace->profile.record[i].gc_mark_time));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(objspace->profile.record[i].gc_sweep_time));
|
rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(objspace->profile.record[i].gc_sweep_time));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), rb_uint2inum(objspace->profile.record[i].allocate_increase));
|
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), rb_uint2inum(objspace->profile.record[i].allocate_increase));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), rb_uint2inum(objspace->profile.record[i].allocate_limit));
|
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), rb_uint2inum(objspace->profile.record[i].allocate_limit));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SLOTS")), rb_uint2inum(objspace->profile.record[i].heap_use_slots));
|
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SLOTS")), rb_uint2inum(objspace->profile.record[i].heap_use_slots));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LONGLIFE_USE_SLOTS")), rb_uint2inum(objspace->profile.record[i].heap_longlife_use_slots));
|
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_live_objects));
|
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_live_objects));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_free_objects));
|
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), rb_uint2inum(objspace->profile.record[i].heap_free_objects));
|
||||||
rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), objspace->profile.record[i].have_finalize);
|
rb_hash_aset(prof, ID2SYM(rb_intern("HAVE_FINALIZE")), objspace->profile.record[i].have_finalize);
|
||||||
|
@ -3232,25 +3013,21 @@ gc_profile_result(void)
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SIZE")))),
|
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SIZE")))),
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")))),
|
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")))),
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")))),
|
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")))),
|
||||||
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_TIME"))))*1000
|
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_TIME"))))*1000);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#if GC_PROFILE_MORE_DETAIL
|
#if GC_PROFILE_MORE_DETAIL
|
||||||
rb_str_cat2(result, "\n\n");
|
rb_str_cat2(result, "\n\n");
|
||||||
rb_str_cat2(result, "More detail.\n");
|
rb_str_cat2(result, "More detail.\n");
|
||||||
rb_str_cat2(result, "Index Allocate Increase Allocate Limit Use Slot Longlife Slot Have Finalize Collection Mark Time(ms) Sweep Time(ms)\n");
|
rb_str_cat2(result, "Index Allocate Increase Allocate Limit Use Slot Have Finalize Mark Time(ms) Sweep Time(ms)\n");
|
||||||
for (i = 0; i < (int)RARRAY_LEN(record); i++) {
|
for (i = 0; i < (int)RARRAY_LEN(record); i++) {
|
||||||
VALUE r = RARRAY_PTR(record)[i];
|
VALUE r = RARRAY_PTR(record)[i];
|
||||||
rb_str_catf(result, "%5d %17d %17d %9d %14d %14s %11s %25.20f %25.20f\n",
|
rb_str_catf(result, "%5d %17d %17d %9d %14s %25.20f %25.20f\n",
|
||||||
i+1, NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("ALLOCATE_INCREASE")))),
|
i+1, NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("ALLOCATE_INCREASE")))),
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("ALLOCATE_LIMIT")))),
|
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("ALLOCATE_LIMIT")))),
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SLOTS")))),
|
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SLOTS")))),
|
||||||
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_LONGLIFE_USE_SLOTS")))),
|
|
||||||
rb_hash_aref(r, ID2SYM(rb_intern("HAVE_FINALIZE")))? "true" : "false",
|
rb_hash_aref(r, ID2SYM(rb_intern("HAVE_FINALIZE")))? "true" : "false",
|
||||||
rb_hash_aref(r, ID2SYM(rb_intern("LONGLIFE_COLLECTION")))? "longlife" : "normal",
|
|
||||||
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_MARK_TIME"))))*1000,
|
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_MARK_TIME"))))*1000,
|
||||||
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_SWEEP_TIME"))))*1000
|
NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_SWEEP_TIME"))))*1000);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,7 +370,6 @@ void rb_gc_mark_maybe(VALUE);
|
||||||
void rb_gc_mark(VALUE);
|
void rb_gc_mark(VALUE);
|
||||||
void rb_gc_force_recycle(VALUE);
|
void rb_gc_force_recycle(VALUE);
|
||||||
void rb_gc(void);
|
void rb_gc(void);
|
||||||
VALUE rb_gc_write_barrier(VALUE);
|
|
||||||
void rb_gc_copy_finalizer(VALUE,VALUE);
|
void rb_gc_copy_finalizer(VALUE,VALUE);
|
||||||
void rb_gc_finalize_deferred(void);
|
void rb_gc_finalize_deferred(void);
|
||||||
void rb_gc_call_finalizer_at_exit(void);
|
void rb_gc_call_finalizer_at_exit(void);
|
||||||
|
|
|
@ -873,7 +873,7 @@ struct RBignum {
|
||||||
|
|
||||||
#define FL_SINGLETON FL_USER0
|
#define FL_SINGLETON FL_USER0
|
||||||
#define FL_MARK (((VALUE)1)<<5)
|
#define FL_MARK (((VALUE)1)<<5)
|
||||||
#define FL_REMEMBERED_SET (((VALUE)1)<<6)
|
#define FL_RESERVED (((VALUE)1)<<6) /* will be used in the future GC */
|
||||||
#define FL_FINALIZE (((VALUE)1)<<7)
|
#define FL_FINALIZE (((VALUE)1)<<7)
|
||||||
#define FL_TAINT (((VALUE)1)<<8)
|
#define FL_TAINT (((VALUE)1)<<8)
|
||||||
#define FL_UNTRUSTED (((VALUE)1)<<9)
|
#define FL_UNTRUSTED (((VALUE)1)<<9)
|
||||||
|
|
8
iseq.c
8
iseq.c
|
@ -180,12 +180,12 @@ set_relation(rb_iseq_t *iseq, const VALUE parent)
|
||||||
/* set class nest stack */
|
/* set class nest stack */
|
||||||
if (type == ISEQ_TYPE_TOP) {
|
if (type == ISEQ_TYPE_TOP) {
|
||||||
/* toplevel is private */
|
/* toplevel is private */
|
||||||
iseq->cref_stack = NEW_NODE_LONGLIFE(NODE_BLOCK, th->top_wrapper ? th->top_wrapper : rb_cObject, 0, 0);
|
iseq->cref_stack = NEW_BLOCK(th->top_wrapper ? th->top_wrapper : rb_cObject);
|
||||||
iseq->cref_stack->nd_file = 0;
|
iseq->cref_stack->nd_file = 0;
|
||||||
iseq->cref_stack->nd_visi = NOEX_PRIVATE;
|
iseq->cref_stack->nd_visi = NOEX_PRIVATE;
|
||||||
}
|
}
|
||||||
else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
|
else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
|
||||||
iseq->cref_stack = NEW_NODE_LONGLIFE(NODE_BLOCK,0,0,0); /* place holder */
|
iseq->cref_stack = NEW_BLOCK(0); /* place holder */
|
||||||
iseq->cref_stack->nd_file = 0;
|
iseq->cref_stack->nd_file = 0;
|
||||||
}
|
}
|
||||||
else if (RTEST(parent)) {
|
else if (RTEST(parent)) {
|
||||||
|
@ -1334,9 +1334,9 @@ rb_iseq_clone(VALUE iseqval, VALUE newcbase)
|
||||||
iseq1->orig = iseqval;
|
iseq1->orig = iseqval;
|
||||||
}
|
}
|
||||||
if (newcbase) {
|
if (newcbase) {
|
||||||
iseq1->cref_stack = NEW_NODE_LONGLIFE(NODE_BLOCK, newcbase, 0, 0);
|
iseq1->cref_stack = NEW_BLOCK(newcbase);
|
||||||
if (iseq0->cref_stack->nd_next) {
|
if (iseq0->cref_stack->nd_next) {
|
||||||
iseq1->cref_stack->nd_next = (NODE *)rb_gc_write_barrier((VALUE)iseq0->cref_stack->nd_next);
|
iseq1->cref_stack->nd_next = iseq0->cref_stack->nd_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
node.h
1
node.h
|
@ -346,7 +346,6 @@ typedef struct RNode {
|
||||||
#define nd_visi u2.argc
|
#define nd_visi u2.argc
|
||||||
|
|
||||||
#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
|
#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
|
||||||
#define NEW_NODE_LONGLIFE(t,a0,a1,a2) rb_node_newnode_longlife((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
|
|
||||||
|
|
||||||
#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d))
|
#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d))
|
||||||
#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d))
|
#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d))
|
||||||
|
|
|
@ -1058,12 +1058,12 @@ static NODE *
|
||||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
||||||
NODE *cref = NEW_NODE_LONGLIFE(NODE_BLOCK, klass, 0, 0);
|
NODE *cref = NEW_BLOCK(klass);
|
||||||
cref->nd_file = 0;
|
cref->nd_file = 0;
|
||||||
cref->nd_visi = noex;
|
cref->nd_visi = noex;
|
||||||
|
|
||||||
if (cfp) {
|
if (cfp) {
|
||||||
cref->nd_next = (NODE *)rb_gc_write_barrier((VALUE)vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp));
|
cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cref;
|
return cref;
|
||||||
|
|
|
@ -154,9 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
|
||||||
|
|
||||||
#define COPY_CREF(c1, c2) do { \
|
#define COPY_CREF(c1, c2) do { \
|
||||||
NODE *__tmp_c2 = (c2); \
|
NODE *__tmp_c2 = (c2); \
|
||||||
c1->nd_clss = rb_gc_write_barrier((VALUE)__tmp_c2->nd_clss);\
|
c1->nd_clss = __tmp_c2->nd_clss; \
|
||||||
c1->nd_visi = __tmp_c2->nd_visi;\
|
c1->nd_visi = __tmp_c2->nd_visi;\
|
||||||
c1->nd_next = (NODE *)rb_gc_write_barrier((VALUE)__tmp_c2->nd_next);\
|
c1->nd_next = __tmp_c2->nd_next; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \
|
#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \
|
||||||
|
|
Загрузка…
Ссылка в новой задаче