Commit 56ba54b4 by Tom Tromey

This commit was generated by cvs2svn to compensate for changes in r27853,

which included commits to RCS files with non-trunk default branches.

From-SVN: r27854
parent 2fa39a0e
...@@ -361,7 +361,6 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n) ...@@ -361,7 +361,6 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n)
return(CORD_substr_closure(x, i, n, CORD_index_access_fn)); return(CORD_substr_closure(x, i, n, CORD_index_access_fn));
} else { } else {
register char * result = GC_MALLOC_ATOMIC(n+1); register char * result = GC_MALLOC_ATOMIC(n+1);
register char * p = result;
if (result == 0) OUT_OF_MEMORY; if (result == 0) OUT_OF_MEMORY;
strncpy(result, x+i, n); strncpy(result, x+i, n);
......
...@@ -231,8 +231,9 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) ...@@ -231,8 +231,9 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
goto done; goto done;
case 'c': case 'c':
if (width == NONE && prec == NONE) { if (width == NONE && prec == NONE) {
register char c = va_arg(args, char); register char c;
c = va_arg(args, char);
CORD_ec_append(result, c); CORD_ec_append(result, c);
goto done; goto done;
} }
......
...@@ -565,7 +565,6 @@ int argc; ...@@ -565,7 +565,6 @@ int argc;
char ** argv; char ** argv;
{ {
int c; int c;
CORD initial;
#if defined(MACINTOSH) #if defined(MACINTOSH)
console_options.title = "\pDumb Editor"; console_options.title = "\pDumb Editor";
......
...@@ -268,6 +268,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, ...@@ -268,6 +268,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
case WM_DESTROY: case WM_DESTROY:
PostQuitMessage (0); PostQuitMessage (0);
GC_win32_free_heap();
return 0; return 0;
case WM_PAINT: case WM_PAINT:
......
...@@ -36,11 +36,19 @@ ...@@ -36,11 +36,19 @@
#endif #endif
#if defined(_MSC_VER) && defined(_DLL) #if defined(_MSC_VER) && defined(_DLL)
#ifdef GC_BUILD # ifdef GC_BUILD
#define GC_API __declspec(dllexport) # define GC_API __declspec(dllexport)
#else # else
#define GC_API __declspec(dllimport) # define GC_API __declspec(dllimport)
# endif
#endif #endif
#if defined(__WATCOMC__) && defined(GC_DLL)
# ifdef GC_BUILD
# define GC_API extern __declspec(dllexport)
# else
# define GC_API extern __declspec(dllimport)
# endif
#endif #endif
#ifndef GC_API #ifndef GC_API
...@@ -126,7 +134,19 @@ GC_API GC_word GC_max_retries; ...@@ -126,7 +134,19 @@ GC_API GC_word GC_max_retries;
/* reporting out of memory after heap */ /* reporting out of memory after heap */
/* expansion fails. Initially 0. */ /* expansion fails. Initially 0. */
GC_API char *GC_stackbottom; /* Cool end of user stack. */
/* May be set in the client prior to */
/* calling any GC_ routines. This */
/* avoids some overhead, and */
/* potentially some signals that can */
/* confuse debuggers. Otherwise the */
/* collector attempts to set it */
/* automatically. */
/* For multithreaded code, this is the */
/* cold end of the stack for the */
/* primordial thread. */
/* Public procedures */ /* Public procedures */
/* /*
* general purpose allocation routines, with roughly malloc calling conv. * general purpose allocation routines, with roughly malloc calling conv.
...@@ -193,8 +213,8 @@ GC_API size_t GC_size GC_PROTO((GC_PTR object_addr)); ...@@ -193,8 +213,8 @@ GC_API size_t GC_size GC_PROTO((GC_PTR object_addr));
/* If the argument is stubborn, the result will have changes enabled. */ /* If the argument is stubborn, the result will have changes enabled. */
/* It is an error to have changes enabled for the original object. */ /* It is an error to have changes enabled for the original object. */
/* Follows ANSI comventions for NULL old_object. */ /* Follows ANSI comventions for NULL old_object. */
GC_API GC_PTR GC_realloc GC_PROTO((GC_PTR old_object, GC_API GC_PTR GC_realloc
size_t new_size_in_bytes)); GC_PROTO((GC_PTR old_object, size_t new_size_in_bytes));
/* Explicitly increase the heap size. */ /* Explicitly increase the heap size. */
/* Returns 0 on failure, 1 on success. */ /* Returns 0 on failure, 1 on success. */
...@@ -248,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void)); ...@@ -248,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void));
/* than normal pause times for incremental collection. However, */ /* than normal pause times for incremental collection. However, */
/* aborted collections do no useful work; the next collection needs */ /* aborted collections do no useful work; the next collection needs */
/* to start from the beginning. */ /* to start from the beginning. */
/* Return 0 if the collection was aborted, 1 if it succeeded. */
typedef int (* GC_stop_func) GC_PROTO((void)); typedef int (* GC_stop_func) GC_PROTO((void));
GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func)); GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
...@@ -604,6 +625,10 @@ GC_API void (*GC_is_valid_displacement_print_proc) ...@@ -604,6 +625,10 @@ GC_API void (*GC_is_valid_displacement_print_proc)
GC_API void (*GC_is_visible_print_proc) GC_API void (*GC_is_visible_print_proc)
GC_PROTO((GC_PTR p)); GC_PROTO((GC_PTR p));
#if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS)
# define SOLARIS_THREADS
#endif
#ifdef SOLARIS_THREADS #ifdef SOLARIS_THREADS
/* We need to intercept calls to many of the threads primitives, so */ /* We need to intercept calls to many of the threads primitives, so */
/* that we can locate thread stacks and stop the world. */ /* that we can locate thread stacks and stop the world. */
...@@ -660,7 +685,10 @@ GC_API void (*GC_is_visible_print_proc) ...@@ -660,7 +685,10 @@ GC_API void (*GC_is_visible_print_proc)
#endif /* IRIX_THREADS || LINUX_THREADS */ #endif /* IRIX_THREADS || LINUX_THREADS */
#if defined(THREADS) && !defined(SRC_M3) # if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
defined(IRIX_JDK_THREADS)
/* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */ /* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */ /* word. Its use can greatly reduce lock contention problems, since */
/* the allocation lock can be acquired and released many fewer times. */ /* the allocation lock can be acquired and released many fewer times. */
...@@ -691,6 +719,13 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ ...@@ -691,6 +719,13 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
# endif # endif
#endif #endif
#if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
|| defined(_WIN32)
/* win32S may not free all resources on process exit. */
/* This explicitly deallocates the heap. */
GC_API void GC_win32_free_heap ();
#endif
#ifdef __cplusplus #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */
#endif #endif
......
...@@ -36,11 +36,19 @@ ...@@ -36,11 +36,19 @@
#endif #endif
#if defined(_MSC_VER) && defined(_DLL) #if defined(_MSC_VER) && defined(_DLL)
#ifdef GC_BUILD # ifdef GC_BUILD
#define GC_API __declspec(dllexport) # define GC_API __declspec(dllexport)
#else # else
#define GC_API __declspec(dllimport) # define GC_API __declspec(dllimport)
# endif
#endif #endif
#if defined(__WATCOMC__) && defined(GC_DLL)
# ifdef GC_BUILD
# define GC_API extern __declspec(dllexport)
# else
# define GC_API extern __declspec(dllimport)
# endif
#endif #endif
#ifndef GC_API #ifndef GC_API
...@@ -126,7 +134,19 @@ GC_API GC_word GC_max_retries; ...@@ -126,7 +134,19 @@ GC_API GC_word GC_max_retries;
/* reporting out of memory after heap */ /* reporting out of memory after heap */
/* expansion fails. Initially 0. */ /* expansion fails. Initially 0. */
GC_API char *GC_stackbottom; /* Cool end of user stack. */
/* May be set in the client prior to */
/* calling any GC_ routines. This */
/* avoids some overhead, and */
/* potentially some signals that can */
/* confuse debuggers. Otherwise the */
/* collector attempts to set it */
/* automatically. */
/* For multithreaded code, this is the */
/* cold end of the stack for the */
/* primordial thread. */
/* Public procedures */ /* Public procedures */
/* /*
* general purpose allocation routines, with roughly malloc calling conv. * general purpose allocation routines, with roughly malloc calling conv.
...@@ -193,8 +213,8 @@ GC_API size_t GC_size GC_PROTO((GC_PTR object_addr)); ...@@ -193,8 +213,8 @@ GC_API size_t GC_size GC_PROTO((GC_PTR object_addr));
/* If the argument is stubborn, the result will have changes enabled. */ /* If the argument is stubborn, the result will have changes enabled. */
/* It is an error to have changes enabled for the original object. */ /* It is an error to have changes enabled for the original object. */
/* Follows ANSI comventions for NULL old_object. */ /* Follows ANSI comventions for NULL old_object. */
GC_API GC_PTR GC_realloc GC_PROTO((GC_PTR old_object, GC_API GC_PTR GC_realloc
size_t new_size_in_bytes)); GC_PROTO((GC_PTR old_object, size_t new_size_in_bytes));
/* Explicitly increase the heap size. */ /* Explicitly increase the heap size. */
/* Returns 0 on failure, 1 on success. */ /* Returns 0 on failure, 1 on success. */
...@@ -248,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void)); ...@@ -248,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void));
/* than normal pause times for incremental collection. However, */ /* than normal pause times for incremental collection. However, */
/* aborted collections do no useful work; the next collection needs */ /* aborted collections do no useful work; the next collection needs */
/* to start from the beginning. */ /* to start from the beginning. */
/* Return 0 if the collection was aborted, 1 if it succeeded. */
typedef int (* GC_stop_func) GC_PROTO((void)); typedef int (* GC_stop_func) GC_PROTO((void));
GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func)); GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
...@@ -604,6 +625,10 @@ GC_API void (*GC_is_valid_displacement_print_proc) ...@@ -604,6 +625,10 @@ GC_API void (*GC_is_valid_displacement_print_proc)
GC_API void (*GC_is_visible_print_proc) GC_API void (*GC_is_visible_print_proc)
GC_PROTO((GC_PTR p)); GC_PROTO((GC_PTR p));
#if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS)
# define SOLARIS_THREADS
#endif
#ifdef SOLARIS_THREADS #ifdef SOLARIS_THREADS
/* We need to intercept calls to many of the threads primitives, so */ /* We need to intercept calls to many of the threads primitives, so */
/* that we can locate thread stacks and stop the world. */ /* that we can locate thread stacks and stop the world. */
...@@ -660,7 +685,10 @@ GC_API void (*GC_is_visible_print_proc) ...@@ -660,7 +685,10 @@ GC_API void (*GC_is_visible_print_proc)
#endif /* IRIX_THREADS || LINUX_THREADS */ #endif /* IRIX_THREADS || LINUX_THREADS */
#if defined(THREADS) && !defined(SRC_M3) # if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
defined(IRIX_JDK_THREADS)
/* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */ /* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */ /* word. Its use can greatly reduce lock contention problems, since */
/* the allocation lock can be acquired and released many fewer times. */ /* the allocation lock can be acquired and released many fewer times. */
...@@ -691,6 +719,13 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ ...@@ -691,6 +719,13 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
# endif # endif
#endif #endif
#if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
|| defined(_WIN32)
/* win32S may not free all resources on process exit. */
/* This explicitly deallocates the heap. */
GC_API void GC_win32_free_heap ();
#endif
#ifdef __cplusplus #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */
#endif #endif
......
...@@ -133,7 +133,8 @@ uses explicit invocation. ...@@ -133,7 +133,8 @@ uses explicit invocation.
#endif #endif
#if ! defined( OPERATOR_NEW_ARRAY ) \ #if ! defined( OPERATOR_NEW_ARRAY ) \
&& (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6)) && (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \
|| __WATCOMC__ >= 1050)
# define OPERATOR_NEW_ARRAY # define OPERATOR_NEW_ARRAY
#endif #endif
...@@ -212,6 +213,8 @@ inline void* gc::operator new( size_t size ) { ...@@ -212,6 +213,8 @@ inline void* gc::operator new( size_t size ) {
inline void* gc::operator new( size_t size, GCPlacement gcp ) { inline void* gc::operator new( size_t size, GCPlacement gcp ) {
if (gcp == GC) if (gcp == GC)
return GC_MALLOC( size ); return GC_MALLOC( size );
else if (gcp == PointerFreeGC)
return GC_MALLOC_ATOMIC( size );
else else
return GC_MALLOC_UNCOLLECTABLE( size );} return GC_MALLOC_UNCOLLECTABLE( size );}
...@@ -234,7 +237,7 @@ inline void gc::operator delete[]( void* obj ) { ...@@ -234,7 +237,7 @@ inline void gc::operator delete[]( void* obj ) {
inline gc_cleanup::~gc_cleanup() { inline gc_cleanup::~gc_cleanup() {
GC_REGISTER_FINALIZER_IGNORE_SELF( this, 0, 0, 0, 0 );} GC_REGISTER_FINALIZER_IGNORE_SELF( GC_base(this), 0, 0, 0, 0 );}
inline void gc_cleanup::cleanup( void* obj, void* displ ) { inline void gc_cleanup::cleanup( void* obj, void* displ ) {
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
......
...@@ -42,7 +42,7 @@ typedef GC_word word; ...@@ -42,7 +42,7 @@ typedef GC_word word;
typedef GC_signed_word signed_word; typedef GC_signed_word signed_word;
# ifndef CONFIG_H # ifndef CONFIG_H
# include "config.h" # include "gcconfig.h"
# endif # endif
# ifndef HEADERS_H # ifndef HEADERS_H
...@@ -336,6 +336,9 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -336,6 +336,9 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
/* space is assumed to be cleared. */ /* space is assumed to be cleared. */
/* In the case os USE_MMAP, the argument must also be a */ /* In the case os USE_MMAP, the argument must also be a */
/* physical page size. */ /* physical page size. */
/* GET_MEM is currently not assumed to retrieve 0 filled space, */
/* though we should perhaps take advantage of the case in which */
/* does. */
# ifdef PCR # ifdef PCR
char * real_malloc(); char * real_malloc();
# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ # define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
...@@ -434,7 +437,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -434,7 +437,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# ifdef LINUX_THREADS # ifdef LINUX_THREADS
# include <pthread.h> # include <pthread.h>
# ifdef __i386__ # ifdef __i386__
inline static GC_test_and_set(volatile unsigned int *addr) { inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval; int oldval;
/* Note: the "xchg" instruction does not need a "lock" prefix */ /* Note: the "xchg" instruction does not need a "lock" prefix */
__asm__ __volatile__("xchgl %0, %1" __asm__ __volatile__("xchgl %0, %1"
...@@ -475,14 +478,15 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -475,14 +478,15 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
} }
# define EXIT_GC() GC_collecting = 0; # define EXIT_GC() GC_collecting = 0;
# endif /* LINUX_THREADS */ # endif /* LINUX_THREADS */
# ifdef IRIX_THREADS # if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
# include <pthread.h> # include <pthread.h>
# include <mutex.h> # include <mutex.h>
# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
# define GC_test_and_set(addr, v) test_and_set(addr,v) # define GC_test_and_set(addr, v) test_and_set(addr,v)
# else # else
# define GC_test_and_set(addr, v) __test_and_set(addr,v) # define GC_test_and_set(addr, v) __test_and_set(addr,v)
# endif # endif
extern unsigned long GC_allocate_lock; extern unsigned long GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */ /* This is not a mutex because mutexes that obey the (optional) */
...@@ -501,10 +505,17 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -501,10 +505,17 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
# else # else
# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); } # define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
# if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) # if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
&& defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700
# define UNLOCK() __lock_release(&GC_allocate_lock) # define UNLOCK() __lock_release(&GC_allocate_lock)
# else # else
# define UNLOCK() GC_allocate_lock = 0 /* The function call in the following should prevent the */
/* compiler from moving assignments to below the UNLOCK. */
/* This is probably not necessary for ucode or gcc 2.8. */
/* It may be necessary for Ragnarok and future gcc */
/* versions. */
# define UNLOCK() { GC_noop1(&GC_allocate_lock); \
*(volatile unsigned long *)(&GC_allocate_lock) = 0; }
# endif # endif
# endif # endif
extern GC_bool GC_collecting; extern GC_bool GC_collecting;
...@@ -513,7 +524,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -513,7 +524,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
GC_collecting = 1; \ GC_collecting = 1; \
} }
# define EXIT_GC() GC_collecting = 0; # define EXIT_GC() GC_collecting = 0;
# endif /* IRIX_THREADS */ # endif /* IRIX_THREADS || IRIX_JDK_THREADS */
# ifdef WIN32_THREADS # ifdef WIN32_THREADS
# include <windows.h> # include <windows.h>
GC_API CRITICAL_SECTION GC_allocate_ml; GC_API CRITICAL_SECTION GC_allocate_ml;
...@@ -567,7 +578,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -567,7 +578,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \ # if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \
|| defined(MSWIN32) || defined(MACOS) || defined(DJGPP) \ || defined(MSWIN32) || defined(MACOS) || defined(DJGPP) \
|| defined(NO_SIGNALS) || defined(IRIX_THREADS) \ || defined(NO_SIGNALS) || defined(IRIX_THREADS) \
|| defined(LINUX_THREADS) || defined(IRIX_JDK_THREADS) || defined(LINUX_THREADS)
/* Also useful for debugging. */ /* Also useful for debugging. */
/* Should probably use thr_sigsetmask for SOLARIS_THREADS. */ /* Should probably use thr_sigsetmask for SOLARIS_THREADS. */
# define DISABLE_SIGNALS() # define DISABLE_SIGNALS()
...@@ -595,7 +606,8 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -595,7 +606,8 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
PCR_waitForever); PCR_waitForever);
# else # else
# if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \ # if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
|| defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(IRIX_THREADS) || defined(LINUX_THREADS) \
|| defined(IRIX_JDK_THREADS)
void GC_stop_world(); void GC_stop_world();
void GC_start_world(); void GC_start_world();
# define STOP_WORLD() GC_stop_world() # define STOP_WORLD() GC_stop_world()
...@@ -864,7 +876,69 @@ struct hblk { ...@@ -864,7 +876,69 @@ struct hblk {
/* Object free list link */ /* Object free list link */
# define obj_link(p) (*(ptr_t *)(p)) # define obj_link(p) (*(ptr_t *)(p))
/* lists of all heap blocks and free lists */ /* The type of mark procedures. This really belongs in gc_mark.h. */
/* But we put it here, so that we can avoid scanning the mark proc */
/* table. */
typedef struct ms_entry * (*mark_proc)(/* word * addr, mark_stack_ptr,
mark_stack_limit, env */);
# define LOG_MAX_MARK_PROCS 6
# define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
/* Root sets. Logically private to mark_rts.c. But we don't want the */
/* tables scanned, so we put them here. */
/* MAX_ROOT_SETS is the maximum number of ranges that can be */
/* registered as static roots. */
# ifdef LARGE_CONFIG
# define MAX_ROOT_SETS 4096
# else
# ifdef PCR
# define MAX_ROOT_SETS 1024
# else
# ifdef MSWIN32
# define MAX_ROOT_SETS 512
/* Under NT, we add only written pages, which can result */
/* in many small root sets. */
# else
# define MAX_ROOT_SETS 64
# endif
# endif
# endif
# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
/* Maximum number of segments that can be excluded from root sets. */
/*
* Data structure for excluded static roots.
*/
struct exclusion {
ptr_t e_start;
ptr_t e_end;
};
/* Data structure for list of root sets. */
/* We keep a hash table, so that we can filter out duplicate additions. */
/* Under Win32, we need to do a better job of filtering overlaps, so */
/* we resort to sequential search, and pay the price. */
struct roots {
ptr_t r_start;
ptr_t r_end;
# ifndef MSWIN32
struct roots * r_next;
# endif
GC_bool r_tmp;
/* Delete before registering new dynamic libraries */
};
#ifndef MSWIN32
/* Size of hash table index to roots. */
# define LOG_RT_SIZE 6
# define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */
#endif
/* Lists of all heap blocks and free lists */
/* as well as other random data structures */
/* that should not be scanned by the */
/* collector. */
/* These are grouped together in a struct */ /* These are grouped together in a struct */
/* so that they can be easily skipped by the */ /* so that they can be easily skipped by the */
/* GC_mark routine. */ /* GC_mark routine. */
...@@ -904,7 +978,10 @@ struct _GC_arrays { ...@@ -904,7 +978,10 @@ struct _GC_arrays {
word _mem_freed; word _mem_freed;
/* Number of explicitly deallocated words of memory */ /* Number of explicitly deallocated words of memory */
/* since last collection. */ /* since last collection. */
mark_proc _mark_procs[MAX_MARK_PROCS];
/* Table of user-defined mark procedures. There is */
/* a small number of these, which can be referenced */
/* by DS_PROC mark descriptors. See gc_mark.h. */
ptr_t _objfreelist[MAXOBJSZ+1]; ptr_t _objfreelist[MAXOBJSZ+1];
/* free list for objects */ /* free list for objects */
ptr_t _aobjfreelist[MAXOBJSZ+1]; ptr_t _aobjfreelist[MAXOBJSZ+1];
...@@ -986,17 +1063,24 @@ struct _GC_arrays { ...@@ -986,17 +1063,24 @@ struct _GC_arrays {
/* GC_modws_valid_offsets[i%sizeof(word)] */ /* GC_modws_valid_offsets[i%sizeof(word)] */
# endif # endif
# ifdef STUBBORN_ALLOC # ifdef STUBBORN_ALLOC
page_hash_table _changed_pages; page_hash_table _changed_pages;
/* Stubborn object pages that were changes since last call to */ /* Stubborn object pages that were changes since last call to */
/* GC_read_changed. */ /* GC_read_changed. */
page_hash_table _prev_changed_pages; page_hash_table _prev_changed_pages;
/* Stubborn object pages that were changes before last call to */ /* Stubborn object pages that were changes before last call to */
/* GC_read_changed. */ /* GC_read_changed. */
# endif # endif
# if defined(PROC_VDB) || defined(MPROTECT_VDB) # if defined(PROC_VDB) || defined(MPROTECT_VDB)
page_hash_table _grungy_pages; /* Pages that were dirty at last */ page_hash_table _grungy_pages; /* Pages that were dirty at last */
/* GC_read_dirty. */ /* GC_read_dirty. */
# endif # endif
# ifdef MPROTECT_VDB
VOLATILE page_hash_table _dirty_pages;
/* Pages dirtied since last GC_read_dirty. */
# endif
# ifdef PROC_VDB
page_hash_table _written_pages; /* Pages ever dirtied */
# endif
# ifdef LARGE_CONFIG # ifdef LARGE_CONFIG
# if CPP_WORDSZ > 32 # if CPP_WORDSZ > 32
# define MAX_HEAP_SECTS 4096 /* overflows at roughly 64 GB */ # define MAX_HEAP_SECTS 4096 /* overflows at roughly 64 GB */
...@@ -1013,6 +1097,11 @@ struct _GC_arrays { ...@@ -1013,6 +1097,11 @@ struct _GC_arrays {
ptr_t _heap_bases[MAX_HEAP_SECTS]; ptr_t _heap_bases[MAX_HEAP_SECTS];
/* Start address of memory regions obtained from kernel. */ /* Start address of memory regions obtained from kernel. */
# endif # endif
struct roots _static_roots[MAX_ROOT_SETS];
# ifndef MSWIN32
struct roots * _root_index[RT_SIZE];
# endif
struct exclusion _excl_table[MAX_EXCLUSIONS];
/* Block header index; see gc_headers.h */ /* Block header index; see gc_headers.h */
bottom_index * _all_nils; bottom_index * _all_nils;
bottom_index * _top_index [TOP_SZ]; bottom_index * _top_index [TOP_SZ];
...@@ -1049,6 +1138,7 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; ...@@ -1049,6 +1138,7 @@ GC_API GC_FAR struct _GC_arrays GC_arrays;
# define GC_words_finalized GC_arrays._words_finalized # define GC_words_finalized GC_arrays._words_finalized
# define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
# define GC_mem_freed GC_arrays._mem_freed # define GC_mem_freed GC_arrays._mem_freed
# define GC_mark_procs GC_arrays._mark_procs
# define GC_heapsize GC_arrays._heapsize # define GC_heapsize GC_arrays._heapsize
# define GC_max_heapsize GC_arrays._max_heapsize # define GC_max_heapsize GC_arrays._max_heapsize
# define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc
...@@ -1057,11 +1147,20 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; ...@@ -1057,11 +1147,20 @@ GC_API GC_FAR struct _GC_arrays GC_arrays;
# ifdef MSWIN32 # ifdef MSWIN32
# define GC_heap_bases GC_arrays._heap_bases # define GC_heap_bases GC_arrays._heap_bases
# endif # endif
# define GC_static_roots GC_arrays._static_roots
# define GC_root_index GC_arrays._root_index
# define GC_excl_table GC_arrays._excl_table
# define GC_all_nils GC_arrays._all_nils # define GC_all_nils GC_arrays._all_nils
# define GC_top_index GC_arrays._top_index # define GC_top_index GC_arrays._top_index
# if defined(PROC_VDB) || defined(MPROTECT_VDB) # if defined(PROC_VDB) || defined(MPROTECT_VDB)
# define GC_grungy_pages GC_arrays._grungy_pages # define GC_grungy_pages GC_arrays._grungy_pages
# endif # endif
# ifdef MPROTECT_VDB
# define GC_dirty_pages GC_arrays._dirty_pages
# endif
# ifdef PROC_VDB
# define GC_written_pages GC_arrays._written_pages
# endif
# ifdef GATHERSTATS # ifdef GATHERSTATS
# define GC_composite_in_use GC_arrays._composite_in_use # define GC_composite_in_use GC_arrays._composite_in_use
# define GC_atomic_in_use GC_arrays._atomic_in_use # define GC_atomic_in_use GC_arrays._atomic_in_use
...@@ -1073,11 +1172,9 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; ...@@ -1073,11 +1172,9 @@ GC_API GC_FAR struct _GC_arrays GC_arrays;
# define beginGC_arrays ((ptr_t)(&GC_arrays)) # define beginGC_arrays ((ptr_t)(&GC_arrays))
# define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays)) # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))
GC_API word GC_fo_entries; /* Object kinds: */
# define MAXOBJKINDS 16 # define MAXOBJKINDS 16
/* Object kinds: */
extern struct obj_kind { extern struct obj_kind {
ptr_t *ok_freelist; /* Array of free listheaders for this kind of object */ ptr_t *ok_freelist; /* Array of free listheaders for this kind of object */
/* Point either to GC_arrays or to storage allocated */ /* Point either to GC_arrays or to storage allocated */
...@@ -1091,8 +1188,14 @@ extern struct obj_kind { ...@@ -1091,8 +1188,14 @@ extern struct obj_kind {
/* Add object size in bytes to descriptor */ /* Add object size in bytes to descriptor */
/* template to obtain descriptor. Otherwise */ /* template to obtain descriptor. Otherwise */
/* template is used as is. */ /* template is used as is. */
GC_bool ok_init; /* Clear objects before putting them on the free list. */ GC_bool ok_init; /* Clear objects before putting them on the free list. */
} GC_obj_kinds[MAXOBJKINDS]; } GC_obj_kinds[MAXOBJKINDS];
# define endGC_obj_kinds (((ptr_t)(&GC_obj_kinds)) + (sizeof GC_obj_kinds))
# define end_gc_area ((ptr_t)endGC_arrays == (ptr_t)(&GC_obj_kinds) ? \
endGC_obj_kinds : endGC_arrays)
/* Predefined kinds: */ /* Predefined kinds: */
# define PTRFREE 0 # define PTRFREE 0
# define NORMAL 1 # define NORMAL 1
...@@ -1108,6 +1211,8 @@ extern struct obj_kind { ...@@ -1108,6 +1211,8 @@ extern struct obj_kind {
extern int GC_n_kinds; extern int GC_n_kinds;
GC_API word GC_fo_entries;
extern word GC_n_heap_sects; /* Number of separately added heap */ extern word GC_n_heap_sects; /* Number of separately added heap */
/* sections. */ /* sections. */
...@@ -1142,17 +1247,19 @@ extern GC_bool GC_is_initialized; /* GC_init() has been run. */ ...@@ -1142,17 +1247,19 @@ extern GC_bool GC_is_initialized; /* GC_init() has been run. */
extern GC_bool GC_objects_are_marked; /* There are marked objects in */ extern GC_bool GC_objects_are_marked; /* There are marked objects in */
/* the heap. */ /* the heap. */
extern GC_bool GC_incremental; /* Using incremental/generational collection. */ #ifndef SMALL_CONFIG
extern GC_bool GC_incremental;
/* Using incremental/generational collection. */
#else
# define GC_incremental TRUE
/* Hopefully allow optimizer to remove some code. */
#endif
extern GC_bool GC_dirty_maintained; extern GC_bool GC_dirty_maintained;
/* Dirty bits are being maintained, */ /* Dirty bits are being maintained, */
/* either for incremental collection, */ /* either for incremental collection, */
/* or to limit the root set. */ /* or to limit the root set. */
# ifndef PCR
extern ptr_t GC_stackbottom; /* Cool end of user stack */
# endif
extern word GC_root_size; /* Total size of registered root sections */ extern word GC_root_size; /* Total size of registered root sections */
extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */ extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */
...@@ -1216,7 +1323,8 @@ void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */ ...@@ -1216,7 +1323,8 @@ void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */
/* Return after about one pages worth of */ /* Return after about one pages worth of */
/* work. */ /* work. */
GC_bool GC_mark_stack_empty(); GC_bool GC_mark_stack_empty();
GC_bool GC_mark_some(); /* Perform about one pages worth of marking */ GC_bool GC_mark_some(/* cold_gc_frame */);
/* Perform about one pages worth of marking */
/* work of whatever kind is needed. Returns */ /* work of whatever kind is needed. Returns */
/* quickly if no collection is in progress. */ /* quickly if no collection is in progress. */
/* Return TRUE if mark phase finished. */ /* Return TRUE if mark phase finished. */
...@@ -1238,7 +1346,31 @@ void GC_push_dirty(/*b,t*/); /* Push all possibly changed */ ...@@ -1238,7 +1346,31 @@ void GC_push_dirty(/*b,t*/); /* Push all possibly changed */
/* on the third arg. */ /* on the third arg. */
void GC_push_all_stack(/*b,t*/); /* As above, but consider */ void GC_push_all_stack(/*b,t*/); /* As above, but consider */
/* interior pointers as valid */ /* interior pointers as valid */
void GC_push_roots(/* GC_bool all */); /* Push all or dirty roots. */ void GC_push_all_eager(/*b,t*/); /* Same as GC_push_all_stack, but */
/* ensures that stack is scanned */
/* immediately, not just scheduled */
/* for scanning. */
#ifndef THREADS
void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */);
/* Similar to GC_push_all_eager, but only the */
/* part hotter than cold_gc_frame is scanned */
/* immediately. Needed to endure that callee- */
/* save registers are not missed. */
#else
/* In the threads case, we push part of the current thread stack */
/* with GC_push_all_eager when we push the registers. This gets the */
/* callee-save registers that may disappear. The remainder of the */
/* stacks are scheduled for scanning in *GC_push_other_roots, which */
/* is thread-package-specific. */
#endif
void GC_push_current_stack(/* ptr_t cold_gc_frame */);
/* Push enough of the current stack eagerly to */
/* ensure that callee-save registers saved in */
/* GC frames are scanned. */
/* In the non-threads case, schedule entire */
/* stack for scanning. */
void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */);
/* Push all or dirty roots. */
extern void (*GC_push_other_roots)(); extern void (*GC_push_other_roots)();
/* Push system or application specific roots */ /* Push system or application specific roots */
/* onto the mark stack. In some environments */ /* onto the mark stack. In some environments */
...@@ -1403,7 +1535,7 @@ GC_bool GC_collect_or_expand(/* needed_blocks */); ...@@ -1403,7 +1535,7 @@ GC_bool GC_collect_or_expand(/* needed_blocks */);
/* blocks available. Should be called */ /* blocks available. Should be called */
/* until the blocks are available or */ /* until the blocks are available or */
/* until it fails by returning FALSE. */ /* until it fails by returning FALSE. */
void GC_init(); /* Initialize collector. */ GC_API void GC_init(); /* Initialize collector. */
void GC_collect_a_little_inner(/* int n */); void GC_collect_a_little_inner(/* int n */);
/* Do n units worth of garbage */ /* Do n units worth of garbage */
/* collection work, if appropriate. */ /* collection work, if appropriate. */
...@@ -1491,7 +1623,7 @@ void GC_write_hint(/* struct hblk * h */); ...@@ -1491,7 +1623,7 @@ void GC_write_hint(/* struct hblk * h */);
void GC_dirty_init(); void GC_dirty_init();
/* Slow/general mark bit manipulation: */ /* Slow/general mark bit manipulation: */
GC_bool GC_is_marked(); GC_API GC_bool GC_is_marked();
void GC_clear_mark_bit(); void GC_clear_mark_bit();
void GC_set_mark_bit(); void GC_set_mark_bit();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment