version 1.4, 2001/04/20 07:39:19 |
version 1.7, 2003/06/24 05:11:33 |
|
|
n_root_sets++; |
n_root_sets++; |
} |
} |
|
|
static roots_were_cleared = FALSE; |
static GC_bool roots_were_cleared = FALSE; |
|
|
void GC_clear_roots GC_PROTO((void)) |
void GC_clear_roots GC_PROTO((void)) |
{ |
{ |
Line 275 void GC_clear_roots GC_PROTO((void)) |
|
Line 275 void GC_clear_roots GC_PROTO((void)) |
|
} |
} |
|
|
/* Internal use only; lock held. */ |
/* Internal use only; lock held. */ |
|
static void GC_remove_root_at_pos(i) |
|
int i; |
|
{ |
|
GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start); |
|
GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; |
|
GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; |
|
GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; |
|
n_root_sets--; |
|
} |
|
|
|
#if !defined(MSWIN32) && !defined(MSWINCE) |
|
static void GC_rebuild_root_index() |
|
{ |
|
register int i; |
|
|
|
for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; |
|
for (i = 0; i < n_root_sets; i++) |
|
add_roots_to_index(GC_static_roots + i); |
|
} |
|
#endif |
|
|
|
/* Internal use only; lock held. */ |
void GC_remove_tmp_roots() |
void GC_remove_tmp_roots() |
{ |
{ |
register int i; |
register int i; |
|
|
for (i = 0; i < n_root_sets; ) { |
for (i = 0; i < n_root_sets; ) { |
if (GC_static_roots[i].r_tmp) { |
if (GC_static_roots[i].r_tmp) { |
GC_root_size -= |
GC_remove_root_at_pos(i); |
(GC_static_roots[i].r_end - GC_static_roots[i].r_start); |
|
GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; |
|
GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; |
|
GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; |
|
n_root_sets--; |
|
} else { |
} else { |
i++; |
i++; |
} |
|
} |
} |
# if !defined(MSWIN32) && !defined(MSWINCE) |
|
{ |
|
register int i; |
|
|
|
for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; |
|
for (i = 0; i < n_root_sets; i++) |
|
add_roots_to_index(GC_static_roots + i); |
|
} |
} |
# endif |
#if !defined(MSWIN32) && !defined(MSWINCE) |
|
GC_rebuild_root_index(); |
|
#endif |
|
} |
|
|
|
#if !defined(MSWIN32) && !defined(MSWINCE) |
|
void GC_remove_roots(b, e) |
|
char * b; char * e; |
|
{ |
|
DCL_LOCK_STATE; |
|
|
|
DISABLE_SIGNALS(); |
|
LOCK(); |
|
GC_remove_roots_inner(b, e); |
|
UNLOCK(); |
|
ENABLE_SIGNALS(); |
} |
} |
|
|
|
/* Should only be called when the lock is held */ |
|
void GC_remove_roots_inner(b,e) |
|
char * b; char * e; |
|
{ |
|
int i; |
|
for (i = 0; i < n_root_sets; ) { |
|
if (GC_static_roots[i].r_start >= (ptr_t)b && GC_static_roots[i].r_end <= (ptr_t)e) { |
|
GC_remove_root_at_pos(i); |
|
} else { |
|
i++; |
|
} |
|
} |
|
GC_rebuild_root_index(); |
|
} |
|
#endif /* !defined(MSWIN32) && !defined(MSWINCE) */ |
|
|
#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) |
#if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) |
/* Workaround for the OS mapping and unmapping behind our back: */ |
/* Workaround for the OS mapping and unmapping behind our back: */ |
/* Is the address p in one of the temporary static root sections? */ |
/* Is the address p in one of the temporary static root sections? */ |
Line 471 ptr_t cold_gc_frame; |
|
Line 510 ptr_t cold_gc_frame; |
|
cold_gc_bs_pointer = bsp - 2048; |
cold_gc_bs_pointer = bsp - 2048; |
if (cold_gc_bs_pointer < BACKING_STORE_BASE) { |
if (cold_gc_bs_pointer < BACKING_STORE_BASE) { |
cold_gc_bs_pointer = BACKING_STORE_BASE; |
cold_gc_bs_pointer = BACKING_STORE_BASE; |
|
} else { |
|
GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer); |
} |
} |
GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer); |
|
} else { |
} else { |
cold_gc_bs_pointer = BACKING_STORE_BASE; |
cold_gc_bs_pointer = BACKING_STORE_BASE; |
} |
} |
Line 501 void GC_push_gc_structures GC_PROTO((void)) |
|
Line 541 void GC_push_gc_structures GC_PROTO((void)) |
|
# endif |
# endif |
} |
} |
|
|
|
#ifdef THREAD_LOCAL_ALLOC |
|
void GC_mark_thread_local_free_lists(); |
|
#endif |
|
|
|
void GC_cond_register_dynamic_libraries() |
|
{ |
|
# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ |
|
|| defined(PCR)) && !defined(SRC_M3) |
|
GC_remove_tmp_roots(); |
|
if (!GC_no_dls) GC_register_dynamic_libraries(); |
|
# else |
|
GC_no_dls = TRUE; |
|
# endif |
|
} |
|
|
/* |
/* |
* Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional |
* Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional |
* on groups of pointers) on every top level accessible pointer. |
* on groups of pointers) on every top level accessible pointer. |
Line 514 void GC_push_roots(all, cold_gc_frame) |
|
Line 569 void GC_push_roots(all, cold_gc_frame) |
|
GC_bool all; |
GC_bool all; |
ptr_t cold_gc_frame; |
ptr_t cold_gc_frame; |
{ |
{ |
register int i; |
int i; |
|
int kind; |
|
|
/* |
/* |
* push registers - i.e., call GC_push_one(r) for each |
|
* register contents r. |
|
*/ |
|
# ifdef USE_GENERIC_PUSH_REGS |
|
GC_generic_push_regs(cold_gc_frame); |
|
# else |
|
GC_push_regs(); /* usually defined in machine_dep.c */ |
|
# endif |
|
|
|
/* |
|
* Next push static data. This must happen early on, since it's |
* Next push static data. This must happen early on, since it's |
* not robust against mark stack overflow. |
* not robust against mark stack overflow. |
*/ |
*/ |
/* Reregister dynamic libraries, in case one got added. */ |
/* Reregister dynamic libraries, in case one got added. */ |
# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ |
/* There is some argument for doing this as late as possible, */ |
|| defined(PCR)) && !defined(SRC_M3) |
/* especially on win32, where it can change asynchronously. */ |
GC_remove_tmp_roots(); |
/* In those cases, we do it here. But on other platforms, it's */ |
if (!GC_no_dls) GC_register_dynamic_libraries(); |
/* not safe with the world stopped, so we do it earlier. */ |
# else |
# if !defined(REGISTER_LIBRARIES_EARLY) |
GC_no_dls = TRUE; |
GC_cond_register_dynamic_libraries(); |
# endif |
# endif |
|
|
/* Mark everything in static data areas */ |
/* Mark everything in static data areas */ |
Line 546 ptr_t cold_gc_frame; |
|
Line 592 ptr_t cold_gc_frame; |
|
GC_static_roots[i].r_end, all); |
GC_static_roots[i].r_end, all); |
} |
} |
|
|
|
/* Mark all free list header blocks, if those were allocated from */ |
|
/* the garbage collected heap. This makes sure they don't */ |
|
/* disappear if we are not marking from static data. It also */ |
|
/* saves us the trouble of scanning them, and possibly that of */ |
|
/* marking the freelists. */ |
|
for (kind = 0; kind < GC_n_kinds; kind++) { |
|
GC_PTR base = GC_base(GC_obj_kinds[kind].ok_freelist); |
|
if (0 != base) { |
|
GC_set_mark_bit(base); |
|
} |
|
} |
|
|
/* Mark from GC internal roots if those might otherwise have */ |
/* Mark from GC internal roots if those might otherwise have */ |
/* been excluded. */ |
/* been excluded. */ |
if (GC_no_dls || roots_were_cleared) { |
if (GC_no_dls || roots_were_cleared) { |
GC_push_gc_structures(); |
GC_push_gc_structures(); |
} |
} |
|
|
|
/* Mark thread local free lists, even if their mark */ |
|
/* descriptor excludes the link field. */ |
|
/* If the world is not stopped, this is unsafe. It is */ |
|
/* also unnecessary, since we will do this again with the */ |
|
/* world stopped. */ |
|
# ifdef THREAD_LOCAL_ALLOC |
|
if (GC_world_stopped) GC_mark_thread_local_free_lists(); |
|
# endif |
|
|
/* |
/* |
* Now traverse stacks. |
* Now traverse stacks, and mark from register contents. |
|
* These must be done last, since they can legitimately overflow |
|
* the mark stack. |
*/ |
*/ |
# if !defined(USE_GENERIC_PUSH_REGS) |
# ifdef USE_GENERIC_PUSH_REGS |
|
GC_generic_push_regs(cold_gc_frame); |
|
/* Also pushes stack, so that we catch callee-save registers */ |
|
/* saved inside the GC_push_regs frame. */ |
|
# else |
|
/* |
|
* push registers - i.e., call GC_push_one(r) for each |
|
* register contents r. |
|
*/ |
|
GC_push_regs(); /* usually defined in machine_dep.c */ |
GC_push_current_stack(cold_gc_frame); |
GC_push_current_stack(cold_gc_frame); |
/* IN the threads case, this only pushes collector frames. */ |
/* In the threads case, this only pushes collector frames. */ |
/* In the USE_GENERIC_PUSH_REGS case, this is done inside */ |
/* In the case of linux threads on IA64, the hot section of */ |
/* GC_push_regs, so that we catch callee-save registers saved */ |
|
/* inside the GC_push_regs frame. */ |
|
/* In the case of linux threads on Ia64, the hot section of */ |
|
/* the main stack is marked here, but the register stack */ |
/* the main stack is marked here, but the register stack */ |
/* backing store is handled in the threads-specific code. */ |
/* backing store is handled in the threads-specific code. */ |
# endif |
# endif |
if (GC_push_other_roots != 0) (*GC_push_other_roots)(); |
if (GC_push_other_roots != 0) (*GC_push_other_roots)(); |
/* In the threads case, this also pushes thread stacks. */ |
/* In the threads case, this also pushes thread stacks. */ |
|
/* Note that without interior pointer recognition lots */ |
|
/* of stuff may have been pushed already, and this */ |
|
/* should be careful about mark stack overflows. */ |
} |
} |
|
|