| version 1.1.1.1, 1999/11/27 10:58:32 |
version 1.1.1.3, 2000/12/01 14:48:26 |
|
|
| /* |
/* |
| * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers |
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers |
| * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. |
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. |
| |
* Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. |
| |
* Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved. |
| * |
* |
| |
* |
| * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED |
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED |
| * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
| * |
* |
|
|
| typedef GC_word word; |
typedef GC_word word; |
| typedef GC_signed_word signed_word; |
typedef GC_signed_word signed_word; |
| |
|
| # ifndef CONFIG_H |
# ifndef GCCONFIG_H |
| # include "gcconfig.h" |
# include "gcconfig.h" |
| # endif |
# endif |
| |
|
| Line 64 typedef char * ptr_t; /* A generic pointer to which we |
|
| Line 67 typedef char * ptr_t; /* A generic pointer to which we |
|
| # include <stddef.h> |
# include <stddef.h> |
| # endif |
# endif |
| # define VOLATILE volatile |
# define VOLATILE volatile |
| # define CONST const |
|
| #else |
#else |
| # ifdef MSWIN32 |
# ifdef MSWIN32 |
| # include <stdlib.h> |
# include <stdlib.h> |
| # endif |
# endif |
| # define VOLATILE |
# define VOLATILE |
| # define CONST |
|
| #endif |
#endif |
| |
|
| #ifdef AMIGA |
#define CONST GC_CONST |
| |
|
| |
#if 0 /* was once defined for AMIGA */ |
| # define GC_FAR __far |
# define GC_FAR __far |
| #else |
#else |
| # define GC_FAR |
# define GC_FAR |
| #endif |
#endif |
| |
|
| |
|
| /*********************************/ |
/*********************************/ |
| /* */ |
/* */ |
| /* Definitions for conservative */ |
/* Definitions for conservative */ |
| Line 170 typedef char * ptr_t; /* A generic pointer to which we |
|
| Line 174 typedef char * ptr_t; /* A generic pointer to which we |
|
| /* May save significant amounts of space for obj_map */ |
/* May save significant amounts of space for obj_map */ |
| /* entries. */ |
/* entries. */ |
| |
|
| #ifndef OLD_BLOCK_ALLOC |
|
| /* Macros controlling large block allocation strategy. */ |
|
| # define EXACT_FIRST /* Make a complete pass through the large object */ |
|
| /* free list before splitting a block */ |
|
| # define PRESERVE_LAST /* Do not divide last allocated heap segment */ |
|
| /* unless we would otherwise need to expand the */ |
|
| /* heap. */ |
|
| #endif |
|
| |
|
| /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ |
/* ALIGN_DOUBLE requires MERGE_SIZES at present. */ |
| # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) |
# if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) |
| # define MERGE_SIZES |
# define MERGE_SIZES |
| Line 278 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 273 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \ |
# define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \ |
| + (double) (a.tv_usec - b.tv_usec) / 1000.0) |
+ (double) (a.tv_usec - b.tv_usec) / 1000.0) |
| #else /* !BSD_TIME */ |
#else /* !BSD_TIME */ |
| |
# ifdef MSWIN32 |
| |
# include <windows.h> |
| |
# include <winbase.h> |
| |
# define CLOCK_TYPE DWORD |
| |
# define GET_TIME(x) x = GetTickCount() |
| |
# define MS_TIME_DIFF(a,b) ((long)((a)-(b))) |
| |
# else /* !MSWIN32, !BSD_TIME */ |
| # include <time.h> |
# include <time.h> |
| # if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) |
# if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) |
| clock_t clock(); /* Not in time.h, where it belongs */ |
clock_t clock(); /* Not in time.h, where it belongs */ |
| Line 303 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 305 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # define GET_TIME(x) x = clock() |
# define GET_TIME(x) x = clock() |
| # define MS_TIME_DIFF(a,b) ((unsigned long) \ |
# define MS_TIME_DIFF(a,b) ((unsigned long) \ |
| (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC)) |
(1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC)) |
| |
# endif /* !MSWIN32 */ |
| #endif /* !BSD_TIME */ |
#endif /* !BSD_TIME */ |
| |
|
| /* We use bzero and bcopy internally. They may not be available. */ |
/* We use bzero and bcopy internally. They may not be available. */ |
| Line 350 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 353 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| + GC_page_size) \ |
+ GC_page_size) \ |
| + GC_page_size-1) |
+ GC_page_size-1) |
| # else |
# else |
| # if defined(AMIGA) || defined(NEXT) || defined(DOS4GW) |
# if defined(AMIGA) || defined(NEXT) || defined(MACOSX) || defined(DOS4GW) |
| # define GET_MEM(bytes) HBLKPTR((size_t) \ |
# define GET_MEM(bytes) HBLKPTR((size_t) \ |
| calloc(1, (size_t)bytes + GC_page_size) \ |
calloc(1, (size_t)bytes + GC_page_size) \ |
| + GC_page_size-1) |
+ GC_page_size-1) |
| Line 434 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 437 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # define LOCK() mutex_lock(&GC_allocate_ml); |
# define LOCK() mutex_lock(&GC_allocate_ml); |
| # define UNLOCK() mutex_unlock(&GC_allocate_ml); |
# define UNLOCK() mutex_unlock(&GC_allocate_ml); |
| # endif |
# endif |
| # ifdef LINUX_THREADS |
# if defined(LINUX_THREADS) |
| |
# if defined(I386)|| defined(POWERPC) || defined(ALPHA) || defined(IA64) \ |
| |
|| defined(M68K) |
| # include <pthread.h> |
# include <pthread.h> |
| # ifdef __i386__ |
# define USE_SPIN_LOCK |
| |
# if defined(I386) |
| inline static int 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 */ |
| Line 445 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 451 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| : "0"(1), "m"(*(addr))); |
: "0"(1), "m"(*(addr))); |
| return oldval; |
return oldval; |
| } |
} |
| # else |
|
| -- > Need implementation of GC_test_and_set() |
|
| # endif |
# endif |
| # define GC_clear(addr) (*(addr) = 0) |
# if defined(IA64) |
| |
inline static int GC_test_and_set(volatile unsigned int *addr) { |
| |
int oldval; |
| |
__asm__ __volatile__("xchg4 %0=%1,%2" |
| |
: "=r"(oldval), "=m"(*addr) |
| |
: "r"(1), "1"(*addr)); |
| |
return oldval; |
| |
} |
| |
inline static void GC_clear(volatile unsigned int *addr) { |
| |
__asm__ __volatile__("st4.rel %0=r0" : "=m" (*addr)); |
| |
} |
| |
# define GC_CLEAR_DEFINED |
| |
# endif |
| |
# ifdef M68K |
| |
/* Contributed by Tony Mantler. I'm not sure how well it was */ |
| |
/* tested. */ |
| |
inline static int GC_test_and_set(volatile unsigned int *addr) { |
| |
char oldval; /* this must be no longer than 8 bits */ |
| |
|
| |
/* The return value is semi-phony. */ |
| |
/* 'tas' sets bit 7 while the return */ |
| |
/* value pretends bit 0 was set */ |
| |
__asm__ __volatile__( |
| |
"tas %1@; sne %0; negb %0" |
| |
: "=d" (oldval) |
| |
: "a" (addr)); |
| |
return oldval; |
| |
} |
| |
# endif |
| |
# if defined(POWERPC) |
| |
inline static int GC_test_and_set(volatile unsigned int *addr) { |
| |
int oldval; |
| |
int temp = 1; // locked value |
| |
|
| |
__asm__ __volatile__( |
| |
"1:\tlwarx %0,0,%3\n" // load and reserve |
| |
"\tcmpwi %0, 0\n" // if load is |
| |
"\tbne 2f\n" // non-zero, return already set |
| |
"\tstwcx. %2,0,%1\n" // else store conditional |
| |
"\tbne- 1b\n" // retry if lost reservation |
| |
"2:\t\n" // oldval is zero if we set |
| |
: "=&r"(oldval), "=p"(addr) |
| |
: "r"(temp), "1"(addr) |
| |
: "memory"); |
| |
return (int)oldval; |
| |
} |
| |
inline static void GC_clear(volatile unsigned int *addr) { |
| |
__asm__ __volatile__("eieio"); |
| |
*(addr) = 0; |
| |
} |
| |
# define GC_CLEAR_DEFINED |
| |
# endif |
| |
# ifdef ALPHA |
| |
inline static int GC_test_and_set(volatile unsigned int * addr) |
| |
{ |
| |
unsigned long oldvalue; |
| |
unsigned long temp; |
| |
|
| |
__asm__ __volatile__( |
| |
"1: ldl_l %0,%1\n" |
| |
" and %0,%3,%2\n" |
| |
" bne %2,2f\n" |
| |
" xor %0,%3,%0\n" |
| |
" stl_c %0,%1\n" |
| |
" beq %0,3f\n" |
| |
" mb\n" |
| |
"2:\n" |
| |
".section .text2,\"ax\"\n" |
| |
"3: br 1b\n" |
| |
".previous" |
| |
:"=&r" (temp), "=m" (*addr), "=&r" (oldvalue) |
| |
:"Ir" (1), "m" (*addr)); |
| |
|
| |
return oldvalue; |
| |
} |
| |
/* Should probably also define GC_clear, since it needs */ |
| |
/* a memory barrier ?? */ |
| |
# endif /* ALPHA */ |
| |
# ifdef ARM32 |
| |
inline static int GC_test_and_set(volatile unsigned int *addr) { |
| |
int oldval; |
| |
/* SWP on ARM is very similar to XCHG on x86. Doesn't lock the |
| |
* bus because there are no SMP ARM machines. If/when there are, |
| |
* this code will likely need to be updated. */ |
| |
/* See linuxthreads/sysdeps/arm/pt-machine.h in glibc-2.1 */ |
| |
__asm__ __volatile__("swp %0, %1, [%2]" |
| |
: "=r"(oldval) |
| |
: "r"(1), "r"(addr)); |
| |
return oldval; |
| |
} |
| |
# endif |
| |
# ifndef GC_CLEAR_DEFINED |
| |
inline static void GC_clear(volatile unsigned int *addr) { |
| |
/* Try to discourage gcc from moving anything past this. */ |
| |
__asm__ __volatile__(" "); |
| |
*(addr) = 0; |
| |
} |
| |
# endif |
| |
|
| extern volatile unsigned int GC_allocate_lock; |
extern volatile unsigned int GC_allocate_lock; |
| /* This is not a mutex because mutexes that obey the (optional) */ |
|
| /* POSIX scheduling rules are subject to convoys in high contention */ |
|
| /* applications. This is basically a spin lock. */ |
|
| extern pthread_t GC_lock_holder; |
extern pthread_t GC_lock_holder; |
| extern void GC_lock(void); |
extern void GC_lock(void); |
| /* Allocation lock holder. Only set if acquired by client through */ |
/* Allocation lock holder. Only set if acquired by client through */ |
| Line 462 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 560 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # define NO_THREAD (pthread_t)(-1) |
# define NO_THREAD (pthread_t)(-1) |
| # define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD |
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD |
| # define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) |
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) |
| # ifdef UNDEFINED |
# define LOCK() \ |
| # define LOCK() pthread_mutex_lock(&GC_allocate_ml) |
|
| # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) |
|
| # else |
|
| # define LOCK() \ |
|
| { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); } |
{ if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); } |
| # define UNLOCK() \ |
# define UNLOCK() \ |
| GC_clear(&GC_allocate_lock) |
GC_clear(&GC_allocate_lock) |
| # endif |
extern VOLATILE GC_bool GC_collecting; |
| extern GC_bool GC_collecting; |
|
| # define ENTER_GC() \ |
# define ENTER_GC() \ |
| { \ |
{ \ |
| GC_collecting = 1; \ |
GC_collecting = 1; \ |
| } |
} |
| # define EXIT_GC() GC_collecting = 0; |
# define EXIT_GC() GC_collecting = 0; |
| |
# else /* LINUX_THREADS on hardware for which we don't know how */ |
| |
/* to do test and set. */ |
| |
# include <pthread.h> |
| |
extern pthread_mutex_t GC_allocate_ml; |
| |
# define LOCK() pthread_mutex_lock(&GC_allocate_ml) |
| |
# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) |
| |
# endif |
| # endif /* LINUX_THREADS */ |
# endif /* LINUX_THREADS */ |
| # if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS) |
# if defined(HPUX_THREADS) |
| # include <pthread.h> |
# include <pthread.h> |
| # include <mutex.h> |
extern pthread_mutex_t GC_allocate_ml; |
| |
# define LOCK() pthread_mutex_lock(&GC_allocate_ml) |
| |
# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) |
| |
# endif |
| |
# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS) |
| |
/* This may also eventually be appropriate for HPUX_THREADS */ |
| |
# include <pthread.h> |
| |
# ifndef HPUX_THREADS |
| |
/* This probably should never be included, but I can't test */ |
| |
/* on Irix anymore. */ |
| |
# include <mutex.h> |
| |
# endif |
| |
|
| # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \ |
# ifndef HPUX_THREADS |
| |
# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \ |
| || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700 |
|| !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 |
| |
# else |
| |
/* I couldn't find a way to do this inline on HP/UX */ |
| # 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) */ |
| Line 500 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 615 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # define NO_THREAD (pthread_t)(-1) |
# define NO_THREAD (pthread_t)(-1) |
| # define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD |
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD |
| # define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) |
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) |
| # ifdef UNDEFINED |
# ifdef HPUX_THREADS |
| # define LOCK() pthread_mutex_lock(&GC_allocate_ml) |
# define LOCK() { if (!GC_test_and_clear(&GC_allocate_lock)) GC_lock(); } |
| # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) |
/* The following is INCORRECT, since the memory model is too weak. */ |
| |
# define UNLOCK() { GC_noop1(&GC_allocate_lock); \ |
| |
*(volatile unsigned long *)(&GC_allocate_lock) = 1; } |
| # 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 |
&& defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700 |
| # define UNLOCK() __lock_release(&GC_allocate_lock) |
# define UNLOCK() __lock_release(&GC_allocate_lock) |
| # else |
# else |
| /* The function call in the following should prevent the */ |
/* The function call in the following should prevent the */ |
| /* compiler from moving assignments to below the UNLOCK. */ |
/* compiler from moving assignments to below the UNLOCK. */ |
| /* This is probably not necessary for ucode or gcc 2.8. */ |
/* This is probably not necessary for ucode or gcc 2.8. */ |
| Line 516 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 633 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| /* versions. */ |
/* versions. */ |
| # define UNLOCK() { GC_noop1(&GC_allocate_lock); \ |
# define UNLOCK() { GC_noop1(&GC_allocate_lock); \ |
| *(volatile unsigned long *)(&GC_allocate_lock) = 0; } |
*(volatile unsigned long *)(&GC_allocate_lock) = 0; } |
| # endif |
# endif |
| # endif |
# endif |
| extern GC_bool GC_collecting; |
extern VOLATILE GC_bool GC_collecting; |
| # define ENTER_GC() \ |
# define ENTER_GC() \ |
| { \ |
{ \ |
| GC_collecting = 1; \ |
GC_collecting = 1; \ |
| Line 607 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| Line 724 void GC_print_callers (/* struct callinfo info[NFRAMES |
|
| # 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) |
|| defined(IRIX_JDK_THREADS) || defined(HPUX_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() |
| Line 823 struct hblkhdr { |
|
| Line 940 struct hblkhdr { |
|
| struct hblk * hb_next; /* Link field for hblk free list */ |
struct hblk * hb_next; /* Link field for hblk free list */ |
| /* and for lists of chunks waiting to be */ |
/* and for lists of chunks waiting to be */ |
| /* reclaimed. */ |
/* reclaimed. */ |
| |
struct hblk * hb_prev; /* Backwards link for free list. */ |
| word hb_descr; /* object descriptor for marking. See */ |
word hb_descr; /* object descriptor for marking. See */ |
| /* mark.h. */ |
/* mark.h. */ |
| char* hb_map; /* A pointer to a pointer validity map of the block. */ |
char* hb_map; /* A pointer to a pointer validity map of the block. */ |
| Line 837 struct hblkhdr { |
|
| Line 955 struct hblkhdr { |
|
| # define IGNORE_OFF_PAGE 1 /* Ignore pointers that do not */ |
# define IGNORE_OFF_PAGE 1 /* Ignore pointers that do not */ |
| /* point to the first page of */ |
/* point to the first page of */ |
| /* this object. */ |
/* this object. */ |
| |
# define WAS_UNMAPPED 2 /* This is a free block, which has */ |
| |
/* been unmapped from the address */ |
| |
/* space. */ |
| |
/* GC_remap must be invoked on it */ |
| |
/* before it can be reallocated. */ |
| |
/* Only set with USE_MUNMAP. */ |
| unsigned short hb_last_reclaimed; |
unsigned short hb_last_reclaimed; |
| /* Value of GC_gc_no when block was */ |
/* Value of GC_gc_no when block was */ |
| /* last allocated or swept. May wrap. */ |
/* last allocated or swept. May wrap. */ |
| |
/* For a free block, this is maintained */ |
| |
/* unly for USE_MUNMAP, and indicates */ |
| |
/* when the header was allocated, or */ |
| |
/* when the size of the block last */ |
| |
/* changed. */ |
| word hb_marks[MARK_BITS_SZ]; |
word hb_marks[MARK_BITS_SZ]; |
| /* Bit i in the array refers to the */ |
/* Bit i in the array refers to the */ |
| /* object starting at the ith word (header */ |
/* object starting at the ith word (header */ |
| /* INCLUDED) in the heap block. */ |
/* INCLUDED) in the heap block. */ |
| /* The lsb of word 0 is numbered 0. */ |
/* The lsb of word 0 is numbered 0. */ |
| |
/* Unused bits are invalid, and are */ |
| |
/* occasionally set, e.g for uncollectable */ |
| |
/* objects. */ |
| }; |
}; |
| |
|
| /* heap block body */ |
/* heap block body */ |
|
|
| /* The type of mark procedures. This really belongs in gc_mark.h. */ |
/* 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 */ |
/* But we put it here, so that we can avoid scanning the mark proc */ |
| /* table. */ |
/* table. */ |
| typedef struct ms_entry * (*mark_proc)(/* word * addr, mark_stack_ptr, |
typedef struct ms_entry * (*mark_proc)(/* word * addr, |
| mark_stack_limit, env */); |
struct ms_entry *mark_stack_ptr, |
| |
struct ms_entry *mark_stack_limit, |
| |
word env */); |
| # define LOG_MAX_MARK_PROCS 6 |
# define LOG_MAX_MARK_PROCS 6 |
| # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS) |
# define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS) |
| |
|
|
|
| struct _GC_arrays { |
struct _GC_arrays { |
| word _heapsize; |
word _heapsize; |
| word _max_heapsize; |
word _max_heapsize; |
| |
word _requested_heapsize; /* Heap size due to explicit expansion */ |
| ptr_t _last_heap_addr; |
ptr_t _last_heap_addr; |
| ptr_t _prev_heap_addr; |
ptr_t _prev_heap_addr; |
| |
word _large_free_bytes; |
| |
/* Total bytes contained in blocks on large object free */ |
| |
/* list. */ |
| word _words_allocd_before_gc; |
word _words_allocd_before_gc; |
| /* Number of words allocated before this */ |
/* Number of words allocated before this */ |
| /* collection cycle. */ |
/* collection cycle. */ |
| Line 978 struct _GC_arrays { |
|
| Line 1116 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. */ |
| |
ptr_t _scratch_end_ptr; |
| |
ptr_t _scratch_last_end_ptr; |
| |
/* Used by headers.c, and can easily appear to point to */ |
| |
/* heap. */ |
| mark_proc _mark_procs[MAX_MARK_PROCS]; |
mark_proc _mark_procs[MAX_MARK_PROCS]; |
| /* Table of user-defined mark procedures. There is */ |
/* Table of user-defined mark procedures. There is */ |
| /* a small number of these, which can be referenced */ |
/* a small number of these, which can be referenced */ |
| Line 1005 struct _GC_arrays { |
|
| Line 1147 struct _GC_arrays { |
|
| /* Number of words in accessible atomic */ |
/* Number of words in accessible atomic */ |
| /* objects. */ |
/* objects. */ |
| # endif |
# endif |
| |
# ifdef USE_MUNMAP |
| |
word _unmapped_bytes; |
| |
# endif |
| # ifdef MERGE_SIZES |
# ifdef MERGE_SIZES |
| unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)]; |
unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)]; |
| /* Number of words to allocate for a given allocation request in */ |
/* Number of words to allocate for a given allocation request in */ |
| Line 1022 struct _GC_arrays { |
|
| Line 1167 struct _GC_arrays { |
|
| /* to an object at */ |
/* to an object at */ |
| /* block_start+i&~3 - WORDS_TO_BYTES(j). */ |
/* block_start+i&~3 - WORDS_TO_BYTES(j). */ |
| /* (If ALL_INTERIOR_POINTERS is defined, then */ |
/* (If ALL_INTERIOR_POINTERS is defined, then */ |
| /* instead ((short *)(hbh_map[sz])[i] is j if */ |
/* instead ((short *)(hb_map[sz])[i] is j if */ |
| /* block_start+WORDS_TO_BYTES(i) is in the */ |
/* block_start+WORDS_TO_BYTES(i) is in the */ |
| /* interior of an object starting at */ |
/* interior of an object starting at */ |
| /* block_start+WORDS_TO_BYTES(i-j)). */ |
/* block_start+WORDS_TO_BYTES(i-j)). */ |
| Line 1135 GC_API GC_FAR struct _GC_arrays GC_arrays; |
|
| Line 1280 GC_API GC_FAR struct _GC_arrays GC_arrays; |
|
| # define GC_prev_heap_addr GC_arrays._prev_heap_addr |
# define GC_prev_heap_addr GC_arrays._prev_heap_addr |
| # define GC_words_allocd GC_arrays._words_allocd |
# define GC_words_allocd GC_arrays._words_allocd |
| # define GC_words_wasted GC_arrays._words_wasted |
# define GC_words_wasted GC_arrays._words_wasted |
| |
# define GC_large_free_bytes GC_arrays._large_free_bytes |
| # 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_scratch_end_ptr GC_arrays._scratch_end_ptr |
| |
# define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr |
| # define GC_mark_procs GC_arrays._mark_procs |
# 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_requested_heapsize GC_arrays._requested_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 |
| # define GC_heap_sects GC_arrays._heap_sects |
# define GC_heap_sects GC_arrays._heap_sects |
| # define GC_last_stack GC_arrays._last_stack |
# define GC_last_stack GC_arrays._last_stack |
| |
# ifdef USE_MUNMAP |
| |
# define GC_unmapped_bytes GC_arrays._unmapped_bytes |
| |
# endif |
| # ifdef MSWIN32 |
# ifdef MSWIN32 |
| # define GC_heap_bases GC_arrays._heap_bases |
# define GC_heap_bases GC_arrays._heap_bases |
| # endif |
# endif |
| Line 1172 GC_API GC_FAR struct _GC_arrays GC_arrays; |
|
| Line 1324 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)) |
| |
|
| |
#define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes) |
| |
|
| /* Object kinds: */ |
/* Object kinds: */ |
| # define MAXOBJKINDS 16 |
# define MAXOBJKINDS 16 |
| |
|
| Line 1236 extern char * GC_invalid_map; |
|
| Line 1390 extern char * GC_invalid_map; |
|
| /* Pointer to the nowhere valid hblk map */ |
/* Pointer to the nowhere valid hblk map */ |
| /* Blocks pointing to this map are free. */ |
/* Blocks pointing to this map are free. */ |
| |
|
| extern struct hblk * GC_hblkfreelist; |
extern struct hblk * GC_hblkfreelist[]; |
| /* List of completely empty heap blocks */ |
/* List of completely empty heap blocks */ |
| /* Linked through hb_next field of */ |
/* Linked through hb_next field of */ |
| /* header structure associated with */ |
/* header structure associated with */ |
| Line 1251 extern GC_bool GC_objects_are_marked; /* There are mar |
|
| Line 1405 extern GC_bool GC_objects_are_marked; /* There are mar |
|
| extern GC_bool GC_incremental; |
extern GC_bool GC_incremental; |
| /* Using incremental/generational collection. */ |
/* Using incremental/generational collection. */ |
| #else |
#else |
| # define GC_incremental TRUE |
# define GC_incremental FALSE |
| /* Hopefully allow optimizer to remove some code. */ |
/* Hopefully allow optimizer to remove some code. */ |
| #endif |
#endif |
| |
|
| Line 1304 extern ptr_t GC_greatest_plausible_heap_addr; |
|
| Line 1458 extern ptr_t GC_greatest_plausible_heap_addr; |
|
| ptr_t GC_approx_sp(); |
ptr_t GC_approx_sp(); |
| |
|
| GC_bool GC_should_collect(); |
GC_bool GC_should_collect(); |
| #ifdef PRESERVE_LAST |
|
| GC_bool GC_in_last_heap_sect(/* ptr_t */); |
|
| /* In last added heap section? If so, avoid breaking up. */ |
|
| #endif |
|
| void GC_apply_to_all_blocks(/*fn, client_data*/); |
void GC_apply_to_all_blocks(/*fn, client_data*/); |
| /* Invoke fn(hbp, client_data) for each */ |
/* Invoke fn(hbp, client_data) for each */ |
| /* allocated heap block. */ |
/* allocated heap block. */ |
| struct hblk * GC_next_block(/* struct hblk * h */); |
struct hblk * GC_next_used_block(/* struct hblk * h */); |
| |
/* Return first in-use block >= h */ |
| |
struct hblk * GC_prev_block(/* struct hblk * h */); |
| |
/* Return last block <= h. Returned block */ |
| |
/* is managed by GC, but may or may not be in */ |
| |
/* use. */ |
| void GC_mark_init(); |
void GC_mark_init(); |
| void GC_clear_marks(); /* Clear mark bits for all heap objects. */ |
void GC_clear_marks(); /* Clear mark bits for all heap objects. */ |
| void GC_invalidate_mark_state(); /* Tell the marker that marked */ |
void GC_invalidate_mark_state(); /* Tell the marker that marked */ |
| Line 1384 extern void (*GC_start_call_back)(/* void */); |
|
| Line 1540 extern void (*GC_start_call_back)(/* void */); |
|
| /* lock held. */ |
/* lock held. */ |
| /* 0 by default. */ |
/* 0 by default. */ |
| void GC_push_regs(); /* Push register contents onto mark stack. */ |
void GC_push_regs(); /* Push register contents onto mark stack. */ |
| |
/* If NURSERY is defined, the default push */ |
| |
/* action can be overridden with GC_push_proc */ |
| void GC_remark(); /* Mark from all marked objects. Used */ |
void GC_remark(); /* Mark from all marked objects. Used */ |
| /* only if we had to drop something. */ |
/* only if we had to drop something. */ |
| |
|
| |
# ifdef NURSERY |
| |
extern void (*GC_push_proc)(ptr_t); |
| |
# endif |
| # if defined(MSWIN32) |
# if defined(MSWIN32) |
| void __cdecl GC_push_one(); |
void __cdecl GC_push_one(); |
| # else |
# else |
| Line 1573 ptr_t GC_allocobj(/* sz_inn_words, kind */); |
|
| Line 1735 ptr_t GC_allocobj(/* sz_inn_words, kind */); |
|
| /* head. */ |
/* head. */ |
| |
|
| void GC_init_headers(); |
void GC_init_headers(); |
| GC_bool GC_install_header(/*h*/); |
struct hblkhdr * GC_install_header(/*h*/); |
| /* Install a header for block h. */ |
/* Install a header for block h. */ |
| /* Return FALSE on failure. */ |
/* Return 0 on failure, or the header */ |
| |
/* otherwise. */ |
| GC_bool GC_install_counts(/*h, sz*/); |
GC_bool GC_install_counts(/*h, sz*/); |
| /* Set up forwarding counts for block */ |
/* Set up forwarding counts for block */ |
| /* h of size sz. */ |
/* h of size sz. */ |
| Line 1608 extern void (*GC_print_heap_obj)(/* ptr_t p */); |
|
| Line 1771 extern void (*GC_print_heap_obj)(/* ptr_t p */); |
|
| /* detailed description of the object */ |
/* detailed description of the object */ |
| /* referred to by p. */ |
/* referred to by p. */ |
| |
|
| |
/* Memory unmapping: */ |
| |
#ifdef USE_MUNMAP |
| |
void GC_unmap_old(void); |
| |
void GC_merge_unmapped(void); |
| |
void GC_unmap(ptr_t start, word bytes); |
| |
void GC_remap(ptr_t start, word bytes); |
| |
void GC_unmap_gap(ptr_t start1, word bytes1, ptr_t start2, word bytes2); |
| |
#endif |
| |
|
| /* Virtual dirty bit implementation: */ |
/* Virtual dirty bit implementation: */ |
| /* Each implementation exports the following: */ |
/* Each implementation exports the following: */ |
| void GC_read_dirty(); /* Retrieve dirty bits. */ |
void GC_read_dirty(); /* Retrieve dirty bits. */ |
| Line 1640 void GC_print_heap_sects(); |
|
| Line 1812 void GC_print_heap_sects(); |
|
| void GC_print_static_roots(); |
void GC_print_static_roots(); |
| void GC_dump(); |
void GC_dump(); |
| |
|
| |
#ifdef KEEP_BACK_PTRS |
| |
void GC_store_back_pointer(ptr_t source, ptr_t dest); |
| |
void GC_marked_for_finalization(ptr_t dest); |
| |
# define GC_STORE_BACK_PTR(source, dest) GC_store_back_pointer(source, dest) |
| |
# define GC_MARKED_FOR_FINALIZATION(dest) GC_marked_for_finalization(dest) |
| |
#else |
| |
# define GC_STORE_BACK_PTR(source, dest) |
| |
# define GC_MARKED_FOR_FINALIZATION(dest) |
| |
#endif |
| |
|
| /* Make arguments appear live to compiler */ |
/* Make arguments appear live to compiler */ |
| # ifdef __WATCOMC__ |
# ifdef __WATCOMC__ |
| void GC_noop(void*, ...); |
void GC_noop(void*, ...); |
| Line 1689 void GC_err_puts(/* char *s */); |
|
| Line 1871 void GC_err_puts(/* char *s */); |
|
| /* Write s to stderr, don't buffer, don't add */ |
/* Write s to stderr, don't buffer, don't add */ |
| /* newlines, don't ... */ |
/* newlines, don't ... */ |
| |
|
| |
|
| |
# ifdef GC_ASSERTIONS |
| |
# define GC_ASSERT(expr) if(!(expr)) {\ |
| |
GC_err_printf2("Assertion failure: %s:%ld\n", \ |
| |
__FILE__, (unsigned long)__LINE__); \ |
| |
ABORT("assertion failure"); } |
| |
# else |
| |
# define GC_ASSERT(expr) |
| |
# endif |
| |
|
| # endif /* GC_PRIVATE_H */ |
# endif /* GC_PRIVATE_H */ |