1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* gc.c: change terminology of heap.

Change "slot" to "page". "Slot" is a space of RVALUE.
  1. "Heap" consists of a set of "heap_page"s (pages).
  2. Each "heap_page" has "heap_page_body".
  3. "heap_page_body" has RVALUE (a.k.a. "slot") spaces.
  4. "sorted" is a sorted array of "heap_page"s, sorted
  by address of heap_page_body (for "is_pointer_to_heap").
  See https://bugs.ruby-lang.org/attachments/4008/data-heap_structure.png.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43350 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2013-10-18 06:33:36 +00:00
parent 54b9ec2d81
commit b443d83a77
2 changed files with 233 additions and 221 deletions

View file

@ -1,3 +1,15 @@
Fri Oct 18 15:23:34 2013 Koichi Sasada <ko1@atdot.net>
* gc.c: change terminology of heap.
Change "slot" to "page". "Slot" is a space of RVALUE.
1. "Heap" consists of a set of "heap_page"s (pages).
2. Each "heap_page" has "heap_page_body".
3. "heap_page_body" has RVALUE (a.k.a. "slot") spaces.
4. "sorted" is a sorted array of "heap_page"s, sorted
by address of heap_page_body (for "is_pointer_to_heap").
See https://bugs.ruby-lang.org/attachments/4008/data-heap_structure.png.
Fri Oct 18 09:40:43 2013 Eric Hodel <drbrain@segment7.net> Fri Oct 18 09:40:43 2013 Eric Hodel <drbrain@segment7.net>
* lib/rubygems: Update to RubyGems master cee6788. Changes: * lib/rubygems: Update to RubyGems master cee6788. Changes:

442
gc.c
View file

