]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - boehm-gc/misc.c
Imported gcc-4.4.3
[msp430-gcc.git] / boehm-gc / misc.c
diff --git a/boehm-gc/misc.c b/boehm-gc/misc.c
deleted file mode 100644 (file)
index f607973..0000000
+++ /dev/null
@@ -1,1085 +0,0 @@
-/* 
- * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
- * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
- * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- */
-/* Boehm, July 31, 1995 5:02 pm PDT */
-
-
-#include <stdio.h>
-#include <limits.h>
-#ifndef _WIN32_WCE
-#include <signal.h>
-#endif
-
-#define I_HIDE_POINTERS        /* To make GC_call_with_alloc_lock visible */
-#include "private/gc_pmark.h"
-
-#ifdef GC_SOLARIS_THREADS
-# include <sys/syscall.h>
-#endif
-#if defined(MSWIN32) || defined(MSWINCE)
-# define WIN32_LEAN_AND_MEAN
-# define NOSERVICE
-# include <windows.h>
-# include <tchar.h>
-#endif
-
-# ifdef THREADS
-#   ifdef PCR
-#     include "il/PCR_IL.h"
-      PCR_Th_ML GC_allocate_ml;
-#   else
-#     ifdef SRC_M3
-       /* Critical section counter is defined in the M3 runtime        */
-       /* That's all we use.                                           */
-#     else
-#      ifdef GC_SOLARIS_THREADS
-         mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
-#      else
-#          ifdef GC_WIN32_THREADS
-#            if !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
-                __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
-#            else
-                CRITICAL_SECTION GC_allocate_ml;
-#            endif
-#          else
-#             if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS)
-#              if defined(USE_SPIN_LOCK)
-                 pthread_t GC_lock_holder = NO_THREAD;
-#              else
-                 pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
-                 pthread_t GC_lock_holder = NO_THREAD;
-                       /* Used only for assertions, and to prevent      */
-                       /* recursive reentry in the system call wrapper. */
-#              endif 
-#            else
-                 --> declare allocator lock here
-#            endif
-#         endif
-#      endif
-#     endif
-#   endif
-# endif
-
-#if defined(NOSYS) || defined(ECOS)
-#undef STACKBASE
-#endif
-
-GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
-
-
-GC_bool GC_debugging_started = FALSE;
-       /* defined here so we don't have to load debug_malloc.o */
-
-void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
-
-void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
-
-ptr_t GC_stackbottom = 0;
-
-#ifdef IA64
-  ptr_t GC_register_stackbottom = 0;
-#endif
-
-GC_bool GC_dont_gc = 0;
-
-GC_bool GC_dont_precollect = 0;
-
-GC_bool GC_quiet = 0;
-
-GC_bool GC_print_stats = 0;
-
-GC_bool GC_print_back_height = 0;
-
-#ifdef FIND_LEAK
-  int GC_find_leak = 1;
-#else
-  int GC_find_leak = 0;
-#endif
-
-#ifdef ALL_INTERIOR_POINTERS
-  int GC_all_interior_pointers = 1;
-#else
-  int GC_all_interior_pointers = 0;
-#endif
-
-long GC_large_alloc_warn_interval = 5;
-       /* Interval between unsuppressed warnings.      */
-
-long GC_large_alloc_warn_suppressed = 0;
-       /* Number of warnings suppressed so far.        */
-
-/*ARGSUSED*/
-GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))
-{
-    return(0);
-}
-
-GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) = GC_default_oom_fn;
-
-extern signed_word GC_mem_found;
-
-# ifdef MERGE_SIZES
-    /* Set things up so that GC_size_map[i] >= words(i),               */
-    /* but not too much bigger                                         */
-    /* and so that size_map contains relatively few distinct entries   */
-    /* This is stolen from Russ Atkinson's Cedar quantization          */
-    /* alogrithm (but we precompute it).                               */
-
-
-    void GC_init_size_map()
-    {
-       register unsigned i;
-
-       /* Map size 0 to something bigger.                      */
-       /* This avoids problems at lower levels.                */
-       /* One word objects don't have to be 2 word aligned,    */
-       /* unless we're using mark bytes.                       */
-         for (i = 0; i < sizeof(word); i++) {
-             GC_size_map[i] = MIN_WORDS;
-         }
-#        if MIN_WORDS > 1
-           GC_size_map[sizeof(word)] = MIN_WORDS;
-#        else
-           GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
-#        endif
-       for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
-           GC_size_map[i] = ALIGNED_WORDS(i);
-       }
-       for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {
-             GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
-       }
-#      ifdef GC_GCJ_SUPPORT
-          /* Make all sizes up to 32 words predictable, so that a      */
-          /* compiler can statically perform the same computation,     */
-          /* or at least a computation that results in similar size    */
-          /* classes.                                                  */
-          for (i = 16*sizeof(word) + 1; i <= 32 * sizeof(word); i++) {
-             GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 3) & (~3);
-          }
-#      endif
-       /* We leave the rest of the array to be filled in on demand. */
-    }
-    
-    /* Fill in additional entries in GC_size_map, including the ith one */
-    /* We assume the ith entry is currently 0.                         */
-    /* Note that a filled in section of the array ending at n always    */
-    /* has length at least n/4.                                                */
-    void GC_extend_size_map(i)
-    word i;
-    {
-        word orig_word_sz = ROUNDED_UP_WORDS(i);
-        word word_sz = orig_word_sz;
-       register word byte_sz = WORDS_TO_BYTES(word_sz);
-                               /* The size we try to preserve.         */
-                               /* Close to to i, unless this would     */
-                               /* introduce too many distinct sizes.   */
-       word smaller_than_i = byte_sz - (byte_sz >> 3);
-       word much_smaller_than_i = byte_sz - (byte_sz >> 2);
-       register word low_limit;        /* The lowest indexed entry we  */
-                                       /* initialize.                  */
-       register word j;
-       
-       if (GC_size_map[smaller_than_i] == 0) {
-           low_limit = much_smaller_than_i;
-           while (GC_size_map[low_limit] != 0) low_limit++;
-       } else {
-           low_limit = smaller_than_i + 1;
-           while (GC_size_map[low_limit] != 0) low_limit++;
-           word_sz = ROUNDED_UP_WORDS(low_limit);
-           word_sz += word_sz >> 3;
-           if (word_sz < orig_word_sz) word_sz = orig_word_sz;
-       }
-#      ifdef ALIGN_DOUBLE
-           word_sz += 1;
-           word_sz &= ~1;
-#      endif
-       if (word_sz > MAXOBJSZ) {
-           word_sz = MAXOBJSZ;
-       }
-       /* If we can fit the same number of larger objects in a block,  */
-       /* do so.                                                       */ 
-       {
-           size_t number_of_objs = BODY_SZ/word_sz;
-           word_sz = BODY_SZ/number_of_objs;
-#          ifdef ALIGN_DOUBLE
-               word_sz &= ~1;
-#          endif
-       }
-       byte_sz = WORDS_TO_BYTES(word_sz);
-       if (GC_all_interior_pointers) {
-           /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
-           byte_sz--;
-       }
-
-       for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;  
-    }
-# endif
-
-
-/*
- * The following is a gross hack to deal with a problem that can occur
- * on machines that are sloppy about stack frame sizes, notably SPARC.
- * Bogus pointers may be written to the stack and not cleared for
- * a LONG time, because they always fall into holes in stack frames
- * that are not written.  We partially address this by clearing
- * sections of the stack whenever we get control.
- */
-word GC_stack_last_cleared = 0;        /* GC_no when we last did this */
-# ifdef THREADS
-#   define BIG_CLEAR_SIZE 2048 /* Clear this much now and then.        */
-#   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.         */
-# endif
-# define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
-# define DEGRADE_RATE 50
-
-word GC_min_sp;                /* Coolest stack pointer value from which we've */
-                       /* already cleared the stack.                   */
-                       
-word GC_high_water;
-                       /* "hottest" stack pointer value we have seen   */
-                       /* recently.  Degrades over time.               */
-
-word GC_words_allocd_at_reset;
-
-#if defined(ASM_CLEAR_CODE)
-  extern ptr_t GC_clear_stack_inner();
-#else  
-/* Clear the stack up to about limit.  Return arg. */
-/*ARGSUSED*/
-ptr_t GC_clear_stack_inner(arg, limit)
-ptr_t arg;
-word limit;
-{
-    word dummy[CLEAR_SIZE];
-    
-    BZERO(dummy, CLEAR_SIZE*sizeof(word));
-    if ((word)(dummy) COOLER_THAN limit) {
-        (void) GC_clear_stack_inner(arg, limit);
-    }
-    /* Make sure the recursive call is not a tail call, and the bzero  */
-    /* call is not recognized as dead code.                            */
-    GC_noop1((word)dummy);
-    return(arg);
-}
-#endif
-
-/* Clear some of the inaccessible part of the stack.  Returns its      */
-/* argument, so it can be used in a tail call position, hence clearing  */
-/* another frame.                                                      */
-ptr_t GC_clear_stack(arg)
-ptr_t arg;
-{
-    register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
-#   ifdef THREADS
-        word dummy[SMALL_CLEAR_SIZE];
-       static unsigned random_no = 0;
-                                        /* Should be more random than it is ... */
-                                /* Used to occasionally clear a bigger  */
-                                /* chunk.                               */
-#   endif
-    register word limit;
-    
-#   define SLOP 400
-       /* Extra bytes we clear every time.  This clears our own        */
-       /* activation record, and should cause more frequent            */
-       /* clearing near the cold end of the stack, a good thing.       */
-#   define GC_SLOP 4000
-       /* We make GC_high_water this much hotter than we really saw    */
-       /* saw it, to cover for GC noise etc. above our current frame.  */
-#   define CLEAR_THRESHOLD 100000
-       /* We restart the clearing process after this many bytes of     */
-       /* allocation.  Otherwise very heavily recursive programs       */
-       /* with sparse stacks may result in heaps that grow almost      */
-       /* without bounds.  As the heap gets larger, collection         */
-       /* frequency decreases, thus clearing frequency would decrease, */
-       /* thus more junk remains accessible, thus the heap gets        */
-       /* larger ...                                                   */
-# ifdef THREADS
-    if (++random_no % 13 == 0) {
-       limit = sp;
-       MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
-        limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
-                       /* implementations of GC_clear_stack_inner.     */
-       return GC_clear_stack_inner(arg, limit);
-    } else {
-       BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
-       return arg;
-    }
-# else
-    if (GC_gc_no > GC_stack_last_cleared) {
-        /* Start things over, so we clear the entire stack again */
-        if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom;
-        GC_min_sp = GC_high_water;
-        GC_stack_last_cleared = GC_gc_no;
-        GC_words_allocd_at_reset = GC_words_allocd;
-    }
-    /* Adjust GC_high_water */
-        MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
-        if (sp HOTTER_THAN GC_high_water) {
-            GC_high_water = sp;
-        }
-        MAKE_HOTTER(GC_high_water, GC_SLOP);
-    limit = GC_min_sp;
-    MAKE_HOTTER(limit, SLOP);
-    if (sp COOLER_THAN limit) {
-        limit &= ~0xf; /* Make it sufficiently aligned for assembly    */
-                       /* implementations of GC_clear_stack_inner.     */
-        GC_min_sp = sp;
-        return(GC_clear_stack_inner(arg, limit));
-    } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset)
-              > CLEAR_THRESHOLD) {
-       /* Restart clearing process, but limit how much clearing we do. */
-       GC_min_sp = sp;
-       MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
-       if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
-       GC_words_allocd_at_reset = GC_words_allocd;
-    }  
-    return(arg);
-# endif
-}
-
-
-/* Return a pointer to the base address of p, given a pointer to a     */
-/* an address within an object.  Return 0 o.w.                         */
-# ifdef __STDC__
-    GC_PTR GC_base(GC_PTR p)
-# else
-    GC_PTR GC_base(p)
-    GC_PTR p;
-# endif
-{
-    register word r;
-    register struct hblk *h;
-    register bottom_index *bi;
-    register hdr *candidate_hdr;
-    register word limit;
-    
-    r = (word)p;
-    if (!GC_is_initialized) return 0;
-    h = HBLKPTR(r);
-    GET_BI(r, bi);
-    candidate_hdr = HDR_FROM_BI(bi, r);
-    if (candidate_hdr == 0) return(0);
-    /* If it's a pointer to the middle of a large object, move it      */
-    /* to the beginning.                                               */
-       while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
-          h = FORWARDED_ADDR(h,candidate_hdr);
-          r = (word)h;
-          candidate_hdr = HDR(h);
-       }
-    if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
-    /* Make sure r points to the beginning of the object */
-       r &= ~(WORDS_TO_BYTES(1) - 1);
-        {
-           register int offset = HBLKDISPL(r);
-           register signed_word sz = candidate_hdr -> hb_sz;
-           register signed_word map_entry;
-             
-           map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
-           if (map_entry > CPP_MAX_OFFSET) {
-               map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz;
-            }
-            r -= WORDS_TO_BYTES(map_entry);
-            limit = r + WORDS_TO_BYTES(sz);
-           if (limit > (word)(h + 1)
-               && sz <= BYTES_TO_WORDS(HBLKSIZE)) {
-               return(0);
-           }
-           if ((word)p >= limit) return(0);
-       }
-    return((GC_PTR)r);
-}
-
-
-/* Return the size of an object, given a pointer to its base.          */
-/* (For small obects this also happens to work from interior pointers, */
-/* but that shouldn't be relied upon.)                                 */
-# ifdef __STDC__
-    size_t GC_size(GC_PTR p)
-# else
-    size_t GC_size(p)
-    GC_PTR p;
-# endif
-{
-    register int sz;
-    register hdr * hhdr = HDR(p);
-    
-    sz = WORDS_TO_BYTES(hhdr -> hb_sz);
-    return(sz);
-}
-
-size_t GC_get_heap_size GC_PROTO(())
-{
-    return ((size_t) GC_heapsize);
-}
-
-size_t GC_get_free_bytes GC_PROTO(())
-{
-    return ((size_t) GC_large_free_bytes);
-}
-
-size_t GC_get_bytes_since_gc GC_PROTO(())
-{
-    return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
-}
-
-size_t GC_get_total_bytes GC_PROTO(())
-{
-    return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc));
-}
-
-GC_bool GC_is_initialized = FALSE;
-
-void GC_init()
-{
-    DCL_LOCK_STATE;
-    
-    DISABLE_SIGNALS();
-
-#ifdef MSWIN32
-    if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
-#endif /* MSWIN32 */
-
-    LOCK();
-    GC_init_inner();
-    UNLOCK();
-    ENABLE_SIGNALS();
-
-#   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
-       /* Make sure marker threads and started and thread local */
-       /* allocation is initialized, in case we didn't get      */
-       /* called from GC_init_parallel();                       */
-        {
-         extern void GC_init_parallel(void);
-         GC_init_parallel();
-       }
-#   endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
-}
-
-#if defined(MSWIN32) || defined(MSWINCE)
-    CRITICAL_SECTION GC_write_cs;
-#endif
-
-#ifdef MSWIN32
-    extern void GC_init_win32 GC_PROTO((void));
-#endif
-
-extern void GC_setpagesize();
-
-#ifdef UNIX_LIKE
-
-extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));
-
-static void looping_handler(sig)
-int sig;
-{
-    GC_err_printf1("Caught signal %d: looping in handler\n", sig);
-    for(;;);
-}
-#endif
-
-#ifdef MSWIN32
-extern GC_bool GC_no_win32_dlls;
-#else
-# define GC_no_win32_dlls FALSE
-#endif
-
-void GC_init_inner()
-{
-#   if !defined(THREADS) && defined(GC_ASSERTIONS)
-        word dummy;
-#   endif
-    word initial_heap_sz = (word)MINHINCR;
-    
-    if (GC_is_initialized) return;
-#   ifdef PRINTSTATS
-      GC_print_stats = 1;
-#   endif
-#   if defined(MSWIN32) || defined(MSWINCE)
-       InitializeCriticalSection(&GC_write_cs);
-#   endif
-
-    if (0 != GETENV("GC_PRINT_STATS")) {
-      GC_print_stats = 1;
-    } 
-    if (0 != GETENV("GC_FIND_LEAK")) {
-      GC_find_leak = 1;
-    }
-    if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
-      GC_all_interior_pointers = 1;
-    }
-    if (0 != GETENV("GC_DONT_GC")) {
-      GC_dont_gc = 1;
-    }
-    if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
-      GC_print_back_height = 1;
-    }
-    if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
-      GC_large_alloc_warn_interval = LONG_MAX;
-    }
-    {
-      char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
-      if (0 != time_limit_string) {
-        long time_limit = atol(time_limit_string);
-        if (time_limit < 5) {
-         WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
-              "or bad syntax: Ignoring\n", 0);
-        } else {
-         GC_time_limit = time_limit;
-        }
-      }
-    }
-    {
-      char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
-      if (0 != interval_string) {
-        long interval = atol(interval_string);
-        if (interval <= 0) {
-         WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
-              "bad value: Ignoring\n", 0);
-        } else {
-         GC_large_alloc_warn_interval = interval;
-        }
-      }
-    }
-#   ifdef UNIX_LIKE
-      if (0 != GETENV("GC_LOOP_ON_ABORT")) {
-        GC_set_and_save_fault_handler(looping_handler);
-      }
-#   endif
-    /* Adjust normal object descriptor for extra allocation.   */
-    if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
-      GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
-    }
-    GC_setpagesize();
-    GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
-    GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
-#   ifdef SEPARATE_GLOBALS
-      GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
-      GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
-#   endif
-#   ifdef MSWIN32
-       GC_init_win32();
-#   endif
-#   if defined(SEARCH_FOR_DATA_START)
-       GC_init_linux_data_start();
-#   endif
-#   if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
-       GC_init_netbsd_elf();
-#   endif
-#   if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)
-        GC_thr_init();
-#   endif
-#   ifdef GC_SOLARIS_THREADS
-       /* We need dirty bits in order to find live stack sections.     */
-        GC_dirty_init();
-#   endif
-#   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
-       || defined(GC_SOLARIS_THREADS)
-      if (GC_stackbottom == 0) {
-       GC_stackbottom = GC_get_stack_base();
-#       if defined(LINUX) && defined(IA64)
-         GC_register_stackbottom = GC_get_register_stack_base();
-#       endif
-      }
-#   endif
-    GC_ASSERT(sizeof (ptr_t) == sizeof(word));
-    GC_ASSERT(sizeof (signed_word) == sizeof(word));
-    GC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
-#   ifndef THREADS
-#     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
-       ABORT(
-         "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
-#     endif
-#     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
-       ABORT(
-         "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
-#     endif
-#     ifdef STACK_GROWS_DOWN
-        GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
-#     else
-        GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
-#     endif
-#   endif
-#   if !defined(_AUX_SOURCE) || defined(__GNUC__)
-      GC_ASSERT((word)(-1) > (word)0);
-      /* word should be unsigned */
-#   endif
-    GC_ASSERT((signed_word)(-1) < (signed_word)0);
-    
-    /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
-    /* might be used.                                                  */
-      GC_register_data_segments();
-    GC_init_headers();
-    GC_bl_init();
-    GC_mark_init();
-    {
-       char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
-       if (sz_str != NULL) {
-         initial_heap_sz = atoi(sz_str);
-         if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
-           WARN("Bad initial heap size %s - ignoring it.\n",
-                sz_str);
-         } 
-         initial_heap_sz = divHBLKSZ(initial_heap_sz);
-       }
-    }
-    if (!GC_expand_hp_inner(initial_heap_sz)) {
-        GC_err_printf0("Can't start up: not enough memory\n");
-        EXIT();
-    }
-    /* Preallocate large object map.  It's otherwise inconvenient to   */
-    /* deal with failure.                                              */
-      if (!GC_add_map_entry((word)0)) {
-        GC_err_printf0("Can't start up: not enough memory\n");
-        EXIT();
-      }
-    GC_register_displacement_inner(0L);
-#   ifdef MERGE_SIZES
-      GC_init_size_map();
-#   endif
-#   ifdef PCR
-      if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
-          != PCR_ERes_okay) {
-          ABORT("Can't lock load state\n");
-      } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
-          ABORT("Can't unlock load state\n");
-      }
-      PCR_IL_Unlock();
-      GC_pcr_install();
-#   endif
-#   if !defined(SMALL_CONFIG)
-      if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
-       GC_ASSERT(!GC_incremental);
-        GC_setpagesize();
-#       ifndef GC_SOLARIS_THREADS
-          GC_dirty_init();
-#       endif
-        GC_ASSERT(GC_words_allocd == 0)
-       GC_incremental = TRUE;
-      }
-#   endif /* !SMALL_CONFIG */
-    /* Get black list set up and/or incrmental GC started */
-      if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
-    GC_is_initialized = TRUE;
-#   ifdef STUBBORN_ALLOC
-       GC_stubborn_init();
-#   endif
-    /* Convince lint that some things are used */
-#   ifdef LINT
-      {
-          extern char * GC_copyright[];
-          extern int GC_read();
-          extern void GC_register_finalizer_no_order();
-          
-          GC_noop(GC_copyright, GC_find_header,
-                  GC_push_one, GC_call_with_alloc_lock, GC_read,
-                  GC_dont_expand,
-#                ifndef NO_DEBUGGING
-                   GC_dump,
-#                endif
-                  GC_register_finalizer_no_order);
-      }
-#   endif
-}
-
-void GC_enable_incremental GC_PROTO(())
-{
-# if !defined(SMALL_CONFIG)
-  if (!GC_find_leak) {
-    DCL_LOCK_STATE;
-    
-    DISABLE_SIGNALS();
-    LOCK();
-    if (GC_incremental) goto out;
-    GC_setpagesize();
-    if (GC_no_win32_dlls) goto out;
-#   ifndef GC_SOLARIS_THREADS
-        GC_dirty_init();
-#   endif
-    if (!GC_is_initialized) {
-        GC_init_inner();
-    }
-    if (GC_incremental) goto out;
-    if (GC_dont_gc) {
-        /* Can't easily do it. */
-        UNLOCK();
-       ENABLE_SIGNALS();
-       return;
-    }
-    if (GC_words_allocd > 0) {
-       /* There may be unmarked reachable objects      */
-       GC_gcollect_inner();
-    }   /* else we're OK in assuming everything's      */
-       /* clean since nothing can point to an          */
-       /* unmarked object.                             */
-    GC_read_dirty();
-    GC_incremental = TRUE;
-out:
-    UNLOCK();
-    ENABLE_SIGNALS();
-  }
-# endif
-}
-
-
-#if defined(MSWIN32) || defined(MSWINCE)
-# define LOG_FILE _T("gc.log")
-
-  HANDLE GC_stdout = 0;
-
-  void GC_deinit()
-  {
-      if (GC_is_initialized) {
-       DeleteCriticalSection(&GC_write_cs);
-      }
-  }
-
-  int GC_write(buf, len)
-  GC_CONST char * buf;
-  size_t len;
-  {
-      BOOL tmp;
-      DWORD written;
-      if (len == 0)
-         return 0;
-      EnterCriticalSection(&GC_write_cs);
-      if (GC_stdout == INVALID_HANDLE_VALUE) {
-         return -1;
-      } else if (GC_stdout == 0) {
-         GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
-                                FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
-                                NULL); 
-         if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed");
-      }
-      tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
-      if (!tmp)
-         DebugBreak();
-      LeaveCriticalSection(&GC_write_cs);
-      return tmp ? (int)written : -1;
-  }
-
-#endif
-
-#if defined(OS2) || defined(MACOS)
-FILE * GC_stdout = NULL;
-FILE * GC_stderr = NULL;
-int GC_tmp;  /* Should really be local ... */
-
-  void GC_set_files()
-  {
-      if (GC_stdout == NULL) {
-       GC_stdout = stdout;
-    }
-    if (GC_stderr == NULL) {
-       GC_stderr = stderr;
-    }
-  }
-#endif
-
-#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
-  int GC_stdout = 1;
-  int GC_stderr = 2;
-# if !defined(AMIGA)
-#   include <unistd.h>
-# endif
-#endif
-
-#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
-    && !defined(MACOS)  && !defined(ECOS) && !defined(NOSYS)
-int GC_write(fd, buf, len)
-int fd;
-GC_CONST char *buf;
-size_t len;
-{
-     register int bytes_written = 0;
-     register int result;
-     
-     while (bytes_written < len) {
-#      ifdef GC_SOLARIS_THREADS
-           result = syscall(SYS_write, fd, buf + bytes_written,
-                                           len - bytes_written);
-#      else
-           result = write(fd, buf + bytes_written, len - bytes_written);
-#      endif
-       if (-1 == result) return(result);
-       bytes_written += result;
-    }
-    return(bytes_written);
-}
-#endif /* UN*X */
-
-#ifdef ECOS
-int GC_write(fd, buf, len)
-{
-  _Jv_diag_write (buf, len);
-  return len;
-}
-#endif
-
-#ifdef NOSYS
-int GC_write(fd, buf, len)
-{
-  /* No writing.  */
-  return len;
-}
-#endif
-
-
-#if defined(MSWIN32) || defined(MSWINCE)
-#   define WRITE(f, buf, len) GC_write(buf, len)
-#else
-#   if defined(OS2) || defined(MACOS)
-#   define WRITE(f, buf, len) (GC_set_files(), \
-                              GC_tmp = fwrite((buf), 1, (len), (f)), \
-                              fflush(f), GC_tmp)
-#   else
-#     define WRITE(f, buf, len) GC_write((f), (buf), (len))
-#   endif
-#endif
-
-/* A version of printf that is unlikely to call malloc, and is thus safer */
-/* to call from the collector in case malloc has been bound to GC_malloc. */
-/* Assumes that no more than 1023 characters are written at once.        */
-/* Assumes that all arguments have been converted to something of the    */
-/* same size as long, and that the format conversions expect something   */
-/* of that size.                                                         */
-void GC_printf(format, a, b, c, d, e, f)
-GC_CONST char * format;
-long a, b, c, d, e, f;
-{
-    char buf[1025];
-    
-    if (GC_quiet) return;
-    buf[1024] = 0x15;
-    (void) sprintf(buf, format, a, b, c, d, e, f);
-    if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
-    if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
-}
-
-void GC_err_printf(format, a, b, c, d, e, f)
-GC_CONST char * format;
-long a, b, c, d, e, f;
-{
-    char buf[1025];
-    
-    buf[1024] = 0x15;
-    (void) sprintf(buf, format, a, b, c, d, e, f);
-    if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
-    if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
-}
-
-void GC_err_puts(s)
-GC_CONST char *s;
-{
-    if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
-}
-
-#if defined(LINUX) && !defined(SMALL_CONFIG)
-void GC_err_write(buf, len)
-GC_CONST char *buf;
-size_t len;
-{
-    if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
-}
-#endif
-
-# if defined(__STDC__) || defined(__cplusplus)
-    void GC_default_warn_proc(char *msg, GC_word arg)
-# else
-    void GC_default_warn_proc(msg, arg)
-    char *msg;
-    GC_word arg;
-# endif
-{
-    GC_err_printf1(msg, (unsigned long)arg);
-}
-
-GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
-
-# if defined(__STDC__) || defined(__cplusplus)
-    GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
-# else
-    GC_warn_proc GC_set_warn_proc(p)
-    GC_warn_proc p;
-# endif
-{
-    GC_warn_proc result;
-
-    LOCK();
-    result = GC_current_warn_proc;
-    GC_current_warn_proc = p;
-    UNLOCK();
-    return(result);
-}
-
-
-#ifndef PCR
-void GC_abort(msg)
-GC_CONST char * msg;
-{
-#   if defined(MSWIN32)
-      (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
-      DebugBreak();
-#   else
-      GC_err_printf1("%s\n", msg);
-#   endif
-    if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
-           /* In many cases it's easier to debug a running process.    */
-           /* It's arguably nicer to sleep, but that makes it harder   */
-           /* to look at the thread if the debugger doesn't know much  */
-           /* about threads.                                           */
-           for(;;) {}
-    }
-#   ifdef MSWIN32
-       DebugBreak();
-#   else
-        (void) abort();
-#   endif
-}
-#endif
-
-#ifdef NEED_CALLINFO
-
-#ifdef HAVE_BUILTIN_BACKTRACE
-# include <execinfo.h>
-# ifdef LINUX
-#   include <unistd.h>
-# endif
-#endif
-
-void GC_print_callers (info)
-struct callinfo info[NFRAMES];
-{
-    register int i;
-    
-#   if NFRAMES == 1
-      GC_err_printf0("\tCaller at allocation:\n");
-#   else
-      GC_err_printf0("\tCall chain at allocation:\n");
-#   endif
-    for (i = 0; i < NFRAMES; i++) {
-       if (info[i].ci_pc == 0) break;
-#      if NARGS > 0
-       {
-         int j;
-
-         GC_err_printf0("\t\targs: ");
-         for (j = 0; j < NARGS; j++) {
-           if (j != 0) GC_err_printf0(", ");
-           GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
-                                       ~(info[i].ci_arg[j]));
-         }
-         GC_err_printf0("\n");
-       }
-#      endif
-#      if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC)
-         /* Unfortunately backtrace_symbols calls malloc, which makes  */
-         /* it dangersous if that has been redirected.                 */
-         {
-           char **sym_name =
-             backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
-           char *name = sym_name[0];
-           GC_bool found_it = (strchr(name, '(') != 0);
-           FILE *pipe;
-#          ifdef LINUX
-             if (!found_it) {
-#              define EXE_SZ 100
-               static char exe_name[EXE_SZ];
-#              define CMD_SZ 200
-               char cmd_buf[CMD_SZ];
-#              define RESULT_SZ 200
-               static char result_buf[RESULT_SZ];
-               size_t result_len;
-               static GC_bool found_exe_name = FALSE;
-               static GC_bool will_fail = FALSE;
-               int ret_code;
-               /* Unfortunately, this is the common case for the       */
-               /* main executable.                                     */
-               /* Try to get it via a hairy and expensive scheme.      */
-               /* First we get the name of the executable:             */
-               if (will_fail) goto out;
-               if (!found_exe_name) { 
-                 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
-                 if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {
-                   will_fail = TRUE;   /* Dont try again. */
-                   goto out;
-                 }
-                 exe_name[ret_code] = '\0';
-                 found_exe_name = TRUE;
-               }
-               /* Then we use popen to start addr2line -e <exe> <addr> */
-               /* There are faster ways to do this, but hopefully this */
-               /* isn't time critical.                                 */
-               sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name,
-                                (unsigned long)info[i].ci_pc);
-               pipe = popen(cmd_buf, "r");
-               if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) {
-                 will_fail = TRUE;
-                 goto out;
-               }
-               result_len = strlen(result_buf);
-               if (result_buf[result_len - 1] == '\n') --result_len;
-               if (result_buf[0] == '?'
-                   || result_buf[result_len-2] == ':' 
-                      && result_buf[result_len-1] == '0')
-                   goto out;
-               if (result_len < RESULT_SZ - 25) {
-                 /* Add in hex address */
-                   sprintf(result_buf + result_len, " [0x%lx]",
-                         (unsigned long)info[i].ci_pc);
-               }
-               name = result_buf;
-               pclose(pipe);
-               out:
-             }
-#          endif
-           GC_err_printf1("\t\t%s\n", name);
-           free(sym_name);
-         }
-#      else
-         GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
-#      endif
-    }
-}
-
-#endif /* SAVE_CALL_CHAIN */
-
-/* Needed by SRC_M3, gcj, and should perhaps be the official interface */
-/* to GC_dont_gc.                                                      */
-void GC_enable()
-{
-    GC_dont_gc--;
-}
-
-void GC_disable()
-{
-    GC_dont_gc++;
-}
-
-#if !defined(NO_DEBUGGING)
-
-void GC_dump()
-{
-    GC_printf0("***Static roots:\n");
-    GC_print_static_roots();
-    GC_printf0("\n***Heap sections:\n");
-    GC_print_heap_sects();
-    GC_printf0("\n***Free blocks:\n");
-    GC_print_hblkfreelist();
-    GC_printf0("\n***Blocks in use:\n");
-    GC_print_block_list();
-}
-
-#endif /* NO_DEBUGGING */