heap_xsb.c

00001 /* File:      heap_xsb.c
00002 ** Author(s): Bart Demoen, Kostis Sagonas
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1998
00006 ** Copyright (C) K.U. Leuven, 1998-1999
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: heap_xsb.c,v 1.52 2006/06/21 20:17:11 dwarren Exp $
00023 ** 
00024 */
00025 
00026 
00027 /*************************************************************************
00028  * This module provides:
00029 
00030         reallocation of the heap/environment area
00031         -----------------------------------------
00032         Function glstack_realloc(new_size,arity)
00033                 originally written by E. Johnson in file
00034                 memory_xsb.c, but completely redone by Bart Demoen
00035 
00036         heap garbage collection
00037         -----------------------
00038         Function gc_heap(arity,IfStringGC) - 
00039            To understand the usefulness logic, see paper:
00040                 B. Demoen and K. Sagonas.
00041                 Memory Management for Prolog with Tabling.
00042                 in Proceedings of the 1998 ACM SIGPLAN International
00043                 Symposium on Memory Management, Vancouver, B.C., Canada,
00044                 Oct. 1998. ACM Press. p. 97-106
00045 
00046            To understand the implementation and for additional information see:
00047                 B. Demoen and K. Sagonas.
00048                 Heap Garbage Collection in XSB: Practice and Experience.
00049                 CW report 272, September 1998; finished February 1999.
00050 
00051 
00052         Function slide_heap() implements a sliding collector a la Morris
00053            It was mostly written by Bart Demoen
00054                for a Prolog specific one see paper:
00055                K. Appleby, M. Carlsson, S. Haridi, and D. Sahlin.
00056                Garbage Collection for Prolog Based on WAM.
00057                Communications of the ACM, 31(6):719--741, June 1988.
00058 
00059 
00060         Function copy_heap() implements a copying collector a la Cheney
00061            It was mostly written by Kostis Sagonas
00062                for a Prolog specific one see paper:
00063                J. Bevemyr and T. Lindgren.
00064                A Simple and Efficient Copying Garbage Collector for Prolog.
00065                In M. Hermenegildo and J. Penjam, editors,
00066                Proceedings of the Sixth International Symposium on
00067                Programming Language Implementation and Logic Programming,
00068                number 844 in LNCS, pages 88--101, Madrid, Spain, Sept.  1994.
00069                Springer-Verlag.
00070 
00071 
00072         printing routines for some areas
00073                 print_heap
00074                 print_ls
00075                 print_cp
00076                 print_regs
00077                 print_tr
00078                 print_all_stacks: does all of the above
00079         some - maybe all - of these were somewhere in the system already
00080                 but weren't entirely what we needed
00081 
00082 
00083 Todo:
00084         adapt the garbage collectors to SLG-WAM
00085         provide a decent user interface to the garbage collector
00086         integrate with compiler
00087 
00088 ****************************************************************************/
00089 /****************************************************************************
00090 String table garbage collection, by mark and collect.  
00091 
00092 First mark all strings in use.  A string Cell is a tagged pointer to a
00093 sequence of chars, word aligned.  The previous word is the link
00094 pointer in the hash bucket chain.  Use the lowest bit in that pointer
00095 as the mark bit.  When marking what looks like a string, be sure it is
00096 a indeed a string by comparing it to the result of calling
00097 string_find.
00098 
00099 Mark: 
00100 
00101 a) Piggyback on marking of heap gc to mark all strings accessible
00102 from stacks and trail.
00103 
00104 b) Mark tries by running trie-node blocks rooted at smTableBTN,
00105 smTSTN, and smAssertBTN.  Changed trie-node free to set 2nd word in
00106 trie node to distinctive pattern (-1), so know to skip those nodes.
00107 (NOT DONE: At the same time could free blocks all of whose nodes are free.  
00108 Mark 2nd work in freed nodes in to-be-freed blocks (-2?), and run free
00109 chain to remove them.  Then free the blocks.)
00110 
00111 c) Mark all strings in code by running atom-table to get entry points,
00112 including through private dispatch tables, and then scanning the code
00113 for instructions containing strings.
00114 
00115 d) Mark all strings in findall buffers by running them.
00116 
00117 e) Mark strings that are used as filenames for open files.
00118 
00119 f) Mark strings used as hash-keys in hashtables.
00120 
00121 g) NOT DONE: Consider ways to deal with string pointers given to C programs in
00122 ptoc_string.
00123 
00124 Collect: run through the string table, freeing unmarked strings and
00125 unmarking marked strings.
00126 
00127 ****************************************************************************/
00128 
00129 /* xsb_config.h must be the first #include. Pls don't move it. */
00130 #include "xsb_config.h"
00131 #include "xsb_debug.h"
00132 
00133 #include <string.h>
00134 #include <stdlib.h>
00135 #include <sys/stat.h>
00136 
00137 /* Take care of the time.h business */
00138 /* #include "xsb_time.h" */
00139 /* But I need time.h, not sys/time.h here! -lfcastro */
00140 #include <time.h>
00141 
00142 #include "auxlry.h"
00143 #include "cell_xsb.h"
00144 #include "memory_xsb.h"
00145 #include "inst_xsb.h"
00146 
00147 /* For Reallocation Routines
00148    ------------------------- */
00149 #include <stdio.h>         /* for printf and friends */
00150 
00151 #include "register.h"      /* breg, trreg */
00152 #include "psc_xsb.h"       /* needed by "tries.h" and "macro_xsb.h" */
00153 #include "tries.h"         /* needed by "choice.h" */
00154 #include "choice.h"        /* choice point structures and macros */
00155 #include "error_xsb.h"     /* xsb_exit() and friends */
00156 #include "macro_xsb.h"     /* Completion Stack and Subgoal Frame def's */
00157 #include "realloc.h"       /* Heap - ls reallocation macros */
00158 #include "flags_xsb.h"     /* for checking whether functionality is enabled */
00159 #include "heap_xsb.h"
00160 #include "io_builtins_xsb.h"
00161 #include "subp.h"          /* for attv_interrupts[][] */
00162 #include "binding.h"       /* for PRE_IMAGE_TRAIL */
00163 #include "thread_xsb.h"    /* for mutex definitions */
00164 #include "debug_xsb.h"
00165 #include "loader_xsb.h" /* for ZOOM_FACTOR, used in stack expansion */
00166 #include "struct_manager.h"
00167 #include "hash_xsb.h"
00168 /*=========================================================================*/
00169 
00170 /* this might belong somewhere else (or should be accessible to init.c),
00171    but in the meantime, this will do */
00172 #ifdef GC
00173 static float mark_threshold = 0.9F;
00174 #endif
00175 
00176 #ifdef DEBUG_VM
00177 #define GC_PROFILE
00178 #endif
00179 
00180 #ifdef GC_PROFILE
00181 
00182 static char count_chains=0, examine_data=0, verbose_gc=0;
00183 unsigned long chains[64];
00184 unsigned long tag_examined[9];
00185 unsigned long deep_mark;
00186 unsigned long current_mark;
00187 unsigned long old_gens;
00188 unsigned long current_gen;
00189 CPtr start_hbreg;
00190 unsigned long functor;
00191 unsigned long chain_from_ls;
00192 unsigned long active_cps, frozen_cps;
00193 void print_cpf_pred(CPtr cpf);
00194 
00195 #endif /* GC_PROFILE */
00196 
00197 extern void extend_enc_dec_as_nec(void *,void *);
00198 extern void free_unused_strings();
00199 extern void mark_nonheap_strings(CTXTdecl);
00200 
00201 /*=========================================================================*/
00202 
00203 /* to choose between copying or sliding collector:
00204    its value is determined based on the the value of pflags[GARBAGE_COLLECT] */
00205 static xsbBool slide;
00206 
00207 #ifdef GC
00208 /* measuring fragmentation without collection - it also sets slide = 0 */
00209 static const int fragmentation_only = 0;
00210 #endif
00211                       
00212 /* choose to do early reset or not */
00213 /* #define EARLY_RESET 1 */
00214 
00215 
00216 /* expresses how often early reset of a trailed heap cell occurs */
00217 static int heap_early_reset;
00218 
00219 /* expresses how often early reset of a trailed local stack cell occurs */
00220 static int ls_early_reset;
00221 
00222 
00223 /* ways to count gc and control the output during a gc */
00224 static int printnum = 0 ;
00225 
00226 #ifdef DEBUG_VERBOSE
00227 static int print_at = 0 ; /* at the print_at-th gc, the stacks are printed */
00228 static int print_after = 0 ; /* if non zero, print all after this numgc */
00229 static int print_anyway = 0 ;
00230 
00231 #define print_on_gc \
00232         ((print_at == num_gc) \
00233          || ((print_after > 0) && (print_after <= num_gc)) \
00234          || print_anyway)
00235 #else
00236 #define print_on_gc 0
00237 #endif
00238 
00239 /* Whether to garbage collect strings on this heap gc or not. */
00240 int gc_strings = FALSE;
00241 
00242 static long last_string_space_size = 10000;
00243 static long last_assert_space_size = 10000;
00244 #define AUTO_STRING_GC_NTH 10
00245 
00246 /******* When to GC string space? *************/
00247 int should_gc_strings() {
00248   static int till_forced_string_gc = 1;  /* string collect first time */
00249 
00250   /* every AUTO_STRING_GC_NTH time that heap gc is done, regardless */
00251   if (!(--till_forced_string_gc)) {
00252     till_forced_string_gc = AUTO_STRING_GC_NTH;
00253     //    printf("should_gc_strings: cycle\n");
00254     return TRUE;
00255   }
00256   /* if already requested by someone else, do it. */
00257   if (gc_strings) {
00258     till_forced_string_gc = AUTO_STRING_GC_NTH;
00259     //    printf("should_gc_strings: requested\n");
00260     return TRUE;
00261   }
00262   /* if string_space has doubled, but assert space hasn't, since last string gc */
00263   if ((pspacesize[STRING_SPACE] > 2*last_string_space_size) &&
00264       (pspacesize[ASSERT_SPACE] < 2*last_assert_space_size)) {
00265     till_forced_string_gc = AUTO_STRING_GC_NTH;
00266     //    printf("should_gc_strings: strings grew\n");
00267     return TRUE;
00268   }
00269   /* if assert space has shrunk alot */
00270   if (pspacesize[ASSERT_SPACE] < last_assert_space_size/4 ||
00271       (last_assert_space_size - pspacesize[ASSERT_SPACE]) > 1000000) {
00272     till_forced_string_gc = AUTO_STRING_GC_NTH;
00273     //    printf("should_gc_strings: assert shrunk\n");
00274     return TRUE;
00275   }
00276   return FALSE;
00277 }
00278 
00279 
00280 /* if SAFE_GC is defined, some more checks are made after gargage collection */
00281 /* #define SAFE_GC */
00282 /* #define DEBUG_ASSERTIONS */
00283 
00284 /* if VERBOSE_GC is defined, garbage collection prints its statistics */
00285 /* #define VERBOSE_GC */
00286 
00287 
00288 /*---------------------------------------------------------------------------*/
00289 /* global variables for top and bottom of some areas + macro to compute them */
00290 /*---------------------------------------------------------------------------*/
00291 
00292 static CPtr heap_bot,heap_top,
00293   ls_bot,ls_top,
00294   tr_bot,tr_top,
00295   cp_bot,cp_top,
00296   compl_top,compl_bot;
00297 static unsigned long heap_marks_size;
00298 
00299 
00300 #define stack_boundaries \
00301   heap_top = hreg; \
00302   ls_top = top_of_localstk - 256;  /* extra space for environment above top */ \
00303   if (ls_top < heap_top) xsb_exit("Heap and local stack are clobbered"); \
00304   heap_bot = (CPtr)glstack.low ; \
00305   ls_bot = (CPtr)glstack.high - 1 ; \
00306   tr_top = (CPtr)(top_of_trail) /*- 1*/ ; \
00307   tr_bot = (CPtr)tcpstack.low ; \
00308   cp_bot = (CPtr)tcpstack.high - 1 ; \
00309   cp_top = top_of_cpstack ; \
00310   compl_top = (CPtr)complstack.low ; /* NOT top_of_complstk !!! */\
00311   compl_bot = (CPtr)complstack.high ;
00312 
00313 #define points_into_heap(p)  ((heap_bot <= p) && (p < heap_top))
00314 #define points_into_ls(p)    ((ls_top <= p) && (p <= ls_bot))
00315 #define points_into_cp(p)    ((cp_top <= p) && (p <= cp_bot))
00316 #define points_into_tr(p)    ((tr_bot <= p) && (p <= tr_top))
00317 #define points_into_compl(p) ((compl_top <= p) && (p <= compl_bot))
00318 
00319 /*======================================================================*/
00320 /* global variables used for statistics.                                */
00321 /*======================================================================*/
00322 
00323 #ifndef MULTI_THREAD
00324 static double total_time_gc = 0 ;
00325 static unsigned long total_collected = 0 ;
00326 static int num_gc = 0 ;
00327 #endif
00328 
00329 /*----------------------------------------------------------------------*/
00330 /* marker bits in different areas.                                      */
00331 /*----------------------------------------------------------------------*/
00332 
00333 static char *heap_marks  = NULL ;
00334 static char *ls_marks    = NULL ;
00335 static char *tr_marks    = NULL ;
00336 static char *cp_marks    = NULL ;
00337 
00338 #define INDIRECTION_SLIDE
00339 #ifdef INDIRECTION_SLIDE
00340 static CPtr *slide_buf= NULL;
00341 static unsigned long slide_top = 0;
00342 static int slide_buffering = 0;
00343 static unsigned long slide_buf_size = 0;
00344 #endif
00345 
00346 #define MARKED    1
00347 #define TRAIL_PRE 2
00348 #define CHAIN_BIT 4                            
00349 
00350 /* in the absence of serious bugs, the test is an invariant of the WAM */
00351 #ifdef DEBUG_ASSERTIONS
00352 #define testreturnit(retp)   if (points_into_heap(retp)) return(retp)
00353 #else
00354 #define testreturnit(retp)   return(retp)
00355 #endif
00356 
00357 /*=========================================================================*/
00358 /* GC-specific includes */
00359 #include "gc_profile.h"
00360 #include "gc_mark.h"
00361 #include "gc_print.h"
00362 #include "gc_slide.h"
00363 #include "gc_copy.h"
00364 /*=========================================================================*/
00365 
00366 
00367 /*==========================================================================
00368         new_size = new size of heap + environmentstack
00369         arity = number of argument registers in use at moment of call
00370 
00371         assumption: the argument registers in use are
00372                         reg+1 up to reg+arity included
00373 
00374         if you call glstack_realloc with new_size == the current size,
00375                 you will get a reallocated area !
00376 
00377         Re-allocate the space for the Global and Local Stacks' data area
00378         to "new_size" K-byte blocks.
00379 
00380 
00381         Optimizations:
00382                 if the heap hasn't been moved, then there is no need to change:
00383                         o pointers INTO the heap;
00384                         o pointers IN the heap (because there shouldn't be
00385                                 any pointing into the local stack).
00386 */
00387 /*----------------------------------------------------------------------*/
00388 
00389 xsbBool glstack_realloc(CTXTdeclc int new_size, int arity)
00390 {
00391   CPtr   new_heap_bot ;       /* bottom of new Global Stack area */
00392   CPtr   new_ls_bot ;         /* bottom of new Local Stack area */
00393 
00394   long   heap_offset ;        /* offsets between the old and new */
00395   long   local_offset ;       /* stack bottoms, measured in Cells */
00396 
00397   CPtr   *cell_ptr ;
00398   Cell   cell_val ;
00399 
00400   size_t new_size_in_bytes, new_size_in_cells ; /* what a mess ! */
00401   double   expandtime ;
00402 
00403   if (new_size <= glstack.size) return 0;
00404 
00405   SYS_MUTEX_LOCK( MUTEX_STACKS ) ;
00406 
00407   xsb_dbgmsg((LOG_REALLOC, 
00408              "Reallocating the Heap and Local Stack data area"));
00409 #ifdef DEBUG_VERBOSE
00410   if (LOG_REALLOC <= cur_log_level) {
00411     if (glstack.size == glstack.init_size) {
00412       xsb_dbgmsg((LOG_REALLOC,"\tBottom:\t\t%p\t\tInitial Size: %ldK",
00413                  glstack.low, glstack.size));
00414       xsb_dbgmsg((LOG_REALLOC,"\tTop:\t\t%p", glstack.high));
00415     }
00416   }
00417 #endif
00418 
00419   expandtime = cpu_time();
00420 
00421   new_size_in_bytes = new_size*K ;
00422   new_size_in_cells = new_size_in_bytes/sizeof(Cell) ;
00423                 /* and let's hope K stays divisible by sizeof(Cell) */
00424 
00425   stack_boundaries ;
00426 
00427   /* Expand the data area and push the Local Stack to the high end. */
00428 
00429   new_heap_bot = (CPtr)realloc(heap_bot, new_size_in_bytes);
00430   if (new_heap_bot == NULL) {
00431     if (2*glstack.size == new_size) { /* if trying to double, try backing off, may not help */
00432       int increment = new_size;
00433       while (new_heap_bot == NULL && increment > 40) {
00434         increment = increment/2;
00435         new_size = glstack.size + increment;
00436         new_size_in_bytes = new_size*K ;
00437         new_size_in_cells = new_size_in_bytes/sizeof(Cell) ;
00438         new_heap_bot = (CPtr)realloc(heap_bot, new_size_in_bytes);
00439       }
00440       if (new_heap_bot == NULL) {
00441         xsb_mesg("Not enough core to resize the Heap and Local Stack!");
00442         SYS_MUTEX_UNLOCK( MUTEX_STACKS ) ;
00443         return 1; /* return an error output -- will be picked up later */
00444       }
00445     } else {
00446       xsb_mesg("Not enough core to resize the Heap and Local Stack!");
00447       SYS_MUTEX_UNLOCK( MUTEX_STACKS ) ;
00448       return 1; /* return an error output -- will be picked up later */
00449     }
00450   }
00451   heap_offset = new_heap_bot - heap_bot ;
00452   new_ls_bot = new_heap_bot + new_size_in_cells - 1 ;
00453   local_offset = new_ls_bot - ls_bot ;
00454 
00455 #if defined(GENERAL_TAGGING)
00456   //  printf("glstack expand %p %p\n",(void *)new_heap_bot,(void *)new_ls_bot+1);
00457   extend_enc_dec_as_nec(new_heap_bot,new_ls_bot+1);
00458 #endif
00459 
00460   memmove(ls_top + local_offset,             /* move to */
00461           ls_top + heap_offset,              /* move from */
00462           (ls_bot - ls_top + 1)*sizeof(Cell) );      /* number of bytes */
00463 
00464   /* Update the Heap links */
00465   for (cell_ptr = (CPtr *)(heap_top + heap_offset);
00466        cell_ptr-- > (CPtr *)new_heap_bot;
00467       )
00468   { reallocate_heap_or_ls_pointer(cell_ptr) ; }
00469 
00470   /* Update the pointers in the Local Stack */
00471   for (cell_ptr = (CPtr *)(ls_top + local_offset);
00472        cell_ptr <= (CPtr *)new_ls_bot;
00473        cell_ptr++)
00474   { reallocate_heap_or_ls_pointer(cell_ptr) ; }
00475 
00476   /* Update the trailed variable pointers */
00477   for (cell_ptr = (CPtr *)top_of_trail - 1;
00478        cell_ptr > (CPtr *)tcpstack.low;
00479        cell_ptr = cell_ptr - 2)
00480   { /* first the value */
00481     reallocate_heap_or_ls_pointer(cell_ptr);
00482     /* now the address */
00483     cell_ptr-- ;
00484     cell_val = (Cell)*cell_ptr ;
00485 #ifdef PRE_IMAGE_TRAIL
00486     if ((unsigned long) cell_val & PRE_IMAGE_MARK) {
00487       /* remove tag */
00488       cell_val = (Cell) ((Cell) cell_val & ~PRE_IMAGE_MARK);
00489       /* realloc and tag */
00490       realloc_ref_pre_image(cell_ptr,(CPtr)cell_val) ;
00491       cell_ptr--;
00492       /* realoc pre-image */
00493       reallocate_heap_or_ls_pointer(cell_ptr);
00494     } else
00495 #endif
00496       realloc_ref(cell_ptr,(CPtr)cell_val) ;
00497   }
00498 
00499   /* Update the CP Stack pointers */
00500   for (cell_ptr = (CPtr *)top_of_cpstack;
00501        cell_ptr < (CPtr *)tcpstack.high;
00502        cell_ptr++)
00503   { reallocate_heap_or_ls_pointer(cell_ptr) ; }
00504 
00505   /* Update the argument registers */
00506   while (arity)
00507   { cell_ptr = (CPtr *)(reg+arity) ;
00508     reallocate_heap_or_ls_pointer(cell_ptr) ;
00509     arity-- ;  
00510   }
00511 
00512   /* Update the attributed variables interrupt list --lfcastro */
00513   { 
00514     int size = int_val(cell(interrupt_reg));
00515     int i;
00516     for (i=0; i<size; i++) {
00517       reallocate_heap_or_ls_pointer(((CPtr *)&(attv_interrupts[i][0])));
00518       reallocate_heap_or_ls_pointer(((CPtr *)&(attv_interrupts[i][1])));
00519     }
00520   }
00521 
00522   /* Update the system variables */
00523   glstack.low = (byte *)new_heap_bot ;
00524   glstack.high = (byte *)(new_ls_bot + 1) ;
00525   glstack.size = new_size ;
00526 
00527   hreg = (CPtr)hreg + heap_offset ;
00528   hbreg = (CPtr)hbreg + heap_offset ;
00529   hfreg = (CPtr)hfreg + heap_offset ;
00530   ereg = (CPtr)ereg + local_offset ;
00531   ebreg = (CPtr)ebreg + local_offset ;
00532   efreg = (CPtr)efreg + local_offset ;
00533 
00534   if (islist(delayreg))
00535     delayreg = (CPtr)makelist(clref_val(delayreg) + heap_offset);
00536 
00537   expandtime = cpu_time() - expandtime;
00538 
00539   xsb_dbgmsg((LOG_REALLOC,"\tNew Bottom:\t%p\t\tNew Size: %ldK",
00540              glstack.low, glstack.size));
00541   xsb_dbgmsg((LOG_REALLOC,"\tNew Top:\t%p", glstack.high));
00542   xsb_dbgmsg((LOG_REALLOC,
00543              "Heap/Local Stack data area expansion - finished in %lf secs\n",
00544              expandtime));
00545 
00546   SYS_MUTEX_UNLOCK( MUTEX_STACKS ) ;
00547 
00548   return 0;
00549 } /* glstack_realloc */
00550 
00551 
00552 /*======================================================================*/
00553 /* The main routine that performs garbage collection.                   */
00554 /*======================================================================*/
00555 
00556 int gc_heap(CTXTdeclc int arity, int ifStringGC)
00557 {
00558 #ifdef GC
00559   CPtr p;
00560   double  begin_marktime, end_marktime,
00561     end_slidetime, end_copy_time,
00562     begin_stringtime, end_stringtime;
00563   int  marked = 0, marked_dregs = 0, i;
00564   int  start_heap_size;
00565   DECL_GC_PROFILE;
00566 
00567   SYS_MUTEX_LOCK( MUTEX_STACKS ) ;
00568   
00569   INIT_GC_PROFILE;
00570   if (pflags[GARBAGE_COLLECT] != NO_GC) {
00571     num_gc++ ;
00572     GC_PROFILE_PRE_REPORT;
00573     slide = (pflags[GARBAGE_COLLECT] == SLIDING_GC) | 
00574       (pflags[GARBAGE_COLLECT] == INDIRECTION_SLIDE_GC);
00575     
00576     if (fragmentation_only) 
00577       slide = FALSE;
00578     heap_early_reset = ls_early_reset = 0;
00579     
00580     GC_PROFILE_START_SUMMARY;
00581     
00582     begin_marktime = cpu_time();
00583     start_heap_size = hreg+1-(CPtr)glstack.low;
00584     
00585     /* make sure the top choice point heap pointer 
00586        that might not point into heap, does */
00587     if (hreg == cp_hreg(breg)) {
00588       *hreg = makeint(666) ;
00589       hreg++ ;
00590     }
00591 #ifdef SLG_GC
00592     /* same for the freeze heap pointer */
00593     if (hfreg == hreg && hreg == cp_hreg(bfreg)) {
00594       *hreg = makeint(66600);
00595       hreg++;
00596     }
00597 #endif
00598     
00599     /* copy the aregs to the top of the heap - only if sliding */
00600     /* just hope there is enough space */
00601     /* this happens best before the stack_boundaries are computed */
00602     if (slide) {
00603       if (delayreg != NULL) {
00604         arity++;
00605         reg[arity] = (Cell)delayreg;
00606       }
00607       for (i = 1; i <= arity; i++) {
00608         *hreg = reg[i];
00609         hreg++;
00610       }
00611     }
00612     
00613 #ifdef SLG_GC
00614     /* in SLGWAM, copy hfreg to the heap */
00615     if (slide) {
00616       *hreg = (unsigned long) hfreg;
00617       hreg++;
00618     }
00619 #endif
00620 
00621     gc_strings = ifStringGC; /* default */
00622     gc_strings = should_gc_strings();
00623     marked = mark_heap(CTXTc arity, &marked_dregs);
00624     
00625     end_marktime = cpu_time();
00626     
00627     if (fragmentation_only) {
00628       /* fragmentation is expressed as ratio not-marked/total heap in use
00629          this is internal fragmentation only.  we print marked and total,
00630          so that postprocessing can do what it wants with this info. */
00631       xsb_dbgmsg((LOG_GC, "marked_used_missed(%d,%d,%d,%d).",
00632                  marked,hreg+1-(CPtr)glstack.low,
00633                  heap_early_reset,ls_early_reset));
00634 
00635     free_marks:
00636 
00637 #ifdef PRE_IMAGE_TRAIL
00638       /* re-tag pre image cells in trail */
00639       for (p = tr_bot; p <= tr_top ; p++ ) {
00640         if (tr_pre_marked(p-tr_bot)) {
00641           *p = *p | PRE_IMAGE_MARK;
00642           tr_clear_pre_mark(p-tr_bot);
00643         }
00644       }
00645 #endif
00646 
00647       /* get rid of the marking areas - if they exist */
00648       if (heap_marks)  { mem_dealloc((heap_marks-1),heap_marks_size,GC_SPACE); heap_marks = NULL; }
00649       if (tr_marks)    { mem_dealloc(tr_marks,tr_top-tr_bot+1,GC_SPACE); tr_marks = NULL; }
00650       if (ls_marks)    { mem_dealloc(ls_marks,ls_bot - ls_top + 1,GC_SPACE); ls_marks = NULL; }
00651       if (cp_marks)    { mem_dealloc(cp_marks,cp_bot - cp_top + 1,GC_SPACE); cp_marks = NULL; }
00652       if (slide_buf)   { mem_dealloc(slide_buf,(slide_buf_size+1)*sizeof(CPtr),GC_SPACE); slide_buf = NULL; }
00653       goto end;
00654     }
00655     
00656     GC_PROFILE_MARK_SUMMARY;
00657     
00658     /* An attempt to add some gc/expansion policy;
00659        ideally this should be user-controlled */
00660 #if (! defined(GC_TEST))
00661     if (marked > ((hreg+1-(CPtr)glstack.low)*mark_threshold))
00662       {
00663         GC_PROFILE_QUIT_MSG;
00664         if (slide)
00665           hreg -= arity;
00666         total_time_gc += (double) 
00667           (end_marktime-begin_marktime);
00668         goto free_marks; /* clean-up temp areas and get out of here... */
00669       }
00670 #endif
00671     
00672     total_collected += (start_heap_size - marked);
00673 
00674     if (slide)
00675       {
00676         GC_PROFILE_SLIDE_START_TIME;
00677 
00678         hreg = slide_heap(marked) ;
00679 
00680         if (hreg != (heap_bot+marked))
00681           xsb_dbgmsg((LOG_GC, "heap sliding gc - inconsistent hreg"));
00682 #ifdef SLG_GC
00683         /* copy hfreg back from the heap */
00684         hreg--;
00685         hfreg = (unsigned long*) *hreg;
00686 #endif
00687 
00688         /* copy the aregs from the top of the heap back */
00689         hreg -= arity;
00690         hbreg = cp_hreg(breg);
00691         
00692         p = hreg;
00693         
00694         for (i = 1; i <= arity; i++)
00695           reg[i] = *p++ ;
00696         if (delayreg != NULL)
00697           delayreg = (CPtr)reg[arity--];
00698 
00699         end_slidetime = cpu_time();
00700         
00701         total_time_gc += (double) 
00702           (end_slidetime - begin_marktime);
00703         
00704         GC_PROFILE_SLIDE_FINAL_SUMMARY;
00705       }
00706     else
00707       { /* else we call the copying collector a la Cheney */
00708         CPtr begin_new_heap, end_new_heap;
00709         
00710         GC_PROFILE_COPY_START_TIME;
00711         
00712         begin_new_heap = (CPtr)mem_alloc(marked*sizeof(Cell),GC_SPACE);
00713         if (begin_new_heap == NULL)
00714           xsb_exit("copying garbage collection could not allocate new heap");
00715         end_new_heap = begin_new_heap+marked;
00716 
00717         hreg = copy_heap(CTXTc marked,begin_new_heap,end_new_heap,arity);
00718 
00719         mem_dealloc(begin_new_heap,marked*sizeof(Cell),GC_SPACE);
00720         adapt_hfreg_from_choicepoints(CTXTc hreg);
00721         hbreg = cp_hreg(breg);
00722 
00723 #ifdef SLG_GC
00724         hfreg = hreg;
00725 #endif
00726         end_copy_time = cpu_time();
00727         
00728         total_time_gc += (double) 
00729           (end_copy_time - begin_marktime);
00730         
00731         GC_PROFILE_COPY_FINAL_SUMMARY;
00732       }
00733     
00734     if (print_on_gc) print_all_stacks(CTXTc arity);
00735     
00736     /* get rid of the marking areas - if they exist */
00737     if (heap_marks)  { 
00738       check_zero(heap_marks,(heap_top - heap_bot),"heap") ;
00739       mem_dealloc((heap_marks-1),heap_marks_size,GC_SPACE) ; /* see its calloc */
00740       heap_marks = NULL ;
00741     }
00742     if (tr_marks)    { 
00743       check_zero(tr_marks,(tr_top - tr_bot + 1),"tr") ;
00744       mem_dealloc(tr_marks,tr_top-tr_bot+1,GC_SPACE) ;
00745       tr_marks = NULL ;
00746     }
00747     if (ls_marks)    { 
00748       check_zero(ls_marks,(ls_bot - ls_top + 1),"ls") ;
00749       mem_dealloc(ls_marks,ls_bot - ls_top + 1,GC_SPACE) ;
00750       ls_marks = NULL ;
00751     }
00752     if (cp_marks)    {  
00753       check_zero(cp_marks,(cp_bot - cp_top + 1),"cp") ;
00754       mem_dealloc(cp_marks,cp_bot - cp_top + 1,GC_SPACE) ;
00755       cp_marks = NULL ;
00756     }
00757     if (slide_buf)   { 
00758       mem_dealloc(slide_buf,(slide_buf_size+1)*sizeof(CPtr),GC_SPACE); 
00759       slide_buf = NULL; 
00760     }
00761 #ifdef SAFE_GC
00762     p = hreg;
00763     while (p < heap_top)
00764       *p++ = 0;
00765 #endif
00766     
00767   } /* if (pflags[GARBAGE_COLLECT]) */
00768 #else
00769   /* for no-GC, there is no gc, but stack expansion can be done */
00770 #endif
00771   
00772 #ifdef GC
00773  end:
00774   
00775   /*************** GC STRING-TABLE (already marked from heap) *******************/
00776 #ifndef NO_STRING_GC
00777 #ifdef MULTI_THREAD
00778   if (flags[NUM_THREADS] == 1) {
00779 #endif
00780     if (gc_strings) {
00781       //      long beg_string_space_size = pspacesize[STRING_SPACE];
00782       begin_stringtime = cpu_time();
00783       mark_nonheap_strings(CTXT);
00784       free_unused_strings();
00785       //      printf("String GC reclaimed: %d bytes\n",beg_string_space_size - pspacesize[STRING_SPACE]);
00786       last_string_space_size = pspacesize[STRING_SPACE];
00787       last_assert_space_size = pspacesize[ASSERT_SPACE];
00788       gc_strings = FALSE;
00789       end_stringtime = cpu_time();
00790       total_time_gc += end_stringtime - begin_stringtime;
00791     }
00792 #ifdef MULTI_THREAD
00793   }
00794 #endif
00795 #endif /* ndef NO_STRING_GC */
00796 
00797   GC_PROFILE_POST_REPORT;
00798   
00799 #endif /* GC */
00800 
00801   SYS_MUTEX_UNLOCK( MUTEX_STACKS ) ;
00802 
00803   return(TRUE);
00804 
00805 } /* gc_heap */
00806 
00807 /*--------------------------------------------------------------------------*/
00808 
00809 xsbBool glstack_ensure_space(CTXTdeclc int extra, int arity) {
00810   if (pflags[GARBAGE_COLLECT] != NO_GC && arity < 255) {
00811     gc_heap(CTXTc arity,FALSE);
00812   }
00813   if ((pb)top_of_localstk < (pb)top_of_heap + OVERFLOW_MARGIN + extra) {
00814     return glstack_realloc(CTXTc resize_stack(glstack.size,extra+OVERFLOW_MARGIN),arity);
00815   }
00816   else return FALSE;
00817 }
00818 
00819 /*--------------------------------------------------------------------------*/
00820 
00821 

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