| version 1.5, 2002/07/24 07:46:19 |
version 1.6, 2002/07/24 08:00:10 |
| Line 264 static void alloc_mark_stack(); |
|
| Line 264 static void alloc_mark_stack(); |
|
| GC_bool GC_mark_some(cold_gc_frame) |
GC_bool GC_mark_some(cold_gc_frame) |
| ptr_t cold_gc_frame; |
ptr_t cold_gc_frame; |
| { |
{ |
| #ifdef MSWIN32 |
#if defined(MSWIN32) && !defined(__GNUC__) |
| /* Windows 98 appears to asynchronously create and remove writable */ |
/* Windows 98 appears to asynchronously create and remove writable */ |
| /* memory mappings, for reasons we haven't yet understood. Since */ |
/* memory mappings, for reasons we haven't yet understood. Since */ |
| /* we look for writable regions to determine the root set, we may */ |
/* we look for writable regions to determine the root set, we may */ |
| Line 274 ptr_t cold_gc_frame; |
|
| Line 274 ptr_t cold_gc_frame; |
|
| /* Note that this code should never generate an incremental GC write */ |
/* Note that this code should never generate an incremental GC write */ |
| /* fault. */ |
/* fault. */ |
| __try { |
__try { |
| #endif |
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
| switch(GC_mark_state) { |
switch(GC_mark_state) { |
| case MS_NONE: |
case MS_NONE: |
| return(FALSE); |
return(FALSE); |
| Line 395 ptr_t cold_gc_frame; |
|
| Line 395 ptr_t cold_gc_frame; |
|
| ABORT("GC_mark_some: bad state"); |
ABORT("GC_mark_some: bad state"); |
| return(FALSE); |
return(FALSE); |
| } |
} |
| #ifdef MSWIN32 |
#if defined(MSWIN32) && !defined(__GNUC__) |
| } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? |
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? |
| EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { |
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { |
| # ifdef CONDPRINT |
# ifdef CONDPRINT |
| Line 410 ptr_t cold_gc_frame; |
|
| Line 410 ptr_t cold_gc_frame; |
|
| scan_ptr = 0; |
scan_ptr = 0; |
| return FALSE; |
return FALSE; |
| } |
} |
| #endif /* MSWIN32 */ |
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
| } |
} |
| |
|
| |
|
| Line 427 GC_bool GC_mark_stack_empty() |
|
| Line 427 GC_bool GC_mark_stack_empty() |
|
| #endif |
#endif |
| |
|
| /* Given a pointer to someplace other than a small object page or the */ |
/* Given a pointer to someplace other than a small object page or the */ |
| /* first page of a large object, return a pointer either to the */ |
/* first page of a large object, either: */ |
| /* start of the large object or NIL. */ |
/* - return a pointer to somewhere in the first page of the large */ |
| /* In the latter case black list the address current. */ |
/* object, if current points to a large object. */ |
| /* Returns NIL without black listing if current points to a block */ |
/* In this case *hhdr is replaced with a pointer to the header */ |
| /* with IGNORE_OFF_PAGE set. */ |
/* for the large object. */ |
| |
/* - just return current if it does not point to a large object. */ |
| /*ARGSUSED*/ |
/*ARGSUSED*/ |
| # ifdef PRINT_BLACK_LIST |
ptr_t GC_find_start(current, hhdr, new_hdr_p) |
| ptr_t GC_find_start(current, hhdr, source) |
|
| word source; |
|
| # else |
|
| ptr_t GC_find_start(current, hhdr) |
|
| # define source 0 |
|
| # endif |
|
| register ptr_t current; |
register ptr_t current; |
| register hdr * hhdr; |
register hdr *hhdr, **new_hdr_p; |
| { |
{ |
| if (GC_all_interior_pointers) { |
if (GC_all_interior_pointers) { |
| if (hhdr != 0) { |
if (hhdr != 0) { |
| Line 457 register hdr * hhdr; |
|
| Line 452 register hdr * hhdr; |
|
| if ((word *)orig - (word *)current |
if ((word *)orig - (word *)current |
| >= (ptrdiff_t)(hhdr->hb_sz)) { |
>= (ptrdiff_t)(hhdr->hb_sz)) { |
| /* Pointer past the end of the block */ |
/* Pointer past the end of the block */ |
| GC_ADD_TO_BLACK_LIST_NORMAL((word)orig, source); |
return(orig); |
| return(0); |
|
| } |
} |
| |
*new_hdr_p = hhdr; |
| return(current); |
return(current); |
| } else { |
} else { |
| GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); |
return(current); |
| return(0); |
|
| } |
} |
| } else { |
} else { |
| GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); |
return(current); |
| return(0); |
|
| } |
} |
| # undef source |
|
| } |
} |
| |
|
| void GC_invalidate_mark_state() |
void GC_invalidate_mark_state() |
| Line 547 mse * mark_stack_limit; |
|
| Line 539 mse * mark_stack_limit; |
|
| /* Large length. */ |
/* Large length. */ |
| /* Process part of the range to avoid pushing too much on the */ |
/* Process part of the range to avoid pushing too much on the */ |
| /* stack. */ |
/* stack. */ |
| |
GC_ASSERT(descr < GC_greatest_plausible_heap_addr |
| |
- GC_least_plausible_heap_addr); |
| # ifdef PARALLEL_MARK |
# ifdef PARALLEL_MARK |
| # define SHARE_BYTES 2048 |
# define SHARE_BYTES 2048 |
| if (descr > SHARE_BYTES && GC_parallel |
if (descr > SHARE_BYTES && GC_parallel |
| && mark_stack_top < mark_stack_limit - 1) { |
&& mark_stack_top < mark_stack_limit - 1) { |
| int new_size = (descr/2) & ~(sizeof(word)-1); |
int new_size = (descr/2) & ~(sizeof(word)-1); |
| GC_ASSERT(descr < GC_greatest_plausible_heap_addr |
|
| - GC_least_plausible_heap_addr); |
|
| mark_stack_top -> mse_start = current_p; |
mark_stack_top -> mse_start = current_p; |
| mark_stack_top -> mse_descr = new_size + sizeof(word); |
mark_stack_top -> mse_descr = new_size + sizeof(word); |
| /* makes sure we handle */ |
/* makes sure we handle */ |
| Line 839 long GC_markers = 2; /* Normally changed by thread-li |
|
| Line 831 long GC_markers = 2; /* Normally changed by thread-li |
|
| /* -specific code. */ |
/* -specific code. */ |
| |
|
| /* Mark using the local mark stack until the global mark stack is empty */ |
/* Mark using the local mark stack until the global mark stack is empty */ |
| /* and ther are no active workers. Update GC_first_nonempty to reflect */ |
/* and there are no active workers. Update GC_first_nonempty to reflect */ |
| /* progress. */ |
/* progress. */ |
| /* Caller does not hold mark lock. */ |
/* Caller does not hold mark lock. */ |
| /* Caller has already incremented GC_helper_count. We decrement it, */ |
/* Caller has already incremented GC_helper_count. We decrement it, */ |
| Line 919 void GC_mark_local(mse *local_mark_stack, int id) |
|
| Line 911 void GC_mark_local(mse *local_mark_stack, int id) |
|
| return; |
return; |
| } |
} |
| /* else there's something on the stack again, or */ |
/* else there's something on the stack again, or */ |
| /* another help may push something. */ |
/* another helper may push something. */ |
| GC_active_count++; |
GC_active_count++; |
| GC_ASSERT(GC_active_count > 0); |
GC_ASSERT(GC_active_count > 0); |
| GC_release_mark_lock(); |
GC_release_mark_lock(); |
| Line 951 void GC_do_parallel_mark() |
|
| Line 943 void GC_do_parallel_mark() |
|
| |
|
| GC_acquire_mark_lock(); |
GC_acquire_mark_lock(); |
| GC_ASSERT(I_HOLD_LOCK()); |
GC_ASSERT(I_HOLD_LOCK()); |
| GC_ASSERT(!GC_help_wanted); |
/* This could be a GC_ASSERT, but it seems safer to keep it on */ |
| GC_ASSERT(GC_active_count == 0); |
/* all the time, especially since it's cheap. */ |
| |
if (GC_help_wanted || GC_active_count != 0 || GC_helper_count != 0) |
| |
ABORT("Tried to start parallel mark in bad state"); |
| # ifdef PRINTSTATS |
# ifdef PRINTSTATS |
| GC_printf1("Starting marking for mark phase number %lu\n", |
GC_printf1("Starting marking for mark phase number %lu\n", |
| (unsigned long)GC_mark_no); |
(unsigned long)GC_mark_no); |
| Line 1375 ptr_t cold_gc_frame; |
|
| Line 1369 ptr_t cold_gc_frame; |
|
| return; |
return; |
| } |
} |
| # ifdef STACK_GROWS_DOWN |
# ifdef STACK_GROWS_DOWN |
| GC_push_all_eager(bottom, cold_gc_frame); |
|
| GC_push_all(cold_gc_frame - sizeof(ptr_t), top); |
GC_push_all(cold_gc_frame - sizeof(ptr_t), top); |
| |
GC_push_all_eager(bottom, cold_gc_frame); |
| # else /* STACK_GROWS_UP */ |
# else /* STACK_GROWS_UP */ |
| GC_push_all_eager(cold_gc_frame, top); |
|
| GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t)); |
GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t)); |
| |
GC_push_all_eager(cold_gc_frame, top); |
| # endif /* STACK_GROWS_UP */ |
# endif /* STACK_GROWS_UP */ |
| } else { |
} else { |
| GC_push_all_eager(bottom, top); |
GC_push_all_eager(bottom, top); |