Reduced all THREAD local GC usage to NewGC *gc = GC; to be replaces with GC_get_GC()
svn: r12306
This commit is contained in:
parent
1d5d7ea18f
commit
4b29ac09c3
|
@ -8,51 +8,53 @@
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* thread list */
|
/* thread list */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
inline static int current_owner(Scheme_Custodian *c);
|
inline static int current_owner(NewGC *gc, Scheme_Custodian *c);
|
||||||
|
|
||||||
inline static void BTC_register_new_thread(void *t, void *c)
|
inline static void BTC_register_new_thread(void *t, void *c)
|
||||||
{
|
{
|
||||||
|
NewGC *gc = GC;
|
||||||
GC_Thread_Info *work;
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
work = (GC_Thread_Info *)malloc(sizeof(GC_Thread_Info));
|
work = (GC_Thread_Info *)malloc(sizeof(GC_Thread_Info));
|
||||||
((Scheme_Thread *)t)->gc_info = work;
|
((Scheme_Thread *)t)->gc_info = work;
|
||||||
work->owner = current_owner((Scheme_Custodian *)c);
|
work->owner = current_owner(gc, (Scheme_Custodian *)c);
|
||||||
work->thread = t;
|
work->thread = t;
|
||||||
|
|
||||||
work->next = GC->thread_infos;
|
work->next = gc->thread_infos;
|
||||||
GC->thread_infos = work;
|
gc->thread_infos = work;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void BTC_register_thread(void *t, void *c)
|
inline static void BTC_register_thread(void *t, void *c)
|
||||||
{
|
{
|
||||||
|
NewGC *gc = GC;
|
||||||
GC_Thread_Info *work;
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
work = ((Scheme_Thread *)t)->gc_info;
|
work = ((Scheme_Thread *)t)->gc_info;
|
||||||
work->owner = current_owner((Scheme_Custodian *)c);
|
work->owner = current_owner(gc, (Scheme_Custodian *)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void mark_threads(int owner)
|
inline static void mark_threads(NewGC *gc, int owner)
|
||||||
{
|
{
|
||||||
GC_Thread_Info *work;
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
for(work = GC->thread_infos; work; work = work->next)
|
for(work = gc->thread_infos; work; work = work->next)
|
||||||
if(work->owner == owner) {
|
if(work->owner == owner) {
|
||||||
if (((Scheme_Thread *)work->thread)->running) {
|
if (((Scheme_Thread *)work->thread)->running) {
|
||||||
GC->normal_thread_mark(work->thread);
|
gc->normal_thread_mark(work->thread);
|
||||||
if (work->thread == scheme_current_thread) {
|
if (work->thread == scheme_current_thread) {
|
||||||
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(), NULL);
|
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(gc), NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void clean_up_thread_list(void)
|
inline static void clean_up_thread_list(NewGC *gc)
|
||||||
{
|
{
|
||||||
GC_Thread_Info *work = GC->thread_infos;
|
GC_Thread_Info *work = gc->thread_infos;
|
||||||
GC_Thread_Info *prev = NULL;
|
GC_Thread_Info *prev = NULL;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if(!pagemap_find_page(GC->page_maps, work->thread) || marked(work->thread)) {
|
if(!pagemap_find_page(gc->page_maps, work->thread) || marked(gc, work->thread)) {
|
||||||
work->thread = GC_resolve(work->thread);
|
work->thread = GC_resolve(work->thread);
|
||||||
prev = work;
|
prev = work;
|
||||||
work = work->next;
|
work = work->next;
|
||||||
|
@ -60,7 +62,7 @@ inline static void clean_up_thread_list(void)
|
||||||
GC_Thread_Info *next = work->next;
|
GC_Thread_Info *next = work->next;
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
if(prev) prev->next = next;
|
||||||
if(!prev) GC->thread_infos = next;
|
if(!prev) gc->thread_infos = next;
|
||||||
free(work);
|
free(work);
|
||||||
work = next;
|
work = next;
|
||||||
}
|
}
|
||||||
|
@ -74,11 +76,11 @@ inline static int thread_get_owner(void *p)
|
||||||
|
|
||||||
#define OWNER_TABLE_INIT_AMT 10
|
#define OWNER_TABLE_INIT_AMT 10
|
||||||
|
|
||||||
inline static int create_blank_owner_set(void)
|
inline static int create_blank_owner_set(NewGC *gc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int curr_size = GC->owner_table_size;
|
unsigned int curr_size = gc->owner_table_size;
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
unsigned int old_size;
|
unsigned int old_size;
|
||||||
OTEntry **naya;
|
OTEntry **naya;
|
||||||
|
|
||||||
|
@ -97,65 +99,66 @@ inline static int create_blank_owner_set(void)
|
||||||
else {
|
else {
|
||||||
curr_size *= 2;
|
curr_size *= 2;
|
||||||
}
|
}
|
||||||
GC->owner_table_size = curr_size;
|
gc->owner_table_size = curr_size;
|
||||||
|
|
||||||
naya = (OTEntry **)malloc(curr_size * sizeof(OTEntry*));
|
naya = (OTEntry **)malloc(curr_size * sizeof(OTEntry*));
|
||||||
memcpy(naya, owner_table, old_size*sizeof(OTEntry*));
|
memcpy(naya, owner_table, old_size*sizeof(OTEntry*));
|
||||||
GC->owner_table = owner_table = naya;
|
gc->owner_table = owner_table = naya;
|
||||||
bzero(((char*)owner_table) + (sizeof(OTEntry*) * old_size),
|
bzero(((char*)owner_table) + (sizeof(OTEntry*) * old_size),
|
||||||
(curr_size - old_size) * sizeof(OTEntry*));
|
(curr_size - old_size) * sizeof(OTEntry*));
|
||||||
|
|
||||||
return create_blank_owner_set();
|
return create_blank_owner_set(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int custodian_to_owner_set(Scheme_Custodian *cust)
|
inline static int custodian_to_owner_set(NewGC *gc,Scheme_Custodian *cust)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (cust->gc_owner_set)
|
if (cust->gc_owner_set)
|
||||||
return cust->gc_owner_set;
|
return cust->gc_owner_set;
|
||||||
|
|
||||||
i = create_blank_owner_set();
|
i = create_blank_owner_set(gc);
|
||||||
GC->owner_table[i]->originator = cust;
|
gc->owner_table[i]->originator = cust;
|
||||||
cust->gc_owner_set = i;
|
cust->gc_owner_set = i;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int current_owner(Scheme_Custodian *c)
|
inline static int current_owner(NewGC *gc, Scheme_Custodian *c)
|
||||||
{
|
{
|
||||||
if (!scheme_current_thread)
|
if (!scheme_current_thread)
|
||||||
return 1;
|
return 1;
|
||||||
else if (!c)
|
else if (!c)
|
||||||
return thread_get_owner(scheme_current_thread);
|
return thread_get_owner(scheme_current_thread);
|
||||||
else
|
else
|
||||||
return custodian_to_owner_set(c);
|
return custodian_to_owner_set(gc, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BTC_register_root_custodian(void *_c)
|
void BTC_register_root_custodian(void *_c)
|
||||||
{
|
{
|
||||||
|
NewGC *gc = GC;
|
||||||
Scheme_Custodian *c = (Scheme_Custodian *)_c;
|
Scheme_Custodian *c = (Scheme_Custodian *)_c;
|
||||||
|
|
||||||
if (GC->owner_table) {
|
if (gc->owner_table) {
|
||||||
/* Reset */
|
/* Reset */
|
||||||
free(GC->owner_table);
|
free(gc->owner_table);
|
||||||
GC->owner_table = NULL;
|
gc->owner_table = NULL;
|
||||||
GC->owner_table_size = 0;
|
gc->owner_table_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_blank_owner_set() != 1) {
|
if (create_blank_owner_set(gc) != 1) {
|
||||||
GCPRINT(GCOUTF, "Something extremely weird (and bad) has happened.\n");
|
GCPRINT(GCOUTF, "Something extremely weird (and bad) has happened.\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
GC->owner_table[1]->originator = c;
|
gc->owner_table[1]->originator = c;
|
||||||
c->gc_owner_set = 1;
|
c->gc_owner_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int custodian_member_owner_set(void *cust, int set)
|
inline static int custodian_member_owner_set(NewGC *gc, void *cust, int set)
|
||||||
{
|
{
|
||||||
Scheme_Custodian_Reference *box;
|
Scheme_Custodian_Reference *box;
|
||||||
Scheme_Custodian *work = (Scheme_Custodian *) GC->owner_table[set]->originator;
|
Scheme_Custodian *work = (Scheme_Custodian *) gc->owner_table[set]->originator;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if(work == cust) return 1;
|
if(work == cust) return 1;
|
||||||
|
@ -165,30 +168,30 @@ inline static int custodian_member_owner_set(void *cust, int set)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void account_memory(int set, long amount)
|
inline static void account_memory(NewGC *gc, int set, long amount)
|
||||||
{
|
{
|
||||||
GC->owner_table[set]->memory_use += amount;
|
gc->owner_table[set]->memory_use += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void free_owner_set(int set)
|
inline static void free_owner_set(NewGC *gc, int set)
|
||||||
{
|
{
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
if(owner_table[set]) {
|
if(owner_table[set]) {
|
||||||
free(owner_table[set]);
|
free(owner_table[set]);
|
||||||
}
|
}
|
||||||
owner_table[set] = NULL;
|
owner_table[set] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void clean_up_owner_table(void)
|
inline static void clean_up_owner_table(NewGC *gc)
|
||||||
{
|
{
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
const int table_size = GC->owner_table_size;
|
const int table_size = gc->owner_table_size;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 1; i < table_size; i++)
|
for(i = 1; i < table_size; i++)
|
||||||
if(owner_table[i]) {
|
if(owner_table[i]) {
|
||||||
/* repair or delete the originator */
|
/* repair or delete the originator */
|
||||||
if(!marked(owner_table[i]->originator)) {
|
if(!marked(gc, owner_table[i]->originator)) {
|
||||||
owner_table[i]->originator = NULL;
|
owner_table[i]->originator = NULL;
|
||||||
} else
|
} else
|
||||||
owner_table[i]->originator = GC_resolve(owner_table[i]->originator);
|
owner_table[i]->originator = GC_resolve(owner_table[i]->originator);
|
||||||
|
@ -196,53 +199,54 @@ inline static void clean_up_owner_table(void)
|
||||||
/* potential delete */
|
/* potential delete */
|
||||||
if(i != 1)
|
if(i != 1)
|
||||||
if((owner_table[i]->memory_use == 0) && !owner_table[i]->originator)
|
if((owner_table[i]->memory_use == 0) && !owner_table[i]->originator)
|
||||||
free_owner_set(i);
|
free_owner_set(gc, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static unsigned long custodian_usage(void *custodian)
|
inline static unsigned long custodian_usage(void *custodian)
|
||||||
{
|
{
|
||||||
OTEntry **owner_table = GC->owner_table;
|
NewGC *gc = GC;
|
||||||
const int table_size = GC->owner_table_size;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
|
const int table_size = gc->owner_table_size;
|
||||||
unsigned long retval = 0;
|
unsigned long retval = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(!GC->really_doing_accounting) {
|
if(!gc->really_doing_accounting) {
|
||||||
GC->park[0] = custodian;
|
gc->park[0] = custodian;
|
||||||
GC->really_doing_accounting = 1;
|
gc->really_doing_accounting = 1;
|
||||||
garbage_collect(1);
|
garbage_collect(1);
|
||||||
custodian = GC->park[0];
|
custodian = gc->park[0];
|
||||||
GC->park[0] = NULL;
|
gc->park[0] = NULL;
|
||||||
}
|
}
|
||||||
for(i = 1; i < table_size; i++)
|
for(i = 1; i < table_size; i++)
|
||||||
if(owner_table[i] && custodian_member_owner_set(custodian, i))
|
if(owner_table[i] && custodian_member_owner_set(gc, custodian, i))
|
||||||
retval += owner_table[i]->memory_use;
|
retval += owner_table[i]->memory_use;
|
||||||
return gcWORDS_TO_BYTES(retval);
|
return gcWORDS_TO_BYTES(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void BTC_memory_account_mark(struct mpage *page, void *ptr)
|
inline static void BTC_memory_account_mark(NewGC *gc, mpage *page, void *ptr)
|
||||||
{
|
{
|
||||||
GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr));
|
GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr));
|
||||||
if(page->big_page) {
|
if(page->big_page) {
|
||||||
struct objhead *info = (struct objhead *)(NUM(page->addr) + PREFIX_SIZE);
|
struct objhead *info = (struct objhead *)(NUM(page->addr) + PREFIX_SIZE);
|
||||||
|
|
||||||
if(info->btc_mark == GC->old_btc_mark) {
|
if(info->btc_mark == gc->old_btc_mark) {
|
||||||
info->btc_mark = GC->new_btc_mark;
|
info->btc_mark = gc->new_btc_mark;
|
||||||
account_memory(GC->current_mark_owner, gcBYTES_TO_WORDS(page->size));
|
account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(page->size));
|
||||||
push_ptr(ptr);
|
push_ptr(ptr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct objhead *info = (struct objhead *)((char*)ptr - WORD_SIZE);
|
struct objhead *info = (struct objhead *)((char*)ptr - WORD_SIZE);
|
||||||
|
|
||||||
if(info->btc_mark == GC->old_btc_mark) {
|
if(info->btc_mark == gc->old_btc_mark) {
|
||||||
info->btc_mark = GC->new_btc_mark;
|
info->btc_mark = gc->new_btc_mark;
|
||||||
account_memory(GC->current_mark_owner, info->size);
|
account_memory(gc, gc->current_mark_owner, info->size);
|
||||||
push_ptr(ptr);
|
push_ptr(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void mark_cust_boxes(Scheme_Custodian *cur)
|
inline static void mark_cust_boxes(NewGC *gc, Scheme_Custodian *cur)
|
||||||
{
|
{
|
||||||
Scheme_Object *pr, *prev = NULL, *next;
|
Scheme_Object *pr, *prev = NULL, *next;
|
||||||
GC_Weak_Box *wb;
|
GC_Weak_Box *wb;
|
||||||
|
@ -254,7 +258,7 @@ inline static void mark_cust_boxes(Scheme_Custodian *cur)
|
||||||
wb = (GC_Weak_Box *)SCHEME_CAR(pr);
|
wb = (GC_Weak_Box *)SCHEME_CAR(pr);
|
||||||
next = SCHEME_CDR(pr);
|
next = SCHEME_CDR(pr);
|
||||||
if (wb->val) {
|
if (wb->val) {
|
||||||
GC->normal_cust_box_mark(wb->val);
|
gc->normal_cust_box_mark(wb->val);
|
||||||
prev = pr;
|
prev = pr;
|
||||||
} else {
|
} else {
|
||||||
if (prev)
|
if (prev)
|
||||||
|
@ -274,8 +278,9 @@ int BTC_thread_mark(void *p)
|
||||||
|
|
||||||
int BTC_custodian_mark(void *p)
|
int BTC_custodian_mark(void *p)
|
||||||
{
|
{
|
||||||
if(custodian_to_owner_set(p) == GC->current_mark_owner)
|
NewGC *gc = GC;
|
||||||
return GC->normal_custodian_mark(p);
|
if(custodian_to_owner_set(gc, p) == gc->current_mark_owner)
|
||||||
|
return gc->normal_custodian_mark(p);
|
||||||
else
|
else
|
||||||
return ((struct objhead *)(NUM(p) - WORD_SIZE))->size;
|
return ((struct objhead *)(NUM(p) - WORD_SIZE))->size;
|
||||||
}
|
}
|
||||||
|
@ -285,7 +290,7 @@ int BTC_cust_box_mark(void *p)
|
||||||
return ((struct objhead *)(NUM(p) - WORD_SIZE))->size;
|
return ((struct objhead *)(NUM(p) - WORD_SIZE))->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void mark_normal_obj(struct mpage *page, void *ptr)
|
inline static void mark_normal_obj(NewGC *gc, mpage *page, void *ptr)
|
||||||
{
|
{
|
||||||
switch(page->page_type) {
|
switch(page->page_type) {
|
||||||
case PAGE_TAGGED: {
|
case PAGE_TAGGED: {
|
||||||
|
@ -295,7 +300,7 @@ inline static void mark_normal_obj(struct mpage *page, void *ptr)
|
||||||
ignore them outright. In the case of custodians, we do need
|
ignore them outright. In the case of custodians, we do need
|
||||||
to do the check; those differences are handled by replacing
|
to do the check; those differences are handled by replacing
|
||||||
the mark procedure in mark_table. */
|
the mark procedure in mark_table. */
|
||||||
GC->mark_table[*(unsigned short*)ptr](ptr);
|
gc->mark_table[*(unsigned short*)ptr](ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PAGE_ATOMIC: break;
|
case PAGE_ATOMIC: break;
|
||||||
|
@ -311,14 +316,14 @@ inline static void mark_normal_obj(struct mpage *page, void *ptr)
|
||||||
unsigned short tag = *(unsigned short*)ptr;
|
unsigned short tag = *(unsigned short*)ptr;
|
||||||
void **temp = ptr, **end = PPTR(info) + (info->size - INSET_WORDS);
|
void **temp = ptr, **end = PPTR(info) + (info->size - INSET_WORDS);
|
||||||
|
|
||||||
while(temp < end) temp += GC->mark_table[tag](temp);
|
while(temp < end) temp += gc->mark_table[tag](temp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PAGE_XTAGGED: GC_mark_xtagged(ptr); break;
|
case PAGE_XTAGGED: GC_mark_xtagged(ptr); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void mark_acc_big_page(struct mpage *page)
|
inline static void mark_acc_big_page(NewGC *gc, mpage *page)
|
||||||
{
|
{
|
||||||
void **start = PPTR(NUM(page->addr) + PREFIX_SIZE + WORD_SIZE);
|
void **start = PPTR(NUM(page->addr) + PREFIX_SIZE + WORD_SIZE);
|
||||||
void **end = PPTR(NUM(page->addr) + page->size);
|
void **end = PPTR(NUM(page->addr) + page->size);
|
||||||
|
@ -327,10 +332,10 @@ inline static void mark_acc_big_page(struct mpage *page)
|
||||||
case PAGE_TAGGED:
|
case PAGE_TAGGED:
|
||||||
{
|
{
|
||||||
unsigned short tag = *(unsigned short*)start;
|
unsigned short tag = *(unsigned short*)start;
|
||||||
if((unsigned long)GC->mark_table[tag] < PAGE_TYPES) {
|
if((unsigned long)gc->mark_table[tag] < PAGE_TYPES) {
|
||||||
/* atomic */
|
/* atomic */
|
||||||
} else
|
} else
|
||||||
GC->mark_table[tag](start); break;
|
gc->mark_table[tag](start); break;
|
||||||
}
|
}
|
||||||
case PAGE_ATOMIC: break;
|
case PAGE_ATOMIC: break;
|
||||||
case PAGE_ARRAY: while(start < end) gcMARK(*(start++)); break;
|
case PAGE_ARRAY: while(start < end) gcMARK(*(start++)); break;
|
||||||
|
@ -338,63 +343,63 @@ inline static void mark_acc_big_page(struct mpage *page)
|
||||||
case PAGE_TARRAY: {
|
case PAGE_TARRAY: {
|
||||||
unsigned short tag = *(unsigned short *)start;
|
unsigned short tag = *(unsigned short *)start;
|
||||||
end -= INSET_WORDS;
|
end -= INSET_WORDS;
|
||||||
while(start < end) start += GC->mark_table[tag](start);
|
while(start < end) start += gc->mark_table[tag](start);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void btc_overmem_abort()
|
static void btc_overmem_abort(NewGC *gc)
|
||||||
{
|
{
|
||||||
GC->kill_propagation_loop = 1;
|
gc->kill_propagation_loop = 1;
|
||||||
GCWARN((GCOUTF, "WARNING: Ran out of memory accounting. "
|
GCWARN((GCOUTF, "WARNING: Ran out of memory accounting. "
|
||||||
"Info will be wrong.\n"));
|
"Info will be wrong.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void propagate_accounting_marks(void)
|
static void propagate_accounting_marks(NewGC *gc)
|
||||||
{
|
{
|
||||||
struct mpage *page;
|
struct mpage *page;
|
||||||
void *p;
|
void *p;
|
||||||
PageMap pagemap = GC->page_maps;
|
PageMap pagemap = gc->page_maps;
|
||||||
while(pop_ptr(&p) && !GC->kill_propagation_loop) {
|
while(pop_ptr(&p) && !gc->kill_propagation_loop) {
|
||||||
page = pagemap_find_page(pagemap, p);
|
page = pagemap_find_page(pagemap, p);
|
||||||
set_backtrace_source(p, page->page_type);
|
set_backtrace_source(p, page->page_type);
|
||||||
GCDEBUG((DEBUGOUTF, "btc_account: popped off page %p:%p, ptr %p\n", page, page->addr, p));
|
GCDEBUG((DEBUGOUTF, "btc_account: popped off page %p:%p, ptr %p\n", page, page->addr, p));
|
||||||
if(page->big_page)
|
if(page->big_page)
|
||||||
mark_acc_big_page(page);
|
mark_acc_big_page(gc, page);
|
||||||
else
|
else
|
||||||
mark_normal_obj(page, p);
|
mark_normal_obj(gc, page, p);
|
||||||
}
|
}
|
||||||
if(GC->kill_propagation_loop)
|
if(gc->kill_propagation_loop)
|
||||||
reset_pointer_stack();
|
reset_pointer_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BTC_do_accounting(void)
|
static void BTC_do_accounting(NewGC *gc)
|
||||||
{
|
{
|
||||||
const int table_size = GC->owner_table_size;
|
const int table_size = gc->owner_table_size;
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
|
|
||||||
if(GC->really_doing_accounting) {
|
if(gc->really_doing_accounting) {
|
||||||
Scheme_Custodian *cur = owner_table[current_owner(NULL)]->originator;
|
Scheme_Custodian *cur = owner_table[current_owner(gc, NULL)]->originator;
|
||||||
Scheme_Custodian_Reference *box = cur->global_next;
|
Scheme_Custodian_Reference *box = cur->global_next;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
GCDEBUG((DEBUGOUTF, "\nBEGINNING MEMORY ACCOUNTING\n"));
|
GCDEBUG((DEBUGOUTF, "\nBEGINNING MEMORY ACCOUNTING\n"));
|
||||||
GC->doing_memory_accounting = 1;
|
gc->doing_memory_accounting = 1;
|
||||||
GC->in_unsafe_allocation_mode = 1;
|
gc->in_unsafe_allocation_mode = 1;
|
||||||
GC->unsafe_allocation_abort = btc_overmem_abort;
|
gc->unsafe_allocation_abort = btc_overmem_abort;
|
||||||
|
|
||||||
if(!GC->normal_thread_mark) {
|
if(!gc->normal_thread_mark) {
|
||||||
GC->normal_thread_mark = GC->mark_table[scheme_thread_type];
|
gc->normal_thread_mark = gc->mark_table[scheme_thread_type];
|
||||||
GC->normal_custodian_mark = GC->mark_table[scheme_custodian_type];
|
gc->normal_custodian_mark = gc->mark_table[scheme_custodian_type];
|
||||||
GC->normal_cust_box_mark = GC->mark_table[GC->cust_box_tag];
|
gc->normal_cust_box_mark = gc->mark_table[gc->cust_box_tag];
|
||||||
}
|
}
|
||||||
|
|
||||||
GC->mark_table[scheme_thread_type] = BTC_thread_mark;
|
gc->mark_table[scheme_thread_type] = BTC_thread_mark;
|
||||||
GC->mark_table[scheme_custodian_type] = BTC_custodian_mark;
|
gc->mark_table[scheme_custodian_type] = BTC_custodian_mark;
|
||||||
GC->mark_table[GC->ephemeron_tag] = BTC_ephemeron_mark;
|
gc->mark_table[gc->ephemeron_tag] = BTC_ephemeron_mark;
|
||||||
GC->mark_table[GC->cust_box_tag] = BTC_cust_box_mark;
|
gc->mark_table[gc->cust_box_tag] = BTC_cust_box_mark;
|
||||||
|
|
||||||
/* clear the memory use numbers out */
|
/* clear the memory use numbers out */
|
||||||
for(i = 1; i < table_size; i++)
|
for(i = 1; i < table_size; i++)
|
||||||
|
@ -409,28 +414,28 @@ static void BTC_do_accounting(void)
|
||||||
|
|
||||||
/* walk backwards for the order we want */
|
/* walk backwards for the order we want */
|
||||||
while(cur) {
|
while(cur) {
|
||||||
int owner = custodian_to_owner_set(cur);
|
int owner = custodian_to_owner_set(gc, cur);
|
||||||
|
|
||||||
GC->current_mark_owner = owner;
|
gc->current_mark_owner = owner;
|
||||||
GCDEBUG((DEBUGOUTF,"MARKING THREADS OF OWNER %i (CUST %p)\n", owner, cur));
|
GCDEBUG((DEBUGOUTF,"MARKING THREADS OF OWNER %i (CUST %p)\n", owner, cur));
|
||||||
GC->kill_propagation_loop = 0;
|
gc->kill_propagation_loop = 0;
|
||||||
mark_threads(owner);
|
mark_threads(gc, owner);
|
||||||
mark_cust_boxes(cur);
|
mark_cust_boxes(gc, cur);
|
||||||
GCDEBUG((DEBUGOUTF, "Propagating accounting marks\n"));
|
GCDEBUG((DEBUGOUTF, "Propagating accounting marks\n"));
|
||||||
propagate_accounting_marks();
|
propagate_accounting_marks(gc);
|
||||||
|
|
||||||
box = cur->global_prev; cur = box ? SCHEME_PTR1_VAL(box) : NULL;
|
box = cur->global_prev; cur = box ? SCHEME_PTR1_VAL(box) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GC->mark_table[scheme_thread_type] = GC->normal_thread_mark;
|
gc->mark_table[scheme_thread_type] = gc->normal_thread_mark;
|
||||||
GC->mark_table[scheme_custodian_type] = GC->normal_custodian_mark;
|
gc->mark_table[scheme_custodian_type] = gc->normal_custodian_mark;
|
||||||
GC->mark_table[GC->ephemeron_tag] = mark_ephemeron;
|
gc->mark_table[gc->ephemeron_tag] = mark_ephemeron;
|
||||||
GC->mark_table[GC->cust_box_tag] = GC->normal_cust_box_mark;
|
gc->mark_table[gc->cust_box_tag] = gc->normal_cust_box_mark;
|
||||||
|
|
||||||
GC->in_unsafe_allocation_mode = 0;
|
gc->in_unsafe_allocation_mode = 0;
|
||||||
GC->doing_memory_accounting = 0;
|
gc->doing_memory_accounting = 0;
|
||||||
GC->old_btc_mark = GC->new_btc_mark;
|
gc->old_btc_mark = gc->new_btc_mark;
|
||||||
GC->new_btc_mark = !GC->new_btc_mark;
|
gc->new_btc_mark = !gc->new_btc_mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_stack_pages();
|
clear_stack_pages();
|
||||||
|
@ -438,23 +443,24 @@ static void BTC_do_accounting(void)
|
||||||
|
|
||||||
inline static void BTC_add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
inline static void BTC_add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
||||||
{
|
{
|
||||||
|
NewGC *gc = GC;
|
||||||
AccountHook *work;
|
AccountHook *work;
|
||||||
|
|
||||||
if(!GC->really_doing_accounting) {
|
if(!gc->really_doing_accounting) {
|
||||||
GC->park[0] = c1;
|
gc->park[0] = c1;
|
||||||
GC->park[1] = c2;
|
gc->park[1] = c2;
|
||||||
GC->really_doing_accounting = 1;
|
gc->really_doing_accounting = 1;
|
||||||
garbage_collect(1);
|
garbage_collect(1);
|
||||||
c1 = GC->park[0]; GC->park[0] = NULL;
|
c1 = gc->park[0]; gc->park[0] = NULL;
|
||||||
c2 = GC->park[1]; GC->park[1] = NULL;
|
c2 = gc->park[1]; gc->park[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == MZACCT_LIMIT)
|
if (type == MZACCT_LIMIT)
|
||||||
GC->reset_limits = 1;
|
gc->reset_limits = 1;
|
||||||
if (type == MZACCT_REQUIRE)
|
if (type == MZACCT_REQUIRE)
|
||||||
GC->reset_required = 1;
|
gc->reset_required = 1;
|
||||||
|
|
||||||
for(work = GC->hooks; work; work = work->next) {
|
for(work = gc->hooks; work; work = work->next) {
|
||||||
if((work->type == type) && (work->c2 == c2) && (work->c1 == c1)) {
|
if((work->type == type) && (work->c2 == c2) && (work->c1 == c1)) {
|
||||||
if(type == MZACCT_REQUIRE) {
|
if(type == MZACCT_REQUIRE) {
|
||||||
if(b > work->amount) work->amount = b;
|
if(b > work->amount) work->amount = b;
|
||||||
|
@ -473,18 +479,18 @@ inline static void BTC_add_account_hook(int type,void *c1,void *c2,unsigned long
|
||||||
work->amount = b;
|
work->amount = b;
|
||||||
|
|
||||||
/* push work onto hooks */
|
/* push work onto hooks */
|
||||||
work->next = GC->hooks;
|
work->next = gc->hooks;
|
||||||
GC->hooks = work;
|
gc->hooks = work;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void clean_up_account_hooks()
|
inline static void clean_up_account_hooks(NewGC *gc)
|
||||||
{
|
{
|
||||||
AccountHook *work = GC->hooks;
|
AccountHook *work = gc->hooks;
|
||||||
AccountHook *prev = NULL;
|
AccountHook *prev = NULL;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if((!work->c1 || marked(work->c1)) && marked(work->c2)) {
|
if((!work->c1 || marked(gc, work->c1)) && marked(gc, work->c2)) {
|
||||||
work->c1 = GC_resolve(work->c1);
|
work->c1 = GC_resolve(work->c1);
|
||||||
work->c2 = GC_resolve(work->c2);
|
work->c2 = GC_resolve(work->c2);
|
||||||
prev = work;
|
prev = work;
|
||||||
|
@ -494,34 +500,34 @@ inline static void clean_up_account_hooks()
|
||||||
AccountHook *next = work->next;
|
AccountHook *next = work->next;
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
if(prev) prev->next = next;
|
||||||
if(!prev) GC->hooks = next;
|
if(!prev) gc->hooks = next;
|
||||||
free(work);
|
free(work);
|
||||||
work = next;
|
work = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long custodian_super_require(void *c)
|
static unsigned long custodian_super_require(NewGC *gc, void *c)
|
||||||
{
|
{
|
||||||
int set = ((Scheme_Custodian *)c)->gc_owner_set;
|
int set = ((Scheme_Custodian *)c)->gc_owner_set;
|
||||||
const int table_size = GC->owner_table_size;
|
const int table_size = gc->owner_table_size;
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
|
|
||||||
if (GC->reset_required) {
|
if (gc->reset_required) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 1; i < table_size; i++)
|
for(i = 1; i < table_size; i++)
|
||||||
if (owner_table[i])
|
if (owner_table[i])
|
||||||
owner_table[i]->required_set = 0;
|
owner_table[i]->required_set = 0;
|
||||||
GC->reset_required = 0;
|
gc->reset_required = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!owner_table[set]->required_set) {
|
if (!owner_table[set]->required_set) {
|
||||||
unsigned long req = 0, r;
|
unsigned long req = 0, r;
|
||||||
AccountHook *work = GC->hooks;
|
AccountHook *work = gc->hooks;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if ((work->type == MZACCT_REQUIRE) && (c == work->c2)) {
|
if ((work->type == MZACCT_REQUIRE) && (c == work->c2)) {
|
||||||
r = work->amount + custodian_super_require(work->c1);
|
r = work->amount + custodian_super_require(gc, work->c1);
|
||||||
if (r > req)
|
if (r > req)
|
||||||
req = r;
|
req = r;
|
||||||
}
|
}
|
||||||
|
@ -534,23 +540,23 @@ static unsigned long custodian_super_require(void *c)
|
||||||
return owner_table[set]->super_required;
|
return owner_table[set]->super_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void BTC_run_account_hooks()
|
inline static void BTC_run_account_hooks(NewGC *gc)
|
||||||
{
|
{
|
||||||
AccountHook *work = GC->hooks;
|
AccountHook *work = gc->hooks;
|
||||||
AccountHook *prev = NULL;
|
AccountHook *prev = NULL;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if( ((work->type == MZACCT_REQUIRE) &&
|
if( ((work->type == MZACCT_REQUIRE) &&
|
||||||
((GC->used_pages > (GC->max_pages_for_use / 2))
|
((gc->used_pages > (gc->max_pages_for_use / 2))
|
||||||
|| ((((GC->max_pages_for_use / 2) - GC->used_pages) * APAGE_SIZE)
|
|| ((((gc->max_pages_for_use / 2) - gc->used_pages) * APAGE_SIZE)
|
||||||
< (work->amount + custodian_super_require(work->c1)))))
|
< (work->amount + custodian_super_require(gc, work->c1)))))
|
||||||
||
|
||
|
||||||
((work->type == MZACCT_LIMIT) &&
|
((work->type == MZACCT_LIMIT) &&
|
||||||
(GC_get_memory_use(work->c1) > work->amount))) {
|
(GC_get_memory_use(work->c1) > work->amount))) {
|
||||||
AccountHook *next = work->next;
|
AccountHook *next = work->next;
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
if(prev) prev->next = next;
|
||||||
if(!prev) GC->hooks = next;
|
if(!prev) gc->hooks = next;
|
||||||
scheme_schedule_custodian_close(work->c2);
|
scheme_schedule_custodian_close(work->c2);
|
||||||
free(work);
|
free(work);
|
||||||
work = next;
|
work = next;
|
||||||
|
@ -561,27 +567,27 @@ inline static void BTC_run_account_hooks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long custodian_single_time_limit(int set)
|
static unsigned long custodian_single_time_limit(NewGC *gc, int set)
|
||||||
{
|
{
|
||||||
OTEntry **owner_table = GC->owner_table;
|
OTEntry **owner_table = gc->owner_table;
|
||||||
const int table_size = GC->owner_table_size;
|
const int table_size = gc->owner_table_size;
|
||||||
|
|
||||||
if (!set)
|
if (!set)
|
||||||
return (unsigned long)(long)-1;
|
return (unsigned long)(long)-1;
|
||||||
|
|
||||||
if (GC->reset_limits) {
|
if (gc->reset_limits) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 1; i < table_size; i++)
|
for(i = 1; i < table_size; i++)
|
||||||
if (owner_table[i])
|
if (owner_table[i])
|
||||||
owner_table[i]->limit_set = 0;
|
owner_table[i]->limit_set = 0;
|
||||||
GC->reset_limits = 0;
|
gc->reset_limits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!owner_table[set]->limit_set) {
|
if (!owner_table[set]->limit_set) {
|
||||||
/* Check for limits on this custodian or one of its ancestors: */
|
/* Check for limits on this custodian or one of its ancestors: */
|
||||||
unsigned long limit = (unsigned long)(long)-1;
|
unsigned long limit = (unsigned long)(long)-1;
|
||||||
Scheme_Custodian *orig = (Scheme_Custodian *) owner_table[set]->originator, *c;
|
Scheme_Custodian *orig = (Scheme_Custodian *) owner_table[set]->originator, *c;
|
||||||
AccountHook *work = GC->hooks;
|
AccountHook *work = gc->hooks;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if ((work->type == MZACCT_LIMIT) && (work->c1 == work->c2)) {
|
if ((work->type == MZACCT_LIMIT) && (work->c1 == work->c2)) {
|
||||||
|
@ -618,7 +624,7 @@ long BTC_get_memory_use(void *o)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BTC_single_allocation_limit(size_t sizeb) {
|
int BTC_single_allocation_limit(NewGC *gc, size_t sizeb) {
|
||||||
/* We're allowed to fail. Check for allocations that exceed a single-time
|
/* We're allowed to fail. Check for allocations that exceed a single-time
|
||||||
* limit. Otherwise, the limit doesn't work as intended, because
|
* limit. Otherwise, the limit doesn't work as intended, because
|
||||||
* a program can allocate a large block that nearly exhausts memory,
|
* a program can allocate a large block that nearly exhausts memory,
|
||||||
|
@ -626,14 +632,16 @@ int BTC_single_allocation_limit(size_t sizeb) {
|
||||||
* is much smaller than the actual available memory, and as long as
|
* is much smaller than the actual available memory, and as long as
|
||||||
* GC_out_of_memory protects any user-requested allocation whose size
|
* GC_out_of_memory protects any user-requested allocation whose size
|
||||||
* is independent of any existing object, then we can enforce the limit. */
|
* is independent of any existing object, then we can enforce the limit. */
|
||||||
return (custodian_single_time_limit(thread_get_owner(scheme_current_thread)) < sizeb);
|
return (custodian_single_time_limit(gc, thread_get_owner(scheme_current_thread)) < sizeb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void BTC_clean_up() {
|
static inline void BTC_clean_up(NewGC *gc) {
|
||||||
clean_up_thread_list();
|
clean_up_thread_list(gc);
|
||||||
clean_up_owner_table();
|
clean_up_owner_table(gc);
|
||||||
clean_up_account_hooks();
|
clean_up_account_hooks(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
# define BTC_set_btc_mark(x) (((struct objhead *)(x))->btc_mark = GC->old_btc_mark)
|
static inline void BTC_set_btc_mark(NewGC *gc, void* x) {
|
||||||
|
((struct objhead *)(x))->btc_mark = gc->old_btc_mark;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "../src/schpriv.h"
|
#include "../src/schpriv.h"
|
||||||
|
|
||||||
static THREAD_LOCAL CompactGC *GC;
|
static THREAD_LOCAL CompactGC *GC;
|
||||||
|
#define GCTYPE CompactGC
|
||||||
|
|
||||||
/**************** Configuration ****************/
|
/**************** Configuration ****************/
|
||||||
|
|
||||||
|
@ -453,12 +454,14 @@ void CompactGC_initialize(CompactGC *gc) {
|
||||||
|
|
||||||
void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox, int ephemeron, int weakarray, int custbox)
|
void GC_init_type_tags(int count, int pair, int mutable_pair, int weakbox, int ephemeron, int weakarray, int custbox)
|
||||||
{
|
{
|
||||||
|
CompactGC *gc;
|
||||||
weak_box_tag = weakbox;
|
weak_box_tag = weakbox;
|
||||||
ephemeron_tag = ephemeron;
|
ephemeron_tag = ephemeron;
|
||||||
weak_array_tag = weakarray;
|
weak_array_tag = weakarray;
|
||||||
|
|
||||||
GC = malloc(sizeof(CompactGC));
|
gc = malloc(sizeof(CompactGC));
|
||||||
CompactGC_initialize(GC);
|
GC = gc;
|
||||||
|
CompactGC_initialize(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_register_traversers(Type_Tag tag, Size_Proc size, Mark_Proc mark, Fixup_Proc fixup,
|
void GC_register_traversers(Type_Tag tag, Size_Proc size, Mark_Proc mark, Fixup_Proc fixup,
|
||||||
|
@ -553,7 +556,7 @@ static int size_on_free_list(void *p)
|
||||||
/* weak arrays and boxes */
|
/* weak arrays and boxes */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int is_marked(void *p);
|
static int is_marked(CompactGC *gc, void *p);
|
||||||
#define weak_box_resolve(p) (p)
|
#define weak_box_resolve(p) (p)
|
||||||
|
|
||||||
#include "weak.c"
|
#include "weak.c"
|
||||||
|
@ -685,7 +688,7 @@ int GC_is_allocated(void *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Works only during GC: */
|
/* Works only during GC: */
|
||||||
static int is_marked(void *p)
|
static int is_marked(CompactGC *gc, void *p)
|
||||||
{
|
{
|
||||||
unsigned long g = ((unsigned long)p >> MAPS_SHIFT);
|
unsigned long g = ((unsigned long)p >> MAPS_SHIFT);
|
||||||
MPage *map;
|
MPage *map;
|
||||||
|
@ -701,7 +704,7 @@ static int is_marked(void *p)
|
||||||
#endif
|
#endif
|
||||||
if (page->flags & MFLAG_BIGBLOCK) {
|
if (page->flags & MFLAG_BIGBLOCK) {
|
||||||
if (page->flags & MFLAG_CONTINUED)
|
if (page->flags & MFLAG_CONTINUED)
|
||||||
return is_marked(page->o.bigblock_start);
|
return is_marked(gc, page->o.bigblock_start);
|
||||||
else
|
else
|
||||||
return (page->flags & (COLOR_MASK | MFLAG_OLD));
|
return (page->flags & (COLOR_MASK | MFLAG_OLD));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2861,7 +2864,7 @@ static void init(void)
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
|
|
||||||
#if GENERATIONS
|
#if GENERATIONS
|
||||||
initialize_signal_handler();
|
initialize_signal_handler(GC);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2958,6 +2961,7 @@ static void fixup_roots()
|
||||||
|
|
||||||
static void gcollect(int full)
|
static void gcollect(int full)
|
||||||
{
|
{
|
||||||
|
CompactGC *gc = GC;
|
||||||
int did_fnls;
|
int did_fnls;
|
||||||
#if TIME
|
#if TIME
|
||||||
struct rusage pre, post;
|
struct rusage pre, post;
|
||||||
|
@ -2977,9 +2981,9 @@ static void gcollect(int full)
|
||||||
|
|
||||||
set_ending_tags();
|
set_ending_tags();
|
||||||
|
|
||||||
init_weak_boxes();
|
init_weak_boxes(gc);
|
||||||
init_ephemerons();
|
init_ephemerons(gc);
|
||||||
init_weak_arrays();
|
init_weak_arrays(gc);
|
||||||
|
|
||||||
did_fnls = 0;
|
did_fnls = 0;
|
||||||
|
|
||||||
|
@ -3118,7 +3122,7 @@ static void gcollect(int full)
|
||||||
|
|
||||||
/* Propagate, mark ready ephemerons */
|
/* Propagate, mark ready ephemerons */
|
||||||
propagate_all_mpages();
|
propagate_all_mpages();
|
||||||
mark_ready_ephemerons();
|
mark_ready_ephemerons(gc);
|
||||||
|
|
||||||
/* Propagate, loop to do finalization */
|
/* Propagate, loop to do finalization */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -3138,7 +3142,7 @@ static void gcollect(int full)
|
||||||
for (f = GC->finalizers; f; f = next) {
|
for (f = GC->finalizers; f; f = next) {
|
||||||
next = f->next;
|
next = f->next;
|
||||||
if (f->eager_level == 3) {
|
if (f->eager_level == 3) {
|
||||||
if (!is_marked(f->p)) {
|
if (!is_marked(gc, f->p)) {
|
||||||
/* Not yet marked. Mark it and enqueue it. */
|
/* Not yet marked. Mark it and enqueue it. */
|
||||||
#if RECORD_MARK_SRC
|
#if RECORD_MARK_SRC
|
||||||
mark_src = f;
|
mark_src = f;
|
||||||
|
@ -3173,7 +3177,7 @@ static void gcollect(int full)
|
||||||
for (wl = fnl_weaks; wl; wl = wl->next) {
|
for (wl = fnl_weaks; wl; wl = wl->next) {
|
||||||
void *wp = (void *)wl->p;
|
void *wp = (void *)wl->p;
|
||||||
int markit;
|
int markit;
|
||||||
markit = is_marked(wp);
|
markit = is_marked(gc, wp);
|
||||||
if (markit) {
|
if (markit) {
|
||||||
#if RECORD_MARK_SRC
|
#if RECORD_MARK_SRC
|
||||||
mark_src = wp;
|
mark_src = wp;
|
||||||
|
@ -3217,7 +3221,7 @@ static void gcollect(int full)
|
||||||
mark_src = f;
|
mark_src = f;
|
||||||
mark_type = MTYPE_TAGGED;
|
mark_type = MTYPE_TAGGED;
|
||||||
#endif
|
#endif
|
||||||
if (!is_marked(f->p)) {
|
if (!is_marked(gc, f->p)) {
|
||||||
/* Not yet marked. Mark content. */
|
/* Not yet marked. Mark content. */
|
||||||
if (f->tagged) {
|
if (f->tagged) {
|
||||||
Type_Tag tag = *(Type_Tag *)f->p;
|
Type_Tag tag = *(Type_Tag *)f->p;
|
||||||
|
@ -3243,7 +3247,7 @@ static void gcollect(int full)
|
||||||
|
|
||||||
while (f) {
|
while (f) {
|
||||||
if (f->eager_level == eager_level) {
|
if (f->eager_level == eager_level) {
|
||||||
if (!is_marked(f->p)) {
|
if (!is_marked(gc, f->p)) {
|
||||||
/* Not yet marked. Move finalization to run queue. */
|
/* Not yet marked. Move finalization to run queue. */
|
||||||
Fnl *next = f->next;
|
Fnl *next = f->next;
|
||||||
|
|
||||||
|
@ -3286,7 +3290,7 @@ static void gcollect(int full)
|
||||||
f = f->next;
|
f = f->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_ready_ephemerons();
|
mark_ready_ephemerons(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
did_fnls++;
|
did_fnls++;
|
||||||
|
@ -3323,9 +3327,9 @@ static void gcollect(int full)
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
|
|
||||||
zero_remaining_ephemerons();
|
zero_remaining_ephemerons(gc);
|
||||||
zero_weak_boxes();
|
zero_weak_boxes(gc);
|
||||||
zero_weak_arrays();
|
zero_weak_arrays(gc);
|
||||||
|
|
||||||
/* Cleanup weak finalization links: */
|
/* Cleanup weak finalization links: */
|
||||||
{
|
{
|
||||||
|
@ -3334,7 +3338,7 @@ static void gcollect(int full)
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
for (wl = fnl_weaks; wl; wl = next) {
|
for (wl = fnl_weaks; wl; wl = next) {
|
||||||
next = wl->next;
|
next = wl->next;
|
||||||
if (!is_marked(wl->p)) {
|
if (!is_marked(gc, wl->p)) {
|
||||||
/* Will be collected. Removed this link. */
|
/* Will be collected. Removed this link. */
|
||||||
wl->p = NULL;
|
wl->p = NULL;
|
||||||
if (prev)
|
if (prev)
|
||||||
|
@ -3472,7 +3476,7 @@ static void gcollect(int full)
|
||||||
|
|
||||||
protect_old_mpages();
|
protect_old_mpages();
|
||||||
|
|
||||||
reset_finalizer_tree();
|
reset_finalizer_tree(GC);
|
||||||
|
|
||||||
#if (COMPACTING == NEVER_COMPACT)
|
#if (COMPACTING == NEVER_COMPACT)
|
||||||
# define THRESH_FREE_LIST_DELTA (FREE_LIST_DELTA >> LOG_WORD_SIZE)
|
# define THRESH_FREE_LIST_DELTA (FREE_LIST_DELTA >> LOG_WORD_SIZE)
|
||||||
|
|
|
@ -26,6 +26,7 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d
|
||||||
void *data, void (**oldf)(void *p, void *data),
|
void *data, void (**oldf)(void *p, void *data),
|
||||||
void **olddata)
|
void **olddata)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
Fnl *fnl;
|
Fnl *fnl;
|
||||||
|
|
||||||
if (!is_finalizable_page(p)) {
|
if (!is_finalizable_page(p)) {
|
||||||
|
@ -35,8 +36,8 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GC->splayed_finalizers = fnl_splay((unsigned long)p, GC->splayed_finalizers);
|
gc->splayed_finalizers = fnl_splay((unsigned long)p, gc->splayed_finalizers);
|
||||||
fnl = GC->splayed_finalizers;
|
fnl = gc->splayed_finalizers;
|
||||||
if (fnl && (fnl->p == p)) {
|
if (fnl && (fnl->p == p)) {
|
||||||
if (oldf) *oldf = fnl->f;
|
if (oldf) *oldf = fnl->f;
|
||||||
if (olddata) *olddata = fnl->data;
|
if (olddata) *olddata = fnl->data;
|
||||||
|
@ -49,12 +50,12 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d
|
||||||
if (fnl->prev)
|
if (fnl->prev)
|
||||||
fnl->prev->next = fnl->next;
|
fnl->prev->next = fnl->next;
|
||||||
else
|
else
|
||||||
GC->finalizers = fnl->next;
|
gc->finalizers = fnl->next;
|
||||||
if (fnl->next)
|
if (fnl->next)
|
||||||
fnl->next->prev = fnl->prev;
|
fnl->next->prev = fnl->prev;
|
||||||
|
|
||||||
--GC->num_fnls;
|
--gc->num_fnls;
|
||||||
GC->splayed_finalizers = fnl_splay_delete((unsigned long)p, GC->splayed_finalizers);
|
gc->splayed_finalizers = fnl_splay_delete((unsigned long)p, gc->splayed_finalizers);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -66,16 +67,16 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Allcation might trigger GC, so we use park: */
|
/* Allcation might trigger GC, so we use park: */
|
||||||
GC->park[0] = p;
|
gc->park[0] = p;
|
||||||
GC->park[1] = data;
|
gc->park[1] = data;
|
||||||
|
|
||||||
fnl = (Fnl *)GC_malloc_atomic(sizeof(Fnl));
|
fnl = (Fnl *)GC_malloc_atomic(sizeof(Fnl));
|
||||||
memset(fnl, 0, sizeof(Fnl));
|
memset(fnl, 0, sizeof(Fnl));
|
||||||
|
|
||||||
p = GC->park[0];
|
p = gc->park[0];
|
||||||
data = GC->park[1];
|
data = gc->park[1];
|
||||||
GC->park[0] = NULL;
|
gc->park[0] = NULL;
|
||||||
GC->park[1] = NULL;
|
gc->park[1] = NULL;
|
||||||
|
|
||||||
|
|
||||||
fnl->p = p;
|
fnl->p = p;
|
||||||
|
@ -111,30 +112,30 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* push finalizer */
|
/* push finalizer */
|
||||||
fnl->next = GC->finalizers;
|
fnl->next = gc->finalizers;
|
||||||
fnl->prev = NULL;
|
fnl->prev = NULL;
|
||||||
if (GC->finalizers) {
|
if (gc->finalizers) {
|
||||||
GC->finalizers->prev = fnl;
|
gc->finalizers->prev = fnl;
|
||||||
}
|
}
|
||||||
GC->finalizers = fnl;
|
gc->finalizers = fnl;
|
||||||
|
|
||||||
GC->splayed_finalizers = fnl_splay_insert((unsigned long)p, fnl, GC->splayed_finalizers);
|
gc->splayed_finalizers = fnl_splay_insert((unsigned long)p, fnl, gc->splayed_finalizers);
|
||||||
|
|
||||||
GC->num_fnls++;
|
gc->num_fnls++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_finalizer_tree()
|
static void reset_finalizer_tree(GCTYPE *gc)
|
||||||
/* After a GC, rebuild the splay tree, since object addresses
|
/* After a GC, rebuild the splay tree, since object addresses
|
||||||
have moved. */
|
have moved. */
|
||||||
{
|
{
|
||||||
Fnl *fnl;
|
Fnl *fnl;
|
||||||
Fnl *prev = NULL;
|
Fnl *prev = NULL;
|
||||||
|
|
||||||
GC->splayed_finalizers = NULL;
|
gc->splayed_finalizers = NULL;
|
||||||
|
|
||||||
for (fnl = GC->finalizers; fnl; fnl = fnl->next) {
|
for (fnl = gc->finalizers; fnl; fnl = fnl->next) {
|
||||||
fnl->prev = prev;
|
fnl->prev = prev;
|
||||||
GC->splayed_finalizers = fnl_splay_insert((unsigned long)fnl->p, fnl, GC->splayed_finalizers);
|
gc->splayed_finalizers = fnl_splay_insert((unsigned long)fnl->p, fnl, gc->splayed_finalizers);
|
||||||
prev = fnl;
|
prev = fnl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,26 @@
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
void **GC_malloc_immobile_box(void *p)
|
void **GC_malloc_immobile_box(void *p)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Immobile_Box *ib = malloc(sizeof(GC_Immobile_Box));
|
GC_Immobile_Box *ib = malloc(sizeof(GC_Immobile_Box));
|
||||||
if(!ib) GCERR((GCOUTF, "Couldn't allocate space for immobile box!\n"));
|
if(!ib) GCERR((GCOUTF, "Couldn't allocate space for immobile box!\n"));
|
||||||
ib->p = p;
|
ib->p = p;
|
||||||
ib->next = GC->immobile_boxes;
|
ib->next = gc->immobile_boxes;
|
||||||
ib->prev = NULL;
|
ib->prev = NULL;
|
||||||
if(ib->next) ib->next->prev = ib;
|
if(ib->next) ib->next->prev = ib;
|
||||||
GC->immobile_boxes = ib;
|
gc->immobile_boxes = ib;
|
||||||
return (void**)ib;
|
return (void**)ib;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_free_immobile_box(void **b)
|
void GC_free_immobile_box(void **b)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Immobile_Box *ib;
|
GC_Immobile_Box *ib;
|
||||||
|
|
||||||
for(ib = GC->immobile_boxes; ib; ib = ib->next)
|
for(ib = gc->immobile_boxes; ib; ib = ib->next)
|
||||||
if(PPTR(ib) == b) {
|
if(PPTR(ib) == b) {
|
||||||
if(ib->prev) ib->prev->next = ib->next;
|
if(ib->prev) ib->prev->next = ib->next;
|
||||||
if(!ib->prev) GC->immobile_boxes = ib->next;
|
if(!ib->prev) gc->immobile_boxes = ib->next;
|
||||||
if(ib->next) ib->next->prev = ib->prev;
|
if(ib->next) ib->next->prev = ib->prev;
|
||||||
free(ib);
|
free(ib);
|
||||||
return;
|
return;
|
||||||
|
@ -30,18 +32,18 @@ void GC_free_immobile_box(void **b)
|
||||||
|
|
||||||
#define traverse_immobiles(gcMUCK, set_bt_src) { \
|
#define traverse_immobiles(gcMUCK, set_bt_src) { \
|
||||||
GC_Immobile_Box *ib; \
|
GC_Immobile_Box *ib; \
|
||||||
for(ib = GC->immobile_boxes; ib; ib = ib->next) { \
|
for(ib = gc->immobile_boxes; ib; ib = ib->next) { \
|
||||||
set_bt_src(ib, BT_IMMOBILE); \
|
set_bt_src(ib, BT_IMMOBILE); \
|
||||||
gcMUCK(ib->p); \
|
gcMUCK(ib->p); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void mark_immobiles(void)
|
inline static void mark_immobiles(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
traverse_immobiles(gcMARK, set_backtrace_source);
|
traverse_immobiles(gcMARK, set_backtrace_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void repair_immobiles(void)
|
inline static void repair_immobiles(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
traverse_immobiles(gcFIXUP, two_arg_no_op);
|
traverse_immobiles(gcFIXUP, two_arg_no_op);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -100,13 +100,13 @@ typedef struct NewGC {
|
||||||
Fnl *last_in_queue;
|
Fnl *last_in_queue;
|
||||||
Weak_Finalizer *weak_finalizers;
|
Weak_Finalizer *weak_finalizers;
|
||||||
|
|
||||||
struct NewGC *primoridal_gc;
|
struct GC *primoridal_gc;
|
||||||
unsigned long max_heap_size;
|
unsigned long max_heap_size;
|
||||||
unsigned long max_pages_in_heap;
|
unsigned long max_pages_in_heap;
|
||||||
unsigned long max_pages_for_use;
|
unsigned long max_pages_for_use;
|
||||||
unsigned long used_pages;
|
unsigned long used_pages;
|
||||||
unsigned long actual_pages_size;
|
unsigned long actual_pages_size;
|
||||||
void (*unsafe_allocation_abort)();
|
void (*unsafe_allocation_abort)(struct NewGC *);
|
||||||
unsigned long memory_in_use; /* the amount of memory in use */
|
unsigned long memory_in_use; /* the amount of memory in use */
|
||||||
|
|
||||||
/* blame the child saved off Mark_Proc pointers */
|
/* blame the child saved off Mark_Proc pointers */
|
||||||
|
|
|
@ -80,7 +80,8 @@ static void sort_and_merge_roots(Roots *roots)
|
||||||
|
|
||||||
void GC_add_roots(void *start, void *end)
|
void GC_add_roots(void *start, void *end)
|
||||||
{
|
{
|
||||||
Roots *roots = &GC->roots;
|
GCTYPE *gc = GC;
|
||||||
|
Roots *roots = &gc->roots;
|
||||||
|
|
||||||
if (roots->count >= roots->size) {
|
if (roots->count >= roots->size) {
|
||||||
grow_roots(roots);
|
grow_roots(roots);
|
||||||
|
|
|
@ -97,7 +97,7 @@ void fault_handler(int sn, siginfo_t *si, void *ctx)
|
||||||
/* init function */
|
/* init function */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static void initialize_signal_handler()
|
static void initialize_signal_handler(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
# ifdef NEED_OSX_MACH_HANDLER
|
# ifdef NEED_OSX_MACH_HANDLER
|
||||||
macosx_init_exception_handler();
|
macosx_init_exception_handler();
|
||||||
|
@ -128,12 +128,12 @@ static void initialize_signal_handler()
|
||||||
if (aveh)
|
if (aveh)
|
||||||
aveh(TRUE, fault_handler);
|
aveh(TRUE, fault_handler);
|
||||||
else
|
else
|
||||||
GC->generations_available = 0;
|
gc->generations_available = 0;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_signal_handler()
|
static void remove_signal_handler(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
# ifdef NEED_OSX_MACH_HANDLER
|
# ifdef NEED_OSX_MACH_HANDLER
|
||||||
# endif
|
# endif
|
||||||
|
@ -148,7 +148,7 @@ static void remove_signal_handler()
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
# ifdef NEED_SIGWIN
|
# ifdef NEED_SIGWIN
|
||||||
if (GC->generations_available) {
|
if (gc->generations_available) {
|
||||||
HMODULE hm;
|
HMODULE hm;
|
||||||
ULONG (WINAPI*rveh)(gcPVECTORED_EXCEPTION_HANDLER);
|
ULONG (WINAPI*rveh)(gcPVECTORED_EXCEPTION_HANDLER);
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,13 @@ static int size_weak_array(void *p)
|
||||||
|
|
||||||
static int mark_weak_array(void *p)
|
static int mark_weak_array(void *p)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Weak_Array *a = (GC_Weak_Array *)p;
|
GC_Weak_Array *a = (GC_Weak_Array *)p;
|
||||||
|
|
||||||
gcMARK(a->replace_val);
|
gcMARK(a->replace_val);
|
||||||
|
|
||||||
a->next = GC->weak_arrays;
|
a->next = gc->weak_arrays;
|
||||||
GC->weak_arrays = a;
|
gc->weak_arrays = a;
|
||||||
|
|
||||||
#if CHECKS
|
#if CHECKS
|
||||||
/* For now, weak arrays only used for symbols, keywords, and falses: */
|
/* For now, weak arrays only used for symbols, keywords, and falses: */
|
||||||
|
@ -83,42 +84,43 @@ static int fixup_weak_array(void *p)
|
||||||
|
|
||||||
void *GC_malloc_weak_array(size_t size_in_bytes, void *replace_val)
|
void *GC_malloc_weak_array(size_t size_in_bytes, void *replace_val)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Weak_Array *w;
|
GC_Weak_Array *w;
|
||||||
|
|
||||||
/* Allcation might trigger GC, so we use park: */
|
/* Allcation might trigger GC, so we use park: */
|
||||||
GC->park[0] = replace_val;
|
gc->park[0] = replace_val;
|
||||||
|
|
||||||
w = (GC_Weak_Array *)GC_malloc_one_tagged(size_in_bytes
|
w = (GC_Weak_Array *)GC_malloc_one_tagged(size_in_bytes
|
||||||
+ sizeof(GC_Weak_Array)
|
+ sizeof(GC_Weak_Array)
|
||||||
- sizeof(void *));
|
- sizeof(void *));
|
||||||
|
|
||||||
replace_val = GC->park[0];
|
replace_val = gc->park[0];
|
||||||
GC->park[0] = NULL;
|
gc->park[0] = NULL;
|
||||||
|
|
||||||
w->type = GC->weak_array_tag;
|
w->type = gc->weak_array_tag;
|
||||||
w->replace_val = replace_val;
|
w->replace_val = replace_val;
|
||||||
w->count = (size_in_bytes >> LOG_WORD_SIZE);
|
w->count = (size_in_bytes >> LOG_WORD_SIZE);
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_weak_arrays() {
|
static void init_weak_arrays(GCTYPE *gc) {
|
||||||
GC->weak_arrays = NULL;
|
gc->weak_arrays = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zero_weak_arrays()
|
static void zero_weak_arrays(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
GC_Weak_Array *wa;
|
GC_Weak_Array *wa;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
wa = GC->weak_arrays;
|
wa = gc->weak_arrays;
|
||||||
while (wa) {
|
while (wa) {
|
||||||
void **data;
|
void **data;
|
||||||
|
|
||||||
data = wa->data;
|
data = wa->data;
|
||||||
for (i = wa->count; i--; ) {
|
for (i = wa->count; i--; ) {
|
||||||
void *p = data[i];
|
void *p = data[i];
|
||||||
if (p && !is_marked(p))
|
if (p && !is_marked(gc, p))
|
||||||
data[i] = wa->replace_val;
|
data[i] = wa->replace_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,13 +139,14 @@ static int size_weak_box(void *p)
|
||||||
|
|
||||||
static int mark_weak_box(void *p)
|
static int mark_weak_box(void *p)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Weak_Box *wb = (GC_Weak_Box *)p;
|
GC_Weak_Box *wb = (GC_Weak_Box *)p;
|
||||||
|
|
||||||
gcMARK(wb->secondary_erase);
|
gcMARK(wb->secondary_erase);
|
||||||
|
|
||||||
if (wb->val) {
|
if (wb->val) {
|
||||||
wb->next = GC->weak_boxes;
|
wb->next = gc->weak_boxes;
|
||||||
GC->weak_boxes = wb;
|
gc->weak_boxes = wb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gcBYTES_TO_WORDS(sizeof(GC_Weak_Box));
|
return gcBYTES_TO_WORDS(sizeof(GC_Weak_Box));
|
||||||
|
@ -161,20 +164,21 @@ static int fixup_weak_box(void *p)
|
||||||
|
|
||||||
void *GC_malloc_weak_box(void *p, void **secondary, int soffset)
|
void *GC_malloc_weak_box(void *p, void **secondary, int soffset)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Weak_Box *w;
|
GC_Weak_Box *w;
|
||||||
|
|
||||||
/* Allcation might trigger GC, so we use park: */
|
/* Allcation might trigger GC, so we use park: */
|
||||||
GC->park[0] = p;
|
gc->park[0] = p;
|
||||||
GC->park[1] = secondary;
|
gc->park[1] = secondary;
|
||||||
|
|
||||||
w = (GC_Weak_Box *)GC_malloc_one_tagged(sizeof(GC_Weak_Box));
|
w = (GC_Weak_Box *)GC_malloc_one_tagged(sizeof(GC_Weak_Box));
|
||||||
|
|
||||||
p = GC->park[0];
|
p = gc->park[0];
|
||||||
secondary = (void **)GC->park[1];
|
secondary = (void **)gc->park[1];
|
||||||
GC->park[0] = NULL;
|
gc->park[0] = NULL;
|
||||||
GC->park[1] = NULL;
|
gc->park[1] = NULL;
|
||||||
|
|
||||||
w->type = GC->weak_box_tag;
|
w->type = gc->weak_box_tag;
|
||||||
w->val = p;
|
w->val = p;
|
||||||
w->secondary_erase = secondary;
|
w->secondary_erase = secondary;
|
||||||
w->soffset = soffset;
|
w->soffset = soffset;
|
||||||
|
@ -182,17 +186,17 @@ void *GC_malloc_weak_box(void *p, void **secondary, int soffset)
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_weak_boxes() {
|
static void init_weak_boxes(GCTYPE *gc) {
|
||||||
GC->weak_boxes = NULL;
|
gc->weak_boxes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zero_weak_boxes()
|
static void zero_weak_boxes(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
GC_Weak_Box *wb;
|
GC_Weak_Box *wb;
|
||||||
|
|
||||||
wb = GC->weak_boxes;
|
wb = gc->weak_boxes;
|
||||||
while (wb) {
|
while (wb) {
|
||||||
if (!is_marked(wb->val)) {
|
if (!is_marked(gc, wb->val)) {
|
||||||
wb->val = NULL;
|
wb->val = NULL;
|
||||||
if (wb->secondary_erase) {
|
if (wb->secondary_erase) {
|
||||||
void **p;
|
void **p;
|
||||||
|
@ -216,11 +220,12 @@ static int size_ephemeron(void *p)
|
||||||
|
|
||||||
static int mark_ephemeron(void *p)
|
static int mark_ephemeron(void *p)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Ephemeron *eph = (GC_Ephemeron *)p;
|
GC_Ephemeron *eph = (GC_Ephemeron *)p;
|
||||||
|
|
||||||
if (eph->val) {
|
if (eph->val) {
|
||||||
eph->next = GC->ephemerons;
|
eph->next = gc->ephemerons;
|
||||||
GC->ephemerons = eph;
|
gc->ephemerons = eph;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
|
return gcBYTES_TO_WORDS(sizeof(GC_Ephemeron));
|
||||||
|
@ -251,55 +256,56 @@ static int fixup_ephemeron(void *p)
|
||||||
|
|
||||||
void *GC_malloc_ephemeron(void *k, void *v)
|
void *GC_malloc_ephemeron(void *k, void *v)
|
||||||
{
|
{
|
||||||
|
GCTYPE *gc = GC;
|
||||||
GC_Ephemeron *eph;
|
GC_Ephemeron *eph;
|
||||||
|
|
||||||
/* Allcation might trigger GC, so we use park: */
|
/* Allcation might trigger GC, so we use park: */
|
||||||
GC->park[0] = k;
|
gc->park[0] = k;
|
||||||
GC->park[1] = v;
|
gc->park[1] = v;
|
||||||
|
|
||||||
eph = (GC_Ephemeron *)GC_malloc_one_tagged(sizeof(GC_Ephemeron));
|
eph = (GC_Ephemeron *)GC_malloc_one_tagged(sizeof(GC_Ephemeron));
|
||||||
|
|
||||||
k = GC->park[0];
|
k = gc->park[0];
|
||||||
v = GC->park[1];
|
v = gc->park[1];
|
||||||
GC->park[0] = NULL;
|
gc->park[0] = NULL;
|
||||||
GC->park[1] = NULL;
|
gc->park[1] = NULL;
|
||||||
|
|
||||||
eph->type = GC->ephemeron_tag;
|
eph->type = gc->ephemeron_tag;
|
||||||
eph->key = k;
|
eph->key = k;
|
||||||
eph->val = v;
|
eph->val = v;
|
||||||
|
|
||||||
return eph;
|
return eph;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_ephemerons() {
|
void init_ephemerons(GCTYPE *gc) {
|
||||||
GC->ephemerons = NULL;
|
gc->ephemerons = NULL;
|
||||||
GC->num_last_seen_ephemerons = 0;
|
gc->num_last_seen_ephemerons = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_ready_ephemerons()
|
static void mark_ready_ephemerons(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
GC_Ephemeron *waiting = NULL, *next, *eph;
|
GC_Ephemeron *waiting = NULL, *next, *eph;
|
||||||
|
|
||||||
for (eph = GC->ephemerons; eph; eph = next) {
|
for (eph = gc->ephemerons; eph; eph = next) {
|
||||||
next = eph->next;
|
next = eph->next;
|
||||||
if (is_marked(eph->key)) {
|
if (is_marked(gc, eph->key)) {
|
||||||
gcMARK(eph->val);
|
gcMARK(eph->val);
|
||||||
GC->num_last_seen_ephemerons++;
|
gc->num_last_seen_ephemerons++;
|
||||||
} else {
|
} else {
|
||||||
eph->next = waiting;
|
eph->next = waiting;
|
||||||
waiting = eph;
|
waiting = eph;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GC->ephemerons = waiting;
|
gc->ephemerons = waiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zero_remaining_ephemerons()
|
static void zero_remaining_ephemerons(GCTYPE *gc)
|
||||||
{
|
{
|
||||||
GC_Ephemeron *eph;
|
GC_Ephemeron *eph;
|
||||||
|
|
||||||
/* After unordered finalization, any remaining ephemerons
|
/* After unordered finalization, any remaining ephemerons
|
||||||
should be zeroed. */
|
should be zeroed. */
|
||||||
for (eph = GC->ephemerons; eph; eph = eph->next) {
|
for (eph = gc->ephemerons; eph; eph = eph->next) {
|
||||||
eph->key = NULL;
|
eph->key = NULL;
|
||||||
eph->val = NULL;
|
eph->val = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user