|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# include "private/gc_priv.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
word * GC_old_normal_bl; |
|
|
|
|
|
word * GC_incomplete_normal_bl; |
|
|
|
|
|
word * GC_old_stack_bl; |
|
word * GC_incomplete_stack_bl; |
|
|
|
word GC_total_stack_black_listed; |
|
|
|
word GC_black_list_spacing = MINHINCR*HBLKSIZE; |
|
|
|
void GC_clear_bl(word *); |
|
|
|
void GC_default_print_heap_obj_proc(ptr_t p) |
|
{ |
|
ptr_t base = GC_base(p); |
|
|
|
GC_err_printf("start: %p, appr. length: %ld", base, |
|
(unsigned long)GC_size(base)); |
|
} |
|
|
|
void (*GC_print_heap_obj) (ptr_t p) = GC_default_print_heap_obj_proc; |
|
|
|
void GC_print_source_ptr(ptr_t p) |
|
{ |
|
ptr_t base = GC_base(p); |
|
if (0 == base) { |
|
if (0 == p) { |
|
GC_err_printf("in register"); |
|
} else { |
|
GC_err_printf("in root set"); |
|
} |
|
} else { |
|
GC_err_printf("in object at "); |
|
(*GC_print_heap_obj)(base); |
|
} |
|
} |
|
|
|
void GC_bl_init(void) |
|
{ |
|
if (!GC_all_interior_pointers) { |
|
GC_old_normal_bl = (word *) |
|
GC_scratch_alloc((word)(sizeof (page_hash_table))); |
|
GC_incomplete_normal_bl = (word *)GC_scratch_alloc |
|
((word)(sizeof(page_hash_table))); |
|
if (GC_old_normal_bl == 0 || GC_incomplete_normal_bl == 0) { |
|
GC_err_printf("Insufficient memory for black list\n"); |
|
EXIT(); |
|
} |
|
GC_clear_bl(GC_old_normal_bl); |
|
GC_clear_bl(GC_incomplete_normal_bl); |
|
} |
|
GC_old_stack_bl = (word *)GC_scratch_alloc((word)(sizeof(page_hash_table))); |
|
GC_incomplete_stack_bl = (word *)GC_scratch_alloc |
|
((word)(sizeof(page_hash_table))); |
|
if (GC_old_stack_bl == 0 || GC_incomplete_stack_bl == 0) { |
|
GC_err_printf("Insufficient memory for black list\n"); |
|
EXIT(); |
|
} |
|
GC_clear_bl(GC_old_stack_bl); |
|
GC_clear_bl(GC_incomplete_stack_bl); |
|
} |
|
|
|
void GC_clear_bl(word *doomed) |
|
{ |
|
BZERO(doomed, sizeof(page_hash_table)); |
|
} |
|
|
|
void GC_copy_bl(word *old, word *new) |
|
{ |
|
BCOPY(old, new, sizeof(page_hash_table)); |
|
} |
|
|
|
static word total_stack_black_listed(void); |
|
|
|
|
|
|
|
void GC_promote_black_lists(void) |
|
{ |
|
word * very_old_normal_bl = GC_old_normal_bl; |
|
word * very_old_stack_bl = GC_old_stack_bl; |
|
|
|
GC_old_normal_bl = GC_incomplete_normal_bl; |
|
GC_old_stack_bl = GC_incomplete_stack_bl; |
|
if (!GC_all_interior_pointers) { |
|
GC_clear_bl(very_old_normal_bl); |
|
} |
|
GC_clear_bl(very_old_stack_bl); |
|
GC_incomplete_normal_bl = very_old_normal_bl; |
|
GC_incomplete_stack_bl = very_old_stack_bl; |
|
GC_total_stack_black_listed = total_stack_black_listed(); |
|
if (GC_print_stats == VERBOSE) |
|
GC_log_printf("%ld bytes in heap blacklisted for interior pointers\n", |
|
(unsigned long)GC_total_stack_black_listed); |
|
if (GC_total_stack_black_listed != 0) { |
|
GC_black_list_spacing = |
|
HBLKSIZE*(GC_heapsize/GC_total_stack_black_listed); |
|
} |
|
if (GC_black_list_spacing < 3 * HBLKSIZE) { |
|
GC_black_list_spacing = 3 * HBLKSIZE; |
|
} |
|
if (GC_black_list_spacing > MAXHINCR * HBLKSIZE) { |
|
GC_black_list_spacing = MAXHINCR * HBLKSIZE; |
|
|
|
|
|
|
|
|
|
} |
|
} |
|
|
|
void GC_unpromote_black_lists(void) |
|
{ |
|
if (!GC_all_interior_pointers) { |
|
GC_copy_bl(GC_old_normal_bl, GC_incomplete_normal_bl); |
|
} |
|
GC_copy_bl(GC_old_stack_bl, GC_incomplete_stack_bl); |
|
} |
|
|
|
|
|
|
|
|
|
#ifdef PRINT_BLACK_LIST |
|
void GC_add_to_black_list_normal(word p, ptr_t source) |
|
#else |
|
void GC_add_to_black_list_normal(word p) |
|
#endif |
|
{ |
|
if (!(GC_modws_valid_offsets[p & (sizeof(word)-1)])) return; |
|
{ |
|
word index = PHT_HASH((word)p); |
|
|
|
if (HDR(p) == 0 || get_pht_entry_from_index(GC_old_normal_bl, index)) { |
|
# ifdef PRINT_BLACK_LIST |
|
if (!get_pht_entry_from_index(GC_incomplete_normal_bl, index)) { |
|
GC_err_printf( |
|
"Black listing (normal) %p referenced from %p ", |
|
(ptr_t) p, source); |
|
GC_print_source_ptr(source); |
|
GC_err_puts("\n"); |
|
} |
|
# endif |
|
set_pht_entry_from_index(GC_incomplete_normal_bl, index); |
|
} |
|
|
|
} |
|
} |
|
|
|
|
|
#ifdef PRINT_BLACK_LIST |
|
void GC_add_to_black_list_stack(word p, ptr_t source) |
|
ptr_t source; |
|
#else |
|
void GC_add_to_black_list_stack(word p) |
|
#endif |
|
{ |
|
word index = PHT_HASH((word)p); |
|
|
|
if (HDR(p) == 0 || get_pht_entry_from_index(GC_old_stack_bl, index)) { |
|
# ifdef PRINT_BLACK_LIST |
|
if (!get_pht_entry_from_index(GC_incomplete_stack_bl, index)) { |
|
GC_err_printf( |
|
"Black listing (stack) %p referenced from %p ", |
|
(ptr_t)p, source); |
|
GC_print_source_ptr(source); |
|
GC_err_puts("\n"); |
|
} |
|
# endif |
|
set_pht_entry_from_index(GC_incomplete_stack_bl, index); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct hblk * GC_is_black_listed(struct hblk *h, word len) |
|
{ |
|
word index = PHT_HASH((word)h); |
|
word i; |
|
word nblocks = divHBLKSZ(len); |
|
|
|
if (!GC_all_interior_pointers) { |
|
if (get_pht_entry_from_index(GC_old_normal_bl, index) |
|
|| get_pht_entry_from_index(GC_incomplete_normal_bl, index)) { |
|
return(h+1); |
|
} |
|
} |
|
|
|
for (i = 0; ; ) { |
|
if (GC_old_stack_bl[divWORDSZ(index)] == 0 |
|
&& GC_incomplete_stack_bl[divWORDSZ(index)] == 0) { |
|
|
|
i += WORDSZ - modWORDSZ(index); |
|
} else { |
|
if (get_pht_entry_from_index(GC_old_stack_bl, index) |
|
|| get_pht_entry_from_index(GC_incomplete_stack_bl, index)) { |
|
return(h+i+1); |
|
} |
|
i++; |
|
} |
|
if (i >= nblocks) break; |
|
index = PHT_HASH((word)(h+i)); |
|
} |
|
return(0); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
word GC_number_stack_black_listed(struct hblk *start, struct hblk *endp1) |
|
{ |
|
register struct hblk * h; |
|
word result = 0; |
|
|
|
for (h = start; h < endp1; h++) { |
|
word index = PHT_HASH((word)h); |
|
|
|
if (get_pht_entry_from_index(GC_old_stack_bl, index)) result++; |
|
} |
|
return(result); |
|
} |
|
|
|
|
|
|
|
static word total_stack_black_listed(void) |
|
{ |
|
register unsigned i; |
|
word total = 0; |
|
|
|
for (i = 0; i < GC_n_heap_sects; i++) { |
|
struct hblk * start = (struct hblk *) GC_heap_sects[i].hs_start; |
|
size_t len = (word) GC_heap_sects[i].hs_bytes; |
|
struct hblk * endp1 = start + len/HBLKSIZE; |
|
|
|
total += GC_number_stack_black_listed(start, endp1); |
|
} |
|
return(total * HBLKSIZE); |
|
} |
|
|
|
|