Commit abdbd4a8 by Bryce McKinlay

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

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

From-SVN: r42374
parent f54d4287
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
# include "cord.h" # include "cord.h"
# include <string.h> # include <string.h>
# include <stdio.h> # include <stdio.h>
# include <stdlib.h>
/* This is a very incomplete test of the cord package. It knows about */ /* This is a very incomplete test of the cord package. It knows about */
/* a few internals of the package (e.g. when C strings are returned) */ /* a few internals of the package (e.g. when C strings are returned) */
/* that real clients shouldn't rely on. */ /* that real clients shouldn't rely on. */
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
// This uses template classes with static members, and hence does not work // This uses template classes with static members, and hence does not work
// with g++ 2.7.2 and earlier. // with g++ 2.7.2 and earlier.
// //
// This code assumes that the collector itself has been compiled with a
// compiler that defines __STDC__ .
//
#include "gc.h" #include "gc.h"
......
...@@ -139,7 +139,7 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. ...@@ -139,7 +139,7 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
#if ! defined( OPERATOR_NEW_ARRAY ) \ #if ! defined( OPERATOR_NEW_ARRAY ) \
&& (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \ && (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \
|| __WATCOMC__ >= 1050) || __WATCOMC__ >= 1050 || _MSC_VER >= 1100)
# define OPERATOR_NEW_ARRAY # define OPERATOR_NEW_ARRAY
#endif #endif
...@@ -179,6 +179,12 @@ private: ...@@ -179,6 +179,12 @@ private:
extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );} extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );}
#ifdef _MSC_VER
// Disable warning that "no matching operator delete found; memory will
// not be freed if initialization throws an exception"
# pragma warning(disable:4291)
#endif
inline void* operator new( inline void* operator new(
size_t size, size_t size,
GCPlacement gcp, GCPlacement gcp,
...@@ -200,6 +206,49 @@ inline void* operator new( ...@@ -200,6 +206,49 @@ inline void* operator new(
#ifdef OPERATOR_NEW_ARRAY #ifdef OPERATOR_NEW_ARRAY
#ifdef _MSC_VER
/** This ensures that the system default operator new[] doesn't get
* undefined, which is what seems to happen on VC++ 6 for some reason
* if we define a multi-argument operator new[].
* There seems to be really redirect new in this environment without
* including this everywhere.
*/
inline void *operator new[]( size_t size )
{
return GC_MALLOC_UNCOLLECTABLE( size );
}
inline void operator delete[](void* obj)
{
GC_FREE(obj);
};
inline void* operator new( size_t size)
{
return GC_MALLOC_UNCOLLECTABLE( size);
};
inline void operator delete(void* obj)
{
GC_FREE(obj);
};
// This new operator is used by VC++ in case of Debug builds !
inline void* operator new( size_t size,
int ,//nBlockUse,
const char * szFileName,
int nLine
) {
# ifndef GC_DEBUG
return GC_malloc_uncollectable( size );
# else
return GC_debug_malloc_uncollectable(size, szFileName, nLine);
# endif
}
#endif /* _MSC_VER */
inline void* operator new[]( inline void* operator new[](
size_t size, size_t size,
GCPlacement gcp, GCPlacement gcp,
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
* may be marked by the mark procedure passed to GC_init_gcj_malloc. * may be marked by the mark procedure passed to GC_init_gcj_malloc.
*/ */
#ifndef GC_GCJ_H
#define GC_GCJ_H
#ifndef MARK_DESCR_OFFSET #ifndef MARK_DESCR_OFFSET
# define MARK_DESCR_OFFSET sizeof(word) # define MARK_DESCR_OFFSET sizeof(word)
#endif #endif
...@@ -41,10 +45,7 @@ ...@@ -41,10 +45,7 @@
#endif #endif
/* The following allocators signal an out of memory condition with */ /* The following allocators signal an out of memory condition with */
/* return GC_oom_action(); */ /* return GC_oom_fn(bytes); */
/* The default GC_oom_action returns 0. */
/* This functionality is currently restricted to the gcj allocators. */
/* We may want to extend it to the others. */
extern void * (*GC_oom_action)(void); extern void * (*GC_oom_action)(void);
...@@ -58,8 +59,6 @@ extern void * (*GC_oom_action)(void); ...@@ -58,8 +59,6 @@ extern void * (*GC_oom_action)(void);
/* to use the same mark_proc for some of its generated mark descriptors.*/ /* to use the same mark_proc for some of its generated mark descriptors.*/
/* In that case, it should use a different "environment" value to */ /* In that case, it should use a different "environment" value to */
/* detect the presence or absence of the debug header. */ /* detect the presence or absence of the debug header. */
/* the debugging interface. */
/* Mp is really of type mark_proc, as defined in gc_mark.h. We don't */ /* Mp is really of type mark_proc, as defined in gc_mark.h. We don't */
/* want to include that here for namespace pollution reasons. */ /* want to include that here for namespace pollution reasons. */
extern void GC_init_gcj_malloc(int mp_index, void * /* really mark_proc */mp); extern void GC_init_gcj_malloc(int mp_index, void * /* really mark_proc */mp);
...@@ -77,6 +76,9 @@ extern void * GC_debug_gcj_malloc(size_t lb, ...@@ -77,6 +76,9 @@ extern void * GC_debug_gcj_malloc(size_t lb,
/* Similar to the above, but the size is in words, and we don't */ /* Similar to the above, but the size is in words, and we don't */
/* adjust it. The size is assumed to be such that it can be */ /* adjust it. The size is assumed to be such that it can be */
/* allocated as a small object. */ /* allocated as a small object. */
/* Unless it is known that the collector is not configured */
/* with USE_MARK_BYTES and unless it is known that the object */
/* has weak alignment requirements, lw must be even. */
extern void * GC_gcj_fast_malloc(size_t lw, extern void * GC_gcj_fast_malloc(size_t lw,
void * ptr_to_struct_containing_descr); void * ptr_to_struct_containing_descr);
extern void * GC_debug_gcj_fast_malloc(size_t lw, extern void * GC_debug_gcj_fast_malloc(size_t lw,
...@@ -91,11 +93,12 @@ extern void * GC_gcj_malloc_ignore_off_page(size_t lb, ...@@ -91,11 +93,12 @@ extern void * GC_gcj_malloc_ignore_off_page(size_t lb,
# ifdef GC_DEBUG # ifdef GC_DEBUG
# define GC_GCJ_MALLOC(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS) # define GC_GCJ_MALLOC(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS)
# define GC_GCJ_FAST_MALLOC(s,d) GC_debug_gcj_fast_malloc(s,d,GC_EXTRAS) # define GC_GCJ_FAST_MALLOC(s,d) GC_debug_gcj_fast_malloc(s,d,GC_EXTRAS)
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) GC_gcj_debug_malloc(s,d,GC_EXTRAS) # define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS)
# else # else
# define GC_GCJ_MALLOC(s,d) GC_gcj_malloc(s,d) # define GC_GCJ_MALLOC(s,d) GC_gcj_malloc(s,d)
# define GC_GCJ_FAST_MALLOC(s,d) GC_gcj_fast_malloc(s,d) # define GC_GCJ_FAST_MALLOC(s,d) GC_gcj_fast_malloc(s,d)
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) \ # define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) \
GC_gcj_debug_malloc_ignore_off_page(s,d) GC_gcj_malloc_ignore_off_page(s,d)
# endif # endif
#endif /* GC_GCJ_H */
...@@ -17,18 +17,22 @@ ...@@ -17,18 +17,22 @@
# include "private/gc_priv.h" # include "private/gc_priv.h"
# endif # endif
/* USE OF THIS FILE IS NOT RECOMMENDED unless the collector has been */ /* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers */
/* compiled without -DALL_INTERIOR_POINTERS or with */ /* is always set, or the collector has been built with */
/* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */ /* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */
/* word at the end. In the standard collector configuration, */ /* word at the end. In the standard collector configuration, */
/* the final word of each object may not be scanned. */ /* the final word of each object may not be scanned. */
/* This is most useful for compilers that generate C. */ /* This iinterface is most useful for compilers that generate C. */
/* Manual use is hereby discouraged. */ /* Manual use is hereby discouraged. */
/* Allocate n words (NOT BYTES). X is made to point to the result. */ /* Allocate n words (NOT BYTES). X is made to point to the result. */
/* It is assumed that n < MAXOBJSZ, and */ /* It is assumed that n < MAXOBJSZ, and */
/* that n > 0. On machines requiring double word alignment of some */ /* that n > 0. On machines requiring double word alignment of some */
/* data, we also assume that n is 1 or even. This bypasses the */ /* data, we also assume that n is 1 or even. */
/* If the collector is built with -DUSE_MARK_BYTES or -DPARALLEL_MARK, */
/* the n = 1 case is also disallowed. */
/* Effectively this means that portable code should make sure n is even.*/
/* This bypasses the */
/* MERGE_SIZES mechanism. In order to minimize the number of distinct */ /* MERGE_SIZES mechanism. In order to minimize the number of distinct */
/* free lists that are maintained, the caller should ensure that a */ /* free lists that are maintained, the caller should ensure that a */
/* small number of distinct values of n are used. (The MERGE_SIZES */ /* small number of distinct values of n are used. (The MERGE_SIZES */
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
// It also doesn't yet understand the new header file names or // It also doesn't yet understand the new header file names or
// namespaces. // namespaces.
// //
// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE // This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE.
// and -DALL_INTERIOR_POINTERS. We also recommend // The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc,
// -DREDIRECT_MALLOC=GC_uncollectable_malloc. // to ensure that object allocated through malloc are traced.
// //
// Some of this could be faster in the explicit deallocation case. // Some of this could be faster in the explicit deallocation case.
// In particular, we spend too much time clearing objects on the // In particular, we spend too much time clearing objects on the
...@@ -43,11 +43,14 @@ ...@@ -43,11 +43,14 @@
// problems. The argument for changing it is that the usual default // problems. The argument for changing it is that the usual default
// allocator is usually a very bad choice for a garbage collected environment.) // allocator is usually a very bad choice for a garbage collected environment.)
// //
// This code assumes that the collector itself has been compiled with a
// compiler that defines __STDC__ .
//
#ifndef GC_ALLOC_H #ifndef GC_ALLOC_H
#include "gc.h" #include "gc.h"
#include <alloc.h> #include <stack> // A more portable way to get stl_alloc.h .
#define GC_ALLOC_H #define GC_ALLOC_H
...@@ -337,6 +340,8 @@ public: \ ...@@ -337,6 +340,8 @@ public: \
{ alloc::ptr_free_deallocate(p, sizeof (T)); } \ { alloc::ptr_free_deallocate(p, sizeof (T)); } \
}; };
__STL_BEGIN_NAMESPACE
__GC_SPECIALIZE(char, gc_alloc) __GC_SPECIALIZE(char, gc_alloc)
__GC_SPECIALIZE(int, gc_alloc) __GC_SPECIALIZE(int, gc_alloc)
__GC_SPECIALIZE(unsigned, gc_alloc) __GC_SPECIALIZE(unsigned, gc_alloc)
...@@ -361,6 +366,8 @@ __GC_SPECIALIZE(unsigned, single_client_traceable_alloc) ...@@ -361,6 +366,8 @@ __GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
__GC_SPECIALIZE(float, single_client_traceable_alloc) __GC_SPECIALIZE(float, single_client_traceable_alloc)
__GC_SPECIALIZE(double, single_client_traceable_alloc) __GC_SPECIALIZE(double, single_client_traceable_alloc)
__STL_END_NAMESPACE
#ifdef __STL_USE_STD_ALLOCATORS #ifdef __STL_USE_STD_ALLOCATORS
__STL_BEGIN_NAMESPACE __STL_BEGIN_NAMESPACE
......
...@@ -24,6 +24,17 @@ typedef struct hblkhdr hdr; ...@@ -24,6 +24,17 @@ typedef struct hblkhdr hdr;
* The 2 level tree data structure that is used to find block headers. * The 2 level tree data structure that is used to find block headers.
* If there are more than 32 bits in a pointer, the top level is a hash * If there are more than 32 bits in a pointer, the top level is a hash
* table. * table.
*
* This defines HDR, GET_HDR, and SET_HDR, the main macros used to
* retrieve and set object headers. We also define some variants to
* retrieve 2 unrelated headers in interleaved fashion. This
* slightly improves scheduling.
*
* Since 5.0 alpha 5, we can also take advantage of a header lookup
* cache. This is a locally declared direct mapped cache, used inside
* the marker. The HC_GET_HDR and HC_GET_HDR2 macros use and maintain this
* cache. Assuming we get reasonable hit rates, this shaves a few
* memory references from each pointer validation.
*/ */
# if CPP_WORDSZ > 32 # if CPP_WORDSZ > 32
...@@ -45,6 +56,127 @@ typedef struct hblkhdr hdr; ...@@ -45,6 +56,127 @@ typedef struct hblkhdr hdr;
# define TOP_SZ (1 << LOG_TOP_SZ) # define TOP_SZ (1 << LOG_TOP_SZ)
# define BOTTOM_SZ (1 << LOG_BOTTOM_SZ) # define BOTTOM_SZ (1 << LOG_BOTTOM_SZ)
#ifndef SMALL_CONFIG
# define USE_HDR_CACHE
#endif
/* #define COUNT_HDR_CACHE_HITS */
extern hdr * GC_invalid_header; /* header for an imaginary block */
/* containing no objects. */
/* Check whether p and corresponding hhdr point to long or invalid */
/* object. If so, advance them to */
/* beginning of block, or set hhdr to GC_invalid_header. */
#define ADVANCE(p, hhdr, source) \
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
p = GC_FIND_START(p, hhdr, (word)source); \
if (p == 0) { \
hhdr = GC_invalid_header; \
} else { \
hhdr = GC_find_header(p); \
} \
}
#ifdef USE_HDR_CACHE
# ifdef COUNT_HDR_CACHE_HITS
extern word GC_hdr_cache_hits;
extern word GC_hdr_cache_misses;
# define HC_HIT() ++GC_hdr_cache_hits
# define HC_MISS() ++GC_hdr_cache_misses
# else
# define HC_HIT()
# define HC_MISS()
# endif
typedef struct hce {
word block_addr; /* right shifted by LOG_HBLKSIZE */
hdr * hce_hdr;
} hdr_cache_entry;
# define HDR_CACHE_SIZE 8 /* power of 2 */
# define DECLARE_HDR_CACHE \
hdr_cache_entry hdr_cache[HDR_CACHE_SIZE]
# define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache));
# define HCE(h) hdr_cache + (((word)(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE-1))
# define HCE_VALID_FOR(hce,h) ((hce) -> block_addr == \
((word)(h) >> LOG_HBLKSIZE))
# define HCE_HDR(h) ((hce) -> hce_hdr)
/* Analogous to GET_HDR, except that in the case of large objects, it */
/* Returns the header for the object beginning, and updates p. */
/* Returns &GC_bad_header instead of 0. All of this saves a branch */
/* in the fast path. */
# define HC_GET_HDR(p, hhdr, source) \
{ \
hdr_cache_entry * hce = HCE(p); \
if (HCE_VALID_FOR(hce, p)) { \
HC_HIT(); \
hhdr = hce -> hce_hdr; \
} else { \
HC_MISS(); \
GET_HDR(p, hhdr); \
ADVANCE(p, hhdr, source); \
hce -> block_addr = (word)(p) >> LOG_HBLKSIZE; \
hce -> hce_hdr = hhdr; \
} \
}
# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \
{ \
hdr_cache_entry * hce1 = HCE(p1); \
hdr_cache_entry * hce2 = HCE(p2); \
if (HCE_VALID_FOR(hce1, p1)) { \
HC_HIT(); \
hhdr1 = hce1 -> hce_hdr; \
} else { \
HC_MISS(); \
GET_HDR(p1, hhdr1); \
ADVANCE(p1, hhdr1, source1); \
hce1 -> block_addr = (word)(p1) >> LOG_HBLKSIZE; \
hce1 -> hce_hdr = hhdr1; \
} \
if (HCE_VALID_FOR(hce2, p2)) { \
HC_HIT(); \
hhdr2 = hce2 -> hce_hdr; \
} else { \
HC_MISS(); \
GET_HDR(p2, hhdr2); \
ADVANCE(p2, hhdr2, source2); \
hce2 -> block_addr = (word)(p2) >> LOG_HBLKSIZE; \
hce2 -> hce_hdr = hhdr2; \
} \
}
#else /* !USE_HDR_CACHE */
# define DECLARE_HDR_CACHE
# define INIT_HDR_CACHE
# define HC_GET_HDR(p, hhdr, source) \
{ \
GET_HDR(p, hhdr); \
ADVANCE(p, hhdr, source); \
}
# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \
{ \
GET_HDR2(p1, hhdr1, p2, hhdr2); \
ADVANCE(p1, hhdr1, source1); \
ADVANCE(p2, hhdr2, source2); \
}
#endif
typedef struct bi { typedef struct bi {
hdr * index[BOTTOM_SZ]; hdr * index[BOTTOM_SZ];
/* /*
...@@ -97,6 +229,8 @@ typedef struct bi { ...@@ -97,6 +229,8 @@ typedef struct bi {
# define GET_HDR(p, hhdr) (hhdr) = HDR(p) # define GET_HDR(p, hhdr) (hhdr) = HDR(p)
# define SET_HDR(p, hhdr) HDR_INNER(p) = (hhdr) # define SET_HDR(p, hhdr) HDR_INNER(p) = (hhdr)
# define GET_HDR_ADDR(p, ha) (ha) = &(HDR_INNER(p)) # define GET_HDR_ADDR(p, ha) (ha) = &(HDR_INNER(p))
# define GET_HDR2(p1, hhdr1, p2, hhdr2) \
{ GET_HDR(p1, hhdr1); GET_HDR(p2, hhdr2); }
# else /* hash */ # else /* hash */
/* Hash function for tree top level */ /* Hash function for tree top level */
# define TL_HASH(hi) ((hi) & (TOP_SZ - 1)) # define TL_HASH(hi) ((hi) & (TOP_SZ - 1))
...@@ -123,6 +257,40 @@ typedef struct bi { ...@@ -123,6 +257,40 @@ typedef struct bi {
# define SET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \ # define SET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \
*_ha = (hhdr); } *_ha = (hhdr); }
# define HDR(p) GC_find_header((ptr_t)(p)) # define HDR(p) GC_find_header((ptr_t)(p))
/* And some interleaved versions for two pointers at once. */
/* This hopefully helps scheduling on processors like IA64. */
# define GET_BI2(p1, bottom_indx1, p2, bottom_indx2) \
{ \
register word hi1 = \
(word)(p1) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
register word hi2 = \
(word)(p2) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
register bottom_index * _bi1 = GC_top_index[TL_HASH(hi1)]; \
register bottom_index * _bi2 = GC_top_index[TL_HASH(hi2)]; \
\
while (_bi1 -> key != hi1 && _bi1 != GC_all_nils) \
_bi1 = _bi1 -> hash_link; \
while (_bi2 -> key != hi2 && _bi2 != GC_all_nils) \
_bi2 = _bi2 -> hash_link; \
(bottom_indx1) = _bi1; \
(bottom_indx2) = _bi2; \
}
# define GET_HDR_ADDR2(p1, ha1, p2, ha2) \
{ \
register bottom_index * bi1; \
register bottom_index * bi2; \
\
GET_BI2(p1, bi1, p2, bi2); \
(ha1) = &(HDR_FROM_BI(bi1, p1)); \
(ha2) = &(HDR_FROM_BI(bi2, p2)); \
}
# define GET_HDR2(p1, hhdr1, p2, hhdr2) \
{ register hdr ** _ha1; \
register hdr ** _ha2; \
GET_HDR_ADDR2(p1, _ha1, p2, _ha2); \
(hhdr1) = *_ha1; \
(hhdr2) = *_ha2; \
}
# endif # endif
/* Is the result a forwarding address to someplace closer to the */ /* Is the result a forwarding address to someplace closer to the */
......
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