00001 # include <stdio.h>
00002 # include "gc_private.h"
00003
00004 # ifdef PCR
00005 # define MAX_ROOT_SETS 1024
00006 # include "pcr/il/PCR_IL.h"
00007 # include "pcr/th/PCR_ThCtl.h"
00008 # include "pcr/mm/PCR_MM.h"
00009 # else
00010 # define MAX_ROOT_SETS 64
00011 # endif
00012
00013
00014
00015 struct roots {
00016 ptr_t r_start;
00017 ptr_t r_end;
00018 struct roots * r_next;
00019 };
00020
00021 static struct roots static_roots[MAX_ROOT_SETS];
00022
00023 static n_root_sets = 0;
00024
00025
00026
00027 #define RT_SIZE 64
00028 #define LOG_RT_SIZE 6
00029
00030 static struct roots * root_index[RT_SIZE];
00031
00032
00033
00034 static int rt_hash(addr)
00035 char * addr;
00036 {
00037 word result = (word) addr;
00038 # if CPP_WORDSZ > 8*LOG_RT_SIZE
00039 result ^= result >> 8*LOG_RT_SIZE;
00040 # endif
00041 # if CPP_WORDSZ > 4*LOG_RT_SIZE
00042 result ^= result >> 4*LOG_RT_SIZE;
00043 # endif
00044 result ^= result >> 2*LOG_RT_SIZE;
00045 result ^= result >> LOG_RT_SIZE;
00046 result &= (RT_SIZE-1);
00047 return(result);
00048 }
00049
00050
00051 static bool roots_present(b, e)
00052 char *b, *e;
00053 {
00054 register int h = rt_hash(b);
00055 register struct roots *p = root_index[h];
00056
00057 while (p != 0) {
00058 if (p -> r_start == (ptr_t)b && p -> r_end >= (ptr_t)e) return(TRUE);
00059 p = p -> r_next;
00060 }
00061 return(FALSE);
00062 }
00063
00064
00065 static void add_roots_to_index(p)
00066 struct roots *p;
00067 {
00068 register int h = rt_hash(p -> r_start);
00069
00070 p -> r_next = root_index[h];
00071 root_index[h] = p;
00072 }
00073
00074
00075 word GC_root_size = 0;
00076
00077 void GC_add_roots(b, e)
00078 char * b; char * e;
00079 {
00080 DCL_LOCK_STATE;
00081
00082 DISABLE_SIGNALS();
00083 LOCK();
00084 GC_add_roots_inner(b, e);
00085 UNLOCK();
00086 ENABLE_SIGNALS();
00087 }
00088
00089
00090
00091
00092
00093
00094 void GC_add_roots_inner(b, e)
00095 char * b; char * e;
00096 {
00097
00098
00099 if ( (ptr_t)b < beginGC_arrays && (ptr_t)e > beginGC_arrays) {
00100 if ((ptr_t)e <= endGC_arrays) {
00101 e = (char *)beginGC_arrays;
00102 } else {
00103 GC_add_roots_inner(b, (char *)beginGC_arrays);
00104 GC_add_roots_inner((char *)endGC_arrays, e);
00105 return;
00106 }
00107 } else if ((ptr_t)b < endGC_arrays && (ptr_t)e > endGC_arrays) {
00108 b = (char *)endGC_arrays;
00109 }
00110 if (roots_present(b,e)) return;
00111 if (n_root_sets == MAX_ROOT_SETS) {
00112 ABORT("Too many root sets\n");
00113 }
00114 static_roots[n_root_sets].r_start = (ptr_t)b;
00115 static_roots[n_root_sets].r_end = (ptr_t)e;
00116 static_roots[n_root_sets].r_next = 0;
00117 add_roots_to_index(static_roots + n_root_sets);
00118 GC_root_size += (ptr_t)e - (ptr_t)b;
00119 n_root_sets++;
00120 }
00121
00122 void GC_clear_roots()
00123 {
00124 DCL_LOCK_STATE;
00125
00126 DISABLE_SIGNALS();
00127 LOCK();
00128 n_root_sets = 0;
00129 GC_root_size = 0;
00130 UNLOCK();
00131 ENABLE_SIGNALS();
00132 }
00133
00134 # ifdef PCR
00135 PCR_ERes GC_mark_thread_stack(PCR_Th_T *t, PCR_Any dummy)
00136 {
00137 struct PCR_ThCtl_TInfoRep info;
00138 PCR_ERes result;
00139
00140 info.ti_stkLow = info.ti_stkHi = 0;
00141 result = PCR_ThCtl_GetInfo(t, &info);
00142 GC_mark_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
00143 return(result);
00144 }
00145
00146 PCR_ERes GC_mark_old_obj(void *p, size_t size, PCR_Any data)
00147 {
00148 GC_mark_all((ptr_t)p, (ptr_t)p + size);
00149 return(PCR_ERes_okay);
00150 }
00151
00152 # else
00153 ptr_t GC_approx_sp()
00154 {
00155 word dummy;
00156
00157 return((ptr_t)(&dummy));
00158 }
00159 # endif
00160
00161
00162
00163
00164
00165
00166 GC_mark_roots()
00167 {
00168 register int i;
00169
00170
00171
00172
00173
00174 GC_mark_regs();
00175
00176
00177 # ifdef PCR
00178
00179 {
00180 extern struct PCR_MM_ProcsRep * GC_old_allocator;
00181
00182 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
00183 GC_mark_old_obj, 0)
00184 != PCR_ERes_okay) {
00185 ABORT("Old object enumeration failed");
00186 }
00187 }
00188
00189
00190 {
00191 PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
00192 PCR_IL_LoadedSegment * q;
00193
00194
00195 while (p != NIL && !(p -> lf_commitPoint)) {
00196
00197
00198
00199
00200
00201 p = p -> lf_prev;
00202 }
00203 for (; p != NIL; p = p -> lf_prev) {
00204 for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
00205 if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
00206 == PCR_IL_SegFlags_Traced_on) {
00207 GC_add_roots_inner
00208 ((char *)(q -> ls_addr),
00209 (char *)(q -> ls_addr) + q -> ls_bytes);
00210 }
00211 }
00212 }
00213 }
00214
00215
00216
00217 if (PCR_ERes_IsErr(
00218 PCR_ThCtl_ApplyToAllOtherThreads(GC_mark_thread_stack,0))
00219 || PCR_ERes_IsErr(GC_mark_thread_stack(PCR_Th_CurrThread(), 0))) {
00220 ABORT("Thread stack marking failed\n");
00221 }
00222 # else
00223
00224 # ifdef STACK_GROWS_DOWN
00225 GC_mark_all_stack( GC_approx_sp(), GC_stackbottom );
00226 # else
00227 GC_mark_all_stack( GC_stackbottom, GC_approx_sp() );
00228 # endif
00229
00230 # endif
00231
00232
00233 GC_register_dynamic_libraries();
00234
00235 for (i = 0; i < n_root_sets; i++) {
00236 GC_mark_all(static_roots[i].r_start, static_roots[i].r_end);
00237 }
00238 }
00239
00240
00241
00242
00243
00244 void GC_tl_mark(p)
00245 word p;
00246 {
00247 word q;
00248
00249 q = p;
00250 GC_mark_all_stack((ptr_t)(&q), (ptr_t)((&q)+1));
00251 }