Back to index

lightning-sunbird  0.9+nobinonly
gc_priv.h
Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991-1994 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 use or copy this program
00009  * for any purpose,  provided the above notices are retained on all copies.
00010  * Permission to modify the code and to distribute modified code is granted,
00011  * provided the above notices are retained, and a notice that the code was
00012  * modified is included with the above copyright notice.
00013  */
00014 /* Boehm, February 16, 1996 2:30 pm PST */
00015  
00016 
00017 # ifndef GC_PRIVATE_H
00018 # define GC_PRIVATE_H
00019 
00020 #if defined(mips) && defined(SYSTYPE_BSD) && defined(sony_news)
00021     /* sony RISC NEWS, NEWSOS 4 */
00022 #   define BSD_TIME
00023 /*    typedef long ptrdiff_t;   -- necessary on some really old systems      */
00024 #endif
00025 
00026 #if defined(mips) && defined(SYSTYPE_BSD43)
00027     /* MIPS RISCOS 4 */
00028 #   define BSD_TIME
00029 #endif
00030 
00031 #ifdef BSD_TIME
00032 #   include <sys/types.h>
00033 #   include <sys/time.h>
00034 #   include <sys/resource.h>
00035 #endif /* BSD_TIME */
00036 
00037 # ifndef GC_H
00038 #   include "gc.h"
00039 # endif
00040 
00041 typedef GC_word word;
00042 typedef GC_signed_word signed_word;
00043 
00044 # ifndef CONFIG_H
00045 #   include "gcconfig.h"
00046 # endif
00047 
00048 # ifndef HEADERS_H
00049 #   include "gc_hdrs.h"
00050 # endif
00051 
00052 typedef int GC_bool;
00053 # define TRUE 1
00054 # define FALSE 0
00055 
00056 typedef char * ptr_t;       /* A generic pointer to which we can add  */
00057                      /* byte displacements.                           */
00058                      /* Preferably identical to caddr_t, if it        */
00059                      /* exists.                                */
00060                      
00061 #if defined(__STDC__)
00062 #   include <stdlib.h>
00063 #   if !(defined( sony_news ) )
00064 #       include <stddef.h>
00065 #   endif
00066 #   define VOLATILE volatile
00067 #   define CONST const
00068 #else
00069 #   ifdef MSWIN32
00070 #      include <stdlib.h>
00071 #   endif
00072 #   define VOLATILE
00073 #   define CONST
00074 #endif
00075 
00076 #ifdef AMIGA
00077 #   define GC_FAR __far
00078 #else
00079 #   define GC_FAR
00080 #endif
00081 
00082 /*********************************/
00083 /*                               */
00084 /* Definitions for conservative  */
00085 /* collector                     */
00086 /*                               */
00087 /*********************************/
00088 
00089 /*********************************/
00090 /*                               */
00091 /* Easily changeable parameters  */
00092 /*                               */
00093 /*********************************/
00094 
00095 #define STUBBORN_ALLOC      /* Define stubborn allocation primitives  */
00096 #if defined(SRC_M3) || defined(SMALL_CONFIG)
00097 # undef STUBBORN_ALLOC
00098 #endif
00099 
00100 
00101 /* #define ALL_INTERIOR_POINTERS */
00102                   /* Forces all pointers into the interior of an      */
00103                   /* object to be considered valid.  Also causes the  */
00104                   /* sizes of all objects to be inflated by at least  */
00105                   /* one byte.  This should suffice to guarantee      */
00106                   /* that in the presence of a compiler that does     */
00107                   /* not perform garbage-collector-unsafe             */
00108                   /* optimizations, all portable, strictly ANSI       */
00109                   /* conforming C programs should be safely usable    */
00110                   /* with malloc replaced by GC_malloc and free       */
00111                   /* calls removed.  There are several disadvantages: */
00112                   /* 1. There are probably no interesting, portable,  */
00113                   /*    strictly ANSI     conforming C programs.             */
00114                   /* 2. This option makes it hard for the collector   */
00115                   /*    to allocate space that is not ``pointed to''  */
00116                   /*    by integers, etc.  Under SunOS 4.X with a     */
00117                   /*    statically linked libc, we empiricaly         */
00118                   /*    observed that it would be difficult to        */
00119                   /*   allocate individual objects larger than 100K.  */
00120                   /*          Even if only smaller objects are allocated,    */
00121                   /*    more swap space is likely to be needed.       */
00122                   /*    Fortunately, much of this will never be       */
00123                   /*    touched.                               */
00124                   /* If you can easily avoid using this option, do.   */
00125                   /* If not, try to keep individual objects small.    */
00126                   
00127 #define PRINTSTATS  /* Print garbage collection statistics            */
00128                   /* For less verbose output, undefine in reclaim.c   */
00129 
00130 #define PRINTTIMES  /* Print the amount of time consumed by each garbage   */
00131                   /* collection.                                         */
00132 
00133 #define PRINTBLOCKS /* Print object sizes associated with heap blocks,     */
00134                   /* whether the objects are atomic or composite, and    */
00135                   /* whether or not the block was found to be empty      */
00136                   /* during the reclaim phase.  Typically generates       */
00137                   /* about one screenful per garbage collection.         */
00138 #undef PRINTBLOCKS
00139 
00140 #ifdef SILENT
00141 #  ifdef PRINTSTATS
00142 #    undef PRINTSTATS
00143 #  endif
00144 #  ifdef PRINTTIMES
00145 #    undef PRINTTIMES
00146 #  endif
00147 #  ifdef PRINTNBLOCKS
00148 #    undef PRINTNBLOCKS
00149 #  endif
00150 #endif
00151 
00152 #if defined(PRINTSTATS) && !defined(GATHERSTATS)
00153 #   define GATHERSTATS
00154 #endif
00155 
00156 #ifdef FINALIZE_ON_DEMAND
00157 #   define GC_INVOKE_FINALIZERS()
00158 #else
00159 #   define GC_INVOKE_FINALIZERS() (void)GC_invoke_finalizers()
00160 #endif
00161 
00162 #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */
00163                   /* free lists are actually maintained.  This applies  */
00164                   /* only to the top level routines in misc.c, not to   */
00165                   /* user generated code that calls GC_allocobj and     */
00166                   /* GC_allocaobj directly.                             */
00167                   /* Slows down average programs slightly.  May however */
00168                   /* substantially reduce fragmentation if allocation   */
00169                   /* request sizes are widely scattered.                */
00170                   /* May save significant amounts of space for obj_map  */
00171                   /* entries.                                           */
00172 
00173 #ifndef OLD_BLOCK_ALLOC
00174    /* Macros controlling large block allocation strategy.      */
00175 #  define EXACT_FIRST       /* Make a complete pass through the large object */
00176                      /* free list before splitting a block             */
00177 #  define PRESERVE_LAST /* Do not divide last allocated heap segment   */
00178                      /* unless we would otherwise need to expand the   */
00179                      /* heap.                                   */
00180 #endif
00181 
00182 /* ALIGN_DOUBLE requires MERGE_SIZES at present. */
00183 # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES)
00184 #   define MERGE_SIZES
00185 # endif
00186 
00187 #if defined(ALL_INTERIOR_POINTERS) && !defined(DONT_ADD_BYTE_AT_END)
00188 # define ADD_BYTE_AT_END
00189 #endif
00190 
00191 
00192 # ifndef LARGE_CONFIG
00193 #   define MINHINCR 16      /* Minimum heap increment, in blocks of HBLKSIZE  */
00194                      /* Must be multiple of largest page size.   */
00195 #   define MAXHINCR 512     /* Maximum heap increment, in blocks              */
00196 # else
00197 #   define MINHINCR 64
00198 #   define MAXHINCR 4096
00199 # endif
00200 
00201 # define TIME_LIMIT 50         /* We try to keep pause times from exceeding   */
00202                         /* this by much. In milliseconds.              */
00203 
00204 # define BL_LIMIT GC_black_list_spacing
00205                         /* If we need a block of N bytes, and we have */
00206                         /* a block of N + BL_LIMIT bytes available,    */
00207                         /* and N > BL_LIMIT,                           */
00208                         /* but all possible positions in it are        */
00209                         /* blacklisted, we just use it anyway (and     */
00210                         /* print a warning, if warnings are enabled). */
00211                         /* This risks subsequently leaking the block   */
00212                         /* due to a false reference.  But not using    */
00213                         /* the block risks unreasonable immediate      */
00214                         /* heap growth.                         */
00215 
00216 /*********************************/
00217 /*                               */
00218 /* Stack saving for debugging       */
00219 /*                               */
00220 /*********************************/
00221 
00222 #ifdef SAVE_CALL_CHAIN
00223 
00224 /*
00225  * Number of frames and arguments to save in objects allocated by
00226  * debugging allocator.
00227  */
00228 #   define NFRAMES 2    /* Number of frames to save. Even for         */
00229                         /* alignment reasons.                         */
00230 #   define NARGS 0      /* Mumber of arguments to save for each call. */
00231 
00232 #   define NEED_CALLINFO
00233 
00234 /* Fill in the pc and argument information for up to NFRAMES of my    */
00235 /* callers.  Ignore my frame and my callers frame.                    */
00236 void GC_save_callers (/* struct callinfo info[NFRAMES] */);
00237 
00238 void GC_print_callers (/* struct callinfo info[NFRAMES] */);
00239 
00240 #else
00241 
00242 # ifdef GC_ADD_CALLER
00243 #   define NFRAMES 1
00244 #   define NARGS 0
00245 #   define NEED_CALLINFO
00246 # endif
00247 
00248 #endif
00249 
00250 #ifdef NEED_CALLINFO
00251     struct callinfo {
00252        word ci_pc;
00253 #      if NARGS > 0
00254            word ci_arg[NARGS];     /* bit-wise complement to avoid retention */
00255 #      endif
00256 #      if defined(ALIGN_DOUBLE) && (NFRAMES * (NARGS + 1)) % 2 == 1
00257            /* Likely alignment problem. */
00258            word ci_dummy;
00259 #      endif
00260     };
00261 #endif
00262 
00263 
00264 /*********************************/
00265 /*                               */
00266 /* OS interface routines     */
00267 /*                               */
00268 /*********************************/
00269 
00270 #ifdef BSD_TIME
00271 #   undef CLOCK_TYPE
00272 #   undef GET_TIME
00273 #   undef MS_TIME_DIFF
00274 #   define CLOCK_TYPE struct timeval
00275 #   define GET_TIME(x) { struct rusage rusage; \
00276                       getrusage (RUSAGE_SELF,  &rusage); \
00277                       x = rusage.ru_utime; }
00278 #   define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \
00279                                + (double) (a.tv_usec - b.tv_usec) / 1000.0)
00280 #else /* !BSD_TIME */
00281 #   include <time.h>
00282 #   if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)
00283       clock_t clock();      /* Not in time.h, where it belongs */
00284 #   endif
00285 #   if defined(FREEBSD) && !defined(CLOCKS_PER_SEC)
00286 #     include <machine/limits.h>
00287 #     define CLOCKS_PER_SEC CLK_TCK
00288 #   endif
00289 #   if !defined(CLOCKS_PER_SEC)
00290 #     define CLOCKS_PER_SEC 1000000
00291 /*
00292  * This is technically a bug in the implementation.  ANSI requires that
00293  * CLOCKS_PER_SEC be defined.  But at least under SunOS4.1.1, it isn't.
00294  * Also note that the combination of ANSI C and POSIX is incredibly gross
00295  * here. The type clock_t is used by both clock() and times().  But on
00296  * some machines these use different notions of a clock tick,  CLOCKS_PER_SEC
00297  * seems to apply only to clock.  Hence we use it here.  On many machines,
00298  * including SunOS, clock actually uses units of microseconds (which are
00299  * not really clock ticks).
00300  */
00301 #   endif
00302 #   define CLOCK_TYPE clock_t
00303 #   define GET_TIME(x) x = clock()
00304 #   define MS_TIME_DIFF(a,b) ((unsigned long) \
00305               (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))
00306 #endif /* !BSD_TIME */
00307 
00308 /* We use bzero and bcopy internally.  They may not be available.     */
00309 # if defined(SPARC) && defined(SUNOS4)
00310 #   define BCOPY_EXISTS
00311 # endif
00312 # if defined(M68K) && defined(AMIGA)
00313 #   define BCOPY_EXISTS
00314 # endif
00315 # if defined(M68K) && defined(NEXT)
00316 #   define BCOPY_EXISTS
00317 # endif
00318 # if defined(VAX)
00319 #   define BCOPY_EXISTS
00320 # endif
00321 # if defined(AMIGA)
00322 #   include <string.h>
00323 #   define BCOPY_EXISTS
00324 # endif
00325 # if defined(MACOS) && defined(POWERPC)
00326 #   include <MacMemory.h>
00327 #   define bcopy(x,y,n) BlockMoveData(x, y, n)
00328 #   define bzero(x,n) BlockZero(x, n)
00329 #   define BCOPY_EXISTS
00330 # endif
00331 
00332 # ifndef BCOPY_EXISTS
00333 #   include <string.h>
00334 #   define BCOPY(x,y,n) memcpy(y, x, (size_t)(n))
00335 #   define BZERO(x,n)  memset(x, 0, (size_t)(n))
00336 # else
00337 #   define BCOPY(x,y,n) bcopy((char *)(x),(char *)(y),(int)(n))
00338 #   define BZERO(x,n) bzero((char *)(x),(int)(n))
00339 # endif
00340 
00341 /* HBLKSIZE aligned allocation.  0 is taken to mean failure    */
00342 /* space is assumed to be cleared.                      */
00343 /* In the case os USE_MMAP, the argument must also be a        */
00344 /* physical page size.                                         */
00345 /* GET_MEM is currently not assumed to retrieve 0 filled space, */
00346 /* though we should perhaps take advantage of the case in which */
00347 /* does.                                                */
00348 # ifdef PCR
00349     char * real_malloc();
00350 #   define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
00351                               + GC_page_size-1)
00352 # else
00353 #   ifdef OS2
00354       void * os2_alloc(size_t bytes);
00355 #     define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \
00356                                 + GC_page_size) \
00357                                     + GC_page_size-1)
00358 #   else
00359 #     if defined(AMIGA) || defined(NEXT) || defined(DOS4GW)
00360 #       define GET_MEM(bytes) HBLKPTR((size_t) \
00361                                   calloc(1, (size_t)bytes + GC_page_size) \
00362                                       + GC_page_size-1)
00363 #     else
00364 #      ifdef MSWIN32
00365           extern ptr_t GC_win32_get_mem();
00366 #         define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
00367 #      else
00368 #        ifdef MACOS
00369 #          if defined(USE_TEMPORARY_MEMORY)
00370               extern Ptr GC_MacTemporaryNewPtr(size_t size,
00371                                            Boolean clearMemory);
00372 #               define GET_MEM(bytes) HBLKPTR( \
00373                   GC_MacTemporaryNewPtr(bytes + GC_page_size, false) \
00374                   + GC_page_size-1)
00375 #          else
00376 #                 define GET_MEM(bytes) HBLKPTR( \
00377                      NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
00378 #          endif
00379 #        else
00380               extern ptr_t GC_unix_get_mem();
00381 #             define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
00382 #        endif
00383 #      endif
00384 #     endif
00385 #   endif
00386 # endif
00387 
00388 /*
00389  * Mutual exclusion between allocator/collector routines.
00390  * Needed if there is more than one allocator thread.
00391  * FASTLOCK() is assumed to try to acquire the lock in a cheap and
00392  * dirty way that is acceptable for a few instructions, e.g. by
00393  * inhibiting preemption.  This is assumed to have succeeded only
00394  * if a subsequent call to FASTLOCK_SUCCEEDED() returns TRUE.
00395  * FASTUNLOCK() is called whether or not FASTLOCK_SUCCEEDED().
00396  * If signals cannot be tolerated with the FASTLOCK held, then
00397  * FASTLOCK should disable signals.  The code executed under
00398  * FASTLOCK is otherwise immune to interruption, provided it is
00399  * not restarted.
00400  * DCL_LOCK_STATE declares any local variables needed by LOCK and UNLOCK
00401  * and/or DISABLE_SIGNALS and ENABLE_SIGNALS and/or FASTLOCK.
00402  * (There is currently no equivalent for FASTLOCK.)
00403  */  
00404 # ifdef THREADS
00405 #  ifdef PCR_OBSOLETE       /* Faster, but broken with multiple lwp's */
00406 #    include  "th/PCR_Th.h"
00407 #    include  "th/PCR_ThCrSec.h"
00408      extern struct PCR_Th_MLRep GC_allocate_ml;
00409 #    define DCL_LOCK_STATE  PCR_sigset_t GC_old_sig_mask
00410 #    define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml) 
00411 #    define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)
00412 #    define FASTLOCK() PCR_ThCrSec_EnterSys()
00413      /* Here we cheat (a lot): */
00414 #        define FASTLOCK_SUCCEEDED() (*(int *)(&GC_allocate_ml) == 0)
00415               /* TRUE if nobody currently holds the lock */
00416 #    define FASTUNLOCK() PCR_ThCrSec_ExitSys()
00417 #  endif
00418 #  ifdef PCR
00419 #    include <base/PCR_Base.h>
00420 #    include <th/PCR_Th.h>
00421      extern PCR_Th_ML GC_allocate_ml;
00422 #    define DCL_LOCK_STATE \
00423         PCR_ERes GC_fastLockRes; PCR_sigset_t GC_old_sig_mask
00424 #    define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml)
00425 #    define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)
00426 #    define FASTLOCK() (GC_fastLockRes = PCR_Th_ML_Try(&GC_allocate_ml))
00427 #    define FASTLOCK_SUCCEEDED() (GC_fastLockRes == PCR_ERes_okay)
00428 #    define FASTUNLOCK()  {\
00429         if( FASTLOCK_SUCCEEDED() ) PCR_Th_ML_Release(&GC_allocate_ml); }
00430 #  endif
00431 #  ifdef SRC_M3
00432      extern word RT0u__inCritical;
00433 #    define LOCK() RT0u__inCritical++
00434 #    define UNLOCK() RT0u__inCritical--
00435 #  endif
00436 #  ifdef SOLARIS_THREADS
00437 #    include <thread.h>
00438 #    include <signal.h>
00439      extern mutex_t GC_allocate_ml;
00440 #    define LOCK() mutex_lock(&GC_allocate_ml);
00441 #    define UNLOCK() mutex_unlock(&GC_allocate_ml);
00442 #  endif
00443 #  ifdef LINUX_THREADS
00444 #error "DADDY?"
00445 #    include <pthread.h>
00446 #    ifdef __i386__
00447        inline static int GC_test_and_set(volatile unsigned int *addr) {
00448          int oldval;
00449          /* Note: the "xchg" instruction does not need a "lock" prefix */
00450          __asm__ __volatile__("xchgl %0, %1"
00451               : "=r"(oldval), "=m"(*(addr))
00452               : "0"(1), "m"(*(addr)));
00453          return oldval;
00454        }
00455 #    else
00456        -- > Need implementation of GC_test_and_set()
00457 #    endif
00458 #    define GC_clear(addr) (*(addr) = 0)
00459 
00460      extern volatile unsigned int GC_allocate_lock;
00461        /* This is not a mutex because mutexes that obey the (optional)     */
00462        /* POSIX scheduling rules are subject to convoys in high contention */
00463        /* applications.  This is basically a spin lock.            */
00464      extern pthread_t GC_lock_holder;
00465      extern void GC_lock(void);
00466        /* Allocation lock holder.  Only set if acquired by client through */
00467        /* GC_call_with_alloc_lock.                                */
00468 #    define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()
00469 #    define NO_THREAD (pthread_t)(-1)
00470 #    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
00471 #    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
00472 #    ifdef UNDEFINED
00473 #      define LOCK() pthread_mutex_lock(&GC_allocate_ml)
00474 #      define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
00475 #    else
00476 #      define LOCK() \
00477               { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
00478 #      define UNLOCK() \
00479               GC_clear(&GC_allocate_lock)
00480 #    endif
00481      extern GC_bool GC_collecting;
00482 #    define ENTER_GC() \
00483               { \
00484                   GC_collecting = 1; \
00485               }
00486 #    define EXIT_GC() GC_collecting = 0;
00487 #  endif /* LINUX_THREADS */
00488 #  if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
00489 #    include <pthread.h>
00490 #    include <mutex.h>
00491 
00492 #    if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
00493        || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
00494 #        define GC_test_and_set(addr, v) test_and_set(addr,v)
00495 #    else
00496 #       define GC_test_and_set(addr, v) __test_and_set(addr,v)
00497 #    endif
00498      extern unsigned long GC_allocate_lock;
00499        /* This is not a mutex because mutexes that obey the (optional)       */
00500        /* POSIX scheduling rules are subject to convoys in high contention   */
00501        /* applications.  This is basically a spin lock.               */
00502      extern pthread_t GC_lock_holder;
00503      extern void GC_lock(void);
00504        /* Allocation lock holder.  Only set if acquired by client through */
00505        /* GC_call_with_alloc_lock.                                */
00506 #    define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()
00507 #    define NO_THREAD (pthread_t)(-1)
00508 #    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
00509 #    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
00510 #    ifdef UNDEFINED
00511 #      define LOCK() pthread_mutex_lock(&GC_allocate_ml)
00512 #      define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
00513 #    else
00514 #      define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
00515 #       if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
00516           && defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700
00517 #          define UNLOCK() __lock_release(&GC_allocate_lock)
00518 #      else
00519            /* The function call in the following should prevent the   */
00520            /* compiler from moving assignments to below the UNLOCK.   */
00521            /* This is probably not necessary for ucode or gcc 2.8.    */
00522            /* It may be necessary for Ragnarok and future gcc         */
00523            /* versions.                                        */
00524 #           define UNLOCK() { GC_noop1(&GC_allocate_lock); \
00525                      *(volatile unsigned long *)(&GC_allocate_lock) = 0; }
00526 #      endif
00527 #    endif
00528      extern GC_bool GC_collecting;
00529 #    define ENTER_GC() \
00530               { \
00531                   GC_collecting = 1; \
00532               }
00533 #    define EXIT_GC() GC_collecting = 0;
00534 #  endif /* IRIX_THREADS || IRIX_JDK_THREADS */
00535 #  ifdef WIN32_THREADS
00536 #    include <windows.h>
00537      GC_API CRITICAL_SECTION GC_allocate_ml;
00538 #    define LOCK() EnterCriticalSection(&GC_allocate_ml);
00539 #    define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
00540 #  endif
00541 #  ifdef GENERIC_THREADS
00542 #    include "generic_threads.h"
00543 #    define LOCK() GC_generic_locker(GC_generic_mutex)
00544 #    define UNLOCK() GC_generic_unlocker(GC_generic_mutex)
00545 #    ifdef MACOS
00546 #      define FASTLOCK()
00547 #      define FASTLOCK_SUCCEEDED() TRUE
00548 #      define FASTUNLOCK()
00549 #    endif /* MACOS */
00550 #  endif /* GENERIC_THREADS */
00551 #  ifndef SET_LOCK_HOLDER
00552 #      define SET_LOCK_HOLDER()
00553 #      define UNSET_LOCK_HOLDER()
00554 #      define I_HOLD_LOCK() FALSE
00555               /* Used on platforms were locks can be reacquired,      */
00556               /* so it doesn't matter if we lie.               */
00557 #  endif
00558 # else
00559 #    define LOCK()
00560 #    define UNLOCK()
00561 # endif
00562 # ifndef SET_LOCK_HOLDER
00563 #   define SET_LOCK_HOLDER()
00564 #   define UNSET_LOCK_HOLDER()
00565 #   define I_HOLD_LOCK() FALSE
00566               /* Used on platforms were locks can be reacquired,      */
00567               /* so it doesn't matter if we lie.               */
00568 # endif
00569 # ifndef ENTER_GC
00570 #   define ENTER_GC()
00571 #   define EXIT_GC()
00572 # endif
00573 
00574 # ifndef DCL_LOCK_STATE
00575 #   define DCL_LOCK_STATE
00576 # endif
00577 # ifndef FASTLOCK
00578 #   define FASTLOCK() LOCK()
00579 #   define FASTLOCK_SUCCEEDED() TRUE
00580 #   define FASTUNLOCK() UNLOCK()
00581 # endif
00582 
00583 /* Delay any interrupts or signals that may abort this thread.  Data  */
00584 /* structures are in a consistent state outside this pair of calls.   */
00585 /* ANSI C allows both to be empty (though the standard isn't very     */
00586 /* clear on that point).  Standard malloc implementations are usually */
00587 /* neither interruptable nor thread-safe, and thus correspond to      */
00588 /* empty definitions.                                                 */
00589 # ifdef PCR
00590 #   define DISABLE_SIGNALS() \
00591                PCR_Th_SetSigMask(PCR_allSigsBlocked,&GC_old_sig_mask)
00592 #   define ENABLE_SIGNALS() \
00593               PCR_Th_SetSigMask(&GC_old_sig_mask, NIL)
00594 # else
00595 #   if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \
00596        || defined(MSWIN32) || defined(MACOS) || defined(DJGPP) \
00597        || defined(NO_SIGNALS) || defined(IRIX_THREADS) \
00598        || defined(IRIX_JDK_THREADS) || defined(LINUX_THREADS) 
00599                      /* Also useful for debugging.             */
00600        /* Should probably use thr_sigsetmask for SOLARIS_THREADS. */
00601 #     define DISABLE_SIGNALS()
00602 #     define ENABLE_SIGNALS()
00603 #   else
00604 #     define DISABLE_SIGNALS() GC_disable_signals()
00605        void GC_disable_signals();
00606 #     define ENABLE_SIGNALS() GC_enable_signals()
00607        void GC_enable_signals();
00608 #   endif
00609 # endif
00610 
00611 /*
00612  * Stop and restart mutator threads.
00613  */
00614 # ifdef PCR
00615 #     include "th/PCR_ThCtl.h"
00616 #     define STOP_WORLD() \
00617        PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_stopNormal, \
00618                                PCR_allSigsBlocked, \
00619                                PCR_waitForever)
00620 #     define START_WORLD() \
00621        PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_null, \
00622                                PCR_allSigsBlocked, \
00623                                PCR_waitForever);
00624 # else
00625 #   if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
00626        || defined(IRIX_THREADS) || defined(LINUX_THREADS) \
00627        || defined(IRIX_JDK_THREADS) || defined(GENERIC_THREADS)
00628       void GC_stop_world();
00629       void GC_start_world();
00630 #     define STOP_WORLD() GC_stop_world()
00631 #     define START_WORLD() GC_start_world()
00632 #   else
00633 #     define STOP_WORLD()
00634 #     define START_WORLD()
00635 #   endif
00636 # endif
00637 
00638 /* Abandon ship */
00639 # ifdef PCR
00640 #   define ABORT(s) PCR_Base_Panic(s)
00641 # else
00642 #   ifdef SMALL_CONFIG
00643 #      define ABORT(msg) abort();
00644 #   else
00645        GC_API void GC_abort();
00646 #       define ABORT(msg) GC_abort(msg);
00647 #   endif
00648 # endif
00649 
00650 /* Exit abnormally, but without making a mess (e.g. out of memory) */
00651 # ifdef PCR
00652 #   define EXIT() PCR_Base_Exit(1,PCR_waitForever)
00653 # else
00654 #   define EXIT() (void)exit(1)
00655 # endif
00656 
00657 /* Print warning message, e.g. almost out of memory.    */
00658 # define WARN(msg,arg) (*GC_current_warn_proc)(msg, (GC_word)(arg))
00659 extern GC_warn_proc GC_current_warn_proc;
00660 
00661 /*********************************/
00662 /*                               */
00663 /* Word-size-dependent defines   */
00664 /*                               */
00665 /*********************************/
00666 
00667 #if CPP_WORDSZ == 32
00668 #  define WORDS_TO_BYTES(x)   ((x)<<2)
00669 #  define BYTES_TO_WORDS(x)   ((x)>>2)
00670 #  define LOGWL               ((word)5)    /* log[2] of CPP_WORDSZ */
00671 #  define modWORDSZ(n) ((n) & 0x1f)        /* n mod size of word          */
00672 #  if ALIGNMENT != 4
00673 #      define UNALIGNED
00674 #  endif
00675 #endif
00676 
00677 #if CPP_WORDSZ == 64
00678 #  define WORDS_TO_BYTES(x)   ((x)<<3)
00679 #  define BYTES_TO_WORDS(x)   ((x)>>3)
00680 #  define LOGWL               ((word)6)    /* log[2] of CPP_WORDSZ */
00681 #  define modWORDSZ(n) ((n) & 0x3f)        /* n mod size of word          */
00682 #  if ALIGNMENT != 8
00683 #      define UNALIGNED
00684 #  endif
00685 #endif
00686 
00687 #define WORDSZ ((word)CPP_WORDSZ)
00688 #define SIGNB  ((word)1 << (WORDSZ-1))
00689 #define BYTES_PER_WORD      ((word)(sizeof (word)))
00690 #define ONES                ((word)(-1))
00691 #define divWORDSZ(n) ((n) >> LOGWL)          /* divide n by size of word      */
00692 
00693 /*********************/
00694 /*                   */
00695 /*  Size Parameters  */
00696 /*                   */
00697 /*********************/
00698 
00699 /*  heap block size, bytes. Should be power of 2 */
00700 
00701 #ifndef HBLKSIZE
00702 # ifdef SMALL_CONFIG
00703 #   define CPP_LOG_HBLKSIZE 10
00704 # else
00705 #   if CPP_WORDSZ == 32
00706 #     define CPP_LOG_HBLKSIZE 12
00707 #   else
00708 #     define CPP_LOG_HBLKSIZE 13
00709 #   endif
00710 # endif
00711 #else
00712 # if HBLKSIZE == 512
00713 #   define CPP_LOG_HBLKSIZE 9
00714 # endif
00715 # if HBLKSIZE == 1024
00716 #   define CPP_LOG_HBLKSIZE 10
00717 # endif
00718 # if HBLKSIZE == 2048
00719 #   define CPP_LOG_HBLKSIZE 11
00720 # endif
00721 # if HBLKSIZE == 4096
00722 #   define CPP_LOG_HBLKSIZE 12
00723 # endif
00724 # if HBLKSIZE == 8192
00725 #   define CPP_LOG_HBLKSIZE 13
00726 # endif
00727 # if HBLKSIZE == 16384
00728 #   define CPP_LOG_HBLKSIZE 14
00729 # endif
00730 # ifndef CPP_LOG_HBLKSIZE
00731     --> fix HBLKSIZE
00732 # endif
00733 # undef HBLKSIZE
00734 #endif
00735 # define CPP_HBLKSIZE (1 << CPP_LOG_HBLKSIZE)
00736 # define LOG_HBLKSIZE   ((word)CPP_LOG_HBLKSIZE)
00737 # define HBLKSIZE ((word)CPP_HBLKSIZE)
00738 
00739 
00740 /*  max size objects supported by freelist (larger objects may be   */
00741 /*  allocated, but less efficiently)                                */
00742 
00743 #define CPP_MAXOBJSZ    BYTES_TO_WORDS(CPP_HBLKSIZE/2)
00744 #define MAXOBJSZ ((word)CPP_MAXOBJSZ)
00745               
00746 # define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
00747 
00748 # define HBLK_PTR_DIFF(p,q) divHBLKSZ((ptr_t)p - (ptr_t)q)
00749        /* Equivalent to subtracting 2 hblk pointers.    */
00750        /* We do it this way because a compiler should   */
00751        /* find it hard to use an integer division       */
00752        /* instead of a shift.  The bundled SunOS 4.1    */
00753        /* o.w. sometimes pessimizes the subtraction to  */
00754        /* involve a call to .div.                */
00755  
00756 # define modHBLKSZ(n) ((n) & (HBLKSIZE-1))
00757  
00758 # define HBLKPTR(objptr) ((struct hblk *)(((word) (objptr)) & ~(HBLKSIZE-1)))
00759 
00760 # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1))
00761 
00762 /* Round up byte allocation requests to integral number of words, etc. */
00763 # ifdef ADD_BYTE_AT_END
00764 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1))
00765 #   ifdef ALIGN_DOUBLE
00766 #       define ALIGNED_WORDS(n) (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2)) & ~1)
00767 #   else
00768 #       define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
00769 #   endif
00770 #   define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ))
00771 #   define ADD_SLOP(bytes) ((bytes)+1)
00772 # else
00773 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1))
00774 #   ifdef ALIGN_DOUBLE
00775 #       define ALIGNED_WORDS(n) \
00776                      (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1) & ~1)
00777 #   else
00778 #       define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
00779 #   endif
00780 #   define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
00781 #   define ADD_SLOP(bytes) (bytes)
00782 # endif
00783 
00784 
00785 /*
00786  * Hash table representation of sets of pages.  This assumes it is
00787  * OK to add spurious entries to sets.
00788  * Used by black-listing code, and perhaps by dirty bit maintenance code.
00789  */
00790  
00791 # ifdef LARGE_CONFIG
00792 #   define LOG_PHT_ENTRIES  17
00793 # else
00794 #   define LOG_PHT_ENTRIES  14     /* Collisions are likely if heap grows    */
00795                             /* to more than 16K hblks = 64MB.  */
00796                             /* Each hash table occupies 2K bytes.   */
00797 # endif
00798 # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
00799 # define PHT_SIZE (PHT_ENTRIES >> LOGWL)
00800 typedef word page_hash_table[PHT_SIZE];
00801 
00802 # define PHT_HASH(addr) ((((word)(addr)) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1))
00803 
00804 # define get_pht_entry_from_index(bl, index) \
00805               (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)
00806 # define set_pht_entry_from_index(bl, index) \
00807               (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index)
00808 # define clear_pht_entry_from_index(bl, index) \
00809               (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index))
00810        
00811 
00812 
00813 /********************************************/
00814 /*                                          */
00815 /*    H e a p   B l o c k s                 */
00816 /*                                          */
00817 /********************************************/
00818 
00819 /*  heap block header */
00820 #define HBLKMASK   (HBLKSIZE-1)
00821 
00822 #define BITS_PER_HBLK (HBLKSIZE * 8)
00823 
00824 #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ)
00825           /* upper bound                                    */
00826           /* We allocate 1 bit/word.  Only the first word   */
00827           /* in each object is actually marked.             */
00828 
00829 # ifdef ALIGN_DOUBLE
00830 #   define MARK_BITS_SZ (((MARK_BITS_PER_HBLK + 2*CPP_WORDSZ - 1) \
00831                        / (2*CPP_WORDSZ))*2)
00832 # else
00833 #   define MARK_BITS_SZ ((MARK_BITS_PER_HBLK + CPP_WORDSZ - 1)/CPP_WORDSZ)
00834 # endif
00835           /* Upper bound on number of mark words per heap block  */
00836 
00837 struct hblkhdr {
00838     word hb_sz;  /* If in use, size in words, of objects in the block. */
00839                /* if free, the size in bytes of the whole block      */
00840     struct hblk * hb_next;  /* Link field for hblk free list    */
00841                             /* and for lists of chunks waiting to be */
00842                             /* reclaimed.                       */
00843     word hb_descr;                 /* object descriptor for marking.  See    */
00844                             /* mark.h.                         */
00845     char* hb_map;    /* A pointer to a pointer validity map of the block. */
00846                      /* See GC_obj_map.                             */
00847                      /* Valid for all blocks with headers.                 */
00848                      /* Free blocks point to GC_invalid_map.               */
00849     unsigned char hb_obj_kind;
00850                       /* Kind of objects in the block.  Each kind     */
00851                       /* identifies a mark procedure and a set of     */
00852                       /* list headers.  Sometimes called regions.     */
00853     unsigned char hb_flags;
00854 #      define IGNORE_OFF_PAGE      1      /* Ignore pointers that do not     */
00855                                    /* point to the first page of      */
00856                                    /* this object.                    */
00857     unsigned short hb_last_reclaimed;
00858                             /* Value of GC_gc_no when block was       */
00859                             /* last allocated or swept. May wrap.   */
00860     word hb_marks[MARK_BITS_SZ];
00861                          /* Bit i in the array refers to the             */
00862                          /* object starting at the ith word (header      */
00863                          /* INCLUDED) in the heap block.                 */
00864                          /* The lsb of word 0 is numbered 0.              */
00865 };
00866 
00867 /*  heap block body */
00868 
00869 # define DISCARD_WORDS 0
00870        /* Number of words to be dropped at the beginning of each block       */
00871        /* Must be a multiple of WORDSZ.  May reasonably be nonzero    */
00872        /* on machines that don't guarantee longword alignment of      */
00873        /* pointers, so that the number of false hits is minimized.    */
00874        /* 0 and WORDSZ are probably the only reasonable values.       */
00875 
00876 # define BODY_SZ ((HBLKSIZE-WORDS_TO_BYTES(DISCARD_WORDS))/sizeof(word))
00877 
00878 struct hblk {
00879 #   if (DISCARD_WORDS != 0)
00880         word garbage[DISCARD_WORDS];
00881 #   endif
00882     word hb_body[BODY_SZ];
00883 };
00884 
00885 # define HDR_WORDS ((word)DISCARD_WORDS)
00886 # define HDR_BYTES ((word)WORDS_TO_BYTES(DISCARD_WORDS))
00887 
00888 # define OBJ_SZ_TO_BLOCKS(sz) \
00889     divHBLKSZ(HDR_BYTES + WORDS_TO_BYTES(sz) + HBLKSIZE-1)
00890     /* Size of block (in units of HBLKSIZE) needed to hold objects of */
00891     /* given sz (in words).                                    */
00892 
00893 /* Object free list link */
00894 # define obj_link(p) (*(ptr_t *)(p))
00895 
00896 /* The type of mark procedures.  This really belongs in gc_mark.h.    */
00897 /* But we put it here, so that we can avoid scanning the mark proc    */
00898 /* table.                                                      */
00899 typedef struct ms_entry * (*mark_proc)(/* word * addr, mark_stack_ptr,
00900                                      mark_stack_limit, env */);
00901 # define LOG_MAX_MARK_PROCS 6
00902 # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
00903 
00904 /* Root sets.  Logically private to mark_rts.c.  But we don't want the       */
00905 /* tables scanned, so we put them here.                               */
00906 /* MAX_ROOT_SETS is the maximum number of ranges that can be   */
00907 /* registered as static roots.                                 */
00908 # ifdef LARGE_CONFIG
00909 #   define MAX_ROOT_SETS 4096
00910 # else
00911 #   ifdef PCR
00912 #     define MAX_ROOT_SETS 1024
00913 #   else
00914 #     ifdef MSWIN32
00915 #      define MAX_ROOT_SETS 512
00916            /* Under NT, we add only written pages, which can result   */
00917            /* in many small root sets.                                */
00918 #     else
00919 #       define MAX_ROOT_SETS 64
00920 #     endif
00921 #   endif
00922 # endif
00923 
00924 # define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
00925 /* Maximum number of segments that can be excluded from root sets.    */
00926 
00927 /*
00928  * Data structure for excluded static roots.
00929  */
00930 struct exclusion {
00931     ptr_t e_start;
00932     ptr_t e_end;
00933 };
00934 
00935 /* Data structure for list of root sets.                       */
00936 /* We keep a hash table, so that we can filter out duplicate additions.      */
00937 /* Under Win32, we need to do a better job of filtering overlaps, so  */
00938 /* we resort to sequential search, and pay the price.                 */
00939 struct roots {
00940        ptr_t r_start;
00941        ptr_t r_end;
00942 #      ifndef MSWIN32
00943          struct roots * r_next;
00944 #      endif
00945        GC_bool r_tmp;
00946               /* Delete before registering new dynamic libraries */
00947 };
00948 
00949 #ifndef MSWIN32
00950     /* Size of hash table index to roots. */
00951 #   define LOG_RT_SIZE 6
00952 #   define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */
00953 #endif
00954 
00955 /* Lists of all heap blocks and free lists       */
00956 /* as well as other random data structures       */
00957 /* that should not be scanned by the             */
00958 /* collector.                             */
00959 /* These are grouped together in a struct */
00960 /* so that they can be easily skipped by the     */
00961 /* GC_mark routine.                       */
00962 /* The ordering is weird to make GC_malloc       */
00963 /* faster by keeping the important fields */
00964 /* sufficiently close together that a            */
00965 /* single load of a base register will do.       */
00966 /* Scalars that could easily appear to           */
00967 /* be pointers are also put here.         */
00968 /* The main fields should precede any            */
00969 /* conditionally included fields, so that */
00970 /* gc_inl.h will work even if a different set    */
00971 /* of macros is defined when the client is       */
00972 /* compiled.                              */
00973 
00974 struct _GC_arrays {
00975   word _heapsize;
00976   word _max_heapsize;
00977   ptr_t _last_heap_addr;
00978   ptr_t _prev_heap_addr;
00979   word _words_allocd_before_gc;
00980               /* Number of words allocated before this  */
00981               /* collection cycle.                      */
00982   word _words_allocd;
00983        /* Number of words allocated during this collection cycle */
00984   word _words_wasted;
00985        /* Number of words wasted due to internal fragmentation */
00986        /* in large objects, or due to dropping blacklisted     */
00987        /* blocks, since last gc.  Approximate.                 */
00988   word _words_finalized;
00989        /* Approximate number of words in objects (and headers) */
00990        /* That became ready for finalization in the last       */
00991        /* collection.                                          */
00992   word _non_gc_bytes_at_gc;
00993        /* Number of explicitly managed bytes of storage        */
00994        /* at last collection.                                  */
00995   word _mem_freed;
00996        /* Number of explicitly deallocated words of memory     */
00997        /* since last collection.                        */
00998   mark_proc _mark_procs[MAX_MARK_PROCS];
00999        /* Table of user-defined mark procedures.  There is     */
01000        /* a small number of these, which can be referenced     */
01001        /* by DS_PROC mark descriptors.  See gc_mark.h.         */
01002   ptr_t _objfreelist[MAXOBJSZ+1];
01003                        /* free list for objects */
01004   ptr_t _aobjfreelist[MAXOBJSZ+1];
01005                        /* free list for atomic objs     */
01006 
01007   ptr_t _uobjfreelist[MAXOBJSZ+1];
01008                        /* uncollectable but traced objs        */
01009                        /* objects on this and auobjfreelist  */
01010                        /* are always marked, except during   */
01011                        /* garbage collections.          */
01012 # ifdef ATOMIC_UNCOLLECTABLE
01013     ptr_t _auobjfreelist[MAXOBJSZ+1];
01014 # endif
01015                        /* uncollectable but traced objs        */
01016 
01017 # ifdef GATHERSTATS
01018     word _composite_in_use;
01019               /* Number of words in accessible composite       */
01020               /* objects.                               */
01021     word _atomic_in_use;
01022               /* Number of words in accessible atomic          */
01023               /* objects.                               */
01024 # endif
01025 # ifdef MERGE_SIZES
01026     unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)];
01027        /* Number of words to allocate for a given allocation request in */
01028        /* bytes.                                                */
01029 # endif 
01030 
01031 # ifdef STUBBORN_ALLOC
01032     ptr_t _sobjfreelist[MAXOBJSZ+1];
01033 # endif
01034                        /* free list for immutable objects      */
01035   ptr_t _obj_map[MAXOBJSZ+1];
01036                        /* If not NIL, then a pointer to a map of valid  */
01037                      /* object addresses. _obj_map[sz][i] is j if the */
01038                      /* address block_start+i is a valid pointer      */
01039                      /* to an object at                        */
01040                      /* block_start+i&~3 - WORDS_TO_BYTES(j).         */
01041                      /* (If ALL_INTERIOR_POINTERS is defined, then    */
01042                      /* instead ((short *)(hbh_map[sz])[i] is j if    */
01043                      /* block_start+WORDS_TO_BYTES(i) is in the       */
01044                      /* interior of an object starting at             */
01045                      /* block_start+WORDS_TO_BYTES(i-j)).             */
01046                      /* It is OBJ_INVALID if                          */
01047                      /* block_start+WORDS_TO_BYTES(i) is not          */
01048                      /* valid as a pointer to an object.              */
01049                      /* We assume all values of j <= OBJ_INVALID.     */
01050                      /* The zeroth entry corresponds to large objects.*/
01051 #   ifdef ALL_INTERIOR_POINTERS
01052 #      define map_entry_type short
01053 #       define OBJ_INVALID 0x7fff
01054 #      define MAP_ENTRY(map, bytes) \
01055               (((map_entry_type *)(map))[BYTES_TO_WORDS(bytes)])
01056 #      define MAP_ENTRIES BYTES_TO_WORDS(HBLKSIZE)
01057 #      define MAP_SIZE (MAP_ENTRIES * sizeof(map_entry_type))
01058 #      define OFFSET_VALID(displ) TRUE
01059 #      define CPP_MAX_OFFSET (HBLKSIZE - HDR_BYTES - 1)
01060 #      define MAX_OFFSET ((word)CPP_MAX_OFFSET)
01061 #   else
01062 #      define map_entry_type char
01063 #       define OBJ_INVALID 0x7f
01064 #      define MAP_ENTRY(map, bytes) \
01065               (map)[bytes]
01066 #      define MAP_ENTRIES HBLKSIZE
01067 #      define MAP_SIZE MAP_ENTRIES
01068 #      define CPP_MAX_OFFSET (WORDS_TO_BYTES(OBJ_INVALID) - 1) 
01069 #      define MAX_OFFSET ((word)CPP_MAX_OFFSET)
01070 #      define VALID_OFFSET_SZ \
01071          (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \
01072           CPP_MAX_OFFSET+1 \
01073           : WORDS_TO_BYTES(CPP_MAXOBJSZ)+1)
01074        char _valid_offsets[VALID_OFFSET_SZ];
01075                             /* GC_valid_offsets[i] == TRUE ==> i      */
01076                             /* is registered as a displacement.       */
01077 #      define OFFSET_VALID(displ) GC_valid_offsets[displ]
01078        char _modws_valid_offsets[sizeof(word)];
01079                             /* GC_valid_offsets[i] ==>           */
01080                             /* GC_modws_valid_offsets[i%sizeof(word)] */
01081 #   endif
01082 # ifdef STUBBORN_ALLOC
01083     page_hash_table _changed_pages;
01084         /* Stubborn object pages that were changes since last call to */
01085        /* GC_read_changed.                                     */
01086     page_hash_table _prev_changed_pages;
01087         /* Stubborn object pages that were changes before last call to       */
01088        /* GC_read_changed.                                     */
01089 # endif
01090 # if defined(PROC_VDB) || defined(MPROTECT_VDB)
01091     page_hash_table _grungy_pages; /* Pages that were dirty at last      */
01092                                  /* GC_read_dirty.                       */
01093 # endif
01094 # ifdef MPROTECT_VDB
01095     VOLATILE page_hash_table _dirty_pages;       
01096                      /* Pages dirtied since last GC_read_dirty. */
01097 # endif
01098 # ifdef PROC_VDB
01099     page_hash_table _written_pages;       /* Pages ever dirtied       */
01100 # endif
01101 # ifdef LARGE_CONFIG
01102 #   if CPP_WORDSZ > 32
01103 #     define MAX_HEAP_SECTS 4096   /* overflows at roughly 64 GB         */
01104 #   else
01105 #     define MAX_HEAP_SECTS 768           /* Separately added heap sections. */
01106 #   endif
01107 # else
01108 #   define MAX_HEAP_SECTS 256
01109 # endif
01110   struct HeapSect {
01111       ptr_t hs_start; word hs_bytes;
01112   } _heap_sects[MAX_HEAP_SECTS];
01113 # ifdef MSWIN32
01114     ptr_t _heap_bases[MAX_HEAP_SECTS];
01115               /* Start address of memory regions obtained from kernel. */
01116 # endif
01117   struct roots _static_roots[MAX_ROOT_SETS];
01118 # ifndef MSWIN32
01119     struct roots * _root_index[RT_SIZE];
01120 # endif
01121   struct exclusion _excl_table[MAX_EXCLUSIONS];
01122   /* Block header index; see gc_headers.h */
01123   bottom_index * _all_nils;
01124   bottom_index * _top_index [TOP_SZ];
01125 #ifdef SAVE_CALL_CHAIN
01126   struct callinfo _last_stack[NFRAMES];   /* Stack at last garbage collection.*/
01127                                    /* Useful for debugging     mysterious  */
01128                                    /* object disappearances.       */
01129                                    /* In the multithreaded case, we    */
01130                                    /* currently only save the calling  */
01131                                    /* stack.                       */
01132 #endif
01133 };
01134 
01135 GC_API GC_FAR struct _GC_arrays GC_arrays; 
01136 
01137 # define GC_objfreelist GC_arrays._objfreelist
01138 # define GC_aobjfreelist GC_arrays._aobjfreelist
01139 # define GC_uobjfreelist GC_arrays._uobjfreelist
01140 # ifdef ATOMIC_UNCOLLECTABLE
01141 #   define GC_auobjfreelist GC_arrays._auobjfreelist
01142 # endif
01143 # define GC_sobjfreelist GC_arrays._sobjfreelist
01144 # define GC_valid_offsets GC_arrays._valid_offsets
01145 # define GC_modws_valid_offsets GC_arrays._modws_valid_offsets
01146 # ifdef STUBBORN_ALLOC
01147 #    define GC_changed_pages GC_arrays._changed_pages
01148 #    define GC_prev_changed_pages GC_arrays._prev_changed_pages
01149 # endif
01150 # define GC_obj_map GC_arrays._obj_map
01151 # define GC_last_heap_addr GC_arrays._last_heap_addr
01152 # define GC_prev_heap_addr GC_arrays._prev_heap_addr
01153 # define GC_words_allocd GC_arrays._words_allocd
01154 # define GC_words_wasted GC_arrays._words_wasted
01155 # define GC_words_finalized GC_arrays._words_finalized
01156 # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
01157 # define GC_mem_freed GC_arrays._mem_freed
01158 # define GC_mark_procs GC_arrays._mark_procs
01159 # define GC_heapsize GC_arrays._heapsize
01160 # define GC_max_heapsize GC_arrays._max_heapsize
01161 # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc
01162 # define GC_heap_sects GC_arrays._heap_sects
01163 # define GC_last_stack GC_arrays._last_stack
01164 # ifdef MSWIN32
01165 #   define GC_heap_bases GC_arrays._heap_bases
01166 # endif
01167 # define GC_static_roots GC_arrays._static_roots
01168 # define GC_root_index GC_arrays._root_index
01169 # define GC_excl_table GC_arrays._excl_table
01170 # define GC_all_nils GC_arrays._all_nils
01171 # define GC_top_index GC_arrays._top_index
01172 # if defined(PROC_VDB) || defined(MPROTECT_VDB)
01173 #   define GC_grungy_pages GC_arrays._grungy_pages
01174 # endif
01175 # ifdef MPROTECT_VDB
01176 #   define GC_dirty_pages GC_arrays._dirty_pages
01177 # endif
01178 # ifdef PROC_VDB
01179 #   define GC_written_pages GC_arrays._written_pages
01180 # endif
01181 # ifdef GATHERSTATS
01182 #   define GC_composite_in_use GC_arrays._composite_in_use
01183 #   define GC_atomic_in_use GC_arrays._atomic_in_use
01184 # endif
01185 # ifdef MERGE_SIZES
01186 #   define GC_size_map GC_arrays._size_map
01187 # endif
01188 
01189 # define beginGC_arrays ((ptr_t)(&GC_arrays))
01190 # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))
01191 
01192 /* Object kinds: */
01193 # define MAXOBJKINDS 16
01194 
01195 extern struct obj_kind {
01196    ptr_t *ok_freelist;      /* Array of free listheaders for this kind of object */
01197                      /* Point either to GC_arrays or to storage allocated */
01198                      /* with GC_scratch_alloc.                      */
01199    struct hblk **ok_reclaim_list;
01200                      /* List headers for lists of blocks waiting to be */
01201                      /* swept.                                   */
01202    word ok_descriptor;  /* Descriptor template for objects in this    */
01203                      /* block.                                 */
01204    GC_bool ok_relocate_descr;
01205                      /* Add object size in bytes to descriptor        */
01206                      /* template to obtain descriptor.  Otherwise     */
01207                      /* template is used as is.                */
01208    GC_bool ok_init;   /* Clear objects before putting them on the free list. */
01209 } GC_obj_kinds[MAXOBJKINDS];
01210 
01211 # define endGC_obj_kinds (((ptr_t)(&GC_obj_kinds)) + (sizeof GC_obj_kinds))
01212 
01213 # define end_gc_area ((ptr_t)endGC_arrays == (ptr_t)(&GC_obj_kinds) ? \
01214                      endGC_obj_kinds : endGC_arrays)
01215 
01216 /* Predefined kinds: */
01217 # define PTRFREE 0
01218 # define NORMAL  1
01219 # define UNCOLLECTABLE 2
01220 # ifdef ATOMIC_UNCOLLECTABLE
01221 #   define AUNCOLLECTABLE 3
01222 #   define STUBBORN 4
01223 #   define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)
01224 # else
01225 #   define STUBBORN 3
01226 #   define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)
01227 # endif
01228 
01229 extern int GC_n_kinds;
01230 
01231 GC_API word GC_fo_entries;
01232 
01233 extern word GC_n_heap_sects;       /* Number of separately added heap */
01234                             /* sections.                       */
01235 
01236 extern word GC_page_size;
01237 
01238 # ifdef MSWIN32
01239 extern word GC_n_heap_bases;       /* See GC_heap_bases.       */
01240 # endif
01241 
01242 extern word GC_total_stack_black_listed;
01243                      /* Number of bytes on stack blacklist.    */
01244 
01245 extern word GC_black_list_spacing;
01246                      /* Average number of bytes between blacklisted   */
01247                      /* blocks. Approximate.                          */
01248                      /* Counts only blocks that are                   */
01249                      /* "stack-blacklisted", i.e. that are            */
01250                      /* problematic in the interior of an object.     */
01251 
01252 extern char * GC_invalid_map;
01253                      /* Pointer to the nowhere valid hblk map */
01254                      /* Blocks pointing to this map are free. */
01255 
01256 extern struct hblk * GC_hblkfreelist;
01257                             /* List of completely empty heap blocks   */
01258                             /* Linked through hb_next field of        */
01259                             /* header structure associated with       */
01260                             /* block.                          */
01261 
01262 extern GC_bool GC_is_initialized;  /* GC_init() has been run.  */
01263 
01264 extern GC_bool GC_objects_are_marked;     /* There are marked objects in  */
01265                                    /* the heap.                */
01266 
01267 #ifndef SMALL_CONFIG
01268   extern GC_bool GC_incremental;
01269                      /* Using incremental/generational collection. */
01270 #else
01271 # define GC_incremental TRUE
01272                      /* Hopefully allow optimizer to remove some code. */
01273 #endif
01274 
01275 extern GC_bool GC_dirty_maintained;
01276                             /* Dirty bits are being maintained,       */
01277                             /* either for incremental collection,     */
01278                             /* or to limit the root set.              */
01279 
01280 extern word GC_root_size;   /* Total size of registered root sections */
01281 
01282 extern GC_bool GC_debugging_started;      /* GC_debug_malloc has been called. */ 
01283 
01284 extern ptr_t GC_least_plausible_heap_addr;
01285 extern ptr_t GC_greatest_plausible_heap_addr;
01286                      /* Bounds on the heap.  Guaranteed valid  */
01287                      /* Likely to include future heap expansion.      */
01288                      
01289 /* Operations */
01290 # ifndef abs
01291 #   define abs(x)  ((x) < 0? (-(x)) : (x))
01292 # endif
01293 
01294 
01295 /*  Marks are in a reserved area in                          */
01296 /*  each heap block.  Each word has one mark bit associated  */
01297 /*  with it. Only those corresponding to the beginning of an */
01298 /*  object are used.                                         */
01299 
01300 
01301 /* Mark bit operations */
01302 
01303 /*
01304  * Retrieve, set, clear the mark bit corresponding
01305  * to the nth word in a given heap block.
01306  *
01307  * (Recall that bit n corresponds to object beginning at word n
01308  * relative to the beginning of the block, including unused words)
01309  */
01310 
01311 # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \
01312                          >> (modWORDSZ(n))) & (word)1)
01313 # define set_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
01314                             |= (word)1 << modWORDSZ(n)
01315 
01316 # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
01317                             &= ~((word)1 << modWORDSZ(n))
01318 
01319 /* Important internal collector routines */
01320 
01321 ptr_t GC_approx_sp();
01322 
01323 GC_bool GC_should_collect();
01324 #ifdef PRESERVE_LAST
01325     GC_bool GC_in_last_heap_sect(/* ptr_t */);
01326        /* In last added heap section?  If so, avoid breaking up.      */
01327 #endif
01328 void GC_apply_to_all_blocks(/*fn, client_data*/);
01329                      /* Invoke fn(hbp, client_data) for each   */
01330                      /* allocated heap block.                  */
01331 struct hblk * GC_next_block(/* struct hblk * h */);
01332 void GC_mark_init();
01333 void GC_clear_marks();      /* Clear mark bits for all heap objects. */
01334 void GC_invalidate_mark_state();   /* Tell the marker that     marked           */
01335                                    /* objects may point to     unmarked   */
01336                                    /* ones, and roots may point to       */
01337                                    /* unmarked objects.           */
01338                                    /* Reset mark stack.           */
01339 void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */
01340                             /* Return after about one pages worth of   */
01341                             /* work.                              */
01342 GC_bool GC_mark_stack_empty();
01343 GC_bool GC_mark_some(/* cold_gc_frame */);
01344                      /* Perform about one pages worth of marking      */
01345                      /* work of whatever kind is needed.  Returns     */
01346                      /* quickly if no collection is in progress.      */
01347                      /* Return TRUE if mark phase finished.           */
01348 void GC_initiate_gc();             /* initiate collection.                   */
01349                             /* If the mark state is invalid, this     */
01350                             /* becomes full colleection.  Otherwise */
01351                             /* it's partial.                   */
01352 void GC_push_all(/*b,t*/);  /* Push everything in a range             */
01353                             /* onto mark stack.                */
01354 void GC_push_dirty(/*b,t*/);      /* Push all possibly changed        */
01355                               /* subintervals of [b,t) onto           */
01356                               /* mark stack.                   */
01357 #ifndef SMALL_CONFIG
01358   void GC_push_conditional(/* ptr_t b, ptr_t t, GC_bool all*/);
01359 #else
01360 # define GC_push_conditional(b, t, all) GC_push_all(b, t)
01361 #endif
01362                                 /* Do either of the above, depending  */
01363                             /* on the third arg.               */
01364 void GC_push_all_stack(/*b,t*/);    /* As above, but consider         */
01365                                 /*  interior pointers as valid        */
01366 void GC_push_all_eager(/*b,t*/);    /* Same as GC_push_all_stack, but   */
01367                                 /* ensures that stack is scanned      */
01368                                 /* immediately, not just scheduled  */
01369                                 /* for scanning.               */
01370 #ifndef THREADS
01371   void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */);
01372                      /* Similar to GC_push_all_eager, but only the    */
01373                      /* part hotter than cold_gc_frame is scanned     */
01374                      /* immediately.  Needed to endure that callee-   */
01375                      /* save registers are not missed.         */
01376 #else
01377   /* In the threads case, we push part of the current thread stack    */
01378   /* with GC_push_all_eager when we push the registers.  This gets the  */
01379   /* callee-save registers that may disappear.  The remainder of the  */
01380   /* stacks are scheduled for scanning in *GC_push_other_roots, which */
01381   /* is thread-package-specific.                               */
01382 #endif
01383 void GC_push_current_stack(/* ptr_t cold_gc_frame */);
01384                      /* Push enough of the current stack eagerly to   */
01385                      /* ensure that callee-save registers saved in    */
01386                      /* GC frames are scanned.                 */
01387                      /* In the non-threads case, schedule entire      */
01388                      /* stack for scanning.                           */
01389 void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */);
01390                      /* Push all or dirty roots. */
01391 extern void (*GC_push_other_roots)();
01392                      /* Push system or application specific roots     */
01393                      /* onto the mark stack.  In some environments    */
01394                      /* (e.g. threads environments) this is           */
01395                      /* predfined to be non-zero.  A client supplied */
01396                      /* replacement should also call the original     */
01397                      /* function.                              */
01398 extern void (*GC_start_call_back)(/* void */);
01399                      /* Called at start of full collections.          */
01400                      /* Not called if 0.  Called with allocation      */
01401                      /* lock held.                             */
01402                      /* 0 by default.                          */
01403 void GC_push_regs(); /* Push register contents onto mark stack.       */
01404 void GC_remark();    /* Mark from all marked objects.  Used    */
01405                      /* only if we had to drop something.      */
01406 # if defined(MSWIN32)
01407   void __cdecl GC_push_one();
01408 # else
01409   void GC_push_one(/*p*/);    /* If p points to an object, mark it    */
01410                               /* and push contents on the mark stack  */
01411 # endif
01412 void GC_push_one_checked(/*p*/); /* Ditto, omits plausibility test    */
01413 void GC_push_marked(/* struct hblk h, hdr * hhdr */);
01414               /* Push contents of all marked objects in h onto */
01415               /* mark stack.                                          */
01416 #ifdef SMALL_CONFIG
01417 # define GC_push_next_marked_dirty(h) GC_push_next_marked(h)
01418 #else
01419   struct hblk * GC_push_next_marked_dirty(/* h */);
01420               /* Invoke GC_push_marked on next dirty block above h.   */
01421               /* Return a pointer just past the end of this block.    */
01422 #endif /* !SMALL_CONFIG */
01423 struct hblk * GC_push_next_marked(/* h */);
01424               /* Ditto, but also mark from clean pages. */
01425 struct hblk * GC_push_next_marked_uncollectable(/* h */);
01426               /* Ditto, but mark only from uncollectable pages.       */
01427 GC_bool GC_stopped_mark(); /* Stop world and mark from all roots      */
01428                      /* and rescuers.                   */
01429 void GC_clear_hdr_marks(/* hhdr */);  /* Clear the mark bits in a header */
01430 void GC_set_hdr_marks(/* hhdr */);  /* Set the mark bits in a header */
01431 void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp));
01432 void GC_remove_roots_inner GC_PROTO((char * b, char * e));
01433 GC_bool GC_is_static_root(/* ptr_t p */);
01434               /* Is the address p in one of the registered static     */
01435               /* root sections?                                */
01436 void GC_register_dynamic_libraries();
01437               /* Add dynamic library data sections to the root set. */
01438 
01439 /* Machine dependent startup routines */
01440 ptr_t GC_get_stack_base();
01441 void GC_register_data_segments();
01442 
01443 /* Black listing: */
01444 void GC_bl_init();   
01445 # ifndef ALL_INTERIOR_POINTERS
01446     void GC_add_to_black_list_normal(/* bits, maybe source */);
01447                      /* Register bits as a possible future false      */
01448                      /* reference from the heap or static data */
01449 #   ifdef PRINT_BLACK_LIST
01450 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
01451                      GC_add_to_black_list_normal(bits, source)
01452 #   else
01453 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
01454                      GC_add_to_black_list_normal(bits)
01455 #   endif
01456 # else
01457 #   ifdef PRINT_BLACK_LIST
01458 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
01459                      GC_add_to_black_list_stack(bits, source)
01460 #   else
01461 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
01462                      GC_add_to_black_list_stack(bits)
01463 #   endif
01464 # endif
01465 
01466 void GC_add_to_black_list_stack(/* bits, maybe source */);
01467 struct hblk * GC_is_black_listed(/* h, len */);
01468                      /* If there are likely to be false references    */
01469                      /* to a block starting at h of the indicated    */
01470                      /* length, then return the next plausible */
01471                      /* starting location for h that might avoid      */
01472                      /* these false references.                */
01473 void GC_promote_black_lists();
01474                      /* Declare an end to a black listing phase.      */
01475 void GC_unpromote_black_lists();
01476                      /* Approximately undo the effect of the above.   */
01477                      /* This actually loses some information, but     */
01478                      /* only in a reasonably safe way.         */
01479 word GC_number_stack_black_listed(/*struct hblk *start, struct hblk *endp1 */);
01480                      /* Return the number of (stack) blacklisted      */
01481                      /* blocks in the range for statistical           */
01482                      /* purposes.                              */
01483                      
01484 ptr_t GC_scratch_alloc(/*bytes*/);
01485                             /* GC internal memory allocation for      */
01486                             /* small objects.  Deallocation is not  */
01487                             /* possible.                       */
01488        
01489 /* Heap block layout maps: */                    
01490 void GC_invalidate_map(/* hdr */);
01491                             /* Remove the object map associated       */
01492                             /* with the block.  This identifies       */
01493                             /* the block as invalid to the mark       */
01494                             /* routines.                       */
01495 GC_bool GC_add_map_entry(/*sz*/);
01496                             /* Add a heap block map for objects of    */
01497                             /* size sz to obj_map.                    */
01498                             /* Return FALSE on failure.        */
01499 void GC_register_displacement_inner(/*offset*/);
01500                             /* Version of GC_register_displacement    */
01501                             /* that assumes lock is already held      */
01502                             /* and signals are already disabled.      */
01503 
01504 /*  hblk allocation: */            
01505 void GC_new_hblk(/*size_in_words, kind*/);
01506                             /* Allocate a new heap block, and build */
01507                             /* a free list in it.                     */                          
01508 struct hblk * GC_allochblk(/*size_in_words, kind*/);
01509                             /* Allocate a heap block, clear it if     */
01510                             /* for composite objects, inform   */
01511                             /* the marker that block is valid  */
01512                             /* for objects of indicated size.  */
01513                             /* sz < 0 ==> atomic.                     */ 
01514 void GC_freehblk();         /* Deallocate a heap block and mark it  */
01515                             /* as invalid.                            */
01516                             
01517 /*  Misc GC: */
01518 void GC_init_inner();
01519 GC_bool GC_expand_hp_inner();
01520 void GC_start_reclaim(/*abort_if_found*/);
01521                             /* Restore unmarked objects to free       */
01522                             /* lists, or (if abort_if_found is */
01523                             /* TRUE) report them.                     */
01524                             /* Sweeping of small object pages is      */
01525                             /* largely deferred.               */
01526 void GC_continue_reclaim(/*size, kind*/);
01527                             /* Sweep pages of the given size and      */
01528                             /* kind, as long as possible, and  */
01529                             /* as long as the corr. free list is    */
01530                             /* empty.                          */
01531 void GC_reclaim_or_delete_all();
01532                             /* Arrange for all reclaim lists to be    */
01533                             /* empty.  Judiciously choose between     */
01534                             /* sweeping and discarding each page.     */
01535 GC_bool GC_reclaim_all(/* GC_stop_func f*/);
01536                             /* Reclaim all blocks.  Abort (in a       */
01537                             /* consistent state) if f returns TRUE. */
01538 GC_bool GC_block_empty(/* hhdr */); /* Block completely unmarked?     */
01539 GC_bool GC_never_stop_func();      /* Returns FALSE.           */
01540 GC_bool GC_try_to_collect_inner(/* GC_stop_func f */);
01541                             /* Collect; caller must have acquired     */
01542                             /* lock and disabled signals.             */
01543                             /* Collection is aborted if f returns     */
01544                             /* TRUE.  Returns TRUE if it completes    */
01545                             /* successfully.                   */
01546 # define GC_gcollect_inner() \
01547        (void) GC_try_to_collect_inner(GC_never_stop_func)
01548 void GC_finish_collection();       /* Finish collection.  Mark bits are      */
01549                             /* consistent and lock is still held.     */
01550 GC_bool GC_collect_or_expand(/* needed_blocks */);
01551                             /* Collect or expand heap in an attempt */
01552                             /* make the indicated number of free      */
01553                             /* blocks available.  Should be called    */
01554                             /* until the blocks are available or      */
01555                             /* until it fails by returning FALSE.     */
01556 GC_API void GC_init();             /* Initialize collector.           */
01557 void GC_collect_a_little_inner(/* int n */);
01558                             /* Do n units worth of garbage            */
01559                             /* collection work, if appropriate.       */
01560                             /* A unit is an amount appropriate for  */
01561                             /* HBLKSIZE bytes of allocation.   */
01562 ptr_t GC_generic_malloc(/* bytes, kind */);
01563                             /* Allocate an object of the given */
01564                             /* kind.  By default, there are only      */
01565                             /* a few kinds: composite(pointerfree), */
01566                             /* atomic, uncollectable, etc.            */
01567                             /* We claim it's possible for clever      */
01568                             /* client code that understands GC */
01569                             /* internals to add more, e.g. to  */
01570                             /* communicate object layout info  */
01571                             /* to the collector.               */
01572 ptr_t GC_generic_malloc_ignore_off_page(/* bytes, kind */);
01573                             /* As above, but pointers past the        */
01574                             /* first page of the resulting object     */
01575                             /* are ignored.                           */
01576 ptr_t GC_generic_malloc_inner(/* bytes, kind */);
01577                             /* Ditto, but I already hold lock, etc.   */
01578 ptr_t GC_generic_malloc_words_small GC_PROTO((size_t words, int kind));
01579                             /* As above, but size in units of words */
01580                             /* Bypasses MERGE_SIZES.  Assumes  */
01581                             /* words <= MAXOBJSZ.                     */
01582 ptr_t GC_generic_malloc_inner_ignore_off_page(/* bytes, kind */);
01583                             /* Allocate an object, where              */
01584                             /* the client guarantees that there       */
01585                             /* will always be a pointer to the        */
01586                             /* beginning of the object while the      */
01587                             /* object is live.                 */
01588 ptr_t GC_allocobj(/* sz_inn_words, kind */);
01589                             /* Make the indicated                     */
01590                             /* free list nonempty, and return its     */
01591                             /* head.                           */
01592 
01593 void GC_init_headers();
01594 GC_bool GC_install_header(/*h*/);
01595                             /* Install a header for block h.   */
01596                             /* Return FALSE on failure.        */
01597 GC_bool GC_install_counts(/*h, sz*/);
01598                             /* Set up forwarding counts for block     */
01599                             /* h of size sz.                   */
01600                             /* Return FALSE on failure.        */
01601 void GC_remove_header(/*h*/);
01602                             /* Remove the header for block h.  */
01603 void GC_remove_counts(/*h, sz*/);
01604                             /* Remove forwarding counts for h. */
01605 hdr * GC_find_header(/*p*/);       /* Debugging only.                 */
01606 
01607 void GC_finalize();  /* Perform all indicated finalization actions    */
01608                      /* on unmarked objects.                          */
01609                      /* Unreachable finalizable objects are enqueued  */
01610                      /* for processing by GC_invoke_finalizers.       */
01611                      /* Invoked with lock.                            */
01612                      
01613 void GC_add_to_heap(/*p, bytes*/);
01614                      /* Add a HBLKSIZE aligned chunk to the heap.     */
01615 
01616 void GC_print_obj(/* ptr_t p */);
01617                      /* P points to somewhere inside an object with   */
01618                      /* debugging info.  Print a human readable       */
01619                      /* description of the object to stderr.          */
01620 extern void (*GC_check_heap)();
01621                      /* Check that all objects in the heap with       */
01622                      /* debugging info are intact.  Print             */
01623                      /* descriptions of any that are not.             */
01624 extern void (*GC_print_heap_obj)(/* ptr_t p */);
01625                      /* If possible print s followed by a more */
01626                      /* detailed description of the object            */
01627                      /* referred to by p.                      */
01628                      
01629 /* Virtual dirty bit implementation:             */
01630 /* Each implementation exports the following:    */
01631 void GC_read_dirty();       /* Retrieve dirty bits.     */
01632 GC_bool GC_page_was_dirty(/* struct hblk * h  */);
01633                      /* Read retrieved dirty bits.      */
01634 GC_bool GC_page_was_ever_dirty(/* struct hblk * h  */);
01635                      /* Could the page contain valid heap pointers?   */
01636 void GC_is_fresh(/* struct hblk * h, word number_of_blocks  */);
01637                      /* Assert the region currently contains no       */
01638                      /* valid pointers.                        */
01639 void GC_write_hint(/* struct hblk * h  */);
01640                      /* h is about to be written.       */
01641 void GC_dirty_init();
01642 
01643 /* Slow/general mark bit manipulation: */
01644 GC_API GC_bool GC_is_marked();
01645 void GC_clear_mark_bit();
01646 void GC_set_mark_bit();
01647 
01648 /* Stubborn objects: */
01649 void GC_read_changed();     /* Analogous to GC_read_dirty */
01650 GC_bool GC_page_was_changed(/* h */);     /* Analogous to GC_page_was_dirty */
01651 void GC_clean_changing_list();     /* Collect obsolete changing list entries */
01652 void GC_stubborn_init();
01653 
01654 /* Debugging print routines: */
01655 void GC_print_block_list();
01656 void GC_print_hblkfreelist();
01657 void GC_print_heap_sects();
01658 void GC_print_static_roots();
01659 void GC_dump();
01660 
01661 /* Make arguments appear live to compiler */
01662 # ifdef __WATCOMC__
01663   void GC_noop(void*, ...);
01664 # else
01665   GC_API void GC_noop();
01666 # endif
01667 
01668 void GC_noop1(/* word arg */);
01669 
01670 /* Logging and diagnostic output:  */
01671 GC_API void GC_printf GC_PROTO((char * format, long, long, long, long, long, long));
01672                      /* A version of printf that doesn't allocate,    */
01673                      /* is restricted to long arguments, and          */
01674                      /* (unfortunately) doesn't use varargs for       */
01675                      /* portability.  Restricted to 6 args and */
01676                      /* 1K total output length.                */
01677                      /* (We use sprintf.  Hopefully that doesn't      */
01678                      /* allocate for long arguments.)          */
01679 # define GC_printf0(f) GC_printf(f, 0l, 0l, 0l, 0l, 0l, 0l)
01680 # define GC_printf1(f,a) GC_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
01681 # define GC_printf2(f,a,b) GC_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
01682 # define GC_printf3(f,a,b,c) GC_printf(f, (long)a, (long)b, (long)c, 0l, 0l, 0l)
01683 # define GC_printf4(f,a,b,c,d) GC_printf(f, (long)a, (long)b, (long)c, \
01684                                        (long)d, 0l, 0l)
01685 # define GC_printf5(f,a,b,c,d,e) GC_printf(f, (long)a, (long)b, (long)c, \
01686                                          (long)d, (long)e, 0l)
01687 # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \
01688                                           (long)d, (long)e, (long)g)
01689 
01690 void GC_err_printf(/* format, a, b, c, d, e, f */);
01691 # define GC_err_printf0(f) GC_err_puts(f)
01692 # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
01693 # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
01694 # define GC_err_printf3(f,a,b,c) GC_err_printf(f, (long)a, (long)b, (long)c, \
01695                                             0l, 0l, 0l)
01696 # define GC_err_printf4(f,a,b,c,d) GC_err_printf(f, (long)a, (long)b, \
01697                                               (long)c, (long)d, 0l, 0l)
01698 # define GC_err_printf5(f,a,b,c,d,e) GC_err_printf(f, (long)a, (long)b, \
01699                                                 (long)c, (long)d, \
01700                                                 (long)e, 0l)
01701 # define GC_err_printf6(f,a,b,c,d,e,g) GC_err_printf(f, (long)a, (long)b, \
01702                                                  (long)c, (long)d, \
01703                                                  (long)e, (long)g)
01704                      /* Ditto, writes to stderr.               */
01705                      
01706 void GC_err_puts(/* char *s */);
01707                      /* Write s to stderr, don't buffer, don't add    */
01708                      /* newlines, don't ...                           */
01709 
01710 
01711 # endif /* GC_PRIVATE_H */