gc_slide.h

00001 /* File:      gc_slide.h
00002 ** Author(s): Luis Castro, Bart Demoen, Kostis Sagonas
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
00006 ** Copyright (C) ECRC, Germany, 1990
00007 ** 
00008 ** XSB is free software; you can redistribute it and/or modify it under the
00009 ** terms of the GNU Library General Public License as published by the Free
00010 ** Software Foundation; either version 2 of the License, or (at your option)
00011 ** any later version.
00012 ** 
00013 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00014 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00015 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00016 ** more details.
00017 ** 
00018 ** You should have received a copy of the GNU Library General Public License
00019 ** along with XSB; if not, write to the Free Software Foundation,
00020 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 **
00022 ** $Id: gc_slide.h,v 1.11 2006/07/02 18:36:29 tswift Exp $
00023 ** 
00024 */
00025 
00026 /*=======================================================================*/
00027 
00028 /* from here to end of slide_heap is code taken to some extent from
00029    BinProlog and adapted to XSB - especially what concerns the
00030    environments
00031    the BinProlog garbage collector was also written originally by Bart Demoen
00032 */
00033 
00034 #ifdef GC
00035 
00036 #define h_set_chained(p)         heap_marks[(p-heap_bot)] |= CHAIN_BIT
00037 #define h_set_unchained(p)       heap_marks[(p-heap_bot)] &= ~CHAIN_BIT
00038 #define h_is_chained(p)          (heap_marks[(p-heap_bot)] & CHAIN_BIT)
00039 
00040 #define ls_set_chained(p)        ls_marks[(p-ls_top)] |= CHAIN_BIT 
00041 #define ls_set_unchained(p)      ls_marks[(p-ls_top)] &= ~CHAIN_BIT
00042 #define ls_is_chained(p)         (ls_marks[(p-ls_top)] & CHAIN_BIT)
00043 
00044 #define cp_set_chained(p)        cp_marks[(p-cp_top)] |= CHAIN_BIT
00045 #define cp_set_unchained(p)      cp_marks[(p-cp_top)] &= ~CHAIN_BIT
00046 #define cp_is_chained(p)         (cp_marks[(p-cp_top)] & CHAIN_BIT)
00047 
00048 #define tr_set_chained(p)        tr_marks[(p-tr_bot)] |= CHAIN_BIT 
00049 #define tr_set_unchained(p)      tr_marks[(p-tr_bot)] &= ~CHAIN_BIT
00050 #define tr_is_chained(p)         (tr_marks[(p-tr_bot)] & CHAIN_BIT)
00051 
00052 static void unchain(CPtr hptr, CPtr destination)
00053 {
00054   CPtr start, pointsto ;
00055   int  whereto, tag ;
00056   int  continue_after_this = 0 ;
00057 
00058 /* hptr is a pointer to the heap and is chained */
00059 /* the whole chain is unchained, i.e.
00060         the end of the chain is put in the beginning and
00061         all other chained elements (up to end included) are made
00062                 to point to the destination
00063         we have to make sure that the tags are ok and that the chain tags
00064                 are switched off
00065    I have implemented a version which can be optimised, but it shows
00066    all intermediate steps as the previous chaining steps - except for
00067    the chain bit of hptr
00068 */
00069 
00070   h_set_unchained(hptr) ;
00071 
00072   do
00073     {
00074       start = (CPtr)(*hptr) ;
00075       /* start is for sure a pointer - possibly with a tag */
00076       pointsto = pointer_from_cell((Cell)start,&tag,&whereto) ;
00077       if (pointsto == NULL) xsb_exit("pointsto error during unchaining") ;
00078       switch (whereto)
00079         {
00080           case TO_HEAP :
00081             continue_after_this = h_is_chained(pointsto) ;
00082             h_set_unchained(pointsto) ;
00083             break ;
00084           case TO_LS :
00085             continue_after_this = ls_is_chained(pointsto) ;
00086             ls_set_unchained(pointsto) ;
00087             break ;
00088           case TO_TR :
00089             continue_after_this = tr_is_chained(pointsto) ;
00090             tr_set_unchained(pointsto) ;
00091             break ;
00092           case TO_CP :
00093             continue_after_this = cp_is_chained(pointsto) ;
00094             cp_set_unchained(pointsto) ;
00095             break ;
00096           default :
00097             xsb_exit("pointsto wrong space error during unchaining");
00098             break;
00099         }
00100       *hptr = *pointsto ;
00101       switch (tag) {
00102       case XSB_REF: 
00103       case XSB_REF1:
00104         *pointsto = (Cell)destination ;
00105         break ;
00106       case XSB_STRUCT :
00107         *pointsto = makecs((Cell)destination) ;
00108         break ;
00109       case XSB_LIST :
00110         *pointsto = makelist((Cell)destination) ;
00111         break ;
00112       case XSB_ATTV :
00113         *pointsto = makeattv((Cell)destination);
00114         break;
00115       default :
00116         xsb_exit("tag error during unchaining") ;
00117       }
00118     }
00119   while (continue_after_this) ;
00120 
00121 } /* unchain */
00122 
00123 /*----------------------------------------------------------------------*/
00124 
00125 inline static void swap_with_tag(CPtr p, CPtr q, int tag)
00126 { /* p points to a cell with contents a tagged pointer
00127      make *q = p + tag, but maybe shift p
00128   */
00129    *p = *q ;
00130    switch (tag) {
00131    case XSB_REF:
00132    case XSB_REF1:
00133      *q = (Cell)p ;
00134      break ;
00135    case XSB_STRUCT :
00136      *q = makecs((Cell)p) ;
00137      break ;
00138    case XSB_LIST :
00139      *q = makelist((Cell)p) ;
00140      break ;
00141    case XSB_ATTV :
00142      *q = makeattv((Cell)p);
00143      break;
00144    default : xsb_exit("error during swap_with_tag") ;
00145    }
00146 } /* swap_with_tag */
00147 
00148 #endif /* GC */
00149 
00150 /*----------------------------------------------------------------------*/
00151 /*
00152         slide_heap: implements a sliding collector for the heap
00153         see: Algorithm of Morris / ACM paper by Appleby et al.
00154         num_marked = number of marked heap cells
00155         the relevant argument registers have been moved to the top
00156         of the heap prior to marking
00157 */
00158 
00159 #ifdef INDIRECTION_SLIDE
00160 
00161 #define mem_swap(a,b) \
00162 { unsigned long temp; \
00163  temp = *a; \
00164  *a = *b; \
00165  *b = temp; \
00166 }
00167 #define push_sort_stack(X,Y) \
00168 addr_stack[stack_index] = X;\
00169 size_stack[stack_index] = Y;\
00170 stack_index++
00171 #define pop_sort_stack(X,Y)\
00172 stack_index--; \
00173 X = addr_stack[stack_index]; \
00174 Y = size_stack[stack_index]
00175 #define sort_stack_empty \
00176 (stack_index == 0)
00177 
00178 static void randomize_data(unsigned long *data, unsigned long size)
00179 {
00180   unsigned long i,j;
00181 
00182   for (i=0; i<size; i++) {
00183     j = (unsigned long) rand()*(size-1)/RAND_MAX;
00184     mem_swap((data+i), (data+j));
00185   }
00186 }
00187 
00188 static void sort_buffer(unsigned long *indata, unsigned long insize)
00189 {
00190   unsigned long *left, *right, *pivot;
00191   unsigned long *data, size;
00192   unsigned long *addr_stack[4000];
00193   unsigned long size_stack[4000];
00194   int stack_index=0;
00195   Integer leftsize;
00196 #ifdef GC_PROFILE
00197   unsigned long begin_sorting, end_sorting;
00198 #endif
00199   
00200   randomize_data(indata,insize);
00201 
00202 #ifdef GC_PROFILE
00203   if (verbose_gc)
00204     begin_sorting = cpu_time();
00205 #endif
00206   push_sort_stack(indata,insize);
00207 
00208   while (!sort_stack_empty) {
00209     
00210     pop_sort_stack(data,size);
00211 
00212     if (size < 1)
00213       continue;
00214 
00215     if (size == 1) {
00216       if (data[0] > data[1])
00217         mem_swap(data, (data+1));
00218       continue;
00219     }
00220     
00221     left = data;
00222     right = &data[size];
00223     
00224     pivot = &data[size/2];
00225     mem_swap(pivot, right);
00226     
00227     pivot = right;
00228     
00229     while (left < right) {
00230       while ((*left < *pivot) && (left < right)) 
00231         left++;
00232       while ((*right >= *pivot) && (left < right))
00233         right--;
00234       if (left < right) { 
00235         mem_swap(left,right);
00236         left++;
00237       }
00238     }
00239     if (right == data) {
00240       mem_swap(right, pivot);
00241       right++;
00242     }
00243     leftsize = right - data;
00244     if (leftsize >= 1)
00245       push_sort_stack(data,leftsize);
00246     if ((size-leftsize) >= 1)
00247       push_sort_stack(right,(size-leftsize));
00248 
00249   } 
00250 #ifdef GC_PROFILE
00251   if (verbose_gc) {
00252     end_sorting = cpu_time();
00253     fprintf(stddbg,"{GC} Sorting took %f ms.\n", (double)
00254             (end_sorting - begin_sorting)*1000/CLOCKS_PER_SEC);
00255   }
00256 #endif
00257 }
00258 
00259 #endif
00260 
00261 #ifdef GC
00262 
00263 static CPtr slide_heap(int num_marked)
00264 {
00265   int  tag ;
00266   Cell contents;
00267   CPtr p, q ;
00268 
00269   /* chain external (to heap) pointers */      
00270 
00271     /* chain argument registers */
00272     /* will be automatic as aregisters were copied to the heap */
00273 
00274     /* chain trail: (TLS) this means to go through the trail, and if a
00275        trail cell points to the heap, then reverse it so that the heap
00276        cell points to the trail cell, and set the CHAIN_BIT in the
00277        corresponding cells of the trail and heap mark areas. */
00278     /* more precise traversal of trail possible */
00279 
00280     { CPtr endtr ;
00281       endtr = tr_top ;
00282       for (p = tr_bot; p <= endtr ; p++ ) 
00283         { contents = cell(p) ;
00284           /* TLS: why is the top of trail special? */
00285 #ifdef SLG_GC
00286         if (!tr_marked(p-tr_bot))
00287           continue;
00288         tr_clear_mark(p-tr_bot);
00289 #endif
00290           q = hp_pointer_from_cell(contents,&tag) ;
00291           if (!q) continue ;
00292           if (! h_marked(q-heap_bot)) {
00293             continue ;
00294           }
00295           if (h_is_chained(q)) tr_set_chained(p) ;
00296           h_set_chained(q) ;
00297           swap_with_tag(p,q,tag) ;
00298         }
00299     }
00300 
00301     /* chain choicepoints */
00302     /* more precise traversal of choice points possible */
00303 
00304     { CPtr endcp ;
00305       endcp = cp_top ;
00306       for (p = cp_bot; p >= endcp ; p--)
00307         { contents = cell(p) ;
00308           q = hp_pointer_from_cell(contents,&tag) ;
00309           if (!q) continue ;
00310           if (! h_marked(q-heap_bot))
00311             { xsb_dbgmsg((LOG_DEBUG, "not marked from cp(%p)",p)); continue ; }
00312           if (h_is_chained(q)) cp_set_chained(p) ;
00313           h_set_chained(q) ;
00314           swap_with_tag(p,q,tag) ;
00315         }
00316     }
00317 
00318 
00319     /* chain local stack */
00320     /* more precise traversal of local stack possible */
00321 
00322     { CPtr endls ;
00323       endls = ls_top ;
00324       for (p = ls_bot; p >= endls ; p-- )
00325         {
00326           if (! ls_marked(p-ls_top)) continue ;
00327           ls_clear_mark((p-ls_top)) ; /* chain bit cannot be on yet */
00328           contents = cell(p) ;
00329           q = hp_pointer_from_cell(contents,&tag) ;
00330           if (!q) continue ;
00331           if (! h_marked(q-heap_bot)) continue ;
00332           if (h_is_chained(q)) ls_set_chained(p) ;
00333           h_set_chained(q) ;
00334           swap_with_tag(p,q,tag) ;
00335         }
00336     }
00337 
00338     /* if (print_on_gc) print_all_stacks() ; */
00339 
00340   { CPtr destination, hptr ;
00341     long garbage = 0 ;
00342     Integer index ;
00343 
00344     /* one phase upwards - from top of heap to bottom of heap */
00345 
00346     index = heap_top - heap_bot ;
00347     destination = heap_bot + num_marked - 1 ;
00348 #ifdef INDIRECTION_SLIDE
00349     if (slide_buffering) {
00350       unsigned long i;
00351 #ifdef GC_PROFILE
00352       if (verbose_gc) {
00353         fprintf(stddbg,"{GC} Using Fast-Slide scheme.\n");
00354       }
00355 #endif
00356       /* sort the buffer */
00357       sort_buffer((unsigned long *)slide_buf, slide_top-1);
00358 
00359       /* upwards phase */
00360       for (i=slide_top; i > 0; i--) {
00361         hptr = slide_buf[i-1];
00362 
00363         if (h_is_chained(hptr)) {
00364           unchain(hptr,destination);
00365         }
00366         p = hp_pointer_from_cell(*hptr,&tag);
00367         if (p &&(p<hptr)) {
00368           swap_with_tag(hptr,p,tag);
00369           if (h_is_chained(p))
00370             h_set_chained(hptr);
00371           else
00372             h_set_chained(p);
00373         }
00374         destination--;
00375       }
00376     } else {
00377 #ifdef GC_PROFILE
00378       if (verbose_gc && pflags[GARBAGE_COLLECT]==INDIRECTION_SLIDE_GC)
00379         fprintf(stddbg,"{GC} Giving up Fast-Slide scheme.\n");
00380 #endif
00381 #endif /* INDIRECTION_SLIDE */
00382       for (hptr = heap_top - 1 ; hptr >= heap_bot ; hptr--) {
00383         if (h_marked(hptr - heap_bot)) {
00384 
00385           /* boxing: (TLS) apparently garbage is used to denote how
00386              long a segment of garbage is -- its put in the bottom
00387              cell of the garbage segment. */
00388 
00389           if (garbage) {
00390             *(hptr+1) = makeint(garbage) ;
00391             garbage = 0 ;
00392           }
00393           if (h_is_chained(hptr)) {
00394             unchain(hptr,destination) ; 
00395           }
00396           p = hp_pointer_from_cell(*hptr,&tag) ;            
00397           if (p && (p < hptr)) {
00398             swap_with_tag(hptr,p,tag) ;
00399             if (h_is_chained(p))
00400               h_set_chained(hptr) ;
00401             else 
00402               h_set_chained(p) ;
00403           }
00404           destination-- ;
00405         }
00406         else 
00407           garbage++ ;
00408         index-- ;
00409       }
00410 #ifdef INDIRECTION_SLIDE
00411     }
00412     if (!slide_buffering)
00413 #endif
00414     if (garbage)
00415       /* the first heap cell is not marked */
00416       *heap_bot = makeint(garbage) ;
00417 
00418     /* one phase downwards - from bottom of heap to top of heap */
00419     index = 0 ;
00420     destination = heap_bot ;
00421 
00422 #ifdef INDIRECTION_SLIDE
00423     if (slide_buffering) {
00424       unsigned long i;
00425       for (i=0; i<slide_top; i++) {
00426         hptr = slide_buf[i];
00427 
00428         if (h_is_chained(hptr)) {
00429           unchain(hptr,destination);
00430         }
00431         if ((Cell)(hptr) == *hptr) /* undef */
00432           bld_free(destination);
00433         else {
00434           p = hp_pointer_from_cell(*hptr,&tag);
00435           *destination = *hptr;
00436           if (p && (p > hptr)) {
00437             swap_with_tag(destination,p,tag);
00438             if (h_is_chained(p))
00439               h_set_chained(destination);
00440             else
00441               h_set_chained(p);
00442           }
00443           h_clear_mark((hptr-heap_bot));
00444         }
00445         destination++;
00446       }     
00447     } else {
00448 #endif /* INDIRECTION_SLIDE */
00449       hptr = heap_bot;
00450       while (hptr < heap_top) {
00451         if (h_marked(hptr - heap_bot)) {
00452           if (h_is_chained(hptr))
00453             { unchain(hptr,destination) ; }
00454           if ((Cell)(hptr) == *hptr) /* UNDEF */
00455             bld_free(destination) ;
00456           else {
00457             p = hp_pointer_from_cell(*hptr,&tag) ;
00458             *destination = *hptr ;
00459             if (p && (p > hptr)) {
00460               swap_with_tag(destination,p,tag) ;
00461               if (h_is_chained(p))           
00462                 h_set_chained(destination) ;   
00463               else 
00464                 h_set_chained(p) ;
00465             }
00466           }
00467           h_clear_mark((hptr-heap_bot)) ;
00468           hptr++ ; destination++ ;
00469           index++ ;
00470         } else {
00471           garbage = int_val(cell(hptr)) ;
00472           index += garbage ;
00473           hptr += garbage ;
00474         }
00475       }
00476       if (destination != (heap_bot+num_marked))
00477         xsb_dbgmsg((LOG_DEBUG, "bad size %p  %p",
00478                    destination,heap_bot+num_marked));
00479 #ifdef INDIRECTION_SLIDE
00480     }  
00481 #endif
00482   }
00483 
00484 #ifdef PRE_IMAGE_TRAIL
00485 
00486     /* re-tag pre image cells in trail */
00487     for (p = tr_bot; p <= tr_top ; p++ ) {
00488       if (tr_pre_marked(p-tr_bot)) {
00489         *p = *p | PRE_IMAGE_MARK;
00490         tr_clear_pre_mark(p-tr_bot);
00491       }
00492     }
00493 #endif
00494 
00495     return(heap_bot + num_marked) ;
00496 
00497 } /* slide_heap */
00498 
00499 static void check_zero(char *b, Integer l, char *s)
00500 { 
00501 #ifdef SAFE_GC
00502   Integer i = 0 ;
00503   while (l--)
00504   {
00505     if (*b++)
00506       xsb_dbgmsg((LOG_DEBUG, "%s - left marker - %d - %d - %d", s,*(b-1),i,l));
00507     i++ ;
00508   }
00509 #endif
00510 } /* check_zero */
00511 
00512 #endif
00513 
00514 /*=======================================================================*/

Generated on Wed Jul 26 13:30:41 2006 for XSB by  doxygen 1.4.5