diff options
Diffstat (limited to 'boehm-gc/mark_rts.c')
-rw-r--r-- | boehm-gc/mark_rts.c | 225 |
1 files changed, 138 insertions, 87 deletions
diff --git a/boehm-gc/mark_rts.c b/boehm-gc/mark_rts.c index efe6b64058f..0e84f2732fc 100644 --- a/boehm-gc/mark_rts.c +++ b/boehm-gc/mark_rts.c @@ -15,46 +15,27 @@ # include <stdio.h> # include "gc_priv.h" -/* MAX_ROOT_SETS is the maximum number of ranges that can be */ -/* registered as static roots. */ -# ifdef LARGE_CONFIG -# define MAX_ROOT_SETS 4096 -# else -# ifdef PCR -# define MAX_ROOT_SETS 1024 -# else -# ifdef MSWIN32 -# define MAX_ROOT_SETS 512 - /* Under NT, we add only written pages, which can result */ - /* in many small root sets. */ -# else -# define MAX_ROOT_SETS 64 -# endif -# endif -# endif - -# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4) -/* Maximum number of segments that can be excluded from root sets. */ - /* Data structure for list of root sets. */ /* We keep a hash table, so that we can filter out duplicate additions. */ /* Under Win32, we need to do a better job of filtering overlaps, so */ /* we resort to sequential search, and pay the price. */ +/* This is really declared in gc_priv.h: struct roots { ptr_t r_start; ptr_t r_end; -# ifndef MSWIN32 + # ifndef MSWIN32 struct roots * r_next; -# endif + # endif GC_bool r_tmp; - /* Delete before registering new dynamic libraries */ + -- Delete before registering new dynamic libraries }; -static struct roots static_roots[MAX_ROOT_SETS]; +struct roots GC_static_roots[MAX_ROOT_SETS]; +*/ static int n_root_sets = 0; - /* static_roots[0..n_root_sets) contains the valid root sets. */ + /* GC_static_roots[0..n_root_sets) contains the valid root sets. */ # if !defined(NO_DEBUGGING) /* For debugging: */ @@ -65,14 +46,14 @@ void GC_print_static_roots() for (i = 0; i < n_root_sets; i++) { GC_printf2("From 0x%lx to 0x%lx ", - (unsigned long) static_roots[i].r_start, - (unsigned long) static_roots[i].r_end); - if (static_roots[i].r_tmp) { + (unsigned long) GC_static_roots[i].r_start, + (unsigned long) GC_static_roots[i].r_end); + if (GC_static_roots[i].r_tmp) { GC_printf0(" (temporary)\n"); } else { GC_printf0("\n"); } - total += static_roots[i].r_end - static_roots[i].r_start; + total += GC_static_roots[i].r_end - GC_static_roots[i].r_start; } GC_printf1("Total size: %ld\n", (unsigned long) total); if (GC_root_size != total) { @@ -92,11 +73,11 @@ ptr_t p; register int i; - if (p >= static_roots[last_root_set].r_start - && p < static_roots[last_root_set].r_end) return(TRUE); + if (p >= GC_static_roots[last_root_set].r_start + && p < GC_static_roots[last_root_set].r_end) return(TRUE); for (i = 0; i < n_root_sets; i++) { - if (p >= static_roots[i].r_start - && p < static_roots[i].r_end) { + if (p >= GC_static_roots[i].r_start + && p < GC_static_roots[i].r_end) { last_root_set = i; return(TRUE); } @@ -105,12 +86,15 @@ ptr_t p; } #ifndef MSWIN32 +/* # define LOG_RT_SIZE 6 -# define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */ +# define RT_SIZE (1 << LOG_RT_SIZE) -- Power of 2, may be != MAX_ROOT_SETS - static struct roots * root_index[RT_SIZE]; - /* Hash table header. Used only to check whether a range is */ - /* already present. */ + struct roots * GC_root_index[RT_SIZE]; + -- Hash table header. Used only to check whether a range is + -- already present. + -- really defined in gc_priv.h +*/ static int rt_hash(addr) char * addr; @@ -134,7 +118,7 @@ struct roots * GC_roots_present(b) char *b; { register int h = rt_hash(b); - register struct roots *p = root_index[h]; + register struct roots *p = GC_root_index[h]; while (p != 0) { if (p -> r_start == (ptr_t)b) return(p); @@ -149,8 +133,8 @@ struct roots *p; { register int h = rt_hash(p -> r_start); - p -> r_next = root_index[h]; - root_index[h] = p; + p -> r_next = GC_root_index[h]; + GC_root_index[h] = p; } # else /* MSWIN32 */ @@ -200,7 +184,7 @@ GC_bool tmp; register int i; for (i = 0; i < n_root_sets; i++) { - old = static_roots + i; + old = GC_static_roots + i; if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) { if ((ptr_t)b < old -> r_start) { old -> r_start = (ptr_t)b; @@ -219,7 +203,7 @@ GC_bool tmp; struct roots *other; for (i++; i < n_root_sets; i++) { - other = static_roots + i; + other = GC_static_roots + i; b = (char *)(other -> r_start); e = (char *)(other -> r_end); if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) { @@ -234,8 +218,8 @@ GC_bool tmp; old -> r_tmp &= other -> r_tmp; /* Delete this entry. */ GC_root_size -= (other -> r_end - other -> r_start); - other -> r_start = static_roots[n_root_sets-1].r_start; - other -> r_end = static_roots[n_root_sets-1].r_end; + other -> r_start = GC_static_roots[n_root_sets-1].r_start; + other -> r_end = GC_static_roots[n_root_sets-1].r_end; n_root_sets--; } } @@ -255,13 +239,13 @@ GC_bool tmp; if (n_root_sets == MAX_ROOT_SETS) { ABORT("Too many root sets\n"); } - static_roots[n_root_sets].r_start = (ptr_t)b; - static_roots[n_root_sets].r_end = (ptr_t)e; - static_roots[n_root_sets].r_tmp = tmp; + GC_static_roots[n_root_sets].r_start = (ptr_t)b; + GC_static_roots[n_root_sets].r_end = (ptr_t)e; + GC_static_roots[n_root_sets].r_tmp = tmp; # ifndef MSWIN32 - static_roots[n_root_sets].r_next = 0; + GC_static_roots[n_root_sets].r_next = 0; # endif - add_roots_to_index(static_roots + n_root_sets); + add_roots_to_index(GC_static_roots + n_root_sets); GC_root_size += (ptr_t)e - (ptr_t)b; n_root_sets++; } @@ -278,7 +262,7 @@ void GC_clear_roots GC_PROTO((void)) { register int i; - for (i = 0; i < RT_SIZE; i++) root_index[i] = 0; + for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; } # endif UNLOCK(); @@ -291,11 +275,12 @@ void GC_remove_tmp_roots() register int i; for (i = 0; i < n_root_sets; ) { - if (static_roots[i].r_tmp) { - GC_root_size -= (static_roots[i].r_end - static_roots[i].r_start); - static_roots[i].r_start = static_roots[n_root_sets-1].r_start; - static_roots[i].r_end = static_roots[n_root_sets-1].r_end; - static_roots[i].r_tmp = static_roots[n_root_sets-1].r_tmp; + if (GC_static_roots[i].r_tmp) { + 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--; } else { i++; @@ -305,8 +290,9 @@ void GC_remove_tmp_roots() { register int i; - for (i = 0; i < RT_SIZE; i++) root_index[i] = 0; - for (i = 0; i < n_root_sets; i++) add_roots_to_index(static_roots + 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 @@ -321,16 +307,19 @@ ptr_t GC_approx_sp() /* * Data structure for excluded static roots. - */ + * Real declaration is in gc_priv.h. + struct exclusion { ptr_t e_start; ptr_t e_end; }; -struct exclusion excl_table[MAX_EXCLUSIONS]; - /* Array of exclusions, ascending */ - /* address order. */ -size_t excl_table_entries = 0; /* Number of entries in use. */ +struct exclusion GC_excl_table[MAX_EXCLUSIONS]; + -- Array of exclusions, ascending + -- address order. +*/ + +size_t GC_excl_table_entries = 0; /* Number of entries in use. */ /* Return the first exclusion range that includes an address >= start_addr */ /* Assumes the exclusion table contains at least one entry (namely the */ @@ -339,20 +328,20 @@ struct exclusion * GC_next_exclusion(start_addr) ptr_t start_addr; { size_t low = 0; - size_t high = excl_table_entries - 1; + size_t high = GC_excl_table_entries - 1; size_t mid; while (high > low) { mid = (low + high) >> 1; /* low <= mid < high */ - if ((word) excl_table[mid].e_end <= (word) start_addr) { + if ((word) GC_excl_table[mid].e_end <= (word) start_addr) { low = mid + 1; } else { high = mid; } } - if ((word) excl_table[low].e_end <= (word) start_addr) return 0; - return excl_table + low; + if ((word) GC_excl_table[low].e_end <= (word) start_addr) return 0; + return GC_excl_table + low; } void GC_exclude_static_roots(start, finish) @@ -362,7 +351,7 @@ GC_PTR finish; struct exclusion * next; size_t next_index, i; - if (0 == excl_table_entries) { + if (0 == GC_excl_table_entries) { next = 0; } else { next = GC_next_exclusion(start); @@ -377,17 +366,17 @@ GC_PTR finish; next -> e_start = (ptr_t)start; return; } - next_index = next - excl_table; - for (i = excl_table_entries; i > next_index; --i) { - excl_table[i] = excl_table[i-1]; + next_index = next - GC_excl_table; + for (i = GC_excl_table_entries; i > next_index; --i) { + GC_excl_table[i] = GC_excl_table[i-1]; } } else { - next_index = excl_table_entries; + next_index = GC_excl_table_entries; } - if (excl_table_entries == MAX_EXCLUSIONS) ABORT("Too many exclusions"); - excl_table[next_index].e_start = (ptr_t)start; - excl_table[next_index].e_end = (ptr_t)finish; - ++excl_table_entries; + if (GC_excl_table_entries == MAX_EXCLUSIONS) ABORT("Too many exclusions"); + GC_excl_table[next_index].e_start = (ptr_t)start; + GC_excl_table[next_index].e_end = (ptr_t)finish; + ++GC_excl_table_entries; } /* Invoke push_conditional on ranges that are not excluded. */ @@ -411,13 +400,72 @@ int all; } /* + * In the absence of threads, push the stack contents. + * In the presence of threads, push enough of the current stack + * to ensure that callee-save registers saved in collector frames have been + * seen. + */ +void GC_push_current_stack(cold_gc_frame) +ptr_t cold_gc_frame; +{ +# if defined(THREADS) + if (0 == cold_gc_frame) return; +# ifdef STACK_GROWS_DOWN + GC_push_all_eager(GC_approx_sp(), cold_gc_frame); +# ifdef IA64 + --> fix this +# endif +# else + GC_push_all_eager( cold_gc_frame, GC_approx_sp() ); +# endif +# else +# ifdef STACK_GROWS_DOWN + GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom, + cold_gc_frame ); +# ifdef IA64 + /* We also need to push the register stack backing store. */ + /* This should really be done in the same way as the */ + /* regular stack. For now we fudge it a bit. */ + /* Note that the backing store grows up, so we can't use */ + /* GC_push_all_stack_partially_eager. */ + { + extern word GC_save_regs_ret_val; + /* Previously set to backing store pointer. */ + ptr_t bsp = (ptr_t) GC_save_regs_ret_val; + ptr_t cold_gc_bs_pointer; +# ifdef ALL_INTERIOR_POINTERS + cold_gc_bs_pointer = bsp - 2048; + if (cold_gc_bs_pointer < BACKING_STORE_BASE) { + cold_gc_bs_pointer = BACKING_STORE_BASE; + } + GC_push_all(BACKING_STORE_BASE, cold_gc_bs_pointer); +# else + cold_gc_bs_pointer = BACKING_STORE_BASE; +# endif + GC_push_all_eager(cold_gc_bs_pointer, bsp); + /* All values should be sufficiently aligned that we */ + /* dont have to worry about the boundary. */ + } +# endif +# else + GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(), + cold_gc_frame ); +# endif +# endif /* !THREADS */ +} + +/* * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional * on groups of pointers) on every top level accessible pointer. * If all is FALSE, arrange to push only possibly altered values. + * Cold_gc_frame is an address inside a GC frame that + * remains valid until all marking is complete. + * A zero value indicates that it's OK to miss some + * register values. */ - -void GC_push_roots(all) +void GC_push_roots(all, cold_gc_frame) GC_bool all; +ptr_t cold_gc_frame; { register int i; @@ -425,7 +473,11 @@ GC_bool all; * 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 @@ -440,20 +492,19 @@ GC_bool all; /* Mark everything in static data areas */ for (i = 0; i < n_root_sets; i++) { GC_push_conditional_with_exclusions( - static_roots[i].r_start, - static_roots[i].r_end, all); + GC_static_roots[i].r_start, + GC_static_roots[i].r_end, all); } /* * Now traverse stacks. */ -# ifndef THREADS - /* Mark everything on the stack. */ -# ifdef STACK_GROWS_DOWN - GC_push_all_stack( GC_approx_sp(), GC_stackbottom ); -# else - GC_push_all_stack( GC_stackbottom, GC_approx_sp() ); -# endif +# if !defined(USE_GENERIC_PUSH_REGS) + GC_push_current_stack(cold_gc_frame); + /* IN the threads case, this only pushes collector frames. */ + /* In the USE_GENERIC_PUSH_REGS case, this is done inside */ + /* GC_push_regs, so that we catch callee-save registers saved */ + /* inside the GC_push_regs frame. */ # endif if (GC_push_other_roots != 0) (*GC_push_other_roots)(); /* In the threads case, this also pushes thread stacks. */ |