00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include <stdio.h>
00025 # include "gc_private.h"
00026
00027 # define INITIAL_MARK_STACK_SIZE (1*HBLKSIZE)
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 mse * GC_mark_stack;
00039
00040 word GC_mark_stack_size = 0;
00041
00042 mse * GC_mark_stack_top;
00043
00044 static bool dropped_some = FALSE;
00045
00046
00047
00048
00049
00050
00051
00052
00053 mse * GC_normal_mark_proc(addr, hhdr, msp, msl)
00054 register word * addr;
00055 register hdr * hhdr;
00056 register mse * msp, * msl;
00057 {
00058 register word sz = hhdr -> hb_sz;
00059
00060 msp++;
00061
00062 if (msp >= msl) {
00063 dropped_some = TRUE;
00064 return(msp-1);
00065 }
00066 msp -> mse_start = addr;
00067 msp -> mse_end = addr + sz;
00068 # ifdef GATHERSTATS
00069 GC_composite_in_use += sz;
00070 # endif
00071 return(msp);
00072 }
00073
00074
00075
00076 mse * GC_no_mark_proc(addr, hhdr, msp, msl)
00077 register word * addr;
00078 register hdr * hhdr;
00079 register mse * msp, * msl;
00080 {
00081 # ifdef GATHERSTATS
00082 GC_atomic_in_use += hhdr -> hb_sz;
00083 # endif
00084 return(msp);
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 void GC_mark()
00097 {
00098 mse * GC_mark_stack_reg = GC_mark_stack;
00099 mse * GC_mark_stack_top_reg = GC_mark_stack_top;
00100 mse * mark_stack_limit = &(GC_mark_stack[GC_mark_stack_size]);
00101 register word * current_p;
00102 register word current;
00103 register word * limit;
00104
00105 register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
00106 register ptr_t least_ha = GC_least_plausible_heap_addr;
00107 # define SPLIT_RANGE_WORDS 128
00108
00109 while (GC_mark_stack_top_reg >= GC_mark_stack_reg) {
00110 register int displ;
00111 register hdr * hhdr;
00112 register map_entry_type map_entry;
00113
00114 current_p = GC_mark_stack_top_reg -> mse_start;
00115 limit = GC_mark_stack_top_reg -> mse_end;
00116 if (limit - current_p > SPLIT_RANGE_WORDS) {
00117
00118
00119 GC_mark_stack_top_reg -> mse_start =
00120 limit = current_p + SPLIT_RANGE_WORDS;
00121
00122
00123 limit += sizeof(word) - ALIGNMENT;
00124 } else {
00125 GC_mark_stack_top_reg--;
00126 }
00127 limit -= 1;
00128
00129 while (current_p <= limit) {
00130 current = *current_p;
00131 current_p = (word *)((char *)current_p + ALIGNMENT);
00132
00133 if ((ptr_t)current < least_ha) continue;
00134 if ((ptr_t)current >= greatest_ha) continue;
00135 hhdr = HDR(current);
00136 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
00137 # ifdef ALL_INTERIOR_POINTERS
00138 if (hhdr != 0) {
00139 register word orig = current;
00140
00141 current = (word)HBLKPTR(current) + HDR_BYTES;
00142 do {
00143 current = current - HBLKSIZE*(int)hhdr;
00144 hhdr = HDR(current);
00145 } while(IS_FORWARDING_ADDR_OR_NIL(hhdr));
00146
00147 if ((word *)orig - (word *)current
00148 >= hhdr->hb_sz) {
00149
00150 GC_ADD_TO_BLACK_LIST_NORMAL(current);
00151 continue;
00152 }
00153 } else {
00154 GC_ADD_TO_BLACK_LIST_NORMAL(current);
00155 continue;
00156 }
00157 # else
00158 GC_ADD_TO_BLACK_LIST_NORMAL(current);
00159 continue;
00160 # endif
00161 }
00162 displ = HBLKDISPL(current);
00163 map_entry = MAP_ENTRY((hhdr -> hb_map), displ);
00164 if (map_entry == OBJ_INVALID) {
00165 GC_ADD_TO_BLACK_LIST_NORMAL(current);
00166 continue;
00167 }
00168 displ = BYTES_TO_WORDS(displ);
00169 displ -= map_entry;
00170
00171 {
00172 register word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(displ);
00173 register word mark_word = *mark_word_addr;
00174 register word mark_bit = 1 << modWORDSZ(displ);
00175
00176 if (mark_word & mark_bit) {
00177
00178 continue;
00179 }
00180
00181 *mark_word_addr = mark_word | mark_bit;
00182 }
00183
00184 GC_mark_stack_top_reg =
00185 (* (hhdr -> hb_mark_proc))((word *)(HBLKPTR(current)) + displ, hhdr,
00186 GC_mark_stack_top_reg, mark_stack_limit);
00187 }
00188 }
00189 GC_mark_stack_top = GC_mark_stack_top_reg;
00190 }
00191
00192
00193
00194 static void alloc_mark_stack(n)
00195 word n;
00196 {
00197 mse * new_stack = (mse *)GET_MEM(n * sizeof(struct ms_entry));
00198
00199 if (GC_mark_stack_size != 0) {
00200 if (new_stack != 0) {
00201
00202 GC_add_to_heap((struct hblk *)GC_mark_stack,
00203 GC_mark_stack_size * sizeof(struct ms_entry));
00204 GC_mark_stack = new_stack;
00205 GC_mark_stack_size = n;
00206 }
00207 } else {
00208 if (new_stack == 0) {
00209 GC_err_printf0("No space for mark stack\n");
00210 EXIT();
00211 }
00212 GC_mark_stack = new_stack;
00213 GC_mark_stack_size = n;
00214 }
00215 GC_mark_stack_top = GC_mark_stack-1;
00216 }
00217
00218 void GC_mark_init()
00219 {
00220 alloc_mark_stack(INITIAL_MARK_STACK_SIZE);
00221 }
00222
00223
00224
00225 void GC_mark_reliable()
00226 {
00227 dropped_some = FALSE;
00228 GC_mark();
00229 while (dropped_some) {
00230 dropped_some = FALSE;
00231 # ifdef PRINTSTATS
00232 GC_printf1("Mark stack overflow; current size = %lu entries\n",
00233 GC_mark_stack_size);
00234 # endif
00235 alloc_mark_stack(2*GC_mark_stack_size);
00236 GC_remark();
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245 void GC_mark_all(bottom, top)
00246 ptr_t bottom;
00247 ptr_t top;
00248 {
00249 word * b = (word *)(((long) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
00250 word * t = (word *)(((long) top) & ~(ALIGNMENT-1));
00251
00252 if (GC_mark_stack_top != GC_mark_stack-1) {
00253 ABORT("GC_mark_all: bad mark stack\n");
00254 }
00255 if (top == 0) return;
00256 GC_mark_stack_top++;
00257 GC_mark_stack_top -> mse_start = b;
00258 GC_mark_stack_top -> mse_end = t;
00259 GC_mark_reliable();
00260 }
00261
00262 word * GC_buffer;
00263 # define BUFSIZE 1024
00264
00265
00266
00267
00268 void GC_mark_all_stack(bottom, top)
00269 ptr_t bottom;
00270 ptr_t top;
00271 {
00272 # ifdef ALL_INTERIOR_POINTERS
00273 GC_mark_all(bottom, top);
00274 # else
00275 word * b = (word *)(((long) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
00276 word * t = (word *)(((long) top) & ~(ALIGNMENT-1));
00277 register word *p;
00278 register word q;
00279 register word r;
00280 register word *lim;
00281 word * bufptr;
00282 word * limit;
00283 register ptr_t greatest_ha = GC_greatest_plausible_heap_addr;
00284 register ptr_t least_ha = GC_least_plausible_heap_addr;
00285
00286 if (top == 0) return;
00287
00288
00289 if (GC_buffer == 0) {
00290 GC_buffer = (word *)GC_scratch_alloc((word)(BUFSIZE * sizeof(word)));
00291 }
00292 bufptr = GC_buffer;
00293 limit = GC_buffer+BUFSIZE;
00294
00295
00296 lim = t - 1 ;
00297 for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) {
00298 q = *p;
00299 if ((ptr_t)q < least_ha
00300 || (ptr_t)q >= greatest_ha) {
00301 continue;
00302 }
00303 # ifdef __STDC__
00304 r = (word)GC_base((void *)q);
00305 # else
00306 r = (word)GC_base((char *)q);
00307 # endif
00308 if (r == 0) {
00309 GC_add_to_black_list_stack(*p);
00310 } else {
00311 *(bufptr++) = r;
00312 if (bufptr == limit) {
00313 GC_mark_all((ptr_t)GC_buffer, (ptr_t)limit);
00314 bufptr = GC_buffer;
00315 }
00316 }
00317 }
00318 if (bufptr != GC_buffer) GC_mark_all((ptr_t)GC_buffer, (ptr_t)bufptr);
00319 # endif
00320 }
00321
00322
00323
00324 static void remark_block(h, dummy)
00325 struct hblk *h;
00326 word dummy;
00327 {
00328 register hdr * hhdr = HDR(h);
00329 register int sz = hhdr -> hb_sz;
00330 register word * p;
00331 register int word_no;
00332 register word * lim;
00333 register mse * GC_mark_stack_top_reg = GC_mark_stack_top;
00334
00335 if (sz < 0) return;
00336 if (sz > MAXOBJSZ) {
00337 lim = (word *)(h + 1);
00338 } else {
00339 lim = (word *)(h + 1) - sz;
00340 }
00341
00342 for (p = (word *)h + HDR_WORDS, word_no = HDR_WORDS; p <= lim;
00343 p += sz, word_no += sz) {
00344 if (mark_bit_from_hdr(hhdr, word_no)) {
00345
00346 GC_mark_stack_top_reg++;
00347 GC_mark_stack_top_reg -> mse_start = p;
00348 GC_mark_stack_top_reg -> mse_end = p + sz;
00349 }
00350 }
00351 GC_mark();
00352 }
00353
00354
00355
00356
00357 void GC_remark()
00358 {
00359 GC_apply_to_all_blocks(remark_block, 0);
00360 }
00361