adaptive future-nursery size

svn: r17252
This commit is contained in:
Matthew Flatt 2009-12-10 02:25:46 +00:00
parent 4e6117b9d8
commit d4aaa9cf6f
6 changed files with 68 additions and 26 deletions

View File

@ -410,9 +410,16 @@ GC2_EXTERN void GC_switch_back_from_master(void *gc);
Switches to back to gc from the master GC
*/
GC2_EXTERN unsigned long GC_make_jit_nursery_page();
GC2_EXTERN long GC_alloc_alignment();
/*
Obtains a nursery page from the GC for thread local allocation.
Guaranteeed alignment for nusery pages. Returns a constant, and
can be called from any thread.
*/
GC2_EXTERN unsigned long GC_make_jit_nursery_page(int count);
/*
Obtains nursery pages from the GC for thread local allocation;
resulting space is count times the allocation alignment.
The result is an unsigned long because it's not a valid
pointer to a GCable object. The result becomes invalid (i.e. it's collected)
with the next GC.

View File

@ -814,6 +814,7 @@ inline static mpage *gen0_create_new_nursery_mpage(NewGC *gc, const size_t page_
newmpage->addr = malloc_dirty_pages(gc, page_size, APAGE_SIZE);
newmpage->size_class = 0;
newmpage->size = PREFIX_SIZE;
newmpage->previous_size = page_size;
pagemap_add_with_size(gc->page_maps, newmpage, page_size);
GCVERBOSEPAGE("NEW gen0", newmpage);
@ -829,18 +830,19 @@ inline static void gen0_free_nursery_mpage(NewGC *gc, mpage *page, size_t page_s
/* Needs to be consistent with GC_alloc_alignment(): */
#define THREAD_LOCAL_PAGE_SIZE APAGE_SIZE
unsigned long GC_make_jit_nursery_page() {
unsigned long GC_make_jit_nursery_page(int count) {
NewGC *gc = GC_get_GC();
mpage *new_mpage;
long size = count * THREAD_LOCAL_PAGE_SIZE;
if((gc->gen0.current_size + THREAD_LOCAL_PAGE_SIZE) >= gc->gen0.max_size) {
if((gc->gen0.current_size + size) >= gc->gen0.max_size) {
if (!gc->dumping_avoid_collection)
garbage_collect(gc, 0);
}
gc->gen0.current_size += THREAD_LOCAL_PAGE_SIZE;
gc->gen0.current_size += size;
{
new_mpage = gen0_create_new_nursery_mpage(gc, THREAD_LOCAL_PAGE_SIZE);
new_mpage = gen0_create_new_nursery_mpage(gc, size);
/* push page */
new_mpage->next = gc->thread_local_pages;
@ -865,7 +867,7 @@ unsigned long GC_make_jit_nursery_page() {
}
inline static void gen0_free_jit_nursery_page(NewGC *gc, mpage *page) {
gen0_free_nursery_mpage(gc, page, THREAD_LOCAL_PAGE_SIZE);
gen0_free_nursery_mpage(gc, page, page->previous_size);
}
inline static mpage *gen0_create_new_mpage(NewGC *gc) {
@ -1211,7 +1213,7 @@ inline static int marked(NewGC *gc, void *p)
if (page->size_class > 1) {
return (page->size_class > 2);
}
} else {
} else if (page->generation) {
if((NUM(page->addr) + page->previous_size) > NUM(p))
return 1;
}

View File

@ -5,8 +5,8 @@ typedef struct mpage {
struct mpage *next;
struct mpage *prev;
void *addr;
unsigned long previous_size; /* for med page, points to place to search for available block */
unsigned long size; /* big page size or med page element size */
unsigned long previous_size; /* for med page, place to search for available block; for jit nursery, allocated size */
unsigned long size; /* big page size, med page element size, or nursery starting point */
unsigned char generation;
/*
unsigned char back_pointers :1;

View File

@ -199,6 +199,10 @@ typedef struct Scheme_Future_Thread_State {
volatile int *fuel_pointer;
volatile unsigned long *stack_boundary_pointer;
volatile int *need_gc_pointer;
unsigned long gen0_start;
unsigned long gen0_size;
unsigned long gen0_initial_offset;
} Scheme_Future_Thread_State;
THREAD_LOCAL_DECL(static Scheme_Future_State *scheme_future_state);
@ -412,6 +416,8 @@ static void init_future_thread(Scheme_Future_State *fs, int i)
fts->threadid = threadid;
fts->gen0_size = 1;
scheme_register_static(&fts->current_ft, sizeof(void*));
scheme_register_static(params.scheme_current_runstack_ptr, sizeof(void*));
scheme_register_static(params.scheme_current_runstack_start_ptr, sizeof(void*));
@ -434,6 +440,9 @@ static void start_gc_not_ok(Scheme_Future_State *fs)
Scheme_Future_Thread_State *fts = scheme_future_thread_state;
if (fts->worker_gc_counter != *fs->gc_counter_ptr) {
GC_gen0_alloc_page_ptr = 0; /* forces future to ask for memory */
fts->gen0_start = 0;
if (fts->gen0_size > 1)
fts->gen0_size >>= 1;
fts->worker_gc_counter = *fs->gc_counter_ptr;
}
}
@ -959,9 +968,8 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts,
}
}
/**********************************************************************/
/* Functions for primitive invocation */
/* Functions for primitive invocation */
/**********************************************************************/
void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void_3args_t f)
XFORM_SKIP_PROC
@ -983,7 +991,9 @@ void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void
future->arg_S0 = NULL;
}
unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_type, prim_alloc_void_pvoid_t f)
#ifdef MZ_PRECISE_GC
unsigned long scheme_rtcall_alloc(const char *who, int src_type)
XFORM_SKIP_PROC
/* Called in future thread */
{
@ -991,21 +1001,43 @@ unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_type, prim
unsigned long retval;
Scheme_Future_Thread_State *fts = scheme_future_thread_state;
Scheme_Future_State *fs = scheme_future_state;
long align;
align = GC_alloc_alignment();
/* Do we actually still have space? */
if (fts->gen0_start) {
long cur;
cur = GC_gen0_alloc_page_ptr;
if (cur < (fts->gen0_start + (fts->gen0_size - 1) * align)) {
cur &= ~(align - 1);
cur += align + fts->gen0_initial_offset;
return cur;
}
}
/* Grow nursery size as long as we don't trigger a GC */
if (fts->gen0_size < 16)
fts->gen0_size <<= 1;
while (1) {
future = fts->current_ft;
future->time_of_request = 0; /* takes too long?: scheme_get_inexact_milliseconds(); */
future->time_of_request = scheme_get_inexact_milliseconds();
future->source_of_request = who;
future->source_type = src_type;
future->prim_protocol = SIG_ALLOC_VOID_PVOID;
future->prim_protocol = SIG_ALLOC;
future->arg_i0 = fts->gen0_size;
future_do_runtimecall(fts, (void*)f, 1);
future_do_runtimecall(fts, (void*)GC_make_jit_nursery_page, 1);
future = fts->current_ft;
retval = future->alloc_retval;
future->alloc_retval = 0;
fts->gen0_start = retval;
fts->gen0_initial_offset = retval & (align - 1);
if (*fs->gc_counter_ptr == future->alloc_retval_counter)
break;
}
@ -1013,6 +1045,8 @@ unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_type, prim
return retval;
}
#endif
static void receive_special_result(future_t *f, Scheme_Object *retval, int clear)
XFORM_SKIP_PROC
/* Called in future or runtime thread */
@ -1108,15 +1142,16 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future)
break;
}
case SIG_ALLOC_VOID_PVOID:
#ifdef MZ_PRECISE_GC
case SIG_ALLOC:
{
unsigned long ret;
prim_alloc_void_pvoid_t func = (prim_alloc_void_pvoid_t)future->prim_func;
ret = func();
ret = GC_make_jit_nursery_page(future->arg_i0);
future->alloc_retval = ret;
future->alloc_retval_counter = scheme_did_gc_count;
break;
}
#endif
# include "jit_ts_runtime_glue.c"
default:
scheme_signal_error("unknown protocol %d", future->prim_protocol);

