C:/Users/Dennis/src/lang/russell.orig/src/gc/black_list.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 # include "gc_private.h"
00012 
00013 /*
00014  * We maintain several hash tables of hblks that have had false hits.
00015  * Each contains one bit per hash bucket;  If any page in the bucket
00016  * has had a false hit, we assume that all of them have.
00017  * False hits from the stack(s) are much more dangerous than false hits
00018  * from elsewhere, since the former can pin a large object that spans the
00019  * block, eventhough it does not start on the dangerous block.
00020  */
00021  
00022 /*
00023  * Externally callable routines are:
00024  
00025  * GC_add_to_black_list_normal
00026  * GC_add_to_black_list_stack
00027  * GC_promote_black_lists
00028  * GC_is_black_listed
00029  *
00030  * All require that the allocator lock is held.
00031  */
00032 
00033 # define LOG_HT_ENTRIES  14     /* Collisions are likely if heap grows  */
00034                                 /* to more than 16K hblks = 64MB.       */
00035                                 /* Each hash table occupies 2K bytes.   */
00036 # define HT_ENTRIES ((word)1 << LOG_HT_ENTRIES)
00037 # define HT_SIZE (HT_ENTRIES >> LOGWL)
00038 typedef word black_list_t[HT_SIZE];
00039 
00040 # define HASH(addr) (((addr) >> LOG_HBLKSIZE) & (HT_ENTRIES - 1))
00041 
00042 /* Pointers to individual tables.  We replace one table by another by   */
00043 /* switching these pointers.  GC_black_lists is not used directly.      */
00044 word * GC_new_normal_bl;
00045                 /* Nonstack false references seen at last complete      */
00046                 /* collection.                                          */
00047 word * GC_old_normal_bl;
00048                 /* Nonstack false references seen at preceding          */
00049                 /* collection.                                          */
00050 word * GC_incomplete_normal_bl;
00051                 /* Nonstack false references seen at current,           */
00052                 /* not yet completed collection.                        */
00053 word * GC_new_stack_bl;
00054 word * GC_old_stack_bl;
00055 word * GC_incomplete_stack_bl;
00056 
00057 # define get_bl_entry_from_index(bl, index) \
00058                 (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)
00059 # define set_bl_entry_from_index(bl, index) \
00060                 (bl)[divWORDSZ(index)] |= 1 << modWORDSZ(index)
00061 # define clear_bl_entry_from_index(bl, index) \
00062                 (bl)[divWORDSZ(index)] &= ~(1 << modWORDSZ(index))
00063                 
00064 GC_bl_init()
00065 {
00066 # ifndef ALL_INTERIOR_POINTERS
00067     GC_new_normal_bl = (word *)GC_scratch_alloc((word)(sizeof(black_list_t)));
00068     GC_old_normal_bl = (word *)GC_scratch_alloc((word)(sizeof (black_list_t)));
00069     GC_incomplete_normal_bl = (word *)GC_scratch_alloc
00070                                         ((word)(sizeof(black_list_t)));
00071 # endif
00072     GC_new_stack_bl = (word *)GC_scratch_alloc((word)(sizeof(black_list_t)));
00073     GC_old_stack_bl = (word *)GC_scratch_alloc((word)(sizeof(black_list_t)));
00074     GC_incomplete_stack_bl = (word *)GC_scratch_alloc
00075                                         ((word)(sizeof(black_list_t)));
00076 }
00077                 
00078 void GC_clear_bl(doomed)
00079 word *doomed;
00080 {
00081     bzero((char *)doomed, (int)HT_SIZE*sizeof(word));
00082 }
00083 
00084 /* Signal the completion of a collection.  Turn the incomplete black    */
00085 /* lists into new black lists, etc.                                     */                       
00086 void GC_promote_black_lists()
00087 {
00088     word * very_old_normal_bl = GC_old_normal_bl;
00089     word * very_old_stack_bl = GC_old_stack_bl;
00090     
00091     GC_old_normal_bl = GC_new_normal_bl;
00092     GC_new_normal_bl = GC_incomplete_normal_bl;
00093     GC_old_stack_bl = GC_new_stack_bl;
00094     GC_new_stack_bl = GC_incomplete_stack_bl;
00095 #   ifndef ALL_INTERIOR_POINTERS
00096       GC_clear_bl(very_old_normal_bl);
00097 #   endif
00098     GC_clear_bl(very_old_stack_bl);
00099     GC_incomplete_normal_bl = very_old_normal_bl;
00100     GC_incomplete_stack_bl = very_old_stack_bl;
00101 }
00102 
00103 # ifndef ALL_INTERIOR_POINTERS
00104 /* P is not a valid pointer reference, but it falls inside      */
00105 /* the plausible heap bounds.                                   */
00106 /* Add it to the normal incomplete black list if appropriate.   */
00107 void GC_add_to_black_list_normal(p)
00108 word p;
00109 {
00110     if (!(GC_modws_valid_offsets[p & (sizeof(word)-1)])) return;
00111     {
00112         register int index = HASH(p);
00113         
00114         if (HDR(p) == 0 || get_bl_entry_from_index(GC_new_normal_bl, index)) {
00115 #           ifdef PRINTBLACKLIST
00116                 if (!get_bl_entry_from_index(GC_incomplete_normal_bl, index)) {
00117                   GC_printf1("Black listing (normal) 0x%lx\n",
00118                              (unsigned long) p);
00119                 }
00120 #           endif
00121             set_bl_entry_from_index(GC_incomplete_normal_bl, index);
00122         } /* else this is probably just an interior pointer to an allocated */
00123           /* object, and isn't worth black listing.                         */
00124     }
00125 }
00126 # endif
00127 
00128 /* And the same for false pointers from the stack. */
00129 void GC_add_to_black_list_stack(p)
00130 word p;
00131 {
00132     register int index = HASH(p);
00133         
00134     if (HDR(p) == 0 || get_bl_entry_from_index(GC_new_stack_bl, index)) {
00135 #       ifdef PRINTBLACKLIST
00136             if (!get_bl_entry_from_index(GC_incomplete_stack_bl, index)) {
00137                   GC_printf1("Black listing (stack) 0x%lx\n",
00138                              (unsigned long)p);
00139             }
00140 #       endif
00141         set_bl_entry_from_index(GC_incomplete_stack_bl, index);
00142     }
00143 }
00144 
00145 /*
00146  * Is the block starting at h of size len bytes black listed?   If so,
00147  * return the address of the next plausible r such that (r, len) might not
00148  * be black listed.  (R may not actually be in the heap.  We guarantee only
00149  * that every smaller value of r after h is also black listed.)
00150  * If (h,len) is not black listed, return 0.
00151  * Knows about the structure of the black list hash tables.
00152  */
00153 struct hblk * GC_is_black_listed(h, len)
00154 struct hblk * h;
00155 word len;
00156 {
00157     register int index = HASH((word)h);
00158     register word i;
00159     word nblocks = divHBLKSZ(len);
00160 
00161 #   ifndef ALL_INTERIOR_POINTERS
00162       if (get_bl_entry_from_index(GC_new_normal_bl, index)
00163         && get_bl_entry_from_index(GC_old_normal_bl, index)) {
00164         return(h+1);
00165       }
00166 #   endif
00167     
00168     for (i = 0; ; ) {
00169         if (GC_new_stack_bl[divWORDSZ(index)] == 0) {
00170             /* An easy case */
00171             i += WORDSZ - modWORDSZ(index);
00172         } else {
00173           if (get_bl_entry_from_index(GC_new_stack_bl, index)
00174             && get_bl_entry_from_index(GC_old_stack_bl, index)) {
00175             return(h+i+1);
00176           }
00177           i++;
00178         }
00179         if (i >= nblocks) break;
00180         index = HASH((word)(h+i));
00181     }
00182     return(0);
00183 }
00184 

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