28
28
* This defines HDR, GET_HDR, and SET_HDR, the main macros used to
29
29
* retrieve and set object headers.
31
* Since 5.0 alpha 5, we can also take advantage of a header lookup
31
* We take advantage of a header lookup
32
32
* cache. This is a locally declared direct mapped cache, used inside
33
33
* the marker. The HC_GET_HDR macro uses and maintains this
34
34
* cache. Assuming we get reasonable hit rates, this shaves a few
61
61
/* #define COUNT_HDR_CACHE_HITS */
63
extern hdr * GC_invalid_header; /* header for an imaginary block */
64
/* containing no objects. */
67
/* Check whether p and corresponding hhdr point to long or invalid */
68
/* object. If so, advance hhdr to */
69
/* beginning of block, or set hhdr to GC_invalid_header. */
70
#define ADVANCE(p, hhdr, source) \
72
hdr * new_hdr = GC_invalid_header; \
73
p = GC_find_start(p, hhdr, &new_hdr); \
79
63
# ifdef COUNT_HDR_CACHE_HITS
80
64
extern word GC_hdr_cache_hits;
81
65
extern word GC_hdr_cache_misses;
96
80
# define DECLARE_HDR_CACHE \
97
81
hdr_cache_entry hdr_cache[HDR_CACHE_SIZE]
99
# define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache));
83
# define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache))
101
85
# define HCE(h) hdr_cache + (((word)(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE-1))
106
90
# define HCE_HDR(h) ((hce) -> hce_hdr)
92
#ifdef PRINT_BLACK_LIST
93
hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce, ptr_t source);
94
# define HEADER_CACHE_MISS(p, hce, source) \
95
GC_header_cache_miss(p, hce, source)
97
hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce);
98
# define HEADER_CACHE_MISS(p, hce, source) GC_header_cache_miss(p, hce)
109
/* Analogous to GET_HDR, except that in the case of large objects, it */
110
/* Returns the header for the object beginning, and updates p. */
111
/* Returns GC_invalid_header instead of 0. All of this saves a branch */
112
/* in the fast path. */
113
# define HC_GET_HDR(p, hhdr, source) \
101
/* Set hhdr to the header for p. Analogous to GET_HDR below, */
102
/* except that in the case of large objects, it */
103
/* gets the header for the object beginning, if GC_all_interior_ptrs */
105
/* Returns zero if p points to somewhere other than the first page */
106
/* of an object, and it is not a valid pointer to the object. */
107
# define HC_GET_HDR(p, hhdr, source, exit_label) \
115
109
hdr_cache_entry * hce = HCE(p); \
116
if (HCE_VALID_FOR(hce, p)) { \
110
if (EXPECT(HCE_VALID_FOR(hce, p), 1)) { \
118
112
hhdr = hce -> hce_hdr; \
122
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
123
ADVANCE(p, hhdr, source); \
125
hce -> block_addr = (word)(p) >> LOG_HBLKSIZE; \
126
hce -> hce_hdr = hhdr; \
131
#else /* !USE_HDR_CACHE */
133
# define DECLARE_HDR_CACHE
135
# define INIT_HDR_CACHE
137
# define HC_GET_HDR(p, hhdr, source) \
140
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
141
ADVANCE(p, hhdr, source); \
114
hhdr = HEADER_CACHE_MISS(p, hce, source); \
115
if (0 == hhdr) goto exit_label; \
146
119
typedef struct bi {
147
120
hdr * index[BOTTOM_SZ];
226
199
/* Is the result a forwarding address to someplace closer to the */
227
200
/* beginning of the block or NIL? */
228
# define IS_FORWARDING_ADDR_OR_NIL(hhdr) ((unsigned long) (hhdr) <= MAX_JUMP)
201
# define IS_FORWARDING_ADDR_OR_NIL(hhdr) ((size_t) (hhdr) <= MAX_JUMP)
230
203
/* Get an HBLKSIZE aligned address closer to the beginning of the block */
231
204
/* h. Assumes hhdr == HDR(h) and IS_FORWARDING_ADDR(hhdr). */
232
# define FORWARDED_ADDR(h, hhdr) ((struct hblk *)(h) - (unsigned long)(hhdr))
205
# define FORWARDED_ADDR(h, hhdr) ((struct hblk *)(h) - (size_t)(hhdr))
233
206
# endif /* GC_HEADERS_H */