Simplified propagate mark code, removed unneeded pagemap calls
svn: r16041
This commit is contained in:
parent
1e0a68516e
commit
027959de52
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user