Simplified propagate mark code, removed unneeded pagemap calls

svn: r16041
This commit is contained in:
Kevin Tew 2009-09-17 14:13:47 +00:00
parent 1e0a68516e
commit 027959de52
2 changed files with 85 additions and 188 deletions

View File

@ -247,7 +247,7 @@ inline static void BTC_memory_account_mark(NewGC *gc, mpage *page, void *ptr)
if(info->btc_mark == gc->old_btc_mark) {
info->btc_mark = gc->new_btc_mark;
account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(page->size));
push_ptr(ptr);
push_ptr(TAG_AS_BIG_PAGE_PTR(ptr));
}
} else {
/* medium page */
@ -328,74 +328,6 @@ int BTC_cust_box_mark(void *p)
return gc->mark_table[btc_redirect_cust_box](p);
}
inline static void mark_normal_obj(NewGC *gc, int type, void *ptr)
{
switch(type) {
case PAGE_TAGGED: {
/* we do not want to mark the pointers in a thread or custodian
unless the object's owner is the current owner. In the case
of threads, we already used it for roots, so we can just
ignore them outright. In the case of custodians, we do need
to do the check; those differences are handled by replacing
the mark procedure in mark_table. */
unsigned short tag = *(unsigned short*)ptr;
ASSERT_TAG(tag);
if((unsigned long)gc->mark_table[tag] < PAGE_TYPES) {
/* atomic */
} else {
GC_ASSERT(mark_table[tag]);
gc->mark_table[tag](ptr);
}
break;
}
case PAGE_ATOMIC: break;
case PAGE_ARRAY: {
objhead *info = OBJPTR_TO_OBJHEAD(ptr);
void **temp = ptr;
void **end = PPTR(info) + info->size;
while(temp < end) gcMARK(*(temp++));
break;
};
case PAGE_TARRAY: {
objhead *info = OBJPTR_TO_OBJHEAD(ptr);
unsigned short tag = *(unsigned short*)ptr;
void **temp = ptr;
void **end = PPTR(info) + (info->size - INSET_WORDS);
while(temp < end) temp += gc->mark_table[tag](temp);
break;
}
case PAGE_XTAGGED: GC_mark_xtagged(ptr); break;
}
}
inline static void mark_acc_big_page(NewGC *gc, mpage *page)
{
void **start = PPTR(BIG_PAGE_TO_OBJECT(page));
void **end = PPTR(NUM(page->addr) + page->size);
switch(page->page_type) {
case PAGE_TAGGED:
{
unsigned short tag = *(unsigned short*)start;
if((unsigned long)gc->mark_table[tag] < PAGE_TYPES) {
/* atomic */
} else
gc->mark_table[tag](start); break;
}
case PAGE_ATOMIC: break;
case PAGE_ARRAY: while(start < end) gcMARK(*(start++)); break;
case PAGE_XTAGGED: GC_mark_xtagged(start); break;
case PAGE_TARRAY: {
unsigned short tag = *(unsigned short *)start;
end -= INSET_WORDS;
while(start < end) start += gc->mark_table[tag](start);
break;
}
}
}
static void btc_overmem_abort(NewGC *gc)
{
gc->kill_propagation_loop = 1;
@ -405,29 +337,13 @@ static void btc_overmem_abort(NewGC *gc)
static void propagate_accounting_marks(NewGC *gc)
{
struct mpage *page;
void *p;
PageMap pagemap = gc->page_maps;
Mark_Proc *mark_table = gc->mark_table;
while(pop_ptr(&p) && !gc->kill_propagation_loop) {
page = pagemap_find_page(pagemap, p);
#ifdef MZ_USE_PLACES
if (!page) {
page = pagemap_find_page(MASTERGC->page_maps, p);
}
#endif
GC_ASSERT(page);
set_backtrace_source(p, page->page_type);
GCDEBUG((DEBUGOUTF, "btc_account: popped off page %p:%p, ptr %p\n", page, page->addr, p));
if(page->size_class) {
if (page->size_class > 1)
mark_acc_big_page(gc, page);
else {
objhead *info = MED_OBJHEAD(p, page->size);
p = OBJHEAD_TO_OBJPTR(info);
mark_normal_obj(gc, info->type, p);
}
} else
mark_normal_obj(gc, page->page_type, p);
/* GCDEBUG((DEBUGOUTF, "btc_account: popped off page %p:%p, ptr %p\n", page, page->addr, p)); */
propagate_marks_worker(pagemap, mark_table, p);
}
if(gc->kill_propagation_loop)
reset_pointer_stack();

View File

@ -517,6 +517,20 @@ static inline int BTC_single_allocation_limit(NewGC *gc, size_t sizeb);
#define PAGE_END_VSS(page) ((void**) (((char *)((page)->addr)) + ((page)->size)))
#define MED_OBJHEAD_TO_OBJECT(ptr, page_size) ((void*) (((char *)MED_OBJHEAD((ptr), (page_size))) + OBJHEAD_SIZE));
static inline void* TAG_AS_BIG_PAGE_PTR(void *p) {
return ((void *)(((unsigned long) p)|1));
}
static inline int IS_BIG_PAGE_PTR(void *p) {
return (((unsigned long) p) & ((unsigned long) 1));
}
static inline void* REMOVE_BIG_PAGE_PTR_TAG(void *p) {
return ((void *)((~((unsigned long) 1)) & ((unsigned long) p)));
}
/* the core allocation functions */
static void *allocate_big(const size_t request_size_bytes, int type)
{
@ -1552,6 +1566,8 @@ inline static void reset_pointer_stack(void)
mark_stack->top = MARK_STACK_START(mark_stack);
}
static inline void propagate_marks_worker(PageMap pagemap, Mark_Proc *mark_table, void *p);
/*****************************************************************************/
/* MEMORY ACCOUNTING */
/*****************************************************************************/
@ -1840,6 +1856,7 @@ void GC_gcollect(void)
garbage_collect(gc, 1);
}
static inline int atomic_mark(void *p) { return 0; }
void GC_register_traversers(short tag, Size_Proc size, Mark_Proc mark,
Fixup_Proc fixup, int constant_Size, int atomic)
{
@ -1944,7 +1961,7 @@ void GC_mark(const void *const_p)
GCDEBUG((DEBUGOUTF, "Marking %p on big page %p\n", p, page));
/* Finally, we want to add this to our mark queue, so we can
propagate its pointers */
push_ptr(p);
push_ptr(TAG_AS_BIG_PAGE_PTR(p));
} else {
/* A medium page. */
objhead *info = MED_OBJHEAD(p, page->size);
@ -2077,6 +2094,66 @@ void GC_mark(const void *const_p)
/* this is the second mark routine. It's not quite as complicated. */
/* this is what actually does mark propagation */
static inline void propagate_marks_worker(PageMap pagemap, Mark_Proc *mark_table, void *pp)
{
void **start;
int alloc_type;
objhead *info;
mpage *page;
int is_big_page = IS_BIG_PAGE_PTR(pp);
void *p = REMOVE_BIG_PAGE_PTR_TAG(pp);
/* we can assume a lot here -- like it's a valid pointer with a page --
because we vet bad cases out in GC_mark, above */
if (is_big_page) {
page = pagemap_find_page(pagemap, p);
start = PPTR(BIG_PAGE_TO_OBJECT(page));
alloc_type = page->page_type;
} else {
info = OBJPTR_TO_OBJHEAD(p);
start = p;
alloc_type = info->type;
}
set_backtrace_source(start, alloc_type);
switch(alloc_type) {
case PAGE_TAGGED:
{
const unsigned short tag = *(unsigned short*)start;
Mark_Proc markproc;
ASSERT_TAG(tag);
markproc = mark_table[tag];
if(((unsigned long) markproc) >= PAGE_TYPES) {
GC_ASSERT(markproc);
markproc(start);
}
break;
}
case PAGE_ATOMIC:
break;
case PAGE_ARRAY:
{
void **end = is_big_page ? PAGE_END_VSS(page) : PPTR(info) + info->size;
while(start < end) gcMARK(*start++); break;
}
case PAGE_TARRAY:
{
void **end = is_big_page ? PAGE_END_VSS(page) : PPTR(info) + info->size;
const unsigned short tag = *(unsigned short *)start;
ASSERT_TAG(tag);
end -= INSET_WORDS;
while(start < end) {
GC_ASSERT(mark_table[tag]);
start += mark_table[tag](start);
}
break;
}
case PAGE_XTAGGED:
GC_mark_xtagged(start); break;
}
}
static void propagate_marks(NewGC *gc)
{
void *p;
@ -2084,104 +2161,8 @@ static void propagate_marks(NewGC *gc)
Mark_Proc *mark_table = gc->mark_table;
while(pop_ptr(&p)) {
mpage *page = pagemap_find_page(pagemap, p);
GCDEBUG((DEBUGOUTF, "Popped pointer %p\n", p));
/* we can assume a lot here -- like it's a valid pointer with a page --
because we vet bad cases out in GC_mark, above */
if(page->size_class) {
if(page->size_class > 1) {
void **start = PPTR(BIG_PAGE_TO_OBJECT(page));
void **end = PAGE_END_VSS(page);
set_backtrace_source(start, page->page_type);
switch(page->page_type) {
case PAGE_TAGGED:
{
unsigned short tag = *(unsigned short*)start;
ASSERT_TAG(tag);
if((unsigned long)mark_table[tag] < PAGE_TYPES) {
/* atomic */
} else {
GC_ASSERT(mark_table[tag]);
mark_table[tag](start); break;
}
}
case PAGE_ATOMIC: break;
case PAGE_ARRAY: while(start < end) gcMARK(*(start++)); break;
case PAGE_XTAGGED: GC_mark_xtagged(start); break;
case PAGE_TARRAY:
{
unsigned short tag = *(unsigned short *)start;
ASSERT_TAG(tag);
end -= INSET_WORDS;
while(start < end) {
GC_ASSERT(mark_table[tag]);
start += mark_table[tag](start);
}
break;
}
}
} else {
/* Medium page */
objhead *info = OBJPTR_TO_OBJHEAD(p);
set_backtrace_source(p, info->type);
switch(info->type) {
case PAGE_TAGGED:
{
unsigned short tag = *(unsigned short*)p;
ASSERT_TAG(tag);
GC_ASSERT(mark_table[tag]);
mark_table[tag](p);
break;
}
case PAGE_ARRAY:
{
void **start = p;
void **end = PPTR(info) + info->size;
while(start < end) gcMARK(*start++);
break;
}
}
}
} else {
objhead *info = OBJPTR_TO_OBJHEAD(p);
set_backtrace_source(p, info->type);
switch(info->type) {
case PAGE_TAGGED:
{
unsigned short tag = *(unsigned short*)p;
ASSERT_TAG(tag);
GC_ASSERT(mark_table[tag]);
mark_table[tag](p);
break;
}
case PAGE_ATOMIC: break;
case PAGE_ARRAY: {
void **start = p;
void **end = PPTR(info) + info->size;
while(start < end) gcMARK(*start++);
break;
}
case PAGE_TARRAY: {
void **start = p;
void **end = PPTR(info) + (info->size - INSET_WORDS);
unsigned short tag = *(unsigned short *)start;
ASSERT_TAG(tag);
while(start < end) {
GC_ASSERT(mark_table[tag]);
start += mark_table[tag](start);
}
break;
}
case PAGE_XTAGGED: GC_mark_xtagged(p); break;
}
}
propagate_marks_worker(pagemap, mark_table, p);
}
}
@ -2552,7 +2533,7 @@ static void mark_backpointers(NewGC *gc)
if(work->size_class) {
/* must be a big page */
work->size_class = 3;
push_ptr(BIG_PAGE_TO_OBJECT(work));
push_ptr(TAG_AS_BIG_PAGE_PTR(BIG_PAGE_TO_OBJECT(work)));
} else {
if(work->page_type != PAGE_ATOMIC) {
void **start = PAGE_START_VSS(work);