* gc.c (heaps_header/heaps_slot): embed bitmaps into heaps_slot.

no need to maintain allocation/free bitmaps.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2013-06-21 01:26:50 +00:00
parent 3cef99564b
commit 7986e98394
2 changed files with 58 additions and 98 deletions

View File

@ -1,3 +1,8 @@
Fri Jun 21 10:21:44 2013 Koichi Sasada <ko1@atdot.net>
* gc.c (heaps_header/heaps_slot): embed bitmaps into heaps_slot.
no need to maintain allocation/free bitmaps.
Fri Jun 21 09:22:16 2013 Koichi Sasada <ko1@atdot.net> Fri Jun 21 09:22:16 2013 Koichi Sasada <ko1@atdot.net>
* gc.c (slot_sweep_body): add counters at a time. * gc.c (slot_sweep_body): add counters at a time.

151
gc.c
View File

@ -126,7 +126,7 @@ void rb_gcdebug_print_obj_condition(VALUE obj);
* 3: show all references * 3: show all references
*/ */
#ifndef RGENGC_CHECK_MODE #ifndef RGENGC_CHECK_MODE
#define RGENGC_CHECK_MODE 0 #define RGENGC_CHECK_MODE 2
#endif #endif
/* RGENGC_PROFILE /* RGENGC_PROFILE
@ -253,30 +253,13 @@ enum {
BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT ) BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
}; };
struct heaps_slot {
struct heaps_header *header;
RVALUE *freelist;
struct heaps_slot *next;
struct heaps_slot *prev;
struct heaps_slot *free_next;
};
struct heaps_header { struct heaps_header {
struct heaps_slot *base; struct heaps_slot *base;
bits_t *mark_bits;
#if USE_RGENGC
bits_t *rememberset_bits;
bits_t *oldgen_bits;
#endif
RVALUE *start; RVALUE *start;
RVALUE *end; RVALUE *end;
size_t limit; size_t limit;
}; };
struct heaps_free_bitmap {
struct heaps_free_bitmap *next;
};
struct gc_list { struct gc_list {
VALUE *varptr; VALUE *varptr;
struct gc_list *next; struct gc_list *next;
@ -316,7 +299,6 @@ typedef struct rb_objspace {
struct heaps_header **sorted; struct heaps_header **sorted;
size_t length; size_t length;
size_t used; size_t used;
struct heaps_free_bitmap *free_bitmap;
RVALUE *range[2]; RVALUE *range[2];
struct heaps_header *freed; struct heaps_header *freed;
size_t free_num; size_t free_num;
@ -421,20 +403,34 @@ enum {
HEAP_BITMAP_PLANES = USE_RGENGC ? 3 : 1 /* RGENGC: mark bits, rememberset bits and oldgen bits */ HEAP_BITMAP_PLANES = USE_RGENGC ? 3 : 1 /* RGENGC: mark bits, rememberset bits and oldgen bits */
}; };
#define HEAP_HEADER(p) ((struct heaps_header *)(p)) struct heaps_slot {
#define GET_HEAP_HEADER(x) (HEAP_HEADER((bits_t)(x) & ~(HEAP_ALIGN_MASK))) struct heaps_header *header;
#define GET_HEAP_SLOT(x) (GET_HEAP_HEADER(x)->base) RVALUE *freelist;
#define GET_HEAP_MARK_BITS(x) (GET_HEAP_HEADER(x)->mark_bits) struct heaps_slot *next;
#define GET_HEAP_REMEMBERSET_BITS(x) (GET_HEAP_HEADER(x)->rememberset_bits) struct heaps_slot *prev;
#define GET_HEAP_OLDGEN_BITS(x) (GET_HEAP_HEADER(x)->oldgen_bits) struct heaps_slot *free_next;
#define NUM_IN_SLOT(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE))
#define BITMAP_INDEX(p) (NUM_IN_SLOT(p) / BITS_BITLENGTH ) bits_t mark_bits[HEAP_BITMAP_LIMIT];
#define BITMAP_OFFSET(p) (NUM_IN_SLOT(p) & (BITS_BITLENGTH-1)) #if USE_RGENGC
#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p)) bits_t rememberset_bits[HEAP_BITMAP_LIMIT];
bits_t oldgen_bits[HEAP_BITMAP_LIMIT];
#endif
};
#define HEAP_HEADER(p) ((struct heaps_header *)(p))
#define GET_HEAP_HEADER(x) (HEAP_HEADER((bits_t)(x) & ~(HEAP_ALIGN_MASK)))
#define GET_HEAP_SLOT(x) (GET_HEAP_HEADER(x)->base)
#define GET_HEAP_MARK_BITS(x) (&GET_HEAP_SLOT(x)->mark_bits[0])
#define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_SLOT(x)->rememberset_bits[0])
#define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_SLOT(x)->oldgen_bits[0])
#define NUM_IN_SLOT(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE))
#define BITMAP_INDEX(p) (NUM_IN_SLOT(p) / BITS_BITLENGTH )
#define BITMAP_OFFSET(p) (NUM_IN_SLOT(p) & (BITS_BITLENGTH-1))
#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
/* Bitmap Operations */ /* Bitmap Operations */
#define MARKED_IN_BITMAP(bits, p) (bits[BITMAP_INDEX(p)] & BITMAP_BIT(p)) #define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p))
#define MARK_IN_BITMAP(bits, p) (bits[BITMAP_INDEX(p)] = bits[BITMAP_INDEX(p)] | BITMAP_BIT(p)) #define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p))
#define CLEAR_IN_BITMAP(bits, p) (bits[BITMAP_INDEX(p)] = bits[BITMAP_INDEX(p)] & ~BITMAP_BIT(p)) #define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p))
/* Aliases */ /* Aliases */
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
@ -647,21 +643,9 @@ rb_objspace_free(rb_objspace_t *objspace)
xfree(list); xfree(list);
} }
} }
if (objspace->heap.free_bitmap) {
struct heaps_free_bitmap *list, *next;
for (list = objspace->heap.free_bitmap; list; list = next) {
next = list->next;
free(list);
}
}
if (objspace->heap.sorted) { if (objspace->heap.sorted) {
size_t i; size_t i;
for (i = 0; i < heaps_used; ++i) { for (i = 0; i < heaps_used; ++i) {
free(objspace->heap.sorted[i]->mark_bits);
#if USE_RGENGC
free(objspace->heap.sorted[i]->rememberset_bits);
free(objspace->heap.sorted[i]->oldgen_bits);
#endif
aligned_free(objspace->heap.sorted[i]); aligned_free(objspace->heap.sorted[i]);
} }
free(objspace->heap.sorted); free(objspace->heap.sorted);
@ -683,8 +667,7 @@ static void
allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
{ {
struct heaps_header **p; struct heaps_header **p;
struct heaps_free_bitmap *bits; size_t size, add;
size_t size, add, i;
size = next_heaps_length*sizeof(struct heaps_header *); size = next_heaps_length*sizeof(struct heaps_header *);
add = next_heaps_length - heaps_used; add = next_heaps_length - heaps_used;
@ -701,17 +684,6 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
during_gc = 0; during_gc = 0;
rb_memerror(); rb_memerror();
} }
for (i = 0; i < add * HEAP_BITMAP_PLANES; i++) {
bits = (struct heaps_free_bitmap *)malloc(HEAP_BITMAP_SIZE);
if (bits == 0) {
during_gc = 0;
rb_memerror();
return;
}
bits->next = objspace->heap.free_bitmap;
objspace->heap.free_bitmap = bits;
}
} }
static void static void
@ -728,23 +700,6 @@ unlink_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot)
slot->free_next = NULL; slot->free_next = NULL;
} }
static bits_t *
alloc_bitmap(rb_objspace_t *objspace)
{
bits_t *bits = (bits_t *)objspace->heap.free_bitmap;
assert(objspace->heap.free_bitmap != NULL);
objspace->heap.free_bitmap = objspace->heap.free_bitmap->next;
memset(bits, 0, HEAP_BITMAP_SIZE);
return bits;
}
static void
free_bitmap(rb_objspace_t *objspace, bits_t *bits)
{
((struct heaps_free_bitmap *)(bits))->next = objspace->heap.free_bitmap;
objspace->heap.free_bitmap = (struct heaps_free_bitmap *)bits;
}
static void static void
assign_heap_slot(rb_objspace_t *objspace) assign_heap_slot(rb_objspace_t *objspace)
{ {
@ -754,11 +709,14 @@ assign_heap_slot(rb_objspace_t *objspace)
size_t objs; size_t objs;
objs = HEAP_OBJ_LIMIT; objs = HEAP_OBJ_LIMIT;
p = (RVALUE*)aligned_malloc(HEAP_ALIGN, HEAP_SIZE); p = (RVALUE*)aligned_malloc(HEAP_ALIGN, HEAP_SIZE);
if (p == 0) { if (p == 0) {
during_gc = 0; during_gc = 0;
rb_memerror(); rb_memerror();
} }
/* assign heaps_slot entry */
slot = (struct heaps_slot *)malloc(sizeof(struct heaps_slot)); slot = (struct heaps_slot *)malloc(sizeof(struct heaps_slot));
if (slot == 0) { if (slot == 0) {
aligned_free(p); aligned_free(p);
@ -771,6 +729,7 @@ assign_heap_slot(rb_objspace_t *objspace)
if (heaps) heaps->prev = slot; if (heaps) heaps->prev = slot;
heaps = slot; heaps = slot;
/* adjust objs (object number available in this slot) */
membase = p; membase = p;
p = (RVALUE*)((VALUE)p + sizeof(struct heaps_header)); p = (RVALUE*)((VALUE)p + sizeof(struct heaps_header));
if ((VALUE)p % sizeof(RVALUE) != 0) { if ((VALUE)p % sizeof(RVALUE) != 0) {
@ -778,6 +737,7 @@ assign_heap_slot(rb_objspace_t *objspace)
objs = (HEAP_SIZE - (size_t)((VALUE)p - (VALUE)membase))/sizeof(RVALUE); objs = (HEAP_SIZE - (size_t)((VALUE)p - (VALUE)membase))/sizeof(RVALUE);
} }
/* setup objspace->heap.sorted */
lo = 0; lo = 0;
hi = heaps_used; hi = heaps_used;
while (lo < hi) { while (lo < hi) {
@ -797,17 +757,14 @@ assign_heap_slot(rb_objspace_t *objspace)
if (hi < heaps_used) { if (hi < heaps_used) {
MEMMOVE(&objspace->heap.sorted[hi+1], &objspace->heap.sorted[hi], struct heaps_header*, heaps_used - hi); MEMMOVE(&objspace->heap.sorted[hi+1], &objspace->heap.sorted[hi], struct heaps_header*, heaps_used - hi);
} }
/* setup header */
heaps->header = (struct heaps_header *)membase; heaps->header = (struct heaps_header *)membase;
objspace->heap.sorted[hi] = heaps->header; objspace->heap.sorted[hi] = heaps->header;
objspace->heap.sorted[hi]->start = p; objspace->heap.sorted[hi]->start = p;
objspace->heap.sorted[hi]->end = (p + objs); objspace->heap.sorted[hi]->end = (p + objs);
objspace->heap.sorted[hi]->base = heaps; objspace->heap.sorted[hi]->base = heaps;
objspace->heap.sorted[hi]->limit = objs; objspace->heap.sorted[hi]->limit = objs;
objspace->heap.sorted[hi]->mark_bits = alloc_bitmap(objspace);
#if USE_RGENGC
objspace->heap.sorted[hi]->rememberset_bits = alloc_bitmap(objspace);
objspace->heap.sorted[hi]->oldgen_bits = alloc_bitmap(objspace);
#endif
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;
@ -820,6 +777,7 @@ assign_heap_slot(rb_objspace_t *objspace)
heaps->freelist = p; heaps->freelist = p;
p++; p++;
} }
link_free_heap_slot(objspace, heaps); link_free_heap_slot(objspace, heaps);
} }
@ -1153,12 +1111,6 @@ free_unused_heaps(rb_objspace_t *objspace)
for (i = j = 1; j < heaps_used; i++) { for (i = j = 1; j < heaps_used; i++) {
if (objspace->heap.sorted[i]->limit == 0) { if (objspace->heap.sorted[i]->limit == 0) {
struct heaps_header* h = objspace->heap.sorted[i];
free_bitmap(objspace, h->mark_bits);
#if USE_RGENGC
free_bitmap(objspace, h->rememberset_bits);
free_bitmap(objspace, h->oldgen_bits);
#endif
if (!last) { if (!last) {
last = objspace->heap.sorted[i]; last = objspace->heap.sorted[i];
} }
@ -2184,13 +2136,13 @@ lazy_sweep_enable(void)
static void static void
gc_clear_slot_bits(struct heaps_slot *slot) gc_clear_slot_bits(struct heaps_slot *slot)
{ {
memset(slot->header->mark_bits, 0, HEAP_BITMAP_SIZE); memset(&slot->mark_bits[0], 0, HEAP_BITMAP_SIZE);
} }
#else #else
static void static void
gc_setup_mark_bits(struct heaps_slot *slot) gc_setup_mark_bits(struct heaps_slot *slot)
{ {
memcpy(slot->header->mark_bits, slot->header->oldgen_bits, HEAP_BITMAP_SIZE); memcpy(&slot->mark_bits[0], &slot->oldgen_bits[0], HEAP_BITMAP_SIZE);
} }
#endif #endif
@ -3552,9 +3504,11 @@ gc_store_bitmaps(rb_objspace_t *objspace)
if (stored_bitmaps == 0) rb_bug("gc_store_bitmaps: not enough memory to test.\n"); if (stored_bitmaps == 0) rb_bug("gc_store_bitmaps: not enough memory to test.\n");
for (i=0; i<heaps_used; i++) { for (i=0; i<heaps_used; i++) {
memcpy(&stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], objspace->heap.sorted[i]->mark_bits, HEAP_BITMAP_SIZE); struct heaps_slot *slot = objspace->heap.sorted[i]->base;
memcpy(&stored_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], objspace->heap.sorted[i]->rememberset_bits, HEAP_BITMAP_SIZE);
memcpy(&stored_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], objspace->heap.sorted[i]->oldgen_bits, HEAP_BITMAP_SIZE); memcpy(&stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], &slot->mark_bits[0], HEAP_BITMAP_SIZE);
memcpy(&stored_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], &slot->rememberset_bits[0], HEAP_BITMAP_SIZE);
memcpy(&stored_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], &slot->oldgen_bits[0], HEAP_BITMAP_SIZE);
} }
return stored_bitmaps; return stored_bitmaps;
@ -3566,15 +3520,15 @@ gc_restore_bitmaps(rb_objspace_t *objspace, bits_t *stored_bitmaps)
size_t i; size_t i;
for (i=0; i<heaps_used; i++) { for (i=0; i<heaps_used; i++) {
bits_t *oldgen_bits = objspace->heap.sorted[i]->oldgen_bits; struct heaps_slot *slot = objspace->heap.sorted[i]->base;
bits_t *oldgen_bits = &slot->oldgen_bits[0];
RVALUE *p = objspace->heap.sorted[i]->start; RVALUE *p = objspace->heap.sorted[i]->start;
RVALUE *pend = p + objspace->heap.sorted[i]->limit; RVALUE *pend = p + objspace->heap.sorted[i]->limit;
/* restore bitmaps */ /* restore bitmaps */
memcpy(objspace->heap.sorted[i]->mark_bits, &stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&slot->mark_bits[0], &stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
memcpy(objspace->heap.sorted[i]->rememberset_bits, &stored_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&slot->rememberset_bits[0], &stored_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
memcpy(objspace->heap.sorted[i]->oldgen_bits, &stored_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&slot->oldgen_bits[0], &stored_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
/* resotre oldgen bits */ /* resotre oldgen bits */
while (p < pend) { while (p < pend) {
@ -3606,7 +3560,7 @@ gc_marks_test(rb_objspace_t *objspace, rb_thread_t *th, bits_t *before_stored_bi
/* check */ /* check */
for (i=0; i<heaps_used; i++) { for (i=0; i<heaps_used; i++) {
bits_t *minor_mark_bits = &stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT]; bits_t *minor_mark_bits = &stored_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT];
bits_t *major_mark_bits = objspace->heap.sorted[i]->mark_bits; bits_t *major_mark_bits = objspace->heap.sorted[i]->base->mark_bits;
RVALUE *p = objspace->heap.sorted[i]->start; RVALUE *p = objspace->heap.sorted[i]->start;
RVALUE *pend = p + objspace->heap.sorted[i]->limit; RVALUE *pend = p + objspace->heap.sorted[i]->limit;
@ -3805,8 +3759,9 @@ rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace)
size_t i; size_t i;
for (i=0; i<heaps_used; i++) { for (i=0; i<heaps_used; i++) {
memset(objspace->heap.sorted[i]->mark_bits, 0, HEAP_BITMAP_SIZE); struct heaps_slot *slot = objspace->heap.sorted[i]->base;
memset(objspace->heap.sorted[i]->rememberset_bits, 0, HEAP_BITMAP_SIZE); memset(&slot->mark_bits[0], 0, HEAP_BITMAP_SIZE);
memset(&slot->rememberset_bits[0], 0, HEAP_BITMAP_SIZE);
} }
} }