From 027959de5230f6109a434e9c05792d1959c8612d Mon Sep 17 00:00:00 2001 From: Kevin Tew Date: Thu, 17 Sep 2009 14:13:47 +0000 Subject: [PATCH] Simplified propagate mark code, removed unneeded pagemap calls svn: r16041 --- src/mzscheme/gc2/mem_account.c | 94 +---------------- src/mzscheme/gc2/newgc.c | 179 +++++++++++++++------------------ 2 files changed, 85 insertions(+), 188 deletions(-) diff --git a/src/mzscheme/gc2/mem_account.c b/src/mzscheme/gc2/mem_account.c index 9dd94cb0be..60ff1af2b5 100644 --- a/src/mzscheme/gc2/mem_account.c +++ b/src/mzscheme/gc2/mem_account.c @@ -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(); diff --git a/src/mzscheme/gc2/newgc.c b/src/mzscheme/gc2/newgc.c index 01f571856a..17359f27b0 100644 --- a/src/mzscheme/gc2/newgc.c +++ b/src/mzscheme/gc2/newgc.c @@ -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);