View File

@ -24,7 +24,6 @@ int scheme_make_prim_w_arity(prim_t func, char *name, int arg1, int arg2);
#include <stdio.h>
typedef void (*prim_void_void_3args_t)(Scheme_Object **);
typedef unsigned long (*prim_alloc_void_pvoid_t)();
typedef Scheme_Object* (*prim_obj_int_pobj_obj_t)(Scheme_Object*, int, Scheme_Object**);
typedef Scheme_Object* (*prim_int_pobj_obj_t)(int, Scheme_Object**);
typedef Scheme_Object* (*prim_int_pobj_obj_obj_t)(int, Scheme_Object**, Scheme_Object*);
@ -105,7 +104,7 @@ typedef struct future_t {
//Signature flags for primitive invocations
//Here the convention is SIG_[arg1type]_[arg2type]..._[return type]
#define SIG_VOID_VOID_3ARGS 1 //void -> void, copy 3 args from runstack
#define SIG_ALLOC_VOID_PVOID 2 //void -> void*
#define SIG_ALLOC 2 //void -> void*
# include "jit_ts_protos.h"
@ -122,7 +121,7 @@ extern Scheme_Object *scheme_ts_scheme_force_value_same_mark(Scheme_Object *v);
}
extern void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void_3args_t f);
extern unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_type, prim_alloc_void_pvoid_t f);
extern unsigned long scheme_rtcall_alloc(const char *who, int src_type);
#else
@ -136,7 +135,7 @@ extern unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_typ
#define LOG_THISCALL LOG(__FUNCTION__)
#define LOG_RTCALL_VOID_VOID_3ARGS(f) LOG("(function=%p)", f)
#define LOG_RTCALL_ALLOC_VOID_PVOID(f) LOG("(function=%p)", f)
#define LOG_RTCALL_ALLOC(f) LOG("(function=%p)", f)
#define LOG_RTCALL_OBJ_INT_POBJ_OBJ(f,a,b,c) LOG("(function = %p, a=%p, b=%d, c=%p)", f, a, b, c)
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c) LOG("(%p, %d, %p)", a, b,c)
#define LOG_RTCALL_INT_OBJARR_OBJ(a,b) LOG("(%d, %p)", a, b)
@ -159,7 +158,7 @@ extern unsigned long scheme_rtcall_alloc_void_pvoid(const char *who, int src_typ
#define LOG_THISCALL
#define LOG_RTCALL_VOID_VOID_3ARGS(f)
#define LOG_RTCALL_ALLOC_VOID_PVOID(f)
#define LOG_RTCALL_ALLOC(f)
#define LOG_RTCALL_OBJ_INT_POBJ_OBJ(f,a,b,c)
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c)
#define LOG_RTCALL_INT_OBJARR_OBJ(a,b)

View File

@ -1394,7 +1394,6 @@ THREAD_LOCAL_DECL(extern unsigned long GC_gen0_alloc_page_ptr);
long GC_initial_word(int sizeb);
void GC_initial_words(char *buffer, int sizeb);
long GC_compute_alloc_size(long sizeb);
long GC_alloc_alignment(void);
static void *retry_alloc_code;
static void *retry_alloc_code_keep_r0_r1;
@ -2257,7 +2256,7 @@ static void *ts_prepare_retry_alloc(void *p, void *p2) XFORM_SKIP_PROC
if (scheme_use_rtcall) {
jit_future_storage[0] = p;
jit_future_storage[1] = p2;
ret = scheme_rtcall_alloc_void_pvoid("[acquire_gc_page]", FSRC_OTHER, GC_make_jit_nursery_page);
ret = scheme_rtcall_alloc("[acquire_gc_page]", FSRC_OTHER);
GC_gen0_alloc_page_ptr = ret;
retry_alloc_r1 = jit_future_storage[1];
p = jit_future_storage[0];