gc_mark.h

00001 /* File:      gc_mark.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_mark.h,v 1.18 2006/04/24 19:34:14 dwarren Exp $
00023 ** 
00024 */
00025 
00026 #ifndef MULTI_THREAD
00027 extern Structure_Manager smTSTN;
00028 #endif
00029 
00030 extern Structure_Manager smTableBTN;
00031 extern Structure_Manager smAssertBTN;
00032 extern PrRef dynpredep_to_prref(CTXTdeclc void *pred_ep);
00033 extern ClRef db_get_clause_code_space(PrRef, ClRef, CPtr *, CPtr *);
00034 extern void mark_findall_strings(CTXTdecl);
00035 extern void mark_open_filenames();
00036 extern void mark_hash_table_strings(CTXTdecl);
00037 
00038 #ifdef INDIRECTION_SLIDE
00039 #define TO_BUFFER(ptr) \
00040 { \
00041   if (slide_buffering) { \
00042     slide_buf[slide_top] = ptr; \
00043     slide_top++; \
00044     slide_buffering = slide_top <= slide_buf_size; \
00045   } \
00046 }
00047 #else
00048 #define TO_BUFFER(ptr)
00049 #endif
00050 
00051 #ifdef GC_PROFILE
00052 #define h_mark(i) \
00053 do { \
00054   CPtr cell_ptr; int place;\
00055   place = i;\
00056   cell_ptr = (CPtr) heap_bot + place;\
00057   inspect_ptr(cell_ptr);  \
00058   heap_marks[place] |= MARKED;\
00059 } while (0)
00060 #else
00061 #define h_mark(i)          heap_marks[i] |= MARKED
00062 #endif
00063 
00064 #define h_marked(i)        (heap_marks[i])
00065 #define h_clear_mark(i)    heap_marks[i] &= ~MARKED
00066 
00067 #define ls_marked(i)       (ls_marks[i])
00068 #ifdef GC_PROFILE
00069 #define ls_mark(i)         \
00070 do { \
00071   int tag, place; \
00072   CPtr ptr; \
00073   place = i; \
00074   ptr = (CPtr) ls_top + place; \
00075   tag = cell_tag(*ptr); \
00076   inspect_chain(ptr); \
00077   ls_marks[place] |= MARKED; \
00078 } while (0)
00079 #else
00080 #define ls_mark(i)         ls_marks[i] |= MARKED
00081 #endif
00082 #define ls_clear_mark(i)   ls_marks[i] = 0
00083 
00084 #define tr_marked(i)         (tr_marks[i])
00085 #define tr_mark(i)           tr_marks[i] |= MARKED
00086 #define tr_clear_mark(i)     tr_marks[i] &= ~MARKED
00087 #define tr_mark_pre(i)       tr_marks[i] |= TRAIL_PRE
00088 #define tr_clear_pre_mark(i) tr_marks[i] &= ~TRAIL_PRE
00089 #define tr_pre_marked(i)     (tr_marks[i] & TRAIL_PRE)
00090 
00091 #define cp_marked(i)       (cp_marks[i])
00092 #define cp_mark(i)         cp_marks[i] |= MARKED
00093 #define cp_clear_mark(i)   cp_marks[i] &= ~MARKED
00094 
00095 /*=========================================================================*/
00096 
00097 #ifdef GC
00098 inline static CPtr hp_pointer_from_cell(Cell cell, int *tag)
00099 {
00100   int t;
00101   CPtr retp;
00102 
00103   t = cell_tag(cell) ;
00104 
00105   /* the use of if-tests rather than a switch is for efficiency ! */
00106   /* as this function is very heavily used - do not modify */
00107   if (t == XSB_LIST)
00108     {
00109       *tag = XSB_LIST;
00110       retp = clref_val(cell);
00111       testreturnit(retp);
00112     }
00113   if (t == XSB_STRUCT)
00114     {
00115       *tag = XSB_STRUCT;
00116       retp = (CPtr)(cs_val(cell));
00117       testreturnit(retp);
00118     }
00119   if ((t == XSB_REF) || (t == XSB_REF1))
00120     {
00121       *tag = t;
00122       retp = (CPtr)cell ;
00123       if (points_into_heap(retp)) return(retp);
00124     }
00125   if (t == XSB_ATTV)
00126     {
00127       *tag = XSB_ATTV;
00128       retp = clref_val(cell);
00129       testreturnit(retp);
00130     }
00131 
00132   return NULL;
00133 } /* hp_pointer_from_cell */
00134 #endif
00135 
00136 static CPtr pointer_from_cell(Cell cell, int *tag, int *whereto)
00137 { int t ;
00138  CPtr retp ;
00139 
00140  *tag = t = cell_tag(cell) ;
00141  switch (t)
00142    {
00143    case XSB_REF:
00144    case XSB_REF1: 
00145      retp = (CPtr)cell ;
00146      break ;
00147    case XSB_LIST: 
00148    case XSB_ATTV:
00149      retp = clref_val(cell) ;
00150      break ;
00151    case XSB_STRUCT:
00152      retp = ((CPtr)(cs_val(cell))) ;
00153      break ;
00154    default:
00155      *whereto = TO_NOWHERE ;
00156      return((CPtr)cell) ;
00157    }
00158 
00159  if (points_into_heap(retp)) *whereto = TO_HEAP ;
00160  else
00161    if (points_into_tr(retp)) *whereto = TO_TR ;
00162    else
00163      if (points_into_ls(retp)) *whereto = TO_LS ;
00164      else
00165        if (points_into_cp(retp)) *whereto = TO_CP ;
00166        else
00167          if (points_into_compl(retp)) *whereto = TO_COMPL ;
00168          else *whereto = TO_NOWHERE ;
00169  return(retp) ;
00170 
00171 } /* pointer_from_cell */
00172 
00173 /*-------------------------------------------------------------------------*/
00174 
00175 inline static char * pr_h_marked(CPtr cell_ptr)
00176 { int i ;
00177  i = cell_ptr - heap_bot ;
00178  if (heap_marks == NULL) return("not_m") ;
00179  if (h_marked(i) == MARKED) return("marked") ;
00180  if (h_marked(i) == CHAIN_BIT) return("chained") ;
00181  if (h_marked(i) == (CHAIN_BIT | MARKED)) return("chained+marked") ;
00182  return("not_m") ;
00183 } /* pr_h_marked */
00184 
00185 inline static char * pr_ls_marked(CPtr cell_ptr) 
00186 { int i ; 
00187  i = cell_ptr - ls_top ;
00188  if (ls_marks == NULL) return("not_m") ;
00189  if (ls_marked(i) == MARKED) return("marked") ;
00190  if (ls_marked(i) == CHAIN_BIT) return("chained") ;
00191  if (ls_marked(i) == (CHAIN_BIT | MARKED)) return("chained+marked") ;
00192  return("not_m") ; 
00193 } /* pr_ls_marked */ 
00194 
00195 inline static char * pr_cp_marked(CPtr cell_ptr) 
00196 { int i ; 
00197  i = cell_ptr - cp_top ;
00198  if (cp_marks == NULL) return("not_m") ;
00199  if (cp_marked(i) == MARKED) return("marked") ;
00200  if (cp_marked(i) == CHAIN_BIT) return("chained") ;
00201  if (cp_marked(i) == (CHAIN_BIT | MARKED)) return("chained+marked") ;
00202  return("not_m") ; 
00203 } /* pr_cp_marked */ 
00204 
00205 inline static char * pr_tr_marked(CPtr cell_ptr) 
00206 { int i ; 
00207  i = cell_ptr - tr_bot ;
00208  if (tr_marks == NULL) return("not_m") ;
00209  if (tr_marked(i) == MARKED) return("marked") ;
00210  if (tr_marked(i) == CHAIN_BIT) return("chained") ;
00211  if (tr_marked(i) == (CHAIN_BIT | MARKED)) return("chained+marked") ;
00212  if (tr_marked(i) == (CHAIN_BIT | MARKED | TRAIL_PRE)) 
00213    return("chained+marked+pre");
00214  return("not_m") ; 
00215 } /* pr_tr_marked */ 
00216 
00217 /*-------------------------------------------------------------------------*/
00218 
00219 /* Function mark_cell() keeps an explicit stack to perform marking.
00220    Marking without using such a stack, as in SICStus, should not be
00221    considered.  It is nice, but slower and more prone to errors.
00222    Recursive marking is the only alternative in my opinion, but one can
00223    construct too easily examples that overflow the C-stack - Bart Demoen.
00224 */
00225 
00226 #define MAXS 3700
00227 #define push_to_mark(p) mark_stack[mark_top++] = p
00228 #define mark_overflow   (mark_top >= MAXS)
00229 static int mark_cell(CPtr cell_ptr)
00230 {
00231   CPtr p ;
00232   Cell cell_val ;
00233   Integer i;
00234   int  m, arity, tag ;
00235   int  mark_top = 0 ;
00236   CPtr mark_stack[MAXS+MAX_ARITY+1] ;
00237 
00238   m = 0 ;
00239  mark_more:
00240   if (!points_into_heap(cell_ptr)) /* defensive marking */
00241     goto pop_more ;
00242  safe_mark_more:
00243   i = cell_ptr - heap_bot ;
00244   if (h_marked(i)) goto pop_more ;
00245   TO_BUFFER(cell_ptr);
00246   h_mark(i) ;
00247   m++ ;
00248 
00249   cell_val = *cell_ptr;
00250   tag = cell_tag(cell_val);
00251 
00252 
00253   if (tag == XSB_LIST || tag == XSB_ATTV)
00254     { cell_ptr = clref_val(cell_val) ;
00255     if (mark_overflow)
00256       { m += mark_cell(cell_ptr+1) ; }
00257     else push_to_mark(cell_ptr+1) ;
00258     goto safe_mark_more ;
00259     }
00260 
00261   if (tag == XSB_STRUCT)
00262     { p = (CPtr)cell_val ;
00263     cell_ptr = ((CPtr)(cs_val(cell_val))) ;
00264     i = cell_ptr - heap_bot ;
00265     if (h_marked(i)) goto pop_more ;
00266     TO_BUFFER(cell_ptr);
00267     h_mark(i) ; m++ ;
00268     cell_val = *cell_ptr;
00269     arity = get_arity((Psc)(cell_val)) ;
00270     p = ++cell_ptr ;
00271     if (mark_overflow)
00272       { while (--arity)
00273         { m += mark_cell(++p) ; }
00274       }
00275     else while (--arity) push_to_mark(++p) ;
00276     goto mark_more ;
00277     }
00278 
00279   if ((tag == XSB_REF) || (tag == XSB_REF1))
00280     { p = (CPtr)cell_val ;
00281       if (p == cell_ptr) goto pop_more ;
00282     cell_ptr = p ;
00283     goto mark_more ;
00284     }
00285 
00286 #ifndef NO_STRING_GC
00287 #ifdef MULTI_THREAD
00288   if (flags[NUM_THREADS] == 1)
00289 #endif
00290     if (gc_strings) {
00291       if (tag == XSB_STRING) {
00292         char *astr = string_val(cell_val);
00293         if (astr && (string_find_safe(astr) == astr))
00294           mark_string_safe(astr,"mark_cell");
00295       }
00296     }
00297 #endif /* ndef NO_STRING_GC */
00298 
00299  pop_more:
00300   if (mark_top--)
00301     { cell_ptr = mark_stack[mark_top] ; goto mark_more ; }
00302   return(m) ;
00303 
00304 } /* mark_cell */
00305 
00306 /*----------------------------------------------------------------------*/
00307 
00308 /* TLS: Overall, attvs are treated analogously to lists in the GC:
00309    thus when an attv is encountered, its attribute list is also
00310    traversed.  Note that when one attv is replaced by another in an
00311    interrupt handler, it should be through a put_attr().  When this
00312    happens a chain of attvs is created, so that starting out from some
00313    cell or another, the old attvs (which may be needed in
00314    backtracking) are marked since they are proximate to attvs.  Thus,
00315    you dont need to set the attvs in the pre-image trail (as I
00316    mistakenly thought), at least not for GC. */
00317 
00318 static int mark_root(Cell cell_val)
00319 {
00320   Integer i;
00321   int m, arity ;
00322   CPtr cell_ptr;
00323   int tag, whereto ;
00324   Cell v ;
00325 
00326   /* this is one of the places to be defensive while marking: an uninitialised
00327      cell in the ls can point to a Psc; the danger is not in following the Psc
00328      and mark something outside of the heap: mark_cell takes care of that; the
00329      dangerous thing is to mark the cell with the Psc on the heap without
00330      marking all its arguments */
00331 
00332   if (cell_val == 0) return(0) ;
00333   switch (cell_tag(cell_val))
00334     {
00335     case XSB_REF:
00336     case XSB_REF1:
00337       v = *(CPtr)cell_val ;
00338       pointer_from_cell(v,&tag,&whereto) ;
00339       switch (tag)
00340         { case XSB_REF: case XSB_REF1:
00341           if (whereto != TO_HEAP) return(0) ;
00342           break ;
00343         }
00344       return(mark_cell((CPtr)cell_val)) ;
00345 
00346     case XSB_STRUCT : 
00347       cell_ptr = ((CPtr)(cs_val(cell_val))) ;
00348       if (!points_into_heap(cell_ptr)) return(0) ;
00349       i = cell_ptr - heap_bot ; 
00350       if (h_marked(i)) return(0) ; 
00351       /* now check that at i, there is a Psc */
00352       v = *cell_ptr ;
00353       pointer_from_cell(v,&tag,&whereto) ;
00354       /* v must be a PSC - the following tries to test this */
00355       switch (tag) {
00356       case XSB_REF: 
00357       case XSB_REF1 :
00358         if (whereto != TO_NOWHERE) return(0) ;
00359         break ;
00360         /* default: return(0); */
00361       }
00362       TO_BUFFER(cell_ptr);
00363       h_mark(i) ; m = 1 ; 
00364       cell_val = *cell_ptr;
00365       arity = get_arity((Psc)(cell_val)) ;
00366       while (arity--) m += mark_cell(++cell_ptr) ;
00367       return(m) ;
00368       
00369     case XSB_LIST: 
00370     case XSB_ATTV:
00371       /* the 2 cells will be marked iff neither of them is a Psc */
00372       cell_ptr = clref_val(cell_val) ;
00373       if (!points_into_heap(cell_ptr)) return(0) ;
00374       v = *cell_ptr ;
00375 #ifndef NO_STRING_GC
00376       if (gc_strings) mark_if_string(v,"attv 1");
00377 #endif
00378       pointer_from_cell(v,&tag,&whereto) ;
00379       switch (tag) {
00380       case XSB_REF:
00381       case XSB_REF1:
00382         if (whereto != TO_HEAP) return(0) ;
00383         break ;
00384       }
00385       v = *(++cell_ptr) ;
00386 #ifndef NO_STRING_GC
00387       if (gc_strings) mark_if_string(v,"attv 2");
00388 #endif
00389       pointer_from_cell(v,&tag,&whereto) ;
00390       switch (tag) {
00391       case XSB_REF:
00392       case XSB_REF1:
00393         if (whereto != TO_HEAP) return(0) ;
00394         break ;
00395       }
00396       m = mark_cell(cell_ptr) ;
00397       cell_ptr-- ; 
00398       m += mark_cell(cell_ptr) ;
00399       return(m) ;
00400 
00401 #ifndef NO_STRING_GC
00402     case XSB_STRING:
00403 #ifdef MULTI_THREAD
00404   if (flags[NUM_THREADS] == 1)
00405 #endif
00406     if (gc_strings) {
00407       char *sstr = string_val(cell_val);
00408       if (sstr && (string_find_safe(sstr) == sstr))
00409         mark_string_safe(sstr,"mark_root");
00410       return(0);
00411     }
00412 #endif /* ndef NO_STRING_GC */
00413 
00414     default : return(0) ;
00415     }
00416 
00417 } /* mark_root */
00418 
00419 /*----------------------------------------------------------------------*/
00420 
00421 inline static int mark_region(CPtr beginp, CPtr endp)
00422 {
00423   int marked = 0 ;
00424 
00425   while (beginp <= endp) {
00426     marked += mark_root(*(beginp++)) ;
00427   }
00428 
00429   return(marked) ;
00430 } /* mark_region */
00431 
00432 /*----------------------------------------------------------------------*/
00433 inline static unsigned long mark_trail_section(CPtr begintr, CPtr endtr)
00434 {
00435   CPtr a = begintr;
00436   CPtr trailed_cell;
00437   unsigned long i=0, marked=0;
00438 #ifdef PRE_IMAGE_TRAIL
00439   CPtr pre_value = NULL;
00440 #endif
00441   
00442   while (a > (CPtr)endtr)
00443     { 
00444       tr_mark(a - tr_bot); /* mark trail cell as visited */
00445       /* lfcastro -- needed for copying */
00446       tr_mark((a-tr_bot)-1);
00447       tr_mark((a-tr_bot)-2);
00448 
00449       trailed_cell = (CPtr) *(a-2);
00450 #ifdef PRE_IMAGE_TRAIL
00451       if ((long) trailed_cell & PRE_IMAGE_MARK) {
00452         trailed_cell = (CPtr) ((Cell) trailed_cell & ~PRE_IMAGE_MARK);
00453         pre_value = (CPtr) *(a-3);
00454         tr_mark_pre((a-tr_bot)-2); /* mark somewhere else */
00455         *(a-2) = ((Cell)trailed_cell & ~PRE_IMAGE_MARK); /* and delete mark */
00456       /* lfcastro -- needed for copying */
00457         tr_mark((a-tr_bot)-3);
00458       }
00459 #endif
00460       
00461       if (points_into_heap(trailed_cell))
00462         { i = trailed_cell - heap_bot ;
00463         if (! h_marked(i))
00464           {
00465 #if (EARLY_RESET == 1)
00466             {
00467               /* instead of marking the word in the heap, 
00468                  we make the trail cell point to itself */
00469               TO_BUFFER(trailed_cell);
00470               h_mark(i) ;
00471               marked++ ;
00472               
00473 #ifdef PRE_IMAGE_TRAIL
00474               if (pre_value) 
00475                 *trailed_cell = (Cell) pre_value;
00476               else
00477 #endif
00478                 bld_free(trailed_cell); /* early reset */
00479               
00480               /* could do trail compaction now or later */
00481               heap_early_reset++;
00482             }
00483 #else
00484             {
00485               marked += mark_root((Cell)trailed_cell);
00486             }
00487 #endif
00488             
00489           }
00490         }
00491       else
00492         /* it must be a ls pointer, but for safety
00493            we take into account between_h_ls */
00494         if (points_into_ls(trailed_cell))
00495           { i = trailed_cell - ls_top ;
00496           if (! ls_marked(i))
00497             {
00498 #if (EARLY_RESET == 1)
00499               {
00500                 /* don't ls_mark(i) because we early reset
00501                    so, it is not a heap pointer
00502                    but marking would be correct */
00503 #ifdef PRE_IMAGE_TRAIL
00504                 if (pre_value)
00505                   *trailed_cell = (Cell) pre_value;
00506                 else
00507 #endif
00508                   bld_free(trailed_cell) ; /* early reset */
00509                 
00510                 /* could do trail compaction now or later */
00511                 ls_early_reset++;
00512               }
00513 #else
00514               { ls_mark(i) ;
00515               marked += mark_region(trailed_cell, trailed_cell);
00516               }
00517 #endif
00518             }
00519           }
00520       
00521       /* mark the forward value */
00522       marked += mark_root((Cell) *(a-1));
00523       
00524 #ifdef PRE_IMAGE_TRAIL
00525       if (pre_value) { 
00526         marked += mark_root((Cell) pre_value);
00527         pre_value = NULL;
00528       }
00529 #endif
00530 
00531       /* stop if we're not going anywhere */
00532       if ((unsigned long) a == (unsigned long) *a)
00533         break;
00534 
00535       /* jump to previous cell */
00536       a = (CPtr) *a;
00537     }
00538   return marked;
00539 }
00540 /*----------------------------------------------------------------------*/
00541 /* TLS: as I understand it, this should mark all WAM-register regions
00542  * of choice points, as well as the substitution factors of tabled
00543  * choice points.  It traverses the CP stack via the special cell
00544  * prev-top which has noting to do with the previous breg.  The part
00545  * of this code that checks first time and resets the register values
00546  * seems a little weird -- I don't see why just takeing the youngest
00547  * of breg/bfreg and traversing from there wouldn't amount to the same
00548  * thing. */
00549 
00550 static int mark_query(CTXTdecl)
00551 {
00552   Integer i;
00553   int yvar, total_marked = 0 ;
00554   CPtr b,e,*tr,a,d;
00555   byte *cp;
00556   int first_time;
00557 
00558   b = breg ;
00559   e = ereg ;
00560   tr = trreg ;
00561   cp = cpreg ;
00562   first_time = 1;
00563 
00564 restart:
00565   while (1)
00566     {
00567       while ((e < ls_bot) && (cp != NULL))
00568         {
00569           if (ls_marked(e - ls_top)) break ;
00570           ls_mark(e - ls_top) ;
00571           /* TLS: get number of perm. vars from cpreg */
00572           yvar = *(cp-2*sizeof(Cell)+3) - 1 ;  
00573           total_marked += mark_region(e-yvar,e-2) ;
00574           i = (e-2) - ls_top ;
00575           while (yvar-- > 1) { ls_mark(i--); }
00576           cp = (byte *)e[-1] ;
00577           e = (CPtr)e[0] ;
00578         }
00579       if (b >= (cp_bot-CP_SIZE)) {
00580         return(total_marked) ;
00581       }
00582       a = (CPtr)tr ;
00583       tr = cp_trreg(b) ;
00584 
00585       /* the answer template is part of the forward computation for 
00586          consumers, so it should be marked before the trail in order
00587          to allow for early reset                      --lfcastro */
00588       
00589       if (is_generator_choicepoint(b)) {
00590         CPtr region;
00591         int at_size;
00592         region = (CPtr) tcp_template(b);
00593         at_size = (int_val(cell(region)) & 0xffff) + 1;
00594         while (at_size--)
00595           total_marked += mark_cell(region--);
00596       } else if (is_consumer_choicepoint(b)) {
00597         CPtr region;
00598         int at_size;
00599         region = (CPtr) nlcp_template(b);
00600         at_size = (int_val(cell(region))&0xffff)+1;
00601         while (at_size--)
00602           total_marked += mark_cell(region--);
00603       }
00604 
00605       /* mark the delay list field of all choice points in CP stack too */
00606       if ((d = cp_pdreg(b)) != NULL) {
00607         total_marked += mark_root((Cell)d);
00608       }
00609 
00610       total_marked += mark_trail_section(a,(CPtr) tr);
00611 
00612       /* mark the arguments in the choicepoint */
00613       /* the choicepoint can be a consumer, a generator or ... */
00614 
00615       /* the code for non-tabled choice points is ok */
00616       /* for all other cps - check that
00617          (1) the saved arguments are marked
00618          (2) the substitution factor is marked
00619       */
00620 
00621       if (is_generator_choicepoint(b))
00622         { /* mark the arguments */
00623           total_marked += mark_region(b+TCP_SIZE, tcp_prevtop(b)-1);
00624         }
00625       else if (is_consumer_choicepoint(b))
00626         { /* mark substitution factor -- skip the number of SF vars */
00627           /* substitution factor is in the choicepoint for consumers */
00628 #ifdef SLG_GC
00629           if (nlcp_prevtop(b) != b+NLCP_SIZE) {
00630             /* this was a producer that was backtracked over --lfcastro */
00631             /* mark the arguments, since chaining & copying consider them */
00632             CPtr ptr;
00633             for (ptr = b+NLCP_SIZE; ptr < nlcp_prevtop(b); ptr++)
00634               *ptr = makeint(6660666);
00635 /*          total_marked += mark_region(b+NLCP_SIZE, nlcp_prevtop(b)-1); */
00636           } 
00637 
00638 #endif
00639         }
00640       else if (is_compl_susp_frame(b)) 
00641         /* there is nothing to do in this case */ ;
00642       else { 
00643         CPtr endregion, beginregion;
00644         endregion = cp_prevtop(b)-1;
00645         beginregion = b+CP_SIZE;
00646         total_marked += mark_region(beginregion,endregion) ;
00647 
00648       }
00649 
00650       e = cp_ereg(b) ;
00651       cp = cp_cpreg(b) ;
00652 #if defined(GC_PROFILE) && defined(CP_DEBUG)
00653       if (examine_data) {
00654         print_cpf_pred(b);
00655         active_cps++;
00656       }
00657 #endif
00658       if (first_time) {
00659         first_time = 0;
00660         if (bfreg < breg) {
00661           b = bfreg;
00662           e = cp_ereg(b);
00663           cp = cp_cpreg(b);
00664           tr = cp_trreg(b);
00665           goto restart;
00666         }
00667       }
00668 
00669       b = cp_prevtop(b);
00670     }
00671 
00672 } /* mark_query */
00673 
00674 /*----------------------------------------------------------------------*/
00675 
00676 static int mark_hreg_from_choicepoints(CTXTdecl)
00677 {
00678   CPtr b, bprev, h;
00679   Integer i;
00680   int  m;
00681 
00682   /* this has to happen after all other marking ! */
00683   /* actually there is no need to do this for a copying collector */
00684 
00685   b = (bfreg < breg ? bfreg : breg);
00686   bprev = 0;
00687   m = 0;
00688     while(1)
00689      {
00690       h = cp_hreg(b) ;
00691       i = h - heap_bot ;
00692       if (! h_marked(i)) /* h from choicepoint should point to something that
00693                             is marked; if not, mark it now and set it
00694                             to something reasonable - int(666) is ok
00695                             although a bit scary :-)
00696                          */
00697         {
00698           cell(h) = makeint(666) ;
00699           TO_BUFFER(h);
00700           h_mark(i) ;
00701           m++ ;
00702         }
00703 #ifdef SLG_GC
00704       /* should mark hfreg for generators, too --lfcastro */
00705       if (is_generator_choicepoint(b)) {
00706         h = tcp_hfreg(b);
00707         i = h - heap_bot;
00708         if (! h_marked(i)) {
00709           cell(h) = makeint(6660);
00710           TO_BUFFER(h);
00711           h_mark(i);
00712           m++;
00713         }
00714       }
00715 #endif
00716       bprev = b; 
00717     b = cp_prevtop(b);
00718     if (b >= (cp_bot-CP_SIZE))
00719       break;
00720   }
00721   return m;
00722 } /* mark_hreg_from_choicepoints */
00723 
00724 /*-------------------------------------------------------------------------*/
00725 
00733 static int mark_from_attv_array(CTXTdecl)
00734 {
00735   int i,max;
00736   int m=0;
00737 
00738   max = int_val(cell(interrupt_reg));
00739 
00740   for (i=0; i<max; i++) {
00741     m += mark_cell((CPtr) attv_interrupts[i][0]);
00742     m += mark_cell((CPtr) attv_interrupts[i][1]);
00743   }
00744   return m;
00745 }
00746 
00747 /*-------------------------------------------------------------------------*/
00748 
00749 
00750 int mark_heap(CTXTdeclc int arity, int *marked_dregs)
00751 {
00752   int avail_dreg_marks = 0, marked = 0;
00753 
00754   /* the following seems unnecessary, but it is not !
00755      mark_heap() may be called directly and not only through gc_heap() */
00756   slide = (pflags[GARBAGE_COLLECT] == SLIDING_GC) |
00757     (pflags[GARBAGE_COLLECT] == INDIRECTION_SLIDE_GC);
00758   
00759   stack_boundaries ;
00760   
00761   if (print_on_gc) print_all_stacks(CTXTc arity);
00762   
00763   if (slide) {
00764 #ifdef INDIRECTION_SLIDE
00765     /* space for keeping pointers to live data */
00766     slide_buf_size = (unsigned long) ((hreg+1-(CPtr)glstack.low)*0.2);
00767     slide_buf = (CPtr *) mem_calloc(slide_buf_size+1, sizeof(CPtr),GC_SPACE);
00768     if (!slide_buf)
00769       xsb_exit("Not enough space to allocate slide_buf");
00770     slide_top=0;
00771     if (pflags[GARBAGE_COLLECT] == INDIRECTION_SLIDE_GC)
00772       slide_buffering=1;
00773     else
00774       slide_buffering=0;
00775 #endif
00776   }
00777   
00778 #ifdef INDIRECTION_SLIDE
00779   else
00780     slide_buffering=0;
00781 #endif
00782   
00783 #ifdef SLG_GC
00784   cp_marks = (char *)mem_calloc(cp_bot - cp_top + 1,1,GC_SPACE);
00785   tr_marks = (char *)mem_calloc(tr_top - tr_bot + 1,1,GC_SPACE);
00786   if ((! cp_marks) || (! tr_marks))
00787     xsb_exit("Not enough core to perform garbage collection chaining phase");
00788 #endif  
00789   heap_marks_size = heap_top - heap_bot + 2 + avail_dreg_marks;
00790   heap_marks = (char * )mem_calloc(heap_marks_size,1,GC_SPACE);
00791   ls_marks   = (char * )mem_calloc(ls_bot - ls_top + 1,1,GC_SPACE);
00792   if ((! heap_marks) || (! ls_marks))
00793     xsb_exit("Not enough core to perform garbage collection marking phase");
00794   
00795   heap_marks += 1; /* see its free; also note that heap_marks[-1] = 0 is
00796                       needed for copying garbage collection see copy_block() */
00797   
00798   /* start marking phase */
00799   marked = mark_region(reg+1,reg+arity);
00800   if (delayreg != NULL) {
00801     marked += mark_root((Cell)delayreg);
00802   }
00803   /* Heap[0] is a global variable */
00804   marked += mark_root((Cell)glstack.low);
00805   
00806   if (slide)
00807     { 
00808       int put_on_heap;
00809       put_on_heap = arity;
00810       marked += put_on_heap;
00811       while (put_on_heap > 0) {
00812 #ifdef SLG_GC
00813         TO_BUFFER((heap_top-put_on_heap-1));
00814         h_mark((heap_top - 1 - put_on_heap--)-heap_bot);
00815 #else
00816         TO_BUFFER((heap_top-put_on_heap));
00817         h_mark((heap_top - put_on_heap--)-heap_bot);
00818 #endif
00819       }
00820     }
00821 
00822 #ifdef SLG_GC
00823   /* hfreg's also kept in the heap so that it's automatically adjusted */
00824   /* only for sliding GC */
00825   if (slide) { 
00826     CPtr hfreg_in_heap;
00827     /* mark from hfreg */
00828     marked += mark_root((Cell)hfreg);
00829   
00830     hfreg_in_heap = heap_top - 1;
00831     TO_BUFFER(hfreg_in_heap);
00832     if (!h_marked(hfreg_in_heap - heap_bot)) {
00833       h_mark(hfreg_in_heap - heap_bot);
00834       marked++;
00835     }
00836   }
00837 #endif
00838 
00839   marked += mark_query(CTXT);
00840 
00841   marked += mark_from_attv_array(CTXT);
00842 
00843   if (slide)
00844     marked += mark_hreg_from_choicepoints(CTXT);
00845 
00846   if (print_on_gc) print_all_stacks(CTXTc arity);
00847 
00848   return marked ;
00849 } /* mark_heap */
00850 
00851 #ifndef NO_STRING_GC
00852 #define mark_trie_strings_for(SM,BType,pStruct,apStruct)        \
00853   pBlock = SM_CurBlock(SM);                                     \
00854   if (pBlock != NULL) {                                         \
00855     int isusedblock, anyunusedblock = FALSE;                    \
00856     for (pStruct = (BType)SMBlk_FirstStruct(pBlock);            \
00857          pStruct < (BType)SM_NextStruct(SM);                    \
00858          pStruct = (BType)SMBlk_NextStruct(pStruct,SM_StructSize(SM))) { \
00859       if (isstring(BTN_Symbol(pStruct)) && (*(((Integer *)pStruct)+1) != FREE_TRIE_NODE_MARK)) {\
00860         mark_string(string_val(BTN_Symbol(pStruct)),"trie 1");  \
00861       }                                                         \
00862     }                                                           \
00863     pBlock = SMBlk_NextBlock(pBlock);                           \
00864     while (pBlock != NULL) {                                    \
00865       isusedblock = FALSE;                                      \
00866       for (pStruct = (BType)SMBlk_FirstStruct(pBlock);          \
00867            pStruct <= (BType)SMBlk_LastStruct(pBlock,SM_StructSize(SM),SM_StructsPerBlock(SM)); \
00868            pStruct = (BType)SMBlk_NextStruct(pStruct,SM_StructSize(SM))) { \
00869         if (*(((Integer *)pStruct)+1) != FREE_TRIE_NODE_MARK) { \
00870           isusedblock = TRUE;                                   \
00871           if (isstring(BTN_Symbol(pStruct)))                    \
00872             mark_string(string_val(BTN_Symbol(pStruct)),"trie 2");\
00873         }                                                       \
00874       }                                                         \
00875       anyunusedblock |= !isusedblock;                           \
00876       if (!isusedblock) {                                       \
00877         /*printf("%p in %p is an unused block\n",pBlock,SM);*/  \
00878         for (pStruct = (BType)SMBlk_FirstStruct(pBlock);        \
00879              pStruct <= (BType)SMBlk_LastStruct(pBlock,SM_StructSize(SM),SM_StructsPerBlock(SM)); \
00880              pStruct = (BType)SMBlk_NextStruct(pStruct,SM_StructSize(SM))) { \
00881           *(((Integer *)pStruct)+1) = FREE_TRIE_BLOCK_MARK;     \
00882         }                                                       \
00883       }                                                         \
00884       pBlock = SMBlk_NextBlock(pBlock);                         \
00885     }                                                           \
00886     if (anyunusedblock) {                                       \
00887       apStruct = (BType *)&SM_FreeList(SM);                     \
00888       while (*apStruct != NULL) {                               \
00889         if (*((Integer *)(*apStruct)+1) == FREE_TRIE_BLOCK_MARK)\
00890           *apStruct = *((void **)(*apStruct));                  \
00891         else apStruct = *(void **)apStruct;                     \
00892       }                                                         \
00893       apBlock = &(SM_CurBlock(SM));                             \
00894       while (*apBlock != NULL) {                                \
00895         if (*((Integer *)(*apBlock)+2) == FREE_TRIE_BLOCK_MARK) {\
00896           pBlock = *apBlock;                                    \
00897           *apBlock = *((void **)(*apBlock));                    \
00898           mem_dealloc(pBlock,SM_NewBlockSize(SM),TABLE_SPACE);  \
00899         } else apBlock = *((void **)(apBlock));                 \
00900       }                                                         \
00901     }                                                           \
00902   }
00903 
00904 
00905 void mark_trie_strings(CTXTdecl) {
00906 
00907   BTNptr pBTNStruct, *apBTNStruct;
00908   TSTNptr pTSTNStruct, *apTSTNStruct;
00909   void *pBlock, **apBlock;
00910 
00911 #ifdef MULTI_THREAD
00912   //  printf("marking private trie strings\n");
00913   mark_trie_strings_for(*private_smTableBTN,BTNptr,pBTNStruct,apBTNStruct);
00914   //  printf("marked private trie strings\n");
00915 #endif  
00916   SYS_MUTEX_LOCK(MUTEX_SM);
00917   mark_trie_strings_for(smTableBTN,BTNptr,pBTNStruct,apBTNStruct);
00918   mark_trie_strings_for(smAssertBTN,BTNptr,pBTNStruct,apBTNStruct);
00919   SYS_MUTEX_UNLOCK(MUTEX_SM);
00920   mark_trie_strings_for(smTSTN,TSTNptr,pTSTNStruct,apTSTNStruct);
00921 }
00922 
00923 void mark_code_strings(int pflag, CPtr inst_addr, CPtr end_addr) {
00924   int  current_opcode, oprand;
00925 
00926   //  printf("buffer\n");
00927   while (inst_addr<end_addr) {
00928     current_opcode = cell_opcode(inst_addr);
00929     //    printf("opcode: %x\n",current_opcode);
00930     inst_addr ++;
00931     for (oprand=1; oprand<=4; oprand++) {
00932       switch (inst_table[current_opcode][oprand]) {
00933       case A: case V: case R: case P: case PP: case PPP:
00934       case PPR: case PRR: case RRR: case X:
00935         break;
00936       case S: case L: case N: case B: case F:
00937       case I: case T:     
00938         inst_addr ++;
00939         break;
00940       case C:
00941       case G:
00942         if (pflag) printf("    %s\n",*(char **)inst_addr);
00943         mark_string(*(char **)inst_addr,"code");
00944         inst_addr ++;
00945         break;
00946       default:
00947         break;
00948       }  /* switch */
00949     } /* for */
00950   }
00951 }
00952 
00953 void mark_atom_and_code_strings(CTXTdecl) {
00954   unsigned long i;
00955   Pair pair_ptr, mod_pair_ptr;
00956   PrRef prref;
00957   ClRef clref;
00958   CPtr code_beg, code_end;
00959 
00960   //  printf("marking atom and code strings\n");
00961   //  printf("marking atoms in usermod\n");
00962   for (i = 0; i < symbol_table.size; i++) {
00963     if (symbol_table.table[i] != NULL) {
00964       for (pair_ptr = (Pair)symbol_table.table[i]; pair_ptr != NULL;
00965            pair_ptr = pair_next(pair_ptr)) {
00966         char *string = get_name(pair_psc(pair_ptr));
00967         mark_string(string,"usermod atom");
00968         if (get_type(pair_psc(pair_ptr)) == T_DYNA) {
00969           //      printf("mark dc for usermod:%s/%d\n",string,get_arity(pair_psc(pair_ptr)));
00970           prref = dynpredep_to_prref(CTXTc get_ep(pair_psc(pair_ptr))); // fix for multi-threading to handle dispatch for privates 
00971           if (prref) {
00972             clref = db_get_clause_code_space(prref,(ClRef)NULL,&code_beg,&code_end);
00973             while (clref) {
00974               mark_code_strings(0,code_beg,code_end);
00975               clref = db_get_clause_code_space(prref,clref,&code_beg,&code_end);
00976             }
00977           }
00978         }
00979       }
00980     }
00981   }
00982   for (mod_pair_ptr = (Pair)flags[MOD_LIST]; 
00983        mod_pair_ptr != NULL; 
00984        mod_pair_ptr = pair_next(mod_pair_ptr)) {
00985     mark_string(get_name(pair_psc(mod_pair_ptr)),"mod");
00986     pair_ptr = (Pair) get_data(pair_psc(mod_pair_ptr));
00987     if ((Integer)pair_ptr != 1) { // not global mod 
00988       while (pair_ptr != NULL) {
00989         char *string = get_name(pair_psc(pair_ptr));
00990         mark_string(string,"mod atom");
00991         if (get_type(pair_psc(pair_ptr)) == T_DYNA) {
00992           //      if (strcmp(get_name(pair_psc(pair_ptr)),"ipObjectSpec_T")==0) printf("mark dc for %s:%s/%d\n",get_name(pair_psc(mod_pair_ptr)),string,get_arity(pair_psc(pair_ptr)));
00993           prref = dynpredep_to_prref(CTXTc get_ep(pair_psc(pair_ptr)));
00994           clref = db_get_clause_code_space(prref,(ClRef)NULL,&code_beg,&code_end);
00995           while (clref) {
00996             //      printf("  mark code from %s/%d(%s), %p\n", string, get_arity(pair_psc(pair_ptr)), get_name(pair_psc(mod_pair_ptr)), clref);
00997             mark_code_strings(0,code_beg,code_end);
00998             clref = db_get_clause_code_space(prref,clref,&code_beg,&code_end);
00999           }
01000         }
01001         pair_ptr = pair_next(pair_ptr);
01002       }
01003     }
01004   }
01005   //  printf("marked atom and code strings\n");
01006 }
01007 
01008 void mark_nonheap_strings(CTXTdecl) {
01009   char *empty;
01010 
01011   mark_string((char *)(ret_psc[0]),"ret"); /* "ret" necessary */
01012   mark_string(nil_string,"[]"); /* necessary */
01013   empty = string_find_safe("");
01014   if (!empty) mark_string(empty,"empty");
01015 
01016   mark_trie_strings(CTXT);
01017   mark_atom_and_code_strings(CTXT);
01018   mark_findall_strings(CTXT);
01019   mark_open_filenames();
01020   mark_hash_table_strings(CTXT);
01021 
01022 }
01023 #endif /* ndef NO_STRING_GC */
01024 

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