@ -214,7 +214,7 @@ typedef struct gc_profile_record {
double gc_mark_time; double gc_mark_time;
double gc_sweep_time; double gc_sweep_time;
size_t heap_use_slots; size_t heap_use_pages;
size_t heap_live_objects; size_t heap_live_objects;
size_t heap_free_objects; size_t heap_free_objects;
@ -287,12 +287,12 @@ enum {
BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT ) BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
}; };
struct heap_slot_header { struct heap_page_header {
struct heap_slot *slot; struct heap_page *page;
}; };
struct heap_slot_body { struct heap_page_body {
struct heap_slot_header header; struct heap_page_header header;
/* char gap[]; */ /* char gap[]; */
/* RVALUE values[]; */ /* RVALUE values[]; */
}; };
@ -329,11 +329,11 @@ typedef struct rb_objspace {
} malloc_params; } malloc_params;
struct { struct {
size_t increment; size_t increment;
struct heap_slot *slots; struct heap_page *pages;
struct heap_slot *sweep_slots; struct heap_page *sweep_pages;
struct heap_slot *free_slots; struct heap_page *free_pages;
struct heap_slot *using_slot; struct heap_page *using_page;
struct heap_slot **sorted; struct heap_page **sorted;
size_t length; size_t length;
size_t used; size_t used;
size_t limit; size_t limit;
@ -439,21 +439,21 @@ enum {
HEAP_ALIGN_MASK = (~(~0UL << HEAP_ALIGN_LOG)), HEAP_ALIGN_MASK = (~(~0UL << HEAP_ALIGN_LOG)),
REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5), REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5),
HEAP_SIZE = (HEAP_ALIGN - REQUIRED_SIZE_BY_MALLOC), HEAP_SIZE = (HEAP_ALIGN - REQUIRED_SIZE_BY_MALLOC),
HEAP_OBJ_LIMIT = (unsigned int)((HEAP_SIZE - sizeof(struct heap_slot_header))/sizeof(struct RVALUE)), HEAP_OBJ_LIMIT = (unsigned int)((HEAP_SIZE - sizeof(struct heap_page_header))/sizeof(struct RVALUE)),
HEAP_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_SIZE, sizeof(struct RVALUE)), BITS_BITLENGTH), HEAP_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_SIZE, sizeof(struct RVALUE)), BITS_BITLENGTH),
HEAP_BITMAP_SIZE = ( BITS_SIZE * HEAP_BITMAP_LIMIT), HEAP_BITMAP_SIZE = ( BITS_SIZE * HEAP_BITMAP_LIMIT),
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 */
}; };
struct heap_slot { struct heap_page {
struct heap_slot_body *body; struct heap_page_body *body;
RVALUE *start; RVALUE *start;
size_t limit; size_t limit;
RVALUE *freelist; RVALUE *freelist;
struct heap_slot *next; struct heap_page *next;
struct heap_slot *prev; struct heap_page *prev;
struct heap_slot *free_next; struct heap_page *free_next;
bits_t mark_bits[HEAP_BITMAP_LIMIT]; bits_t mark_bits[HEAP_BITMAP_LIMIT];
#if USE_RGENGC #if USE_RGENGC
@ -467,15 +467,15 @@ struct heap_slot {
#endif #endif
}; };
#define GET_SLOT_BODY(x) ((struct heap_slot_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK))) #define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK)))
#define GET_SLOT_HEADER(x) (&GET_SLOT_BODY(x)->header) #define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
#define GET_HEAP_SLOT(x) (GET_SLOT_HEADER(x)->slot) #define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
#define GET_HEAP_MARK_BITS(x) (&GET_HEAP_SLOT(x)->mark_bits[0]) #define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0])
#define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_SLOT(x)->rememberset_bits[0]) #define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_PAGE(x)->rememberset_bits[0])
#define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_SLOT(x)->oldgen_bits[0]) #define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_PAGE(x)->oldgen_bits[0])
#define NUM_IN_SLOT(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE)) #define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_ALIGN_MASK)/sizeof(RVALUE))
#define BITMAP_INDEX(p) (NUM_IN_SLOT(p) / BITS_BITLENGTH ) #define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
#define BITMAP_OFFSET(p) (NUM_IN_SLOT(p) & (BITS_BITLENGTH-1)) #define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p)) #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))
@ -495,7 +495,7 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#define malloc_limit objspace->malloc_params.limit #define malloc_limit objspace->malloc_params.limit
#define malloc_increase objspace->malloc_params.increase #define malloc_increase objspace->malloc_params.increase
#define malloc_allocated_size objspace->malloc_params.allocated_size #define malloc_allocated_size objspace->malloc_params.allocated_size
#define heap_slots objspace->heap.slots #define heap_pages objspace->heap.pages
#define heap_length objspace->heap.length #define heap_length objspace->heap.length
#define heap_used objspace->heap.used #define heap_used objspace->heap.used
#define heap_limit objspace->heap.limit #define heap_limit objspace->heap.limit
@ -519,7 +519,7 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#define initial_free_min initial_params.initial_free_min #define initial_free_min initial_params.initial_free_min
#define initial_growth_factor initial_params.initial_growth_factor #define initial_growth_factor initial_params.initial_growth_factor
#define is_lazy_sweeping(objspace) ((objspace)->heap.sweep_slots != 0) #define is_lazy_sweeping(objspace) ((objspace)->heap.sweep_pages != 0)
#if SIZEOF_LONG == SIZEOF_VOIDP #if SIZEOF_LONG == SIZEOF_VOIDP
# define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG) # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
@ -643,15 +643,15 @@ RVALUE_PROMOTE(VALUE obj)
static inline int static inline int
is_before_sweep(VALUE obj) is_before_sweep(VALUE obj)
{ {
struct heap_slot *slot; struct heap_page *page;
rb_objspace_t *objspace = &rb_objspace; rb_objspace_t *objspace = &rb_objspace;
if (is_lazy_sweeping(objspace)) { if (is_lazy_sweeping(objspace)) {
slot = objspace->heap.sweep_slots; page = objspace->heap.sweep_pages;
while (slot) { while (page) {
if (slot->body == GET_SLOT_BODY(obj)) { if (page->body == GET_PAGE_BODY(obj)) {
return TRUE; return TRUE;
} }
slot = slot->next; page = page->next;
} }
} }
return FALSE; return FALSE;
@ -685,7 +685,7 @@ rb_objspace_alloc(void)
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
static void free_stack_chunks(mark_stack_t *); static void free_stack_chunks(mark_stack_t *);
static void free_heap_slot(rb_objspace_t *objspace, struct heap_slot *slot); static void free_heap_page(rb_objspace_t *objspace, struct heap_page *page);
void void
rb_objspace_free(rb_objspace_t *objspace) rb_objspace_free(rb_objspace_t *objspace)
@ -706,12 +706,12 @@ rb_objspace_free(rb_objspace_t *objspace)
if (objspace->heap.sorted) { if (objspace->heap.sorted) {
size_t i; size_t i;
for (i = 0; i < heap_used; ++i) { for (i = 0; i < heap_used; ++i) {
free_heap_slot(objspace, objspace->heap.sorted[i]); free_heap_page(objspace, objspace->heap.sorted[i]);
} }
free(objspace->heap.sorted); free(objspace->heap.sorted);
heap_used = 0; heap_used = 0;
heap_limit = 0; heap_limit = 0;
heap_slots = 0; heap_pages = 0;
} }
free_stack_chunks(&objspace->mark_stack); free_stack_chunks(&objspace->mark_stack);
free(objspace); free(objspace);
@ -721,17 +721,17 @@ rb_objspace_free(rb_objspace_t *objspace)
static void static void
heap_allocate_sorted_array(rb_objspace_t *objspace, size_t next_heap_length) heap_allocate_sorted_array(rb_objspace_t *objspace, size_t next_heap_length)
{ {
struct heap_slot **p; struct heap_page **p;
size_t size; size_t size;
size = next_heap_length * sizeof(struct heap_slot *); size = next_heap_length * sizeof(struct heap_page *);
if (heap_used > 0) { if (heap_used > 0) {
p = (struct heap_slot **)realloc(objspace->heap.sorted, size); p = (struct heap_page **)realloc(objspace->heap.sorted, size);
if (p) objspace->heap.sorted = p; if (p) objspace->heap.sorted = p;
} }
else { else {
p = objspace->heap.sorted = (struct heap_slot **)malloc(size); p = objspace->heap.sorted = (struct heap_page **)malloc(size);
} }
if (p == 0) { if (p == 0) {
@ -741,61 +741,61 @@ heap_allocate_sorted_array(rb_objspace_t *objspace, size_t next_heap_length)
} }
static inline void static inline void
heap_slot_add_freeobj(rb_objspace_t *objspace, struct heap_slot *slot, VALUE obj) heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
{ {
RVALUE *p = (RVALUE *)obj; RVALUE *p = (RVALUE *)obj;
p->as.free.flags = 0; p->as.free.flags = 0;
p->as.free.next = slot->freelist; p->as.free.next = page->freelist;
slot->freelist = p; page->freelist = p;
rgengc_report(3, objspace, "heap_slot_add_freeobj: %p (%s) is added to freelist\n", p, obj_type_name(obj)); rgengc_report(3, objspace, "heap_page_add_freeobj: %p (%s) is added to freelist\n", p, obj_type_name(obj));
} }
static inline void static inline void
heap_add_freeslot(rb_objspace_t *objspace, struct heap_slot *slot) heap_add_freepage(rb_objspace_t *objspace, struct heap_page *page)
{ {
if (slot->freelist) { if (page->freelist) {
slot->free_next = objspace->heap.free_slots; page->free_next = objspace->heap.free_pages;
objspace->heap.free_slots = slot; objspace->heap.free_pages = page;
} }
} }
static void static void
heap_assign_slot(rb_objspace_t *objspace) heap_assign_page(rb_objspace_t *objspace)
{ {
RVALUE *start, *end, *p; RVALUE *start, *end, *p;
struct heap_slot *slot; struct heap_page *page;
struct heap_slot_body *slot_body = 0; struct heap_page_body *page_body = 0;
size_t hi, lo, mid; size_t hi, lo, mid;
size_t limit = HEAP_OBJ_LIMIT; size_t limit = HEAP_OBJ_LIMIT;
/* assign heap_slot body (contains heap_slot_header and RVALUEs) */ /* assign heap_page body (contains heap_page_header and RVALUEs) */
slot_body = (struct heap_slot_body *)aligned_malloc(HEAP_ALIGN, HEAP_SIZE); page_body = (struct heap_page_body *)aligned_malloc(HEAP_ALIGN, HEAP_SIZE);
if (slot_body == 0) { if (page_body == 0) {
during_gc = 0; during_gc = 0;
rb_memerror(); rb_memerror();
} }
/* assign heap_slot entry */ /* assign heap_page entry */
slot = (struct heap_slot *)malloc(sizeof(struct heap_slot)); page = (struct heap_page *)malloc(sizeof(struct heap_page));
if (slot == 0) { if (page == 0) {
aligned_free(slot_body); aligned_free(page_body);
during_gc = 0; during_gc = 0;
rb_memerror(); rb_memerror();
} }
MEMZERO((void*)slot, struct heap_slot, 1); MEMZERO((void*)page, struct heap_page, 1);
slot->body = slot_body; page->body = page_body;
slot->next = objspace->heap.slots; page->next = objspace->heap.pages;
if (objspace->heap.slots) objspace->heap.slots->prev = slot; if (objspace->heap.pages) objspace->heap.pages->prev = page;
objspace->heap.slots = slot; objspace->heap.pages = page;
/* adjust obj_limit (object number available in this slot) */ /* adjust obj_limit (object number available in this page) */
start = (RVALUE*)((VALUE)slot_body + sizeof(struct heap_slot_header)); start = (RVALUE*)((VALUE)page_body + sizeof(struct heap_page_header));
if ((VALUE)start % sizeof(RVALUE) != 0) { if ((VALUE)start % sizeof(RVALUE) != 0) {
int delta = (int)(sizeof(RVALUE) - ((VALUE)start % sizeof(RVALUE))); int delta = (int)(sizeof(RVALUE) - ((VALUE)start % sizeof(RVALUE)));
start = (RVALUE*)((VALUE)start + delta); start = (RVALUE*)((VALUE)start + delta);
limit = (HEAP_SIZE - (size_t)((VALUE)start - (VALUE)slot_body))/sizeof(RVALUE); limit = (HEAP_SIZE - (size_t)((VALUE)start - (VALUE)page_body))/sizeof(RVALUE);
} }
end = start + limit; end = start + limit;
@ -803,28 +803,28 @@ heap_assign_slot(rb_objspace_t *objspace)
lo = 0; lo = 0;
hi = heap_used; hi = heap_used;
while (lo < hi) { while (lo < hi) {
struct heap_slot *mid_slot; struct heap_page *mid_page;
mid = (lo + hi) / 2; mid = (lo + hi) / 2;
mid_slot = objspace->heap.sorted[mid]; mid_page = objspace->heap.sorted[mid];
if (mid_slot->body < slot_body) { if (mid_page->body < page_body) {
lo = mid + 1; lo = mid + 1;
} }
else if (mid_slot->body > slot_body) { else if (mid_page->body > page_body) {
hi = mid; hi = mid;
} }
else { else {
rb_bug("same heap slot is allocated: %p at %"PRIuVALUE, (void *)slot_body, (VALUE)mid); rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
} }
} }
if (hi < heap_used) { if (hi < heap_used) {
MEMMOVE(&objspace->heap.sorted[hi+1], &objspace->heap.sorted[hi], struct heap_slot_header*, heap_used - hi); MEMMOVE(&objspace->heap.sorted[hi+1], &objspace->heap.sorted[hi], struct heap_page_header*, heap_used - hi);
} }
/* setup slot */ /* setup page */
slot->start = start; page->start = start;
slot->limit = limit; page->limit = limit;
slot_body->header.slot = objspace->heap.sorted[hi] = slot; page_body->header.page = objspace->heap.sorted[hi] = page;
if (lomem == 0 || lomem > start) lomem = start; if (lomem == 0 || lomem > start) lomem = start;
if (himem < end) himem = end; if (himem < end) himem = end;
@ -832,15 +832,15 @@ heap_assign_slot(rb_objspace_t *objspace)
heap_limit += limit; heap_limit += limit;
for (p = start; p != end; p++) { for (p = start; p != end; p++) {
rgengc_report(3, objspace, "assign_heap_slot: %p is added to freelist\n"); rgengc_report(3, objspace, "assign_heap_page: %p is added to freelist\n");
heap_slot_add_freeobj(objspace, slot, (VALUE)p); heap_page_add_freeobj(objspace, page, (VALUE)p);
} }
heap_add_freeslot(objspace, slot); heap_add_freepage(objspace, page);
} }
static void static void
heap_add_slots(rb_objspace_t *objspace, size_t add) heap_add_pages(rb_objspace_t *objspace, size_t add)
{ {
size_t i; size_t i;
size_t next_heap_length; size_t next_heap_length;
@ -853,7 +853,7 @@ heap_add_slots(rb_objspace_t *objspace, size_t add)
} }
for (i = 0; i < add; i++) { for (i = 0; i < add; i++) {
heap_assign_slot(objspace); heap_assign_page(objspace);
} }
heap_inc = 0; heap_inc = 0;
} }
@ -861,7 +861,7 @@ heap_add_slots(rb_objspace_t *objspace, size_t add)
static void static void
heap_init(rb_objspace_t *objspace) heap_init(rb_objspace_t *objspace)
{ {
heap_add_slots(objspace, initial_heap_min_slots / HEAP_OBJ_LIMIT); heap_add_pages(objspace, initial_heap_min_slots / HEAP_OBJ_LIMIT);
init_mark_stack(&objspace->mark_stack); init_mark_stack(&objspace->mark_stack);
#ifdef USE_SIGALTSTACK #ifdef USE_SIGALTSTACK
@ -904,15 +904,15 @@ heap_increment(rb_objspace_t *objspace)
rgengc_report(5, objspace, "heap_increment: heap_inc: %d\n", heap_inc); rgengc_report(5, objspace, "heap_increment: heap_inc: %d\n", heap_inc);
if (heap_inc > 0) { if (heap_inc > 0) {
heap_assign_slot(objspace); heap_assign_page(objspace);
heap_inc--; heap_inc--;
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
static struct heap_slot * static struct heap_page *
heap_prepare_freeslot(rb_objspace_t *objspace) heap_prepare_freepage(rb_objspace_t *objspace)
{ {
if (!GC_ENABLE_LAZY_SWEEP && objspace->flags.dont_lazy_sweep) { if (!GC_ENABLE_LAZY_SWEEP && objspace->flags.dont_lazy_sweep) {
if (heap_increment(objspace) == 0 && if (heap_increment(objspace) == 0 &&
@ -922,7 +922,7 @@ heap_prepare_freeslot(rb_objspace_t *objspace)
goto ok; goto ok;
} }
if (!ready_to_gc(objspace)) return objspace->heap.free_slots; if (!ready_to_gc(objspace)) return objspace->heap.free_pages;
during_gc++; during_gc++;
@ -942,21 +942,21 @@ heap_prepare_freeslot(rb_objspace_t *objspace)
} }
ok: ok:
during_gc = 0; during_gc = 0;
return objspace->heap.free_slots; return objspace->heap.free_pages;
} }
static inline struct heap_slot * static inline struct heap_page *
heap_get_freeslot(rb_objspace_t *objspace) heap_get_freepage(rb_objspace_t *objspace)
{ {
struct heap_slot *slot; struct heap_page *page;
slot = objspace->heap.free_slots; page = objspace->heap.free_pages;
while (slot == NULL) { while (page == NULL) {
slot = heap_prepare_freeslot(objspace); page = heap_prepare_freepage(objspace);
} }
objspace->heap.free_slots = slot->free_next; objspace->heap.free_pages = page->free_next;
return slot; return page;
} }
static inline VALUE static inline VALUE
@ -965,10 +965,10 @@ heap_get_freeobj(rb_objspace_t *objspace)
RVALUE *p = objspace->freelist; RVALUE *p = objspace->freelist;
while (UNLIKELY(p == NULL)) { while (UNLIKELY(p == NULL)) {
struct heap_slot *slot = heap_get_freeslot(objspace); struct heap_page *page = heap_get_freepage(objspace);
objspace->heap.using_slot = slot; objspace->heap.using_page = page;
p = objspace->freelist = slot->freelist; p = objspace->freelist = page->freelist;
slot->freelist = NULL; page->freelist = NULL;
} }
objspace->freelist = p->as.free.next; objspace->freelist = p->as.free.next;
@ -1118,7 +1118,7 @@ static inline int
is_pointer_to_heap(rb_objspace_t *objspace, void *ptr) is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
{ {
register RVALUE *p = RANY(ptr); register RVALUE *p = RANY(ptr);
register struct heap_slot *slot; register struct heap_page *page;
register size_t hi, lo, mid; register size_t hi, lo, mid;
if (p < lomem || p > himem) return FALSE; if (p < lomem || p > himem) return FALSE;
@ -1129,9 +1129,9 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
hi = heap_used; hi = heap_used;
while (lo < hi) { while (lo < hi) {
mid = (lo + hi) / 2; mid = (lo + hi) / 2;
slot = objspace->heap.sorted[mid]; page = objspace->heap.sorted[mid];
if (slot->start <= p) { if (page->start <= p) {
if (p < slot->start + slot->limit) { if (p < page->start + page->limit) {
return TRUE; return TRUE;
} }
lo = mid + 1; lo = mid + 1;
@ -1174,42 +1174,42 @@ rb_free_const_table(st_table *tbl)
} }
static void static void
unlink_heap_slot(rb_objspace_t *objspace, struct heap_slot *slot) unlink_heap_page(rb_objspace_t *objspace, struct heap_page *page)
{ {
if (slot->prev) if (page->prev)
slot->prev->next = slot->next; page->prev->next = page->next;
if (slot->next) if (page->next)
slot->next->prev = slot->prev; page->next->prev = page->prev;
if (heap_slots == slot) if (heap_pages == page)
heap_slots = slot->next; heap_pages = page->next;
if (objspace->heap.sweep_slots == slot) if (objspace->heap.sweep_pages == page)
objspace->heap.sweep_slots = slot->next; objspace->heap.sweep_pages = page->next;
slot->prev = NULL; page->prev = NULL;
slot->next = NULL; page->next = NULL;
} }
static void static void
free_heap_slot(rb_objspace_t *objspace, struct heap_slot *slot) free_heap_page(rb_objspace_t *objspace, struct heap_page *page)
{ {
aligned_free(slot->body); aligned_free(page->body);
free(slot); free(page);
} }
static void static void
free_unused_slots(rb_objspace_t *objspace) free_unused_pages(rb_objspace_t *objspace)
{ {
size_t i, j; size_t i, j;
for (i = j = 1; j < heap_used; i++) { for (i = j = 1; j < heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
if (slot->limit == 0) { if (page->limit == 0) {
free_heap_slot(objspace, slot); free_heap_page(objspace, page);
heap_used--; heap_used--;
} }
else { else {
if (i != j) { if (i != j) {
objspace->heap.sorted[j] = slot; objspace->heap.sorted[j] = page;
} }
j++; j++;
} }
@ -1409,8 +1409,8 @@ static VALUE
objspace_each_objects(VALUE arg) objspace_each_objects(VALUE arg)
{ {
size_t i; size_t i;
struct heap_slot_body *last_body = 0; struct heap_page_body *last_body = 0;
struct heap_slot *slot; struct heap_page *page;
RVALUE *pstart, *pend; RVALUE *pstart, *pend;
rb_objspace_t *objspace = &rb_objspace; rb_objspace_t *objspace = &rb_objspace;
struct each_obj_args *args = (struct each_obj_args *)arg; struct each_obj_args *args = (struct each_obj_args *)arg;
@ -1421,11 +1421,11 @@ objspace_each_objects(VALUE arg)
while (i < heap_used && objspace->heap.sorted[i]->body <= last_body) i++; while (i < heap_used && objspace->heap.sorted[i]->body <= last_body) i++;
if (heap_used <= i) break; if (heap_used <= i) break;
slot = objspace->heap.sorted[i]; page = objspace->heap.sorted[i];
last_body = slot->body; last_body = page->body;
pstart = slot->start; pstart = page->start;
pend = pstart + slot->limit; pend = pstart + page->limit;
if ((*args->callback)(pstart, pend, sizeof(RVALUE), args->data)) { if ((*args->callback)(pstart, pend, sizeof(RVALUE), args->data)) {
break; break;
@ -1441,10 +1441,10 @@ objspace_each_objects(VALUE arg)
* To be frank, you should not use it. Or you need to read the * To be frank, you should not use it. Or you need to read the
* source code of this function and understand what this function does. * source code of this function and understand what this function does.
* *
* 'callback' will be called several times (the number of heap slot, * 'callback' will be called several times (the number of heap page,
* at current implementation) with: * at current implementation) with:
* vstart: a pointer to the first living object of the heap_slot. * vstart: a pointer to the first living object of the heap_page.
* vend: a pointer to next to the valid heap_slot area. * vend: a pointer to next to the valid heap_page area.
* stride: a distance to next VALUE. * stride: a distance to next VALUE.
* *
* If callback() returns non-zero, the iteration will be stopped. * If callback() returns non-zero, the iteration will be stopped.
@ -1461,10 +1461,10 @@ objspace_each_objects(VALUE arg)
* return 0; // continue to iteration * return 0; // continue to iteration
* } * }
* *
* Note: 'vstart' is not a top of heap_slot. This point the first * Note: 'vstart' is not a top of heap_page. This point the first
* living object to grasp at least one object to avoid GC issue. * living object to grasp at least one object to avoid GC issue.
* This means that you can not walk through all Ruby object slot * This means that you can not walk through all Ruby object page
* including freed object slot. * including freed object page.
* *
* Note: On this implementation, 'stride' is same as sizeof(RVALUE). * Note: On this implementation, 'stride' is same as sizeof(RVALUE).
* However, there are possibilities to pass variable values with * However, there are possibilities to pass variable values with
@ -1775,12 +1775,12 @@ finalize_list(rb_objspace_t *objspace, RVALUE *p)
run_final(objspace, (VALUE)p); run_final(objspace, (VALUE)p);
objspace->total_freed_object_num++; objspace->total_freed_object_num++;
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
heap_slot_add_freeobj(objspace, GET_HEAP_SLOT(p), (VALUE)p); heap_page_add_freeobj(objspace, GET_HEAP_PAGE(p), (VALUE)p);
objspace->heap.swept_num++; objspace->heap.swept_num++;
} }
else { else {
struct heap_slot *slot = (struct heap_slot *)(VALUE)RDATA(p)->dmark; struct heap_page *page = (struct heap_page *)(VALUE)RDATA(p)->dmark;
slot->limit--; page->limit--;
} }
p = tmp; p = tmp;
} }
@ -1929,12 +1929,12 @@ is_id_value(rb_objspace_t *objspace, VALUE ptr)
static inline int static inline int
is_swept_object(rb_objspace_t *objspace, VALUE ptr) is_swept_object(rb_objspace_t *objspace, VALUE ptr)
{ {
struct heap_slot *slot = objspace->heap.sweep_slots; struct heap_page *page = objspace->heap.sweep_pages;
while (slot) { while (page) {
if ((VALUE)slot->start <= ptr && ptr < (VALUE)(slot->start + slot->limit)) if ((VALUE)page->start <= ptr && ptr < (VALUE)(page->start + page->limit))
return FALSE; return FALSE;
slot = slot->next; page = page->next;
} }
return TRUE; return TRUE;
} }
@ -2164,10 +2164,10 @@ count_objects(int argc, VALUE *argv, VALUE os)
} }
for (i = 0; i < heap_used; i++) { for (i = 0; i < heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
RVALUE *p, *pend; RVALUE *p, *pend;
p = slot->start; pend = p + slot->limit; p = page->start; pend = p + page->limit;
for (;p < pend; p++) { for (;p < pend; p++) {
if (p->as.basic.flags) { if (p->as.basic.flags) {
counts[BUILTIN_TYPE(p)]++; counts[BUILTIN_TYPE(p)]++;
@ -2176,7 +2176,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
freed++; freed++;
} }
} }
total += slot->limit; total += page->limit;
} }
if (hash == Qnil) { if (hash == Qnil) {
@ -2255,19 +2255,19 @@ objspace_free_num(rb_objspace_t *objspace)
} }
static void static void
gc_setup_mark_bits(struct heap_slot *slot) gc_setup_mark_bits(struct heap_page *page)
{ {
#if USE_RGENGC #if USE_RGENGC
/* copy oldgen bitmap to mark bitmap */ /* copy oldgen bitmap to mark bitmap */
memcpy(&slot->mark_bits[0], &slot->oldgen_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->mark_bits[0], &page->oldgen_bits[0], HEAP_BITMAP_SIZE);
#else #else
/* clear mark bitmap */ /* clear mark bitmap */
memset(&slot->mark_bits[0], 0, HEAP_BITMAP_SIZE); memset(&page->mark_bits[0], 0, HEAP_BITMAP_SIZE);
#endif #endif
} }
static inline void static inline void
gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot) gc_page_sweep(rb_objspace_t *objspace, struct heap_page *sweep_page)
{ {
int i; int i;
size_t empty_num = 0, freed_num = 0, final_num = 0; size_t empty_num = 0, freed_num = 0, final_num = 0;
@ -2276,10 +2276,10 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
int deferred; int deferred;
bits_t *bits, bitset; bits_t *bits, bitset;
rgengc_report(1, objspace, "slot_sweep: start.\n"); rgengc_report(1, objspace, "page_sweep: start.\n");
p = sweep_slot->start; pend = p + sweep_slot->limit; p = sweep_page->start; pend = p + sweep_page->limit;
offset = p - NUM_IN_SLOT(p); offset = p - NUM_IN_PAGE(p);
bits = GET_HEAP_MARK_BITS(p); bits = GET_HEAP_MARK_BITS(p);
/* create guard : fill 1 out-of-range */ /* create guard : fill 1 out-of-range */
@ -2293,10 +2293,10 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
do { do {
if ((bitset & 1) && BUILTIN_TYPE(p) != T_ZOMBIE) { if ((bitset & 1) && BUILTIN_TYPE(p) != T_ZOMBIE) {
if (p->as.basic.flags) { if (p->as.basic.flags) {
rgengc_report(3, objspace, "slot_sweep: free %p (%s)\n", p, obj_type_name((VALUE)p)); rgengc_report(3, objspace, "page_sweep: free %p (%s)\n", p, obj_type_name((VALUE)p));
#if USE_RGENGC && RGENGC_CHECK_MODE #if USE_RGENGC && RGENGC_CHECK_MODE
if (objspace->rgengc.during_minor_gc && RVALUE_PROMOTED(p)) rb_bug("slot_sweep: %p (%s) is promoted.\n", p, obj_type_name((VALUE)p)); if (objspace->rgengc.during_minor_gc && RVALUE_PROMOTED(p)) rb_bug("page_sweep: %p (%s) is promoted.\n", p, obj_type_name((VALUE)p));
if (rgengc_remembered(objspace, (VALUE)p)) rb_bug("slot_sweep: %p (%s) is remembered.\n", p, obj_type_name((VALUE)p)); if (rgengc_remembered(objspace, (VALUE)p)) rb_bug("page_sweep: %p (%s) is remembered.\n", p, obj_type_name((VALUE)p));
#endif #endif
if ((deferred = obj_free(objspace, (VALUE)p)) || (FL_TEST(p, FL_FINALIZE))) { if ((deferred = obj_free(objspace, (VALUE)p)) || (FL_TEST(p, FL_FINALIZE))) {
if (!deferred) { if (!deferred) {
@ -2310,8 +2310,8 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
} }
else { else {
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
heap_slot_add_freeobj(objspace, sweep_slot, (VALUE)p); heap_page_add_freeobj(objspace, sweep_page, (VALUE)p);
rgengc_report(3, objspace, "slot_sweep: %p (%s) is added to freelist\n", p, obj_type_name((VALUE)p)); rgengc_report(3, objspace, "page_sweep: %p (%s) is added to freelist\n", p, obj_type_name((VALUE)p));
freed_num++; freed_num++;
} }
} }
@ -2325,7 +2325,7 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
} }
} }
gc_setup_mark_bits(sweep_slot); gc_setup_mark_bits(sweep_page);
#if GC_PROFILE_MORE_DETAIL #if GC_PROFILE_MORE_DETAIL
if (objspace->profile.run) { if (objspace->profile.run) {
@ -2335,24 +2335,24 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
} }
#endif #endif
if (final_num + freed_num + empty_num == sweep_slot->limit && if (final_num + freed_num + empty_num == sweep_page->limit &&
objspace->heap.swept_num > objspace->heap.do_heap_free) { objspace->heap.swept_num > objspace->heap.do_heap_free) {
RVALUE *pp; RVALUE *pp;
for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) { for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) {
RDATA(pp)->dmark = (void (*)(void *))(VALUE)sweep_slot; RDATA(pp)->dmark = (void (*)(void *))(VALUE)sweep_page;
pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
} }
heap_limit -= sweep_slot->limit; heap_limit -= sweep_page->limit;
sweep_slot->limit = final_num; sweep_page->limit = final_num;
unlink_heap_slot(objspace, sweep_slot); unlink_heap_page(objspace, sweep_page);
} }
else { else {
if (freed_num + empty_num > 0) { if (freed_num + empty_num > 0) {
heap_add_freeslot(objspace, sweep_slot); heap_add_freepage(objspace, sweep_page);
} }
else { else {
sweep_slot->free_next = NULL; sweep_page->free_next = NULL;
} }
objspace->heap.swept_num += freed_num + empty_num; objspace->heap.swept_num += freed_num + empty_num;
} }
@ -2366,7 +2366,7 @@ gc_slot_sweep(rb_objspace_t *objspace, struct heap_slot *sweep_slot)
} }
} }
rgengc_report(1, objspace, "slot_sweep: end.\n"); rgengc_report(1, objspace, "page_sweep: end.\n");
} }
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
@ -2385,13 +2385,13 @@ gc_before_sweep(rb_objspace_t *objspace)
objspace->heap.do_heap_free = initial_free_min; objspace->heap.do_heap_free = initial_free_min;
} }
} }
objspace->heap.sweep_slots = heap_slots; objspace->heap.sweep_pages = heap_pages;
objspace->heap.swept_num = 0; objspace->heap.swept_num = 0;
objspace->heap.free_slots = NULL; objspace->heap.free_pages = NULL;
if (objspace->heap.using_slot) { if (objspace->heap.using_page) {
objspace->heap.using_slot->freelist = objspace->freelist; objspace->heap.using_page->freelist = objspace->freelist;
objspace->heap.using_slot = NULL; objspace->heap.using_page = NULL;
} }
objspace->freelist = NULL; objspace->freelist = NULL;
@ -2454,7 +2454,7 @@ gc_after_sweep(rb_objspace_t *objspace)
gc_prof_set_heap_info(objspace); gc_prof_set_heap_info(objspace);
free_unused_slots(objspace); free_unused_pages(objspace);
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END, 0 /* TODO: pass minor/immediate flag? */); gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END, 0 /* TODO: pass minor/immediate flag? */);
} }
@ -2462,26 +2462,26 @@ gc_after_sweep(rb_objspace_t *objspace)
static int static int
gc_lazy_sweep(rb_objspace_t *objspace) gc_lazy_sweep(rb_objspace_t *objspace)
{ {
struct heap_slot *slot, *next; struct heap_page *page, *next;
int result = FALSE; int result = FALSE;
gc_prof_sweep_timer_start(objspace); gc_prof_sweep_timer_start(objspace);
slot = objspace->heap.sweep_slots; page = objspace->heap.sweep_pages;
while (slot) { while (page) {
objspace->heap.sweep_slots = next = slot->next; objspace->heap.sweep_pages = next = page->next;
gc_slot_sweep(objspace, slot); gc_page_sweep(objspace, page);
if (!next) gc_after_sweep(objspace); if (!next) gc_after_sweep(objspace);
if (objspace->heap.free_slots) { if (objspace->heap.free_pages) {
result = TRUE; result = TRUE;
break; break;
} }
slot = next; page = next;
} }
gc_prof_sweep_timer_stop(objspace); gc_prof_sweep_timer_stop(objspace);
@ -2505,14 +2505,14 @@ static void
gc_sweep(rb_objspace_t *objspace, int immediate_sweep) gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
{ {
if (immediate_sweep) { if (immediate_sweep) {
struct heap_slot *next; struct heap_page *next;
gc_prof_sweep_timer_start(objspace); gc_prof_sweep_timer_start(objspace);
gc_before_sweep(objspace); gc_before_sweep(objspace);
while (objspace->heap.sweep_slots) { while (objspace->heap.sweep_pages) {
next = objspace->heap.sweep_slots->next; next = objspace->heap.sweep_pages->next;
gc_slot_sweep(objspace, objspace->heap.sweep_slots); gc_page_sweep(objspace, objspace->heap.sweep_pages);
objspace->heap.sweep_slots = next; objspace->heap.sweep_pages = next;
} }
gc_after_sweep(objspace); gc_after_sweep(objspace);
@ -2523,8 +2523,8 @@ gc_sweep(rb_objspace_t *objspace, int immediate_sweep)
gc_lazy_sweep(objspace); gc_lazy_sweep(objspace);
} }
if (!objspace->heap.free_slots) { if (!objspace->heap.free_pages) {
/* there is no free after slot_sweep() */ /* there is no free after page_sweep() */
heap_set_increment(objspace); heap_set_increment(objspace);
if (!heap_increment(objspace)) { /* can't allocate additional free objects */ if (!heap_increment(objspace)) { /* can't allocate additional free objects */
during_gc = 0; during_gc = 0;
@ -3002,8 +3002,8 @@ rgengc_check_shady(rb_objspace_t *objspace, VALUE obj)
{ {
#if USE_RGENGC #if USE_RGENGC
#if RGENGC_CHECK_MODE >= 2 #if RGENGC_CHECK_MODE >= 2
#define SAVED_OLD(x) MARKED_IN_BITMAP(GET_HEAP_SLOT(x)->saved_oldgen_bits, (x)) #define SAVED_OLD(x) MARKED_IN_BITMAP(GET_HEAP_PAGE(x)->saved_oldgen_bits, (x))
#define SAVED_REM(x) MARKED_IN_BITMAP(GET_HEAP_SLOT(x)->saved_rememberset_bits, (x)) #define SAVED_REM(x) MARKED_IN_BITMAP(GET_HEAP_PAGE(x)->saved_rememberset_bits, (x))
VALUE parent = objspace->rgengc.parent_object; VALUE parent = objspace->rgengc.parent_object;
if (objspace->rgengc.have_saved_bitmaps && !monitor_level) { if (objspace->rgengc.have_saved_bitmaps && !monitor_level) {
@ -3636,11 +3636,11 @@ gc_marks_body(rb_objspace_t *objspace, int full_mark)
#if RGENGC_CHECK_MODE >= 2 #if RGENGC_CHECK_MODE >= 2
static void static void
gc_oldgen_bitmap2flag(struct heap_slot *slot) gc_oldgen_bitmap2flag(struct heap_page *page)
{ {
bits_t *oldgen_bits = &slot->oldgen_bits[0]; bits_t *oldgen_bits = &page->oldgen_bits[0];
RVALUE *p = slot->start; RVALUE *p = page->start;
RVALUE *pend = p + slot->limit; RVALUE *pend = p + page->limit;
while (p < pend) { while (p < pend) {
if (MARKED_IN_BITMAP(oldgen_bits, p)) FL_SET2(p, FL_OLDGEN); if (MARKED_IN_BITMAP(oldgen_bits, p)) FL_SET2(p, FL_OLDGEN);
@ -3658,11 +3658,11 @@ gc_export_bitmaps(rb_objspace_t *objspace)
if (exported_bitmaps == 0) rb_bug("gc_store_bitmaps: not enough memory to test.\n"); if (exported_bitmaps == 0) rb_bug("gc_store_bitmaps: not enough memory to test.\n");
for (i=0; i<heap_used; i++) { for (i=0; i<heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
memcpy(&exported_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], &slot->mark_bits[0], HEAP_BITMAP_SIZE); memcpy(&exported_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], &page->mark_bits[0], HEAP_BITMAP_SIZE);
memcpy(&exported_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], &slot->rememberset_bits[0], HEAP_BITMAP_SIZE); memcpy(&exported_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], &page->rememberset_bits[0], HEAP_BITMAP_SIZE);
memcpy(&exported_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], &slot->oldgen_bits[0], HEAP_BITMAP_SIZE); memcpy(&exported_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], &page->oldgen_bits[0], HEAP_BITMAP_SIZE);
} }
return exported_bitmaps; return exported_bitmaps;
@ -3674,15 +3674,15 @@ gc_restore_exported_bitmaps(rb_objspace_t *objspace, bits_t *exported_bitmaps)
size_t i; size_t i;
for (i=0; i<heap_used; i++) { for (i=0; i<heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
/* restore bitmaps */ /* restore bitmaps */
memcpy(&slot->mark_bits[0], &exported_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&page->mark_bits[0], &exported_bitmaps[(3*i+0)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
memcpy(&slot->rememberset_bits[0], &exported_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&page->rememberset_bits[0], &exported_bitmaps[(3*i+1)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
memcpy(&slot->oldgen_bits[0], &exported_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE); memcpy(&page->oldgen_bits[0], &exported_bitmaps[(3*i+2)*HEAP_BITMAP_LIMIT], HEAP_BITMAP_SIZE);
/* restore oldgen flags */ /* restore oldgen flags */
gc_oldgen_bitmap2flag(slot); gc_oldgen_bitmap2flag(page);
} }
} }
@ -3698,12 +3698,12 @@ gc_save_bitmaps(rb_objspace_t *objspace)
size_t i; size_t i;
for (i=0; i<heap_used; i++) { for (i=0; i<heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
/* save bitmaps */ /* save bitmaps */
memcpy(&slot->saved_mark_bits[0], &slot->mark_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->saved_mark_bits[0], &page->mark_bits[0], HEAP_BITMAP_SIZE);
memcpy(&slot->saved_rememberset_bits[0], &slot->rememberset_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->saved_rememberset_bits[0], &page->rememberset_bits[0], HEAP_BITMAP_SIZE);
memcpy(&slot->saved_oldgen_bits[0], &slot->oldgen_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->saved_oldgen_bits[0], &page->oldgen_bits[0], HEAP_BITMAP_SIZE);
} }
objspace->rgengc.have_saved_bitmaps = TRUE; objspace->rgengc.have_saved_bitmaps = TRUE;
@ -3715,14 +3715,14 @@ gc_load_bitmaps(rb_objspace_t *objspace)
size_t i; size_t i;
for (i=0; i<heap_used; i++) { for (i=0; i<heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
/* load bitmaps */ /* load bitmaps */
memcpy(&slot->mark_bits[0], &slot->saved_mark_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->mark_bits[0], &page->saved_mark_bits[0], HEAP_BITMAP_SIZE);
memcpy(&slot->rememberset_bits[0], &slot->saved_rememberset_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->rememberset_bits[0], &page->saved_rememberset_bits[0], HEAP_BITMAP_SIZE);
memcpy(&slot->oldgen_bits[0], &slot->saved_oldgen_bits[0], HEAP_BITMAP_SIZE); memcpy(&page->oldgen_bits[0], &page->saved_oldgen_bits[0], HEAP_BITMAP_SIZE);
gc_oldgen_bitmap2flag(slot); gc_oldgen_bitmap2flag(page);
} }
} }
@ -3965,7 +3965,7 @@ rgengc_rememberset_mark(rb_objspace_t *objspace)
p = objspace->heap.sorted[i]->start; p = objspace->heap.sorted[i]->start;
bits = GET_HEAP_REMEMBERSET_BITS(p); bits = GET_HEAP_REMEMBERSET_BITS(p);
offset = p - NUM_IN_SLOT(p); offset = p - NUM_IN_PAGE(p);
for (j=0; j < HEAP_BITMAP_LIMIT; j++) { for (j=0; j < HEAP_BITMAP_LIMIT; j++) {
if (bits[j]) { if (bits[j]) {
@ -4016,9 +4016,9 @@ rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace)
size_t i; size_t i;
for (i=0; i<heap_used; i++) { for (i=0; i<heap_used; i++) {
struct heap_slot *slot = objspace->heap.sorted[i]; struct heap_page *page = objspace->heap.sorted[i];
memset(&slot->mark_bits[0], 0, HEAP_BITMAP_SIZE); memset(&page->mark_bits[0], 0, HEAP_BITMAP_SIZE);
memset(&slot->rememberset_bits[0], 0, HEAP_BITMAP_SIZE); memset(&page->rememberset_bits[0], 0, HEAP_BITMAP_SIZE);
} }
} }
@ -4162,7 +4162,7 @@ rb_gc_force_recycle(VALUE p)
#endif #endif
objspace->total_freed_object_num++; objspace->total_freed_object_num++;
heap_slot_add_freeobj(objspace, GET_HEAP_SLOT(p), p); heap_page_add_freeobj(objspace, GET_HEAP_PAGE(p), p);
if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) { if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
objspace->heap.swept_num++; objspace->heap.swept_num++;
@ -4283,7 +4283,7 @@ static int
ready_to_gc(rb_objspace_t *objspace) ready_to_gc(rb_objspace_t *objspace)
{ {
if (dont_gc || during_gc) { if (dont_gc || during_gc) {
if (!objspace->freelist && !objspace->heap.free_slots) { if (!objspace->freelist && !objspace->heap.free_pages) {
if (!heap_increment(objspace)) { if (!heap_increment(objspace)) {
heap_set_increment(objspace); heap_set_increment(objspace);
heap_increment(objspace); heap_increment(objspace);
@ -4297,7 +4297,7 @@ ready_to_gc(rb_objspace_t *objspace)
static int static int
garbage_collect(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason) garbage_collect(rb_objspace_t *objspace, int full_mark, int immediate_sweep, int reason)
{ {
if (!heap_slots) { if (!heap_pages) {
during_gc = 0; during_gc = 0;
return FALSE; return FALSE;
} }
@ -4394,7 +4394,7 @@ rb_gc(void)
rb_objspace_t *objspace = &rb_objspace; rb_objspace_t *objspace = &rb_objspace;
garbage_collect(objspace, TRUE, TRUE, GPR_FLAG_METHOD); garbage_collect(objspace, TRUE, TRUE, GPR_FLAG_METHOD);
if (!finalizing) finalize_deferred(objspace); if (!finalizing) finalize_deferred(objspace);
free_unused_slots(objspace); free_unused_pages(objspace);
} }
int int
@ -4693,7 +4693,7 @@ rb_gc_set_params(void)
min_size = initial_heap_min_slots / HEAP_OBJ_LIMIT; min_size = initial_heap_min_slots / HEAP_OBJ_LIMIT;
if (min_size > heap_used) { if (min_size > heap_used) {
heap_add_slots(objspace, min_size - heap_used); heap_add_pages(objspace, min_size - heap_used);
} }
} }
@ -5523,7 +5523,7 @@ gc_prof_set_heap_info(rb_objspace_t *objspace)
size_t total = objspace->profile.heap_used_at_gc_start * HEAP_OBJ_LIMIT; size_t total = objspace->profile.heap_used_at_gc_start * HEAP_OBJ_LIMIT;
#if GC_PROFILE_MORE_DETAIL #if GC_PROFILE_MORE_DETAIL
record->heap_use_slots = objspace->profile.heap_used_at_gc_start; record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
record->heap_live_objects = live; record->heap_live_objects = live;
record->heap_free_objects = total - live; record->heap_free_objects = total - live;
#endif #endif
@ -5621,7 +5621,7 @@ gc_profile_flags(int flags)
* +:GC_SWEEP_TIME+:: * +:GC_SWEEP_TIME+::
* +:ALLOCATE_INCREASE+:: * +:ALLOCATE_INCREASE+::
* +:ALLOCATE_LIMIT+:: * +:ALLOCATE_LIMIT+::
* +:HEAP_USE_SLOTS+:: * +:HEAP_USE_PAGES+::
* +:HEAP_LIVE_OBJECTS+:: * +:HEAP_LIVE_OBJECTS+::
* +:HEAP_FREE_OBJECTS+:: * +:HEAP_FREE_OBJECTS+::
* +:HAVE_FINALIZE+:: * +:HAVE_FINALIZE+::
@ -5656,7 +5656,7 @@ gc_profile_record_get(void)
rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(record->gc_sweep_time)); rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(record->gc_sweep_time));
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(record->allocate_increase)); rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(record->allocate_increase));
rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(record->allocate_limit)); rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(record->allocate_limit));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SLOTS")), SIZET2NUM(record->heap_use_slots)); rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_PAGES")), SIZET2NUM(record->heap_use_pages));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects)); rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects)); rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects));
@ -5734,7 +5734,7 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
#if CALC_EXACT_MALLOC_SIZE #if CALC_EXACT_MALLOC_SIZE
record->allocated_size, record->allocated_size,
#endif #endif
record->heap_use_slots, record->heap_use_pages,
record->gc_mark_time*1000, record->gc_mark_time*1000,
record->gc_sweep_time*1000, record->gc_sweep_time*1000,
record->prepare_time*1000, record->prepare_time*1000,