00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdio.h>
00013 #include "gc_private.h"
00014
00015 signed_word GC_mem_found = 0;
00016
00017
00018 # ifdef FIND_LEAK
00019 static report_leak(p, sz)
00020 ptr_t p;
00021 word sz;
00022 {
00023 if (HDR(p) -> hb_obj_kind == PTRFREE) {
00024 GC_err_printf0("Leaked atomic object at ");
00025 } else {
00026 GC_err_printf0("Leaked composite object at ");
00027 }
00028 if (GC_debugging_started && GC_has_debug_info(p)) {
00029 GC_print_obj(p);
00030 } else {
00031 GC_err_printf1("0x%lx (appr. size = %ld)\n",
00032 (unsigned long)WORDS_TO_BYTES(sz));
00033 }
00034 }
00035
00036 # define FOUND_FREE(hblk, word_no) \
00037 if (abort_if_found) { \
00038 report_leak((long)hblk + WORDS_TO_BYTES(word_no), \
00039 HDR(hblk) -> hb_sz); \
00040 }
00041 # else
00042 # define FOUND_FREE(hblk, word_no)
00043 # endif
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 bool GC_block_empty(hhdr)
00058 register hdr * hhdr;
00059 {
00060 register word *p = (word *)(&(hhdr -> hb_marks[0]));
00061 register word * plim =
00062 (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
00063 while (p < plim) {
00064 if (*p++) return(FALSE);
00065 }
00066 return(TRUE);
00067 }
00068
00069 # ifdef GATHERSTATS
00070 # define INCR_WORDS(sz) n_words_found += (sz)
00071 # else
00072 # define INCR_WORDS(sz)
00073 # endif
00074
00075
00076
00077
00078
00079
00080 ptr_t GC_reclaim_clear(hbp, hhdr, sz, list, abort_if_found)
00081 register struct hblk *hbp;
00082 register hdr * hhdr;
00083 bool abort_if_found;
00084 register ptr_t list;
00085 register word sz;
00086 {
00087 register int word_no;
00088 register word *p, *q, *plim;
00089 # ifdef GATHERSTATS
00090 register int n_words_found = 0;
00091 # endif
00092
00093 p = (word *)(hbp->hb_body);
00094 word_no = HDR_WORDS;
00095 plim = (word *)((((word)hbp) + HBLKSIZE)
00096 - WORDS_TO_BYTES(sz));
00097
00098
00099 while( p <= plim ) {
00100 if( mark_bit_from_hdr(hhdr, word_no) ) {
00101 p += sz;
00102 } else {
00103 FOUND_FREE(hbp, word_no);
00104 INCR_WORDS(sz);
00105
00106 obj_link(p) = list;
00107 list = ((ptr_t)p);
00108
00109 q = p + sz;
00110 p++;
00111 while (p < q) {
00112 *p++ = 0;
00113 }
00114 }
00115 word_no += sz;
00116 }
00117 # ifdef GATHERSTATS
00118 GC_mem_found += n_words_found;
00119 # endif
00120 return(list);
00121 }
00122
00123
00124
00125
00126
00127 ptr_t GC_reclaim_clear2(hbp, hhdr, list, abort_if_found)
00128 register struct hblk *hbp;
00129 hdr * hhdr;
00130 bool abort_if_found;
00131 register ptr_t list;
00132 {
00133 register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00134 register word *p, *plim;
00135 # ifdef GATHERSTATS
00136 register int n_words_found = 0;
00137 # endif
00138 register int mark_word;
00139 # define DO_OBJ(start_displ) \
00140 if (!(mark_word & (1 << start_displ))) { \
00141 FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00142 p[start_displ] = (word)list; \
00143 list = (ptr_t)(p+start_displ); \
00144 p[start_displ+1] = 0; \
00145 INCR_WORDS(2); \
00146 }
00147
00148 p = (word *)(hbp->hb_body);
00149 plim = (word *)(((unsigned)hbp) + HBLKSIZE);
00150
00151
00152 while( p < plim ) {
00153 mark_word = *mark_word_addr++;
00154 DO_OBJ(0);
00155 DO_OBJ(2);
00156 DO_OBJ(4);
00157 DO_OBJ(6);
00158 DO_OBJ(8);
00159 DO_OBJ(10);
00160 DO_OBJ(12);
00161 DO_OBJ(14);
00162 DO_OBJ(16);
00163 DO_OBJ(18);
00164 DO_OBJ(20);
00165 DO_OBJ(22);
00166 DO_OBJ(24);
00167 DO_OBJ(26);
00168 DO_OBJ(28);
00169 DO_OBJ(30);
00170 p+=32;
00171 }
00172 # ifdef GATHERSTATS
00173 GC_mem_found += n_words_found;
00174 # endif
00175 return(list);
00176 # undef DO_OBJ
00177 }
00178
00179
00180
00181
00182
00183 ptr_t GC_reclaim_clear4(hbp, hhdr, list, abort_if_found)
00184 register struct hblk *hbp;
00185 hdr * hhdr;
00186 bool abort_if_found;
00187 register ptr_t list;
00188 {
00189 register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00190 register word *p, *plim;
00191 # ifdef GATHERSTATS
00192 register int n_words_found = 0;
00193 # endif
00194 register int mark_word;
00195 # define DO_OBJ(start_displ) \
00196 if (!(mark_word & (1 << start_displ))) { \
00197 FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00198 p[start_displ] = (word)list; \
00199 list = (ptr_t)(p+start_displ); \
00200 p[start_displ+1] = 0; \
00201 p[start_displ+2] = 0; \
00202 p[start_displ+3] = 0; \
00203 INCR_WORDS(4); \
00204 }
00205
00206 p = (word *)(hbp->hb_body);
00207 plim = (word *)(((unsigned)hbp) + HBLKSIZE);
00208
00209
00210 while( p < plim ) {
00211 mark_word = *mark_word_addr++;
00212 DO_OBJ(0);
00213 DO_OBJ(4);
00214 DO_OBJ(8);
00215 DO_OBJ(12);
00216 DO_OBJ(16);
00217 DO_OBJ(20);
00218 DO_OBJ(24);
00219 DO_OBJ(28);
00220 p+=32;
00221 }
00222 # ifdef GATHERSTATS
00223 GC_mem_found += n_words_found;
00224 # endif
00225 return(list);
00226 # undef DO_OBJ
00227 }
00228
00229
00230
00231 ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list, abort_if_found)
00232 register struct hblk *hbp;
00233 register hdr * hhdr;
00234 bool abort_if_found;
00235 register ptr_t list;
00236 register word sz;
00237 {
00238 register int word_no;
00239 register word *p, *plim;
00240 # ifdef GATHERSTATS
00241 register int n_words_found = 0;
00242 # endif
00243
00244 p = (word *)(hbp->hb_body);
00245 word_no = HDR_WORDS;
00246 plim = (word *)((((unsigned)hbp) + HBLKSIZE)
00247 - WORDS_TO_BYTES(sz));
00248
00249
00250 while( p <= plim ) {
00251 if( !mark_bit_from_hdr(hhdr, word_no) ) {
00252 FOUND_FREE(hbp, word_no);
00253 INCR_WORDS(sz);
00254
00255 obj_link(p) = list;
00256 list = ((ptr_t)p);
00257 }
00258 p += sz;
00259 word_no += sz;
00260 }
00261 # ifdef GATHERSTATS
00262 GC_mem_found += n_words_found;
00263 # endif
00264 return(list);
00265 }
00266
00267
00268
00269
00270
00271 ptr_t GC_reclaim_uninit2(hbp, hhdr, list, abort_if_found)
00272 register struct hblk *hbp;
00273 hdr * hhdr;
00274 bool abort_if_found;
00275 register ptr_t list;
00276 {
00277 register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00278 register word *p, *plim;
00279 # ifdef GATHERSTATS
00280 register int n_words_found = 0;
00281 # endif
00282 register int mark_word;
00283 # define DO_OBJ(start_displ) \
00284 if (!(mark_word & (1 << start_displ))) { \
00285 FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00286 p[start_displ] = (word)list; \
00287 list = (ptr_t)(p+start_displ); \
00288 INCR_WORDS(2); \
00289 }
00290
00291 p = (word *)(hbp->hb_body);
00292 plim = (word *)(((unsigned)hbp) + HBLKSIZE);
00293
00294
00295 while( p < plim ) {
00296 mark_word = *mark_word_addr++;
00297 DO_OBJ(0);
00298 DO_OBJ(2);
00299 DO_OBJ(4);
00300 DO_OBJ(6);
00301 DO_OBJ(8);
00302 DO_OBJ(10);
00303 DO_OBJ(12);
00304 DO_OBJ(14);
00305 DO_OBJ(16);
00306 DO_OBJ(18);
00307 DO_OBJ(20);
00308 DO_OBJ(22);
00309 DO_OBJ(24);
00310 DO_OBJ(26);
00311 DO_OBJ(28);
00312 DO_OBJ(30);
00313 p+=32;
00314 }
00315 # ifdef GATHERSTATS
00316 GC_mem_found += n_words_found;
00317 # endif
00318 return(list);
00319 # undef DO_OBJ
00320 }
00321
00322
00323
00324
00325
00326 ptr_t GC_reclaim_uninit4(hbp, hhdr, list, abort_if_found)
00327 register struct hblk *hbp;
00328 hdr * hhdr;
00329 bool abort_if_found;
00330 register ptr_t list;
00331 {
00332 register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00333 register word *p, *plim;
00334 # ifdef GATHERSTATS
00335 register int n_words_found = 0;
00336 # endif
00337 register int mark_word;
00338 # define DO_OBJ(start_displ) \
00339 if (!(mark_word & (1 << start_displ))) { \
00340 FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00341 p[start_displ] = (word)list; \
00342 list = (ptr_t)(p+start_displ); \
00343 INCR_WORDS(4); \
00344 }
00345
00346 p = (word *)(hbp->hb_body);
00347 plim = (word *)(((unsigned)hbp) + HBLKSIZE);
00348
00349
00350 while( p < plim ) {
00351 mark_word = *mark_word_addr++;
00352 DO_OBJ(0);
00353 DO_OBJ(4);
00354 DO_OBJ(8);
00355 DO_OBJ(12);
00356 DO_OBJ(16);
00357 DO_OBJ(20);
00358 DO_OBJ(24);
00359 DO_OBJ(28);
00360 p+=32;
00361 }
00362 # ifdef GATHERSTATS
00363 GC_mem_found += n_words_found;
00364 # endif
00365 return(list);
00366 # undef DO_OBJ
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 GC_reclaim_small_nonempty_block(hbp, abort_if_found)
00376 register struct hblk *hbp;
00377 int abort_if_found;
00378 {
00379 hdr * hhdr;
00380 register word sz;
00381 register struct obj_kind * ok;
00382 register ptr_t * flh;
00383
00384 hhdr = HDR(hbp);
00385 sz = hhdr -> hb_sz;
00386 ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
00387 flh = &(ok -> ok_freelist[sz]);
00388
00389 if (ok -> ok_init) {
00390 switch(sz) {
00391 case 2:
00392 *flh = GC_reclaim_clear2(hbp, hhdr, *flh, abort_if_found);
00393 break;
00394 case 4:
00395 *flh = GC_reclaim_clear4(hbp, hhdr, *flh, abort_if_found);
00396 break;
00397 default:
00398 *flh = GC_reclaim_clear(hbp, hhdr, sz, *flh, abort_if_found);
00399 break;
00400 }
00401 } else {
00402 switch(sz) {
00403 case 2:
00404 *flh = GC_reclaim_uninit2(hbp, hhdr, *flh, abort_if_found);
00405 break;
00406 case 4:
00407 *flh = GC_reclaim_uninit4(hbp, hhdr, *flh, abort_if_found);
00408 break;
00409 default:
00410 *flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh, abort_if_found);
00411 break;
00412 }
00413 }
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423 void GC_reclaim_block(hbp, abort_if_found)
00424 register struct hblk *hbp;
00425 int abort_if_found;
00426 {
00427 register hdr * hhdr;
00428 register word sz;
00429 bool empty;
00430 register struct obj_kind * ok;
00431 struct hblk ** rlh;
00432
00433 hhdr = HDR(hbp);
00434 sz = hhdr -> hb_sz;
00435 ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
00436 # ifdef PRINTBLOCKS
00437 GC_printf1("%ld(", (unsigned long)sz);
00438 if (hhdr -> hb_obj_kind == PTRFREE) {
00439 GC_printf0("a");
00440 } else if (hhdr -> hb_obj_kind == NORMAL){
00441 GC_printf0("c");
00442 } else {
00443 GC_printf0("o");
00444 }
00445 # endif
00446
00447 if( sz > MAXOBJSZ ) {
00448 if( mark_bit_from_hdr(hhdr, HDR_WORDS) ) {
00449 empty = FALSE;
00450 } else {
00451 FOUND_FREE(hbp, HDR_WORDS);
00452 # ifdef GATHERSTATS
00453 GC_mem_found += sz;
00454 # endif
00455 GC_freehblk(hbp);
00456 empty = TRUE;
00457 }
00458 } else {
00459 empty = GC_block_empty(hhdr);
00460 if (abort_if_found) {
00461 GC_reclaim_small_nonempty_block(hbp, abort_if_found);
00462 } else if (empty) {
00463 # ifdef GATHERSTATS
00464 GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
00465 # endif
00466 GC_freehblk(hbp);
00467 } else {
00468
00469 rlh = &(ok -> ok_reclaim_list[sz]);
00470 hhdr -> hb_next = *rlh;
00471 *rlh = hbp;
00472 }
00473 }
00474 # ifdef PRINTBLOCKS
00475 if (empty) {GC_printf0("e),");} else {GC_printf0("n),");}
00476 # endif
00477 }
00478
00479
00480
00481
00482
00483 void GC_start_reclaim(abort_if_found)
00484 int abort_if_found;
00485 {
00486 int kind;
00487
00488
00489 for (kind = 0; kind < GC_n_kinds; kind++) {
00490 register ptr_t *fop;
00491 register ptr_t *lim;
00492 register struct hblk ** hbpp;
00493 register struct hblk ** hlim;
00494
00495 if (!abort_if_found) {
00496 lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
00497 for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
00498 *fop = 0;
00499 }
00500 }
00501
00502 hlim = &(GC_obj_kinds[kind].ok_reclaim_list[MAXOBJSZ+1]);
00503 for( hbpp = GC_obj_kinds[kind].ok_reclaim_list;
00504 hbpp < hlim; hbpp++ ) {
00505 *hbpp = 0;
00506 }
00507 }
00508
00509 # ifdef PRINTBLOCKS
00510 GC_printf0("GC_reclaim: current block sizes:\n");
00511 # endif
00512
00513
00514
00515 GC_apply_to_all_blocks(GC_reclaim_block, abort_if_found);
00516
00517 # ifdef PRINTBLOCKS
00518 GC_printf0("\n");
00519 # endif
00520 }
00521
00522
00523
00524
00525
00526
00527 void GC_continue_reclaim(sz, kind)
00528 word sz;
00529 int kind;
00530 {
00531 register hdr * hhdr;
00532 register struct hblk * hbp;
00533 register struct obj_kind * ok = &(GC_obj_kinds[kind]);
00534 struct hblk ** rlh = &(ok -> ok_reclaim_list[sz]);
00535 ptr_t *flh = &(ok -> ok_freelist[sz]);
00536
00537
00538 while ((hbp = *rlh) != 0) {
00539 hhdr = HDR(hbp);
00540 *rlh = hhdr -> hb_next;
00541 GC_reclaim_small_nonempty_block(hbp, FALSE);
00542 if (*flh != 0) break;
00543 }
00544 }