C:/Users/Dennis/src/lang/russell.orig/src/gc/reclaim.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991, 1992 by Xerox Corporation.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to copy this garbage collector for any purpose,
00009  * provided the above notices are retained on all copies.
00010  */
00011 
00012 #include <stdio.h>
00013 #include "gc_private.h"
00014 
00015 signed_word GC_mem_found = 0;
00016                         /* Number of longwords of memory GC_reclaimed     */
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  * reclaim phase
00047  *
00048  */
00049 
00050 
00051 /*
00052  * Test whether a block is completely empty, i.e. contains no marked
00053  * objects.  This does not require the block to be in physical
00054  * memory.
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  * Restore unmarked small objects in h of size sz to the object
00076  * free list.  Returns the new list.
00077  * Clears unmarked objects.
00078  */
00079 /*ARGSUSED*/
00080 ptr_t GC_reclaim_clear(hbp, hhdr, sz, list, abort_if_found)
00081 register struct hblk *hbp;      /* ptr to current heap block            */
00082 register hdr * hhdr;
00083 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
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                 /* object is available - put on list */
00106                     obj_link(p) = list;
00107                     list = ((ptr_t)p);
00108                 /* Clear object, advance p to next object in the process */
00109                     q = p + sz;
00110                     p++; /* Skip link field */
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  * A special case for 2 word composite objects (e.g. cons cells):
00125  */
00126 /*ARGSUSED*/
00127 ptr_t GC_reclaim_clear2(hbp, hhdr, list, abort_if_found)
00128 register struct hblk *hbp;      /* ptr to current heap block            */
00129 hdr * hhdr;
00130 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
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  * Another special case for 4 word composite objects:
00181  */
00182 /*ARGSUSED*/
00183 ptr_t GC_reclaim_clear4(hbp, hhdr, list, abort_if_found)
00184 register struct hblk *hbp;      /* ptr to current heap block            */
00185 hdr * hhdr;
00186 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
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 /* The same thing, but don't clear objects: */
00230 /*ARGSUSED*/
00231 ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list, abort_if_found)
00232 register struct hblk *hbp;      /* ptr to current heap block            */
00233 register hdr * hhdr;
00234 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
00250         while( p <= plim )  {
00251             if( !mark_bit_from_hdr(hhdr, word_no) ) {
00252                 FOUND_FREE(hbp, word_no);
00253                 INCR_WORDS(sz);
00254                 /* object is available - put on list */
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  * Another special case for 2 word atomic objects:
00269  */
00270 /*ARGSUSED*/
00271 ptr_t GC_reclaim_uninit2(hbp, hhdr, list, abort_if_found)
00272 register struct hblk *hbp;      /* ptr to current heap block            */
00273 hdr * hhdr;
00274 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
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  * Another special case for 4 word atomic objects:
00324  */
00325 /*ARGSUSED*/
00326 ptr_t GC_reclaim_uninit4(hbp, hhdr, list, abort_if_found)
00327 register struct hblk *hbp;      /* ptr to current heap block            */
00328 hdr * hhdr;
00329 bool abort_if_found;            /* Abort if a reclaimable object is 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     /* go through all words in block */
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  * Restore unmarked small objects in the block pointed to by hbp
00371  * to the appropriate object free list.
00372  * If entirely empty blocks are to be completely deallocated, then
00373  * caller should perform that check.
00374  */
00375 GC_reclaim_small_nonempty_block(hbp, abort_if_found)
00376 register struct hblk *hbp;      /* ptr to current heap block            */
00377 int abort_if_found;             /* Abort if a reclaimable object is found */
00378 {
00379     hdr * hhdr;
00380     register word sz;           /* size of objects in current block     */
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  * Restore an unmarked large object or an entirely empty blocks of small objects
00418  * to the heap block free list.
00419  * Otherwise enqueue the block for later processing
00420  * by GC_reclaim_small_nonempty_block.
00421  * If abort_if_found is TRUE, then process any block immediately.
00422  */
00423 void GC_reclaim_block(hbp, abort_if_found)
00424 register struct hblk *hbp;      /* ptr to current heap block            */
00425 int abort_if_found;             /* Abort if a reclaimable object is found */
00426 {
00427     register hdr * hhdr;
00428     register word sz;           /* size of objects in current block     */
00429     bool empty;                 /* used only for PRINTBLOCKS    */
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 ) {  /* 1 big object */
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           /* group of smaller objects, enqueue the real work */
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  * Do the same thing on the entire heap, after first clearing small object
00481  * free lists (if we are not just looking for leaks).
00482  */
00483 void GC_start_reclaim(abort_if_found)
00484 int abort_if_found;             /* Abort if a GC_reclaimable object is found */
00485 {
00486     int kind;
00487     
00488     /* Clear reclaim- and free-lists */
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         } /* otherwise free list objects are marked,    */
00501           /* and its safe to leave them                 */
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   /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
00514   /* or enqueue the block for later processing.                            */
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  * Sweep blocks of the indicated object size and kind until either the
00524  * appropriate free list is nonempty, or there are no more blocks to
00525  * sweep.
00526  */
00527 void GC_continue_reclaim(sz, kind)
00528 word sz;        /* words */
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 }

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4