Commit 56293c2b by Bryce McKinlay

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

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

From-SVN: r33245
parent 0eebf9e5
...@@ -29,9 +29,11 @@ ...@@ -29,9 +29,11 @@
/* source is heap object ==> *base_p != 0, *offset_p = offset */ /* source is heap object ==> *base_p != 0, *offset_p = offset */
/* Returns 1 on success, 0 if source couldn't be determined. */ /* Returns 1 on success, 0 if source couldn't be determined. */
/* Dest can be any address within a heap object. */ /* Dest can be any address within a heap object. */
typedef enum { GC_UNREFERENCED, /* No refence info available. */ typedef enum { GC_UNREFERENCED, /* No reference info available. */
GC_NO_SPACE, /* Dest not allocated with debug alloc */ GC_NO_SPACE, /* Dest not allocated with debug alloc */
GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p */ GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p */
GC_REFD_FROM_REG, /* Referenced from a register, i.e. */
/* a root without an address. */
GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */ GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */
GC_FINALIZER_REFD /* Finalizable and hence accessible. */ GC_FINALIZER_REFD /* Finalizable and hence accessible. */
} GC_ref_kind; } GC_ref_kind;
...@@ -53,4 +55,9 @@ void * GC_generate_random_valid_address(void); ...@@ -53,4 +55,9 @@ void * GC_generate_random_valid_address(void);
/* source in dbg_mlc.c also serves as a sample client. */ /* source in dbg_mlc.c also serves as a sample client. */
void GC_generate_random_backtrace(void); void GC_generate_random_backtrace(void);
/* Print a backtrace from a specific address. Used by the */
/* above. The client should call GC_gcollect() immediately */
/* before invocation. */
void GC_print_backtrace(void *);
...@@ -233,7 +233,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) ...@@ -233,7 +233,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
if (width == NONE && prec == NONE) { if (width == NONE && prec == NONE) {
register char c; register char c;
c = va_arg(args, char); c = va_arg(args, int);
CORD_ec_append(result, c); CORD_ec_append(result, c);
goto done; goto done;
} }
......
/* /*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright 1996 by Silicon Graphics. All rights reserved. * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright 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.
...@@ -352,11 +353,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb)); ...@@ -352,11 +353,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
#ifdef GC_ADD_CALLER #ifdef GC_ADD_CALLER
# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__ # define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * descr_string, # define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * s,
int descr_int int i
#else #else
# define GC_EXTRAS __FILE__, __LINE__ # define GC_EXTRAS __FILE__, __LINE__
# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int # define GC_EXTRA_PARAMS GC_CONST char * s, int i
#endif #endif
/* Debugging (annotated) allocation. GC_gcollect will check */ /* Debugging (annotated) allocation. GC_gcollect will check */
......
...@@ -387,7 +387,8 @@ int GC_is_thread_stack(ptr_t addr) ...@@ -387,7 +387,8 @@ int GC_is_thread_stack(ptr_t addr)
} }
# endif # endif
/* We hold allocation lock. We assume the world is stopped. */ /* We hold allocation lock. Should do exactly the right thing if the */
/* world is stopped. Should not fail if it isn't. */
void GC_push_all_stacks() void GC_push_all_stacks()
{ {
register int i; register int i;
......
...@@ -29,9 +29,11 @@ ...@@ -29,9 +29,11 @@
/* source is heap object ==> *base_p != 0, *offset_p = offset */ /* source is heap object ==> *base_p != 0, *offset_p = offset */
/* Returns 1 on success, 0 if source couldn't be determined. */ /* Returns 1 on success, 0 if source couldn't be determined. */
/* Dest can be any address within a heap object. */ /* Dest can be any address within a heap object. */
typedef enum { GC_UNREFERENCED, /* No refence info available. */ typedef enum { GC_UNREFERENCED, /* No reference info available. */
GC_NO_SPACE, /* Dest not allocated with debug alloc */ GC_NO_SPACE, /* Dest not allocated with debug alloc */
GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p */ GC_REFD_FROM_ROOT, /* Referenced directly by root *base_p */
GC_REFD_FROM_REG, /* Referenced from a register, i.e. */
/* a root without an address. */
GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */ GC_REFD_FROM_HEAP, /* Referenced from another heap obj. */
GC_FINALIZER_REFD /* Finalizable and hence accessible. */ GC_FINALIZER_REFD /* Finalizable and hence accessible. */
} GC_ref_kind; } GC_ref_kind;
...@@ -53,4 +55,9 @@ void * GC_generate_random_valid_address(void); ...@@ -53,4 +55,9 @@ void * GC_generate_random_valid_address(void);
/* source in dbg_mlc.c also serves as a sample client. */ /* source in dbg_mlc.c also serves as a sample client. */
void GC_generate_random_backtrace(void); void GC_generate_random_backtrace(void);
/* Print a backtrace from a specific address. Used by the */
/* above. The client should call GC_gcollect() immediately */
/* before invocation. */
void GC_print_backtrace(void *);
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
* This interface is fairly big, largely for performance reasons. * This interface is fairly big, largely for performance reasons.
* The most basic constants and functions: * The most basic constants and functions:
* *
* CORD - the type fo a cord; * CORD - the type of a cord;
* CORD_EMPTY - empty cord; * CORD_EMPTY - empty cord;
* CORD_len(cord) - length of a cord; * CORD_len(cord) - length of a cord;
* CORD_cat(cord1,cord2) - concatenation of two cords; * CORD_cat(cord1,cord2) - concatenation of two cords;
......
/* /*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright 1996 by Silicon Graphics. All rights reserved. * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright 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.
...@@ -35,6 +36,14 @@ ...@@ -35,6 +36,14 @@
#include "libgc_globals.h" #include "libgc_globals.h"
#endif #endif
#if defined(__MINGW32__) && defined(WIN32_THREADS)
# ifdef GC_BUILD
# define GC_API __declspec(dllexport)
# else
# define GC_API __declspec(dllimport)
# 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)
...@@ -130,6 +139,17 @@ GC_API int GC_dont_expand; ...@@ -130,6 +139,17 @@ GC_API int GC_dont_expand;
/* Dont expand heap unless explicitly requested */ /* Dont expand heap unless explicitly requested */
/* or forced to. */ /* or forced to. */
GC_API int GC_use_entire_heap;
/* Causes the nonincremental collector to use the */
/* entire heap before collecting. This was the only */
/* option for GC versions < 5.0. This sometimes */
/* results in more large block fragmentation, since */
/* very larg blocks will tend to get broken up */
/* during each GC cycle. It is likely to result in a */
/* larger working set, but lower collection */
/* frequencies, and hence fewer instructions executed */
/* in the collector. */
GC_API int GC_full_freq; /* Number of partial collections between */ GC_API int GC_full_freq; /* Number of partial collections between */
/* full collections. Matters only if */ /* full collections. Matters only if */
/* GC_incremental is set. */ /* GC_incremental is set. */
...@@ -352,11 +372,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb)); ...@@ -352,11 +372,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
#ifdef GC_ADD_CALLER #ifdef GC_ADD_CALLER
# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__ # define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * descr_string, # define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * s,
int descr_int int i
#else #else
# define GC_EXTRAS __FILE__, __LINE__ # define GC_EXTRAS __FILE__, __LINE__
# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int # define GC_EXTRA_PARAMS GC_CONST char * s, int i
#endif #endif
/* Debugging (annotated) allocation. GC_gcollect will check */ /* Debugging (annotated) allocation. GC_gcollect will check */
...@@ -387,6 +407,8 @@ GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); ...@@ -387,6 +407,8 @@ GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR));
GC_debug_register_finalizer(p, f, d, of, od) GC_debug_register_finalizer(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \ # define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
GC_debug_register_finalizer_ignore_self(p, f, d, of, od) GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
GC_debug_register_finalizer_no_order(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS); # define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS);
# define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p) # define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p) # define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
...@@ -403,6 +425,8 @@ GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); ...@@ -403,6 +425,8 @@ GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR));
GC_register_finalizer(p, f, d, of, od) GC_register_finalizer(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \ # define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
GC_register_finalizer_ignore_self(p, f, d, of, od) GC_register_finalizer_ignore_self(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
GC_register_finalizer_no_order(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz) # define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz)
# define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p) # define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p) # define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
...@@ -481,6 +505,16 @@ GC_API void GC_debug_register_finalizer_ignore_self ...@@ -481,6 +505,16 @@ GC_API void GC_debug_register_finalizer_ignore_self
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd, GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd)); GC_finalization_proc *ofn, GC_PTR *ocd));
/* Another version of the above. It ignores all cycles. */
/* It should probably only be used by Java implementations. */
GC_API void GC_register_finalizer_no_order
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
GC_API void GC_debug_register_finalizer_no_order
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
/* The following routine may be used to break cycles between */ /* The following routine may be used to break cycles between */
/* finalizable objects, thus causing cyclic finalizable */ /* finalizable objects, thus causing cyclic finalizable */
/* objects to be finalized in the correct order. Standard */ /* objects to be finalized in the correct order. Standard */
...@@ -537,6 +571,9 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */)); ...@@ -537,6 +571,9 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */));
GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data)); GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data));
GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data)); GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data));
/* Returns !=0 if GC_invoke_finalizers has something to do. */
GC_API int GC_should_invoke_finalizers GC_PROTO((void));
GC_API int GC_invoke_finalizers GC_PROTO((void)); GC_API int GC_invoke_finalizers GC_PROTO((void));
/* Run finalizers for all objects that are ready to */ /* Run finalizers for all objects that are ready to */
/* be finalized. Return the number of finalizers */ /* be finalized. Return the number of finalizers */
...@@ -700,7 +737,8 @@ GC_API void (*GC_is_visible_print_proc) ...@@ -700,7 +737,8 @@ GC_API void (*GC_is_visible_print_proc)
# endif /* SOLARIS_THREADS */ # endif /* SOLARIS_THREADS */
#if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS) #if !defined(USE_LD_WRAP) && \
(defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS))
/* We treat these similarly. */ /* We treat these similarly. */
# include <pthread.h> # include <pthread.h>
# include <signal.h> # include <signal.h>
...@@ -714,8 +752,9 @@ GC_API void (*GC_is_visible_print_proc) ...@@ -714,8 +752,9 @@ GC_API void (*GC_is_visible_print_proc)
# define pthread_create GC_pthread_create # define pthread_create GC_pthread_create
# define pthread_sigmask GC_pthread_sigmask # define pthread_sigmask GC_pthread_sigmask
# define pthread_join GC_pthread_join # define pthread_join GC_pthread_join
# define dlopen GC_dlopen
#endif /* IRIX_THREADS || LINUX_THREADS */ #endif /* xxxxx_THREADS */
# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \ # if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \ defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
......
...@@ -16,12 +16,11 @@ the code was modified is included with the above copyright notice. ...@@ -16,12 +16,11 @@ the code was modified is included with the above copyright notice.
C++ Interface to the Boehm Collector C++ Interface to the Boehm Collector
John R. Ellis and Jesse Hull John R. Ellis and Jesse Hull
Last modified on Mon Jul 24 15:43:42 PDT 1995 by ellis
This interface provides access to the Boehm collector. It provides This interface provides access to the Boehm collector. It provides
basic facilities similar to those described in "Safe, Efficient basic facilities similar to those described in "Safe, Efficient
Garbage Collection for C++", by John R. Elis and David L. Detlefs Garbage Collection for C++", by John R. Elis and David L. Detlefs
(ftp.parc.xerox.com:/pub/ellis/gc). (ftp://ftp.parc.xerox.com/pub/ellis/gc).
All heap-allocated objects are either "collectable" or All heap-allocated objects are either "collectable" or
"uncollectable". Programs must explicitly delete uncollectable "uncollectable". Programs must explicitly delete uncollectable
...@@ -38,7 +37,7 @@ Objects derived from class "gc" are collectable. For example: ...@@ -38,7 +37,7 @@ Objects derived from class "gc" are collectable. For example:
A* a = new A; // a is collectable. A* a = new A; // a is collectable.
Collectable instances of non-class types can be allocated using the GC Collectable instances of non-class types can be allocated using the GC
placement: (or UseGC) placement:
typedef int A[ 10 ]; typedef int A[ 10 ];
A* a = new (GC) A; A* a = new (GC) A;
...@@ -124,6 +123,12 @@ invoked using the ANSI-conforming syntax t->~T(). If you're using ...@@ -124,6 +123,12 @@ invoked using the ANSI-conforming syntax t->~T(). If you're using
cfront 3.0, you'll have to comment out the class gc_cleanup, which cfront 3.0, you'll have to comment out the class gc_cleanup, which
uses explicit invocation. uses explicit invocation.
5. GC name conflicts:
Many other systems seem to use the identifier "GC" as an abbreviation
for "Graphics Context". Since version 5.0, GC placement has been replaced
by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
****************************************************************************/ ****************************************************************************/
#include "gc.h" #include "gc.h"
...@@ -138,7 +143,11 @@ uses explicit invocation. ...@@ -138,7 +143,11 @@ uses explicit invocation.
# define OPERATOR_NEW_ARRAY # define OPERATOR_NEW_ARRAY
#endif #endif
enum GCPlacement {GC, NoGC, PointerFreeGC}; enum GCPlacement {UseGC,
#ifndef GC_NAME_CONFLICT
GC=UseGC,
#endif
NoGC, PointerFreeGC};
class gc {public: class gc {public:
inline void* operator new( size_t size ); inline void* operator new( size_t size );
...@@ -211,7 +220,7 @@ inline void* gc::operator new( size_t size ) { ...@@ -211,7 +220,7 @@ inline void* gc::operator new( size_t size ) {
return GC_MALLOC( size );} return GC_MALLOC( 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 == UseGC)
return GC_MALLOC( size ); return GC_MALLOC( size );
else if (gcp == PointerFreeGC) else if (gcp == PointerFreeGC)
return GC_MALLOC_ATOMIC( size ); return GC_MALLOC_ATOMIC( size );
...@@ -261,7 +270,7 @@ inline void* operator new( ...@@ -261,7 +270,7 @@ inline void* operator new(
{ {
void* obj; void* obj;
if (gcp == GC) { if (gcp == UseGC) {
obj = GC_MALLOC( size ); obj = GC_MALLOC( size );
if (cleanup != 0) if (cleanup != 0)
GC_REGISTER_FINALIZER_IGNORE_SELF( GC_REGISTER_FINALIZER_IGNORE_SELF(
......
...@@ -61,6 +61,7 @@ GC_API GC_PTR GC_malloc_explicitly_typed ...@@ -61,6 +61,7 @@ GC_API GC_PTR GC_malloc_explicitly_typed
GC_PROTO((size_t size_in_bytes, GC_descr d)); GC_PROTO((size_t size_in_bytes, GC_descr d));
/* Allocate an object whose layout is described by d. */ /* Allocate an object whose layout is described by d. */
/* The resulting object MAY NOT BE PASSED TO REALLOC. */ /* The resulting object MAY NOT BE PASSED TO REALLOC. */
/* The returned object is cleared. */
GC_API GC_PTR GC_malloc_explicitly_typed_ignore_off_page GC_API GC_PTR GC_malloc_explicitly_typed_ignore_off_page
GC_PROTO((size_t size_in_bytes, GC_descr d)); GC_PROTO((size_t size_in_bytes, GC_descr d));
...@@ -75,6 +76,7 @@ GC_API GC_PTR GC_calloc_explicitly_typed ...@@ -75,6 +76,7 @@ GC_API GC_PTR GC_calloc_explicitly_typed
/* alignment required for pointers. E.g. on a 32-bit */ /* alignment required for pointers. E.g. on a 32-bit */
/* machine with 16-bit aligned pointers, size_in_bytes */ /* machine with 16-bit aligned pointers, size_in_bytes */
/* must be a multiple of 2. */ /* must be a multiple of 2. */
/* Returned object is cleared. */
#ifdef GC_DEBUG #ifdef GC_DEBUG
# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes) # define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes)
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
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
...@@ -82,6 +82,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ ...@@ -82,6 +82,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
# define GC_FAR # define GC_FAR
#endif #endif
/*********************************/ /*********************************/
/* */ /* */
/* Definitions for conservative */ /* Definitions for conservative */
...@@ -173,15 +174,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ ...@@ -173,15 +174,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
/* 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
...@@ -281,6 +273,13 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -281,6 +273,13 @@ 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 */
...@@ -306,6 +305,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -306,6 +305,7 @@ 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. */
...@@ -437,8 +437,11 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -437,8 +437,11 @@ 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>
# define USE_SPIN_LOCK
# if defined(I386) # 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;
...@@ -448,7 +451,36 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -448,7 +451,36 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
: "0"(1), "m"(*(addr))); : "0"(1), "m"(*(addr)));
return oldval; return oldval;
} }
# else # endif
# 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) # if defined(POWERPC)
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;
...@@ -466,10 +498,14 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); ...@@ -466,10 +498,14 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
: "memory"); : "memory");
return (int)oldval; return (int)oldval;
} }
# else inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("eieio");
*(addr) = 0;
}
# define GC_CLEAR_DEFINED
# endif
# ifdef ALPHA # ifdef ALPHA
inline static int GC_test_and_set(volatile unsigned int * inline static int GC_test_and_set(volatile unsigned int * addr)
addr)
{ {
unsigned long oldvalue; unsigned long oldvalue;
unsigned long temp; unsigned long temp;
...@@ -486,25 +522,36 @@ addr) ...@@ -486,25 +522,36 @@ addr)
".section .text2,\"ax\"\n" ".section .text2,\"ax\"\n"
"3: br 1b\n" "3: br 1b\n"
".previous" ".previous"
:"=&r" (temp), "=m" (*addr), "=&r" :"=&r" (temp), "=m" (*addr), "=&r" (oldvalue)
(oldvalue)
:"Ir" (1), "m" (*addr)); :"Ir" (1), "m" (*addr));
return oldvalue; return oldvalue;
} }
# else /* Should probably also define GC_clear, since it needs */
-- > Need implementation of GC_test_and_set() /* a memory barrier ?? */
# endif # endif /* ALPHA */
# endif # 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 # endif
# ifndef GC_CLEAR_DEFINED
inline static void GC_clear(volatile unsigned int *addr) { inline static void GC_clear(volatile unsigned int *addr) {
/* Try to discourage gcc from moving anything past this. */
__asm__ __volatile__(" ");
*(addr) = 0; *(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 */
...@@ -517,12 +564,19 @@ addr) ...@@ -517,12 +564,19 @@ addr)
{ 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)
extern GC_bool GC_collecting; extern VOLATILE 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(HPUX_THREADS) # if defined(HPUX_THREADS)
# include <pthread.h> # include <pthread.h>
...@@ -581,7 +635,7 @@ addr) ...@@ -581,7 +635,7 @@ addr)
*(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; \
...@@ -957,8 +1011,10 @@ struct hblk { ...@@ -957,8 +1011,10 @@ struct hblk {
/* 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)
...@@ -1035,6 +1091,7 @@ struct roots { ...@@ -1035,6 +1091,7 @@ struct roots {
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; word _large_free_bytes;
...@@ -1059,6 +1116,10 @@ struct _GC_arrays { ...@@ -1059,6 +1116,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. */
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 */
...@@ -1223,9 +1284,12 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; ...@@ -1223,9 +1284,12 @@ 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_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
...@@ -1260,6 +1324,8 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; ...@@ -1260,6 +1324,8 @@ 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
...@@ -1392,10 +1458,7 @@ extern ptr_t GC_greatest_plausible_heap_addr; ...@@ -1392,10 +1458,7 @@ 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. */
...@@ -1672,9 +1735,10 @@ ptr_t GC_allocobj(/* sz_inn_words, kind */); ...@@ -1672,9 +1735,10 @@ 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. */
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
* modified is included with the above copyright notice. * modified is included with the above copyright notice.
*/ */
#ifndef CONFIG_H #ifndef GCCONFIG_H
# define CONFIG_H # define GCCONFIG_H
/* Machine dependent parameters. Some tuning parameters can be found */ /* Machine dependent parameters. Some tuning parameters can be found */
/* near the top of gc_private.h. */ /* near the top of gc_private.h. */
...@@ -53,6 +53,11 @@ ...@@ -53,6 +53,11 @@
# define NETBSD # define NETBSD
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(__NetBSD__) && defined(arm32)
# define ARM32
# define NETBSD
# define mach_type_known
# endif
# if defined(vax) # if defined(vax)
# define VAX # define VAX
# ifdef ultrix # ifdef ultrix
...@@ -64,15 +69,18 @@ ...@@ -64,15 +69,18 @@
# endif # endif
# if defined(mips) || defined(__mips) # if defined(mips) || defined(__mips)
# define MIPS # define MIPS
# if !defined(LINUX)
# if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__) # if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
# define ULTRIX # define ULTRIX
# else # else
# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__) # if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \
|| defined(__SYSTYPE_SVR4__)
# define IRIX5 /* or IRIX 6.X */ # define IRIX5 /* or IRIX 6.X */
# else # else
# define RISCOS /* or IRIX 4.X */ # define RISCOS /* or IRIX 4.X */
# endif # endif
# endif # endif
# endif /* !LINUX */
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(sequent) && defined(i386) # if defined(sequent) && defined(i386)
...@@ -130,15 +138,22 @@ ...@@ -130,15 +138,22 @@
# define SYSV # define SYSV
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) \ # if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__hppa__) || defined(hppa) || defined(__hppa__)
# define HP_PA # define HP_PA
# ifndef LINUX
# define HPUX
# endif
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(LINUX) && (defined(i386) || defined(__i386__)) # if defined(LINUX) && (defined(i386) || defined(__i386__))
# define I386 # define I386
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(LINUX) && (defined(__ia64__) || defined(__ia64))
# define IA64
# define mach_type_known
# endif
# if defined(LINUX) && defined(powerpc) # if defined(LINUX) && defined(powerpc)
# define POWERPC # define POWERPC
# define mach_type_known # define mach_type_known
...@@ -147,10 +162,14 @@ ...@@ -147,10 +162,14 @@
# define M68K # define M68K
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(LINUX) && defined(sparc) # if defined(LINUX) && (defined(sparc) || defined(__sparc__))
# define SPARC # define SPARC
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(LINUX) && defined(arm)
# define ARM32
# define mach_type_known
# endif
# if defined(__alpha) || defined(__alpha__) # if defined(__alpha) || defined(__alpha__)
# define ALPHA # define ALPHA
# if !defined(LINUX) # if !defined(LINUX)
...@@ -243,6 +262,11 @@ ...@@ -243,6 +262,11 @@
# define CYGWIN32 # define CYGWIN32
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(__MINGW32__)
# define I386
# define MSWIN32
# define mach_type_known
# endif
# if defined(__BORLANDC__) # if defined(__BORLANDC__)
# define I386 # define I386
# define MSWIN32 # define MSWIN32
...@@ -253,6 +277,10 @@ ...@@ -253,6 +277,10 @@
# define UTS4 # define UTS4
# define mach_type_known # define mach_type_known
# endif # endif
# if defined(__pj__)
# define PJ
# define mach_type_known
# endif
/* Ivan Demakov */ /* Ivan Demakov */
# if defined(__WATCOMC__) && defined(__386__) # if defined(__WATCOMC__) && defined(__386__)
# define I386 # define I386
...@@ -307,6 +335,9 @@ ...@@ -307,6 +335,9 @@
/* (CX_UX and DGUX) */ /* (CX_UX and DGUX) */
/* S370 ==> 370-like machine */ /* S370 ==> 370-like machine */
/* running Amdahl UTS4 */ /* running Amdahl UTS4 */
/* ARM32 ==> Intel StrongARM */
/* IA64 ==> Intel IA64 */
/* (e.g. Itanium) */
/* /*
...@@ -392,6 +423,15 @@ ...@@ -392,6 +423,15 @@
* *
* An architecture may define DYNAMIC_LOADING if dynamic_load.c * An architecture may define DYNAMIC_LOADING if dynamic_load.c
* defined GC_register_dynamic_libraries() for the architecture. * defined GC_register_dynamic_libraries() for the architecture.
*
* An architecture may define PREFETCH(x) to preload the cache with *x.
* This defaults to a no-op.
*
* PREFETCH_FOR_WRITE(x) is used if *x is about to be written.
*
* An architecture may also define CLEAR_DOUBLE(x) to be a fast way to
* clear the two words at GC_malloc-aligned address x. By default,
* word stores of 0 are used instead.
*/ */
...@@ -516,7 +556,7 @@ ...@@ -516,7 +556,7 @@
# undef STACK_GRAN # undef STACK_GRAN
# define STACK_GRAN 0x10000000 # define STACK_GRAN 0x10000000
/* Stack usually starts at 0x80000000 */ /* Stack usually starts at 0x80000000 */
# define DATASTART GC_data_start # define LINUX_DATA_START
extern int _end; extern int _end;
# define DATAEND (&_end) # define DATAEND (&_end)
# endif # endif
...@@ -615,7 +655,7 @@ ...@@ -615,7 +655,7 @@
# ifdef LINUX # ifdef LINUX
# define OS_TYPE "LINUX" # define OS_TYPE "LINUX"
# ifdef __ELF__ # ifdef __ELF__
# define DATASTART GC_data_start # define LINUX_DATA_START
# define DYNAMIC_LOADING # define DYNAMIC_LOADING
# else # else
Linux Sparc non elf ? Linux Sparc non elf ?
...@@ -684,6 +724,8 @@ ...@@ -684,6 +724,8 @@
# endif # endif
# ifdef LINUX # ifdef LINUX
# define OS_TYPE "LINUX" # define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# if 0
# define HEURISTIC1 # define HEURISTIC1
# undef STACK_GRAN # undef STACK_GRAN
# define STACK_GRAN 0x10000000 # define STACK_GRAN 0x10000000
...@@ -691,6 +733,7 @@ ...@@ -691,6 +733,7 @@
/* different kernel configurations. In particular, systems */ /* different kernel configurations. In particular, systems */
/* with 2GB physical memory will usually move the user */ /* with 2GB physical memory will usually move the user */
/* address space limit, and hence initial SP to 0x80000000. */ /* address space limit, and hence initial SP to 0x80000000. */
# endif
# if !defined(LINUX_THREADS) || !defined(REDIRECT_MALLOC) # if !defined(LINUX_THREADS) || !defined(REDIRECT_MALLOC)
# define MPROTECT_VDB # define MPROTECT_VDB
# else # else
...@@ -706,8 +749,7 @@ ...@@ -706,8 +749,7 @@
# endif # endif
# include <features.h> # include <features.h>
# if defined(__GLIBC__) && __GLIBC__ >= 2 # if defined(__GLIBC__) && __GLIBC__ >= 2
extern int __data_start; # define LINUX_DATA_START
# define DATASTART ((ptr_t)(&__data_start))
# else # else
extern char **__environ; extern char **__environ;
# define DATASTART ((ptr_t)(&__environ)) # define DATASTART ((ptr_t)(&__environ))
...@@ -726,6 +768,26 @@ ...@@ -726,6 +768,26 @@
extern int etext; extern int etext;
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) # define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
# endif # endif
# ifdef USE_I686_PREFETCH
# define PREFETCH(x) \
__asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x)))
/* Empirically prefetcht0 is much more effective at reducing */
/* cache miss stalls for the targetted load instructions. But it */
/* seems to interfere enough with other cache traffic that the net */
/* result is worse than prefetchnta. */
# if 0
/* Using prefetches for write seems to have a slight negative */
/* impact on performance, at least for a PIII/500. */
# define PREFETCH_FOR_WRITE(x) \
__asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x)))
# endif
# endif
# ifdef USE_3DNOW_PREFETCH
# define PREFETCH(x) \
__asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x)))
# define PREFETCH_FOR_WRITE(x)
__asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x)))
# endif
# endif # endif
# ifdef CYGWIN32 # ifdef CYGWIN32
# define OS_TYPE "CYGWIN32" # define OS_TYPE "CYGWIN32"
...@@ -836,11 +898,36 @@ ...@@ -836,11 +898,36 @@
# ifdef MIPS # ifdef MIPS
# define MACH_TYPE "MIPS" # define MACH_TYPE "MIPS"
# ifndef IRIX5 /* # define STACKBOTTOM ((ptr_t)0x7fff8000) sometimes also works. */
# ifdef LINUX
/* This was developed for a linuxce style platform. Probably */
/* needs to be tweaked for workstation class machines. */
# define OS_TYPE "LINUX"
extern int __data_start;
# define DATASTART ((ptr_t)(&__data_start))
# define ALIGNMENT 4
# define USE_GENERIC_PUSH_REGS 1
# define STACKBOTTOM 0x80000000
/* In many cases, this should probably use LINUX_STACKBOTTOM */
/* instead. But some kernel versions seem to give the wrong */
/* value from /proc. */
# endif /* Linux */
# ifdef ULTRIX
# define HEURISTIC2
# define DATASTART (ptr_t)0x10000000 # define DATASTART (ptr_t)0x10000000
/* Could probably be slightly higher since */ /* Could probably be slightly higher since */
/* startup code allocates lots of stuff. */ /* startup code allocates lots of stuff. */
# else # define OS_TYPE "ULTRIX"
# define ALIGNMENT 4
# endif
# ifdef RISCOS
# define HEURISTIC2
# define DATASTART (ptr_t)0x10000000
# define OS_TYPE "RISCOS"
# define ALIGNMENT 4 /* Required by hardware */
# endif
# ifdef IRIX5
# define HEURISTIC2
extern int _fdata; extern int _fdata;
# define DATASTART ((ptr_t)(&_fdata)) # define DATASTART ((ptr_t)(&_fdata))
# ifdef USE_MMAP # ifdef USE_MMAP
...@@ -853,18 +940,6 @@ ...@@ -853,18 +940,6 @@
/* In either case it is used to identify */ /* In either case it is used to identify */
/* heap sections so they're not */ /* heap sections so they're not */
/* considered as roots. */ /* considered as roots. */
# endif /* IRIX5 */
# define HEURISTIC2
/* # define STACKBOTTOM ((ptr_t)0x7fff8000) sometimes also works. */
# ifdef ULTRIX
# define OS_TYPE "ULTRIX"
# define ALIGNMENT 4
# endif
# ifdef RISCOS
# define OS_TYPE "RISCOS"
# define ALIGNMENT 4 /* Required by hardware */
# endif
# ifdef IRIX5
# define OS_TYPE "IRIX5" # define OS_TYPE "IRIX5"
# define MPROTECT_VDB # define MPROTECT_VDB
# ifdef _MIPS_SZPTR # ifdef _MIPS_SZPTR
...@@ -892,9 +967,17 @@ ...@@ -892,9 +967,17 @@
# endif # endif
# ifdef HP_PA # ifdef HP_PA
/* OS is assumed to be HP/UX */
# define MACH_TYPE "HP_PA" # define MACH_TYPE "HP_PA"
# define OS_TYPE "HPUX"
# ifdef __LP64__
# define CPP_WORDSZ 64
# define ALIGNMENT 8
# else
# define CPP_WORDSZ 32
# define ALIGNMENT 4 # define ALIGNMENT 4
# define ALIGN_DOUBLE # define ALIGN_DOUBLE
# endif
extern int __data_start; extern int __data_start;
# define DATASTART ((ptr_t)(&__data_start)) # define DATASTART ((ptr_t)(&__data_start))
# if 0 # if 0
...@@ -911,14 +994,21 @@ ...@@ -911,14 +994,21 @@
# endif # endif
# define STACK_GROWS_UP # define STACK_GROWS_UP
# define DYNAMIC_LOADING # define DYNAMIC_LOADING
# ifndef HPUX_THREADS
# define MPROTECT_VDB
# endif
# include <unistd.h> # include <unistd.h>
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) # define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
/* They misspelled the Posix macro? */
# endif # endif
# ifdef ALPHA # ifdef ALPHA
# define MACH_TYPE "ALPHA" # define MACH_TYPE "ALPHA"
# define ALIGNMENT 8 # define ALIGNMENT 8
# define USE_GENERIC_PUSH_REGS
/* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */
/* fp registers in some cases when the target is a 21264. The assembly */
/* code doesn't handle that yet, and version dependencies make that a */
/* bit tricky. Do the easy thing for now. */
# ifdef OSF1 # ifdef OSF1
# define OS_TYPE "OSF1" # define OS_TYPE "OSF1"
# define DATASTART ((ptr_t) 0x140000000) # define DATASTART ((ptr_t) 0x140000000)
...@@ -939,13 +1029,9 @@ ...@@ -939,13 +1029,9 @@
# define CPP_WORDSZ 64 # define CPP_WORDSZ 64
# define STACKBOTTOM ((ptr_t) 0x120000000) # define STACKBOTTOM ((ptr_t) 0x120000000)
# ifdef __ELF__ # ifdef __ELF__
# if 0 # define LINUX_DATA_START
/* __data_start apparently disappeared in some recent releases. */
extern int __data_start;
# define DATASTART &__data_start
# endif
# define DATASTART GC_data_start
# define DYNAMIC_LOADING # define DYNAMIC_LOADING
/* This doesn't work if the collector is in a dynamic library. */
# else # else
# define DATASTART ((ptr_t) 0x140000000) # define DATASTART ((ptr_t) 0x140000000)
# endif # endif
...@@ -957,6 +1043,49 @@ ...@@ -957,6 +1043,49 @@
# endif # endif
# endif # endif
# ifdef IA64
# define MACH_TYPE "IA64"
# define ALIGN_DOUBLE
/* Requires 16 byte alignment for malloc */
# define ALIGNMENT 8
# define USE_GENERIC_PUSH_REGS
/* We need to get preserved registers in addition to register windows. */
/* That's easiest to do with setjmp. */
# ifdef HPUX
--> needs work
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
# define CPP_WORDSZ 64
/* This should really be done through /proc, but that */
/* requires we run on an IA64 kernel. */
# define STACKBOTTOM ((ptr_t) 0xa000000000000000l)
/* We also need the base address of the register stack */
/* backing store. There is probably a better way to */
/* get that, too ... */
# define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l)
# if 1
# define SEARCH_FOR_DATA_START
# define DATASTART GC_data_start
# else
extern int data_start;
# define DATASTART ((ptr_t)(&data_start))
# endif
# define DYNAMIC_LOADING
# define MPROTECT_VDB
/* Requires Linux 2.3.47 or later. */
extern int _end;
# define DATAEND (&_end)
/* PREFETCH appears to have a large performance impact. */
# define PREFETCH(x) \
__asm__ (" lfetch [%0]": : "r"((void *)(x)))
# define PREFETCH_FOR_WRITE(x) \
__asm__ (" lfetch.excl [%0]": : "r"((void *)(x)))
# define CLEAR_DOUBLE(x) \
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
# endif
# endif
# ifdef M88K # ifdef M88K
# define MACH_TYPE "M88K" # define MACH_TYPE "M88K"
# define ALIGNMENT 4 # define ALIGNMENT 4
...@@ -987,6 +1116,69 @@ ...@@ -987,6 +1116,69 @@
# define HEURISTIC2 # define HEURISTIC2
# endif # endif
# if defined(PJ)
# define ALIGNMENT 4
extern int _etext;
# define DATASTART ((ptr_t)(&_etext))
# define HEURISTIC1
# endif
# ifdef ARM32
# define CPP_WORDSZ 32
# define MACH_TYPE "ARM32"
# define ALIGNMENT 4
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
extern char etext;
# define DATASTART ((ptr_t)(&etext))
# define USE_GENERIC_PUSH_REGS
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
# define HEURISTIC1
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
# define USE_GENERIC_PUSH_REGS
# ifdef __ELF__
# define DYNAMIC_LOADING
# include <features.h>
# if defined(__GLIBC__) && __GLIBC__ >= 2
# define LINUX_DATA_START
# else
extern char **__environ;
# define DATASTART ((ptr_t)(&__environ))
/* hideous kludge: __environ is the first */
/* word in crt0.o, and delimits the start */
/* of the data segment, no matter which */
/* ld options were passed through. */
/* We could use _etext instead, but that */
/* would include .rodata, which may */
/* contain large read-only data tables */
/* that we'd rather not scan. */
# endif
extern int _end;
# define DATAEND (&_end)
# else
extern int etext;
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
# endif
# endif
#endif
#ifdef LINUX_DATA_START
/* Some Linux distributions arrange to define __data_start. Some */
/* define data_start as a weak symbol. The latter is technically */
/* broken, since the user program may define data_start, in which */
/* case we lose. Nonetheless, we try both, prefering __data_start. */
/* We assume gcc. */
# pragma weak __data_start
extern int __data_start;
# pragma weak data_start
extern int data_start;
# define DATASTART ((ptr_t)(&__data_start != 0? &__data_start : &data_start))
#endif
# ifndef STACK_GROWS_UP # ifndef STACK_GROWS_UP
# define STACK_GROWS_DOWN # define STACK_GROWS_DOWN
# endif # endif
...@@ -1029,6 +1221,10 @@ ...@@ -1029,6 +1221,10 @@
# define SUNOS5SIGS # define SUNOS5SIGS
# endif # endif
# if defined(HPUX)
# define SUNOS5SIGS
# endif
# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
-> bad word size -> bad word size
# endif # endif
...@@ -1063,6 +1259,26 @@ ...@@ -1063,6 +1259,26 @@
# define DEFAULT_VDB # define DEFAULT_VDB
# endif # endif
# ifndef PREFETCH
# define PREFETCH(x)
# define NO_PREFETCH
# endif
# ifndef PREFETCH_FOR_WRITE
# define PREFETCH_FOR_WRITE(x)
# define NO_PREFETCH_FOR_WRITE
# endif
# ifndef CACHE_LINE_SIZE
# define CACHE_LINE_SIZE 32 /* Wild guess */
# endif
# ifndef CLEAR_DOUBLE
# define CLEAR_DOUBLE(x) \
((word*)x)[0] = 0; \
((word*)x)[1] = 0;
# endif /* CLEAR_DOUBLE */
# if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS) # if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS)
# define SOLARIS_THREADS # define SOLARIS_THREADS
# endif # endif
...@@ -1078,10 +1294,13 @@ ...@@ -1078,10 +1294,13 @@
# if defined(SOLARIS_THREADS) && !defined(SUNOS5) # if defined(SOLARIS_THREADS) && !defined(SUNOS5)
--> inconsistent configuration --> inconsistent configuration
# endif # endif
# if defined(HPUX_THREADS) && !defined(HPUX)
--> inconsistent configuration
# endif
# if defined(PCR) || defined(SRC_M3) || \ # if defined(PCR) || defined(SRC_M3) || \
defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \ 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)
# define THREADS # define THREADS
# endif # endif
...@@ -1096,4 +1315,4 @@ ...@@ -1096,4 +1315,4 @@
/* include assembly code to do it well. */ /* include assembly code to do it well. */
# endif # endif
# endif # endif /* GCCONFIG_H */
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