diff --git a/src/mzscheme/gc2/commongc_internal.h b/src/mzscheme/gc2/commongc_internal.h index b65714840b..46b9fcaa92 100644 --- a/src/mzscheme/gc2/commongc_internal.h +++ b/src/mzscheme/gc2/commongc_internal.h @@ -51,3 +51,19 @@ typedef struct GC_Immobile_Box { struct GC_Immobile_Box *prev; } GC_Immobile_Box; +typedef struct finalizer { + char eager_level; + char tagged; + void *p; + GC_finalization_proc f; + void *data; +#if CHECKS + long size; +#endif + struct finalizer *next; + /* Patched after GC: */ + struct finalizer *prev; + struct finalizer *left; + struct finalizer *right; +} Fnl; + diff --git a/src/mzscheme/gc2/compact.c b/src/mzscheme/gc2/compact.c index eb6661b0e9..dafb6f1509 100644 --- a/src/mzscheme/gc2/compact.c +++ b/src/mzscheme/gc2/compact.c @@ -13,10 +13,10 @@ #include "gc2.h" #define NUMBER_OF_TAGS 512 -#include "newgc_internal.h" +#include "compactgc_internal.h" #include "../src/schpriv.h" -static THREAD_LOCAL NewGC *GC; +static THREAD_LOCAL CompactGC *GC; /**************** Configuration ****************/ diff --git a/src/mzscheme/gc2/compactgc_internal.h b/src/mzscheme/gc2/compactgc_internal.h index 67948544ad..ed387700fd 100644 --- a/src/mzscheme/gc2/compactgc_internal.h +++ b/src/mzscheme/gc2/compactgc_internal.h @@ -1 +1,21 @@ #include "commongc_internal.h" + +typedef struct CompactGC { + void *park[2]; + void *park_save[2]; + + unsigned short weak_array_tag; + unsigned short weak_box_tag; + unsigned short ephemeron_tag; + unsigned short cust_box_tag; + + Roots roots; + GC_Weak_Array *weak_arrays; + GC_Weak_Box *weak_boxes; + GC_Ephemeron *ephemerons; + int num_last_seen_ephemerons; +} CompactGC; + +void CompactGC_initialize(CompactGC *newgc) { + memset(newgc, 0, sizeof(CompactGC)); +} diff --git a/src/mzscheme/gc2/newgc.c b/src/mzscheme/gc2/newgc.c index b3baa00498..722cc2f04f 100644 --- a/src/mzscheme/gc2/newgc.c +++ b/src/mzscheme/gc2/newgc.c @@ -39,6 +39,18 @@ /* the number of tags to use for tagged objects */ #define NUMBER_OF_TAGS 512 +#ifdef SIXTY_FOUR_BIT_INTEGERS +#define PAGEMAP64_LEVEL1_SIZE (1 << 16) +#define PAGEMAP64_LEVEL2_SIZE (1 << 16) +#define PAGEMAP64_LEVEL3_SIZE (1 << (32 - LOG_APAGE_SIZE)) +#define PAGEMAP64_LEVEL1_BITS(p) (((unsigned long)(p)) >> 48) +#define PAGEMAP64_LEVEL2_BITS(p) ((((unsigned long)(p)) >> 32) & ((PAGEMAP64_LEVEL2_SIZE) - 1)) +#define PAGEMAP64_LEVEL3_BITS(p) ((((unsigned long)(p)) >> LOG_APAGE_SIZE) & ((PAGEMAP64_LEVEL3_SIZE) - 1)) +#else +#define PAGEMAP32_SIZE (1 << (32 - LOG_APAGE_SIZE)) +#define PAGEMAP32_BITS(x) (NUM(x) >> LOG_APAGE_SIZE) +#endif + #include "newgc_internal.h" static THREAD_LOCAL NewGC *GC; @@ -88,12 +100,6 @@ static THREAD_LOCAL NewGC *GC; #define PTR(x) ((void*)(x)) #define PPTR(x) ((void**)(x)) #define NUM(x) ((unsigned long)(x)) -#define USEFUL_ADDR_BITS (32 - LOG_APAGE_SIZE) -#ifdef SIXTY_FOUR_BIT_INTEGERS -# define ADDR_BITS(x) ((NUM(x) >> LOG_APAGE_SIZE) & ((1 << USEFUL_ADDR_BITS) - 1)) -#else -# define ADDR_BITS(x) (NUM(x) >> LOG_APAGE_SIZE) -#endif #define WORD_SIZE (1 << LOG_WORD_SIZE) #define WORD_BITS (8 * WORD_SIZE) #define APAGE_SIZE (1 << LOG_APAGE_SIZE) @@ -184,6 +190,105 @@ int GC_mtrace_union_current_with(int newval) return 0; } +/*****************************************************************************/ +/* Page Map Routines */ +/*****************************************************************************/ + +/* the page map makes a nice mapping from addresses to pages, allowing + fairly fast lookup. this is useful. */ + +inline static void pagemap_set(void *p, mpage *value) { +#ifdef SIXTY_FOUR_BIT_INTEGERS + unsigned long pos; + mpage ***page_maps; + mapge **page_map; + + pos = PAGEMAP64_LEVEL1_BITS(p); + page_maps = GC->page_mapss[pos]; + if (!page_maps) { + page_maps = (mpage ***)calloc(PAGEMAP64_LEVEL2_SIZE, sizeof(mpage **)); + page_mapss[pos] = page_maps; + } + pos = PAGEMAP64_LEVEL2_BITS(p); + page_map = page_maps[pos]; + if (!page_map) { + page_map = (mpage **)calloc(PAGEMAP64_LEVEL3_SIZE, sizeof(mpage *)); + page_maps[pos] = page_map; + } + page_map[PAGEMAP64_LEVEL3_BITS(p)] = value; +#else + GC->page_map[PAGEMAP32_BITS(p)] = value; +#endif +} + +inline static struct mpage *pagemap_find_page(void *p) { +#ifdef SIXTY_FOUR_BIT_INTEGERS + mpage ***page_maps; + mpage **page_map; + + page_maps = GC->page_mapss[PAGEMAP64_LEVEL1_BITS(p)]; + if (!page_maps) return NULL; + page_map = page_maps[PAGEMAP64_LEVEL2_BITS(p)]; + if (!page_map) return NULL; + return page_map[PAGEMAP64_LEVEL3_BITS(p)]; +#else + return GC->page_map[PAGEMAP32_BITS(p)]; +#endif +} + +/* These procedures modify or use the page map. The page map provides us very + fast mappings from pointers to the page the reside on, if any. The page + map itself serves two important purposes: + + Between collections, it maps pointers to write-protected pages, so that + the write-barrier can identify what page a write has happened to and + mark it as potentially containing pointers from gen 1 to gen 0. + + During collections, it maps pointers to "from" pages. */ + +/* pagemap_modify_with_size could be optimized more for the 64 bit case + repeatedly calling pagemap_set for the 64 bit case is not optimal */ +inline static void pagemap_modify_with_size(mpage *page, long size, mpage *val) { + void *p = page->addr; + + while(size > 0) { + pagemap_set(p, val); + size -= APAGE_SIZE; + p = (char *)p + APAGE_SIZE; + } +} + +inline static void pagemap_modify(mpage *page, mpage *val) { + long size = page->big_page ? page->size : APAGE_SIZE; + pagemap_modify_with_size(page, size, val); +} + +inline static void pagemap_add(struct mpage *page) +{ + pagemap_modify(page, page); +} + +inline static void pagemap_add_with_size(struct mpage *page, long size) +{ + pagemap_modify_with_size(page, size, page); +} + +inline static void pagemap_remove(struct mpage *page) +{ + pagemap_modify(page, NULL); +} + +inline static void pagemap_remove_with_size(struct mpage *page, long size) +{ + pagemap_modify_with_size(page, size, NULL); +} + +int GC_is_allocated(void *p) +{ + return !!pagemap_find_page(p); +} + + /*****************************************************************************/ /* Allocation */ /*****************************************************************************/ @@ -236,46 +341,6 @@ static const char *type_name[PAGE_TYPES] = { "big" }; -/* the page map makes a nice mapping from addresses to pages, allowing - fairly fast lookup. this is useful. */ -#ifdef SIXTY_FOUR_BIT_INTEGERS -static struct mpage ***page_mapss[1 << 16]; -# define DECL_PAGE_MAP struct mpage **page_map; -# define GET_PAGE_MAP(p) page_map = create_page_map(p); -# define FIND_PAGE_MAP(p) page_map = get_page_map(p); if (!page_map) return NULL -inline static struct mpage **create_page_map(void *p) { - unsigned long pos; - struct mpage ***page_maps, **page_map; - pos = (unsigned long)p >> 48; - page_maps = page_mapss[pos]; - if (!page_maps) { - page_maps = (struct mpage ***)calloc(1 << 16, sizeof(struct mpage **)); - page_mapss[pos] = page_maps; - } - pos = ((unsigned long)p >> 32) & ((1 << 16) - 1); - page_map = page_maps[pos]; - if (!page_map) { - page_map = (struct mpage **)calloc(1 << USEFUL_ADDR_BITS, sizeof(struct mpage *)); - page_maps[pos] = page_map; - } - return page_map; -} -inline static struct mpage **get_page_map(void *p) { - unsigned long pos; - struct mpage ***page_maps; - pos = (unsigned long)p >> 48; - page_maps = page_mapss[pos]; - if (!page_maps) - return NULL; - pos = ((unsigned long)p >> 32) & ((1 << 16) - 1); - return page_maps[pos]; -} -#else -static struct mpage *page_map[1 << USEFUL_ADDR_BITS]; -# define DECL_PAGE_MAP /**/ -# define GET_PAGE_MAP(p) /**/ -# define FIND_PAGE_MAP(p) /**/ -#endif /* Generation 0. Generation 0 is a set of very large pages in a list(GC->gen0.pages), plus a set of smaller bigpages in a separate list(GC->gen0.big_pages). @@ -297,50 +362,6 @@ static struct mpage *pages[PAGE_TYPES]; /* miscellaneous variables */ static const char *zero_sized[4]; /* all 0-sized allocs get this */ -/* These procedures modify or use the page map. The page map provides us very - fast mappings from pointers to the page the reside on, if any. The page - map itself serves two important purposes: - - Between collections, it maps pointers to write-protected pages, so that - the write-barrier can identify what page a write has happened to and - mark it as potentially containing pointers from gen 1 to gen 0. - - During collections, it maps pointers to "from" pages. */ -#define modify_page_map(addr, page, val) { \ - long size_left = page->big_page ? page->size : APAGE_SIZE; \ - void *p = addr; \ - DECL_PAGE_MAP; \ - \ - while(size_left > 0) { \ - GET_PAGE_MAP(p); \ - page_map[ADDR_BITS(p)] = val; \ - size_left -= APAGE_SIZE; \ - p = (char *)p + APAGE_SIZE; \ - } \ - } - -inline static void pagemap_add(struct mpage *page) -{ - modify_page_map(page->addr, page, page); -} - -inline static void pagemap_remove(struct mpage *page) -{ - modify_page_map(page->addr, page, NULL); -} - -inline static mpage *pagemap_find_page(void *p) -{ - DECL_PAGE_MAP; - FIND_PAGE_MAP(p); - return page_map[ADDR_BITS(p)]; -} - -int GC_is_allocated(void *p) -{ - return !!pagemap_find_page(p); -} - static size_t round_to_apage_size(size_t sizeb) { sizeb += APAGE_SIZE - 1; @@ -362,6 +383,8 @@ static void free_mpage(struct mpage *page) free(page); } + + static unsigned long custodian_single_time_limit(int set); inline static int thread_get_owner(void *p); @@ -453,17 +476,21 @@ static void *allocate_big(size_t sizeb, int type) #endif inline static struct mpage *gen0_create_new_mpage() { - struct mpage *work; - work = malloc_mpage(); - work->addr = malloc_dirty_pages(GEN0_PAGE_SIZE, APAGE_SIZE); + mpage *newmpage; - work->big_page = 1; /* until added */ - work->size = GEN0_PAGE_SIZE; /* until added */ - pagemap_add(work); - work->size = PREFIX_SIZE; - work->big_page = 0; + newmpage = malloc_mpage(); + newmpage->addr = malloc_dirty_pages(GEN0_PAGE_SIZE, APAGE_SIZE); + newmpage->big_page = 0; + newmpage->size = PREFIX_SIZE; + pagemap_add_with_size(newmpage, GEN0_PAGE_SIZE); - return work; + return newmpage; +} + +inline static void gen0_free_mpage(mpage *page) { + pagemap_remove_with_size(page, GEN0_PAGE_SIZE); + free_pages(page->addr, GEN0_PAGE_SIZE); + free_mpage(page); } //#define OVERFLOWS_GEN0(ptr) ((ptr) > (NUM(GC->gen0.curr_alloc_page->addr) + GEN0_PAGE_SIZE)) diff --git a/src/mzscheme/gc2/newgc_internal.h b/src/mzscheme/gc2/newgc_internal.h index d6bce9376b..0bda767faa 100644 --- a/src/mzscheme/gc2/newgc_internal.h +++ b/src/mzscheme/gc2/newgc_internal.h @@ -71,22 +71,6 @@ typedef struct Gen0 { unsigned long max_size; } Gen0; -typedef struct finalizer { - char eager_level; - char tagged; - void *p; - GC_finalization_proc f; - void *data; -#if CHECKS - long size; -#endif - struct finalizer *next; - /* Patched after GC: */ - struct finalizer *prev; - struct finalizer *left; - struct finalizer *right; -} Fnl; - typedef struct Weak_Finalizer { void *p; int offset; @@ -105,6 +89,11 @@ typedef struct NewGC { Gen0 gen0; Mark_Proc *mark_table; /* the table of mark procs */ Fixup_Proc *fixup_table; /* the table of repair procs */ +#ifdef SIXTY_FOUR_BIT_INTEGERS + mpage ****page_mapss; +#else + mpage **page_map; +#endif /* Finalization */ Fnl *run_queue; @@ -121,9 +110,6 @@ typedef struct NewGC { void (*unsafe_allocation_abort)(); unsigned long memory_in_use; /* the amount of memory in use */ - void *park[2]; - void *park_save[2]; - /* blame the child saved off Mark_Proc pointers */ Mark_Proc normal_thread_mark; Mark_Proc normal_custodian_mark; @@ -145,6 +131,12 @@ typedef struct NewGC { unsigned long num_minor_collects; unsigned long num_major_collects; + GC_Immobile_Box *immobile_boxes; + + /* Common with CompactGC */ + void *park[2]; + void *park_save[2]; + unsigned short weak_array_tag; unsigned short weak_box_tag; unsigned short ephemeron_tag; @@ -155,13 +147,18 @@ typedef struct NewGC { GC_Weak_Box *weak_boxes; GC_Ephemeron *ephemerons; int num_last_seen_ephemerons; - GC_Immobile_Box *immobile_boxes; } NewGC; void NewGC_initialize(NewGC *newgc) { memset(newgc, 0, sizeof(NewGC)); newgc->mark_table = malloc(NUMBER_OF_TAGS * sizeof (Mark_Proc)); newgc->fixup_table = malloc(NUMBER_OF_TAGS * sizeof (Fixup_Proc)); +#ifdef SIXTY_FOUR_BIT_INTEGERS + newgc->page_mapss = malloc(PAGEMAP64_LEVEL1_SIZE * sizeof (mpage***)); +#else + newgc->page_map = malloc(PAGEMAP32_SIZE * sizeof (mpage*)); +#endif + newgc->primoridal_gc = NULL; newgc->max_heap_size = 0; newgc->max_pages_in_heap = 0;