import gc6.1alpha5

This commit is contained in:
Fumitoshi UKAI
2002-07-10 14:21:11 +00:00
parent adfa59bd5f
commit bb118b7356
72 changed files with 18914 additions and 8111 deletions
+9 -1
View File
@@ -115,16 +115,24 @@ typedef struct {
#ifdef SHORT_DBG_HDRS
# define DEBUG_BYTES (sizeof (oh))
# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES
#else
/* Add space for END_FLAG, but use any extra space that was already */
/* added to catch off-the-end pointers. */
# define DEBUG_BYTES (sizeof (oh) + sizeof (word) - EXTRA_BYTES)
/* For uncollectable objects, the extra byte is not added. */
# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word))
# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)
#endif
#define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh))
/* Round bytes to words without adding extra byte at end. */
#define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
/* ADD_CALL_CHAIN stores a (partial) call chain into an object */
/* header. It may be called with or without the allocation */
/* lock. */
/* PRINT_CALL_CHAIN prints the call chain stored in an object */
/* to stderr. It requires that we do not hold the lock. */
#ifdef SAVE_CALL_CHAIN
# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci)
# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
+1 -1
View File
@@ -70,7 +70,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
#define ADVANCE(p, hhdr, source) \
{ \
hdr * new_hdr = GC_invalid_header; \
p = GC_FIND_START(p, hhdr, &new_hdr, (word)source); \
p = GC_find_start(p, hhdr, &new_hdr); \
hhdr = new_hdr; \
}
+33 -18
View File
@@ -145,15 +145,15 @@
# if defined(POWERPC)
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
int temp = 1; // locked value
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
"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");
@@ -161,7 +161,7 @@
}
# define GC_TEST_AND_SET_DEFINED
inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("eieio" ::: "memory");
__asm__ __volatile__("eieio" : : : "memory");
*(addr) = 0;
}
# define GC_CLEAR_DEFINED
@@ -219,11 +219,19 @@
# define GC_TEST_AND_SET_DEFINED
# endif
# ifdef MIPS
# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
# ifdef LINUX
# include <sys/tas.h>
# define GC_test_and_set(addr) _test_and_set((int *) addr,1)
# define GC_TEST_AND_SET_DEFINED
# elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
# define GC_test_and_set(addr, v) test_and_set(addr,v)
# ifdef __GNUC__
# define GC_test_and_set(addr) _test_and_set(addr,1)
# else
# define GC_test_and_set(addr) test_and_set(addr,1)
# endif
# else
# define GC_test_and_set(addr, v) __test_and_set(addr,v)
# define GC_test_and_set(addr) __test_and_set(addr,1)
# define GC_clear(addr) __lock_release(addr);
# define GC_CLEAR_DEFINED
# endif
@@ -262,7 +270,7 @@
# endif
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS)
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
# define NO_THREAD (pthread_t)(-1)
# include <pthread.h>
# if defined(PARALLEL_MARK)
@@ -431,7 +439,7 @@
# define NO_THREAD (pthread_t)(-1)
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
# define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
# define UNLOCK() GC_clear(&GC_allocate_lock);
extern VOLATILE GC_bool GC_collecting;
# define ENTER_GC() \
@@ -440,11 +448,18 @@
}
# define EXIT_GC() GC_collecting = 0;
# endif /* GC_IRIX_THREADS */
# ifdef GC_WIN32_THREADS
# include <windows.h>
GC_API CRITICAL_SECTION GC_allocate_ml;
# define LOCK() EnterCriticalSection(&GC_allocate_ml);
# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
# if defined(GC_WIN32_THREADS)
# if defined(GC_PTHREADS)
# 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)
# else
# include <windows.h>
GC_API CRITICAL_SECTION GC_allocate_ml;
# define LOCK() EnterCriticalSection(&GC_allocate_ml);
# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
# endif
# endif
# ifndef SET_LOCK_HOLDER
# define SET_LOCK_HOLDER()
+3 -13
View File
@@ -137,7 +137,7 @@ extern mse * GC_mark_stack;
#ifdef __STDC__
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p,
ptr_t source);
word source);
# else
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif
@@ -145,7 +145,7 @@ extern mse * GC_mark_stack;
ptr_t GC_find_start();
#endif
mse * GC_signal_mark_stack_overflow();
mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp));
# ifdef GATHERSTATS
# define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
@@ -174,14 +174,6 @@ mse * GC_signal_mark_stack_overflow();
} \
}
#ifdef PRINT_BLACK_LIST
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p, source)
#else
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p)
#endif
/* Push the contents of current onto the mark stack if it is a valid */
/* ptr to a currently unmarked object. Mark it. */
/* If we assumed a standard-conforming compiler, we could probably */
@@ -195,8 +187,7 @@ mse * GC_signal_mark_stack_overflow();
GET_HDR(my_current, my_hhdr); \
if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
hdr * new_hdr = GC_invalid_header; \
my_current = GC_FIND_START(my_current, my_hhdr, \
&new_hdr, (word)source); \
my_current = GC_find_start(my_current, my_hhdr, &new_hdr); \
my_hhdr = new_hdr; \
} \
PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
@@ -236,7 +227,6 @@ exit_label: ; \
# define SET_MARK_BIT_EXIT_IF_SET(hhdr,displ,exit_label) \
{ \
register word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(displ); \
register word mark_word = *mark_word_addr; \
\
OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(displ), \
exit_label); \
+53 -103
View File
@@ -30,6 +30,12 @@
# define BSD_TIME
#endif
#ifdef DGUX
# include <sys/types.h>
# include <sys/time.h>
# include <sys/resource.h>
#endif /* DGUX */
#ifdef BSD_TIME
# include <sys/types.h>
# include <sys/time.h>
@@ -44,10 +50,6 @@
# include "../gc_mark.h"
# endif
# ifndef GCCONFIG_H
# include "gcconfig.h"
# endif
typedef GC_word word;
typedef GC_signed_word signed_word;
@@ -60,6 +62,10 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
/* Preferably identical to caddr_t, if it */
/* exists. */
# ifndef GCCONFIG_H
# include "gcconfig.h"
# endif
# ifndef HEADERS_H
# include "gc_hdrs.h"
# endif
@@ -205,6 +211,11 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
/* odd numbered words to have mark bits. */
#endif
#if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE)
/* GCJ's Hashtable synchronization code requires 64-bit alignment. */
# define ALIGN_DOUBLE
#endif
/* ALIGN_DOUBLE requires MERGE_SIZES at present. */
# if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES)
# define MERGE_SIZES
@@ -249,20 +260,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
#ifdef SAVE_CALL_CHAIN
/*
* Number of frames and arguments to save in objects allocated by
* debugging allocator.
*/
# ifndef SAVE_CALL_COUNT
# define NFRAMES 6 /* Number of frames to save. Even for */
/* alignment reasons. */
# else
# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
# endif
# define NARGS 2 /* Mumber of arguments to save for each call. */
# define NEED_CALLINFO
/* Fill in the pc and argument information for up to NFRAMES of my */
/* callers. Ignore my frame and my callers frame. */
struct callinfo;
@@ -270,14 +267,6 @@ void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
#else
# ifdef GC_ADD_CALLER
# define NFRAMES 1
# define NARGS 0
# define NEED_CALLINFO
# endif
#endif
#ifdef NEED_CALLINFO
@@ -376,68 +365,6 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
# define BZERO(x,n) bzero((char *)(x),(int)(n))
# endif
/* HBLKSIZE aligned allocation. 0 is taken to mean failure */
/* space is assumed to be cleared. */
/* In the case os USE_MMAP, the argument must also be a */
/* 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. */
struct hblk; /* See below. */
# ifdef PCR
char * real_malloc();
# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# else
# ifdef OS2
void * os2_alloc(size_t bytes);
# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \
+ GC_page_size) \
+ GC_page_size-1)
# else
# if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
(defined(SUNOS5) && !defined(USE_MMAP))
# define GET_MEM(bytes) HBLKPTR((size_t) \
calloc(1, (size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# else
# ifdef MSWIN32
extern ptr_t GC_win32_get_mem();
# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
# else
# ifdef MACOS
# if defined(USE_TEMPORARY_MEMORY)
extern Ptr GC_MacTemporaryNewPtr(size_t size,
Boolean clearMemory);
# define GET_MEM(bytes) HBLKPTR( \
GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \
+ GC_page_size-1)
# else
# define GET_MEM(bytes) HBLKPTR( \
NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
# endif
# else
# ifdef MSWINCE
extern ptr_t GC_wince_get_mem();
# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
# else
# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
extern void *GC_amiga_get_mem(size_t size);
define GET_MEM(bytes) HBLKPTR((size_t) \
GC_amiga_get_mem((size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# else
extern ptr_t GC_unix_get_mem();
# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
# endif
# endif
# endif
# endif
# endif
# endif
# endif
/* Delay any interrupts or signals that may abort this thread. Data */
/* structures are in a consistent state outside this pair of calls. */
/* ANSI C allows both to be empty (though the standard isn't very */
@@ -502,7 +429,7 @@ struct hblk; /* See below. */
# ifdef SMALL_CONFIG
# define ABORT(msg) abort();
# else
GC_API void GC_abort();
GC_API void GC_abort GC_PROTO((GC_CONST char * msg));
# define ABORT(msg) GC_abort(msg);
# endif
# endif
@@ -515,7 +442,7 @@ struct hblk; /* See below. */
# endif
/* Print warning message, e.g. almost out of memory. */
# define WARN(msg,arg) (*GC_current_warn_proc)(msg, (GC_word)(arg))
# define WARN(msg,arg) (*GC_current_warn_proc)("GC Warning: " msg, (GC_word)(arg))
extern GC_warn_proc GC_current_warn_proc;
/* Get environment entry */
@@ -788,12 +715,11 @@ struct hblkhdr {
# define BODY_SZ (HBLKSIZE/sizeof(word))
struct hblk {
# if 0 /* DISCARDWORDS no longer supported */
word garbage[DISCARD_WORDS];
# endif
word hb_body[BODY_SZ];
};
# define HBLK_IS_FREE(hdr) ((hdr) -> hb_map == GC_invalid_map)
# define OBJ_SZ_TO_BLOCKS(sz) \
divHBLKSZ(WORDS_TO_BYTES(sz) + HBLKSIZE-1)
/* Size of block (in units of HBLKSIZE) needed to hold objects of */
@@ -914,6 +840,10 @@ struct _GC_arrays {
word _mem_freed;
/* Number of explicitly deallocated words of memory */
/* since last collection. */
word _finalizer_mem_freed;
/* Words of memory explicitly deallocated while */
/* finalizers were running. Used to approximate mem. */
/* explicitly deallocated by finalizers. */
ptr_t _scratch_end_ptr;
ptr_t _scratch_last_end_ptr;
/* Used by headers.c, and can easily appear to point to */
@@ -1084,6 +1014,7 @@ GC_API GC_FAR struct _GC_arrays GC_arrays;
# define GC_words_finalized GC_arrays._words_finalized
# define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
# define GC_mem_freed GC_arrays._mem_freed
# define GC_finalizer_mem_freed GC_arrays._finalizer_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
@@ -1218,17 +1149,19 @@ extern struct hblk * GC_hblkfreelist[];
/* header structure associated with */
/* block. */
extern GC_bool GC_is_initialized; /* GC_init() has been run. */
extern GC_bool GC_objects_are_marked; /* There are marked objects in */
/* the heap. */
#ifndef SMALL_CONFIG
extern GC_bool GC_incremental;
/* Using incremental/generational collection. */
# define TRUE_INCREMENTAL \
(GC_incremental && GC_time_limit != GC_TIME_UNLIMITED)
/* True incremental, not just generational, mode */
#else
# define GC_incremental FALSE
/* Hopefully allow optimizer to remove some code. */
# define TRUE_INCREMENTAL FALSE
#endif
extern GC_bool GC_dirty_maintained;
@@ -1240,7 +1173,12 @@ extern word GC_root_size; /* Total size of registered root sections */
extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */
extern long GC_large_alloc_warn_interval;
/* Interval between unsuppressed warnings. */
extern long GC_large_alloc_warn_suppressed;
/* Number of warnings suppressed so far. */
/* Operations */
# ifndef abs
# define abs(x) ((x) < 0? (-(x)) : (x))
@@ -1630,7 +1568,8 @@ GC_bool GC_collect_or_expand GC_PROTO(( \
/* blocks available. Should be called */
/* until the blocks are available or */
/* until it fails by returning FALSE. */
GC_API void GC_init GC_PROTO((void)); /* Initialize collector. */
extern GC_bool GC_is_initialized; /* GC_init() has been run. */
#if defined(MSWIN32) || defined(MSWINCE)
void GC_deinit GC_PROTO((void));
@@ -1712,8 +1651,11 @@ void GC_print_obj GC_PROTO((ptr_t p));
/* description of the object to stderr. */
extern void (*GC_check_heap) GC_PROTO((void));
/* Check that all objects in the heap with */
/* debugging info are intact. Print */
/* descriptions of any that are not. */
/* debugging info are intact. */
/* Add any that are not to GC_smashed list. */
extern void (*GC_print_all_smashed) GC_PROTO((void));
/* Print GC_smashed if it's not empty. */
/* Clear GC_smashed list. */
extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p));
/* If possible print s followed by a more */
/* detailed description of the object */
@@ -1767,8 +1709,12 @@ GC_bool GC_page_was_ever_dirty GC_PROTO((struct hblk *h));
void GC_is_fresh GC_PROTO((struct hblk *h, word n));
/* Assert the region currently contains no */
/* valid pointers. */
void GC_write_hint GC_PROTO((struct hblk *h));
/* h is about to be written. */
void GC_remove_protection GC_PROTO((struct hblk *h, word nblocks,
GC_bool pointerfree));
/* h is about to be writteni or allocated. Ensure */
/* that it's not write protected by the virtual */
/* dirty bit implementation. */
void GC_dirty_init GC_PROTO((void));
/* Slow/general mark bit manipulation: */
@@ -1915,7 +1861,7 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
/* in Linux glibc, but it's not exported.) Thus we continue to use */
/* the same hard-coded signals we've always used. */
# if !defined(SIG_SUSPEND)
# if defined(GC_LINUX_THREADS)
# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
# if defined(SPARC) && !defined(SIGPWR)
/* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.
* It is aliased to SIGLOST in asm/signal.h, though. */
@@ -1925,7 +1871,11 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
# define SIG_SUSPEND SIGPWR
# endif
# else /* !GC_LINUX_THREADS */
# define SIG_SUSPEND _SIGRTMIN + 6
# if defined(_SIGRTMIN)
# define SIG_SUSPEND _SIGRTMIN + 6
# else
# define SIG_SUSPEND SIGRTMIN + 6
# endif
# endif
# endif /* !SIG_SUSPEND */
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -16,7 +16,8 @@
# define DETACHED 2 /* Thread is intended to be detached. */
# define CLIENT_OWNS_STACK 4
/* Stack was supplied by client. */
# define SUSPENDED 8 /* Currently suspended. */
# define SUSPNDED 8 /* Currently suspended. */
/* SUSPENDED is used insystem header. */
ptr_t stack;
size_t stack_size;
cond_t join_cv;
+18 -6
View File
@@ -27,16 +27,22 @@
#define TS_HASH_SIZE 1024
#define HASH(n) (((((long)n) >> 8) ^ (long)n) & (TS_HASH_SIZE - 1))
/* An entry describing a thread-specific value for a given thread. */
/* All such accessible structures preserve the invariant that if either */
/* thread is a valid pthread id or qtid is a valid "quick tread id" */
/* for a thread, then value holds the corresponding thread specific */
/* value. This invariant must be preserved at ALL times, since */
/* asynchronous reads are allowed. */
typedef struct thread_specific_entry {
unsigned long qtid; /* quick thread id, only for cache */
void * value;
pthread_t thread;
struct thread_specific_entry *next;
pthread_t thread;
} tse;
/* We represent each thread-specific datum as two tables. The first is */
/* a cache, index by a "quick thread identifier". The "quick" thread */
/* a cache, indexed by a "quick thread identifier". The "quick" thread */
/* identifier is an easy to compute value, which is guaranteed to */
/* determine the thread, though a thread may correspond to more than */
/* one value. We typically use the address of a page in the stack. */
@@ -45,12 +51,15 @@ typedef struct thread_specific_entry {
/* Return the "quick thread id". Default version. Assumes page size, */
/* or at least thread stack separation, is at least 4K. */
static __inline__ long quick_thread_id() {
/* Must be defined so that it never returns 0. (Page 0 can't really */
/* be part of any stack, since that would make 0 a valid stack pointer.)*/
static __inline__ unsigned long quick_thread_id() {
int dummy;
return (long)(&dummy) >> 12;
return (unsigned long)(&dummy) >> 12;
}
#define INVALID_QTID ((unsigned long)(-1))
#define INVALID_QTID ((unsigned long)0)
#define INVALID_THREADID ((pthread_t)0)
typedef struct thread_specific_data {
tse * volatile cache[TS_CACHE_SIZE];
@@ -76,7 +85,10 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) {
unsigned hash_val = CACHE_HASH(qtid);
tse * volatile * entry_ptr = key -> cache + hash_val;
tse * entry = *entry_ptr; /* Must be loaded only once. */
if (entry -> qtid == qtid) return entry -> value;
if (entry -> qtid == qtid) {
GC_ASSERT(entry -> thread == pthread_self());
return entry -> value;
}
return PREFIXED(slow_getspecific) (key, qtid, entry_ptr);
}