Places: message allocators
This commit is contained in:
parent
04dceafe49
commit
d43cbab863
|
@ -462,6 +462,27 @@ GC2_EXTERN void GC_allow_master_gc_check();
|
||||||
in master gc collections
|
in master gc collections
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
GC2_EXTERN void GC_create_message_allocator();
|
||||||
|
/*
|
||||||
|
Saves off the gc->gen0 to gc->saved_allocator.
|
||||||
|
Captures all memory allocations until GC_finish_message_allocator i
|
||||||
|
is called so they can be sent to another place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GC2_EXTERN void *GC_finish_message_allocator();
|
||||||
|
/*
|
||||||
|
Stops memory allocation capture.
|
||||||
|
Restores gc->saved_allocator to gc->gen0.
|
||||||
|
Returns a void* that represents the message memory captured.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GC2_EXTERN void GC_adopt_message_allocator(void *msg_memory);
|
||||||
|
/*
|
||||||
|
Adopts the message memory captures by the sending place into
|
||||||
|
the current receiving place's gc
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
};
|
};
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -820,7 +820,17 @@ static void *allocate_big(const size_t request_size_bytes, int type)
|
||||||
bpage->next = gc->gen0.big_pages;
|
bpage->next = gc->gen0.big_pages;
|
||||||
if(bpage->next) bpage->next->prev = bpage;
|
if(bpage->next) bpage->next->prev = bpage;
|
||||||
gc->gen0.big_pages = bpage;
|
gc->gen0.big_pages = bpage;
|
||||||
pagemap_add(gc->page_maps, bpage);
|
|
||||||
|
|
||||||
|
/* orphan this page from the current GC */
|
||||||
|
/* this page is going to be sent to a different place, don't account for it here */
|
||||||
|
/* message memory pages shouldn't go into the page_map, they are getting sent to another place */
|
||||||
|
if (gc->saved_allocator) {
|
||||||
|
mmu_memory_allocated_dec(gc->mmu, allocate_size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pagemap_add(gc->page_maps, bpage);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
void * objptr = BIG_PAGE_TO_OBJECT(bpage);
|
void * objptr = BIG_PAGE_TO_OBJECT(bpage);
|
||||||
|
@ -962,7 +972,17 @@ inline static mpage *gen0_create_new_nursery_mpage(NewGC *gc, const size_t page_
|
||||||
page->size_class = 0;
|
page->size_class = 0;
|
||||||
page->size = PREFIX_SIZE;
|
page->size = PREFIX_SIZE;
|
||||||
GEN0_ALLOC_SIZE(page) = page_size;
|
GEN0_ALLOC_SIZE(page) = page_size;
|
||||||
pagemap_add_with_size(gc->page_maps, page, page_size);
|
|
||||||
|
/* orphan this page from the current GC */
|
||||||
|
/* this page is going to be sent to a different place, don't account for it here */
|
||||||
|
/* message memory pages shouldn't go into the page_map, they are getting sent to another place */
|
||||||
|
if (gc->saved_allocator) {
|
||||||
|
mmu_memory_allocated_dec(gc->mmu, page_size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pagemap_add_with_size(gc->page_maps, page, page_size);
|
||||||
|
}
|
||||||
|
|
||||||
GCVERBOSEPAGE(gc, "NEW gen0", page);
|
GCVERBOSEPAGE(gc, "NEW gen0", page);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
|
@ -1034,13 +1054,32 @@ inline static size_t gen0_size_in_use(NewGC *gc) {
|
||||||
|
|
||||||
#define BYTES_MULTIPLE_OF_WORD_TO_WORDS(sizeb) ((sizeb) >> gcLOG_WORD_SIZE)
|
#define BYTES_MULTIPLE_OF_WORD_TO_WORDS(sizeb) ((sizeb) >> gcLOG_WORD_SIZE)
|
||||||
|
|
||||||
inline unsigned long allocate_slowpath(NewGC *gc, size_t allocate_size, unsigned long newptr)
|
inline static void gen0_sync_page_size_from_globals(NewGC *gc) {
|
||||||
|
gc->gen0.curr_alloc_page->size = GC_gen0_alloc_page_ptr - NUM(gc->gen0.curr_alloc_page->addr);
|
||||||
|
gc->gen0.current_size += gc->gen0.curr_alloc_page->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void gen0_allocate_and_setup_new_page(NewGC *gc) {
|
||||||
|
mpage *new_mpage = gen0_create_new_mpage(gc);
|
||||||
|
|
||||||
|
/* push page */
|
||||||
|
new_mpage->next = gc->gen0.curr_alloc_page;
|
||||||
|
if (new_mpage->next) {
|
||||||
|
new_mpage->next->prev = new_mpage;
|
||||||
|
}
|
||||||
|
gc->gen0.curr_alloc_page = new_mpage;
|
||||||
|
|
||||||
|
GC_gen0_alloc_page_ptr = NUM(new_mpage->addr);
|
||||||
|
ASSERT_VALID_OBJPTR(GC_gen0_alloc_page_ptr);
|
||||||
|
GC_gen0_alloc_page_end = NUM(new_mpage->addr) + GEN0_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static unsigned long allocate_slowpath(NewGC *gc, size_t allocate_size, unsigned long newptr)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
/* master always overflows and uses allocate_medium because master allocations can't move */
|
/* master always overflows and uses allocate_medium because master allocations can't move */
|
||||||
/* bring page size used up to date */
|
/* bring page size used up to date */
|
||||||
gc->gen0.curr_alloc_page->size = GC_gen0_alloc_page_ptr - NUM(gc->gen0.curr_alloc_page->addr);
|
gen0_sync_page_size_from_globals(gc);
|
||||||
gc->gen0.current_size += gc->gen0.curr_alloc_page->size;
|
|
||||||
|
|
||||||
/* try next nursery page if present */
|
/* try next nursery page if present */
|
||||||
if(gc->gen0.curr_alloc_page->next) {
|
if(gc->gen0.curr_alloc_page->next) {
|
||||||
|
@ -1052,16 +1091,7 @@ inline unsigned long allocate_slowpath(NewGC *gc, size_t allocate_size, unsigned
|
||||||
/* WARNING: tries to avoid a collection but
|
/* WARNING: tries to avoid a collection but
|
||||||
* gen0_create_new_mpage can cause a collection via malloc_pages due to check_used_against_max */
|
* gen0_create_new_mpage can cause a collection via malloc_pages due to check_used_against_max */
|
||||||
else if (gc->dumping_avoid_collection) {
|
else if (gc->dumping_avoid_collection) {
|
||||||
mpage *new_mpage = gen0_create_new_mpage(gc);
|
gen0_allocate_and_setup_new_page(gc);
|
||||||
|
|
||||||
/* push page */
|
|
||||||
new_mpage->next = gc->gen0.curr_alloc_page;
|
|
||||||
new_mpage->next->prev = new_mpage;
|
|
||||||
|
|
||||||
gc->gen0.curr_alloc_page = new_mpage;
|
|
||||||
GC_gen0_alloc_page_ptr = NUM(new_mpage->addr);
|
|
||||||
ASSERT_VALID_OBJPTR(GC_gen0_alloc_page_ptr);
|
|
||||||
GC_gen0_alloc_page_end = NUM(new_mpage->addr) + GEN0_PAGE_SIZE;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef INSTRUMENT_PRIMITIVES
|
#ifdef INSTRUMENT_PRIMITIVES
|
||||||
|
@ -1265,6 +1295,119 @@ long GC_alloc_alignment()
|
||||||
|
|
||||||
long GC_malloc_stays_put_threshold() { return MAX_OBJECT_SIZE; }
|
long GC_malloc_stays_put_threshold() { return MAX_OBJECT_SIZE; }
|
||||||
|
|
||||||
|
void GC_create_message_allocator() {
|
||||||
|
NewGC *gc = GC_get_GC();
|
||||||
|
Allocator *a;
|
||||||
|
|
||||||
|
GC_ASSERT(gc->saved_allocator == NULL);
|
||||||
|
gc->saved_allocator = (Allocator *) ofm_malloc(sizeof(Allocator));
|
||||||
|
a = gc->saved_allocator;
|
||||||
|
|
||||||
|
a->savedGen0.curr_alloc_page = gc->gen0.curr_alloc_page;
|
||||||
|
a->savedGen0.pages = gc->gen0.pages;
|
||||||
|
a->savedGen0.big_pages = gc->gen0.big_pages;
|
||||||
|
a->savedGen0.current_size = gc->gen0.current_size;
|
||||||
|
a->savedGen0.max_size = gc->gen0.max_size;
|
||||||
|
a->saved_alloc_page_ptr = GC_gen0_alloc_page_ptr;
|
||||||
|
a->saved_alloc_page_end = GC_gen0_alloc_page_end;
|
||||||
|
|
||||||
|
/* allocate initial gen0.page */
|
||||||
|
gc->gen0.pages = NULL;
|
||||||
|
gc->gen0.curr_alloc_page = NULL;
|
||||||
|
gen0_allocate_and_setup_new_page(gc);
|
||||||
|
gc->gen0.pages = gc->gen0.curr_alloc_page;
|
||||||
|
gc->gen0.big_pages = NULL;
|
||||||
|
gc->gen0.current_size = 0;
|
||||||
|
gc->gen0.max_size = 100 * 1024 * 1024; /* some big number, doesn't matter because collection will be disabled */
|
||||||
|
|
||||||
|
gc->in_unsafe_allocation_mode = 1;
|
||||||
|
gc->dumping_avoid_collection++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *GC_finish_message_allocator() {
|
||||||
|
NewGC *gc = GC_get_GC();
|
||||||
|
Allocator *a = gc->saved_allocator;
|
||||||
|
MsgMemory *msgm = (MsgMemory *) ofm_malloc(sizeof(MsgMemory));
|
||||||
|
|
||||||
|
gen0_sync_page_size_from_globals(gc);
|
||||||
|
|
||||||
|
msgm->pages = gc->gen0.pages;
|
||||||
|
msgm->big_pages = gc->gen0.big_pages;
|
||||||
|
msgm->size = gc->gen0.current_size;
|
||||||
|
|
||||||
|
gc->gen0.curr_alloc_page = a->savedGen0.curr_alloc_page ;
|
||||||
|
gc->gen0.pages = a->savedGen0.pages ;
|
||||||
|
gc->gen0.big_pages = a->savedGen0.big_pages ;
|
||||||
|
gc->gen0.current_size = a->savedGen0.current_size ;
|
||||||
|
gc->gen0.max_size = a->savedGen0.max_size ;
|
||||||
|
GC_gen0_alloc_page_ptr = a->saved_alloc_page_ptr ;
|
||||||
|
GC_gen0_alloc_page_end = a->saved_alloc_page_end ;
|
||||||
|
|
||||||
|
free(a);
|
||||||
|
gc->saved_allocator = NULL;
|
||||||
|
|
||||||
|
gc->in_unsafe_allocation_mode = 0;
|
||||||
|
gc->dumping_avoid_collection--;
|
||||||
|
|
||||||
|
return (void *) msgm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GC_adopt_message_allocator(void *param) {
|
||||||
|
NewGC *gc = GC_get_GC();
|
||||||
|
mpage *tmp;
|
||||||
|
MsgMemory *msgm = (MsgMemory *) param;
|
||||||
|
|
||||||
|
if (msgm->big_pages)
|
||||||
|
{
|
||||||
|
tmp = msgm->big_pages;
|
||||||
|
pagemap_add(gc->page_maps, tmp);
|
||||||
|
mmu_memory_allocated_inc(gc->mmu, tmp->size);
|
||||||
|
while (tmp->next) {
|
||||||
|
tmp = tmp->next;
|
||||||
|
|
||||||
|
pagemap_add(gc->page_maps, tmp);
|
||||||
|
mmu_memory_allocated_inc(gc->mmu, tmp->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* push msgm->big_pages onto the head of the list */
|
||||||
|
tmp->next = gc->gen0.big_pages;
|
||||||
|
if (tmp->next) {
|
||||||
|
tmp->next->prev = tmp;
|
||||||
|
}
|
||||||
|
gc->gen0.big_pages = msgm->big_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgm->pages)
|
||||||
|
{
|
||||||
|
mpage *gen0end;
|
||||||
|
|
||||||
|
tmp = msgm->pages;
|
||||||
|
mmu_memory_allocated_dec(gc->mmu, GEN0_ALLOC_SIZE(tmp));
|
||||||
|
pagemap_add_with_size(gc->page_maps, tmp, GEN0_ALLOC_SIZE(tmp));
|
||||||
|
while (tmp->next) {
|
||||||
|
tmp = tmp->next;
|
||||||
|
|
||||||
|
mmu_memory_allocated_dec(gc->mmu, GEN0_ALLOC_SIZE(tmp));
|
||||||
|
pagemap_add_with_size(gc->page_maps, tmp, GEN0_ALLOC_SIZE(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preserve locality of gen0, when it resizes by adding message pages to end of gen0.pages list */
|
||||||
|
/* append msgm->big_pages onto the tail of the list */
|
||||||
|
gen0end = gc->gen0.curr_alloc_page;
|
||||||
|
while (gen0end->next) {
|
||||||
|
gen0end = gen0end->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen0end->next = msgm->pages;
|
||||||
|
msgm->pages->prev = gen0end;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc->gen0.current_size += msgm->size;
|
||||||
|
|
||||||
|
free(msgm);
|
||||||
|
}
|
||||||
|
|
||||||
/* this function resizes generation 0 to the closest it can get (erring high)
|
/* this function resizes generation 0 to the closest it can get (erring high)
|
||||||
to the size we've computed as ideal */
|
to the size we've computed as ideal */
|
||||||
inline static void resize_gen0(NewGC *gc, unsigned long new_size)
|
inline static void resize_gen0(NewGC *gc, unsigned long new_size)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct mpage {
|
typedef struct mpage {
|
||||||
struct mpage *next;
|
struct mpage *next;
|
||||||
struct mpage *prev;
|
struct mpage *prev;
|
||||||
|
@ -43,13 +42,25 @@ typedef struct mpage {
|
||||||
} mpage;
|
} mpage;
|
||||||
|
|
||||||
typedef struct Gen0 {
|
typedef struct Gen0 {
|
||||||
struct mpage *curr_alloc_page;
|
struct mpage *curr_alloc_page;
|
||||||
struct mpage *pages;
|
struct mpage *pages;
|
||||||
struct mpage *big_pages;
|
struct mpage *big_pages;
|
||||||
unsigned long current_size;
|
unsigned long current_size;
|
||||||
unsigned long max_size;
|
unsigned long max_size;
|
||||||
} Gen0;
|
} Gen0;
|
||||||
|
|
||||||
|
typedef struct MsgMemory {
|
||||||
|
struct mpage *pages;
|
||||||
|
struct mpage *big_pages;
|
||||||
|
unsigned long size;
|
||||||
|
} MsgMemory;
|
||||||
|
|
||||||
|
typedef struct Allocator {
|
||||||
|
Gen0 savedGen0;
|
||||||
|
unsigned long saved_alloc_page_ptr;
|
||||||
|
unsigned long saved_alloc_page_end;
|
||||||
|
} Allocator;
|
||||||
|
|
||||||
typedef struct MarkSegment {
|
typedef struct MarkSegment {
|
||||||
struct MarkSegment *prev;
|
struct MarkSegment *prev;
|
||||||
struct MarkSegment *next;
|
struct MarkSegment *next;
|
||||||
|
@ -232,6 +243,8 @@ typedef struct NewGC {
|
||||||
int num_last_seen_ephemerons;
|
int num_last_seen_ephemerons;
|
||||||
struct MMU *mmu;
|
struct MMU *mmu;
|
||||||
|
|
||||||
|
Allocator *saved_allocator;
|
||||||
|
|
||||||
#if defined(GC_DEBUG_PAGES)
|
#if defined(GC_DEBUG_PAGES)
|
||||||
FILE *GCVERBOSEFH;
|
FILE *GCVERBOSEFH;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -222,14 +222,22 @@ static size_t mmu_memory_allocated(MMU *mmu) {
|
||||||
return mmu->memory_allocated;
|
return mmu->memory_allocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ( defined(_WIN32) || defined(OSKIT) )
|
|
||||||
|
/* _WIN32 and OSKIT use these functions
|
||||||
|
On OSX and Linux the block and alloc caches
|
||||||
|
manipulate mmu->memory_allocated directly.
|
||||||
|
|
||||||
|
The gc calls mmu_memory_allocated_dec for
|
||||||
|
pages that are going to be orphaned sent to a different place.
|
||||||
|
The gc calls mmu_memory_allocated_inc for
|
||||||
|
pages that are going to be adopted from another place.
|
||||||
|
*/
|
||||||
static void mmu_memory_allocated_inc(MMU *mmu, long amt) {
|
static void mmu_memory_allocated_inc(MMU *mmu, long amt) {
|
||||||
mmu->memory_allocated += amt;
|
mmu->memory_allocated += amt;
|
||||||
}
|
}
|
||||||
static void mmu_memory_allocated_dec(MMU *mmu, long amt) {
|
static void mmu_memory_allocated_dec(MMU *mmu, long amt) {
|
||||||
mmu->memory_allocated -= amt;
|
mmu->memory_allocated -= amt;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _WIN32 /* Windows */
|
#if _WIN32 /* Windows */
|
||||||
# include "vm_win.c"
|
# include "vm_win.c"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user