1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright (c) 1997 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
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
*
* Permission is hereby granted to use or copy this program
* for any purpose, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*/
/*
* This is mostly an internal header file. Typical clients should
* not use it. Clients that define their own object kinds with
* debugging allocators will probably want to include this, however.
* No attempt is made to keep the namespace clean. This should not be
* included from header files that are frequently included by clients.
*/
#ifndef _DBG_MLC_H
#define _DBG_MLC_H
# define I_HIDE_POINTERS
# include "gc_priv.h"
# ifdef KEEP_BACK_PTRS
# include "gc_backptr.h"
# endif
#ifndef HIDE_POINTER
/* Gc.h was previously included, and hence the I_HIDE_POINTERS */
/* definition had no effect. Repeat the gc.h definitions here to */
/* get them anyway. */
typedef GC_word GC_hidden_pointer;
# define HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
# define REVEAL_POINTER(p) ((GC_PTR)(HIDE_POINTER(p)))
#endif /* HIDE_POINTER */
# define START_FLAG ((word)0xfedcedcb)
# define END_FLAG ((word)0xbcdecdef)
/* Stored both one past the end of user object, and one before */
/* the end of the object as seen by the allocator. */
# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) \
|| defined(MAKE_BACK_GRAPH)
/* Pointer "source"s that aren't real locations. */
/* Used in oh_back_ptr fields and as "source" */
/* argument to some marking functions. */
# define NOT_MARKED (ptr_t)(0)
# define MARKED_FOR_FINALIZATION (ptr_t)(2)
/* Object was marked because it is finalizable. */
# define MARKED_FROM_REGISTER (ptr_t)(4)
/* Object was marked from a rgister. Hence the */
/* source of the reference doesn't have an address. */
# endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */
/* Object header */
typedef struct {
# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
/* We potentially keep two different kinds of back */
/* pointers. KEEP_BACK_PTRS stores a single back */
/* pointer in each reachable object to allow reporting */
/* of why an object was retained. MAKE_BACK_GRAPH */
/* builds a graph containing the inverse of all */
/* "points-to" edges including those involving */
/* objects that have just become unreachable. This */
/* allows detection of growing chains of unreachable */
/* objects. It may be possible to eventually combine */
/* both, but for now we keep them separate. Both */
/* kinds of back pointers are hidden using the */
/* following macros. In both cases, the plain version */
/* is constrained to have an least significant bit of 1,*/
/* to allow it to be distinguished from a free list */
/* link. This means the plain version must have an */
/* lsb of 0. */
/* Note that blocks dropped by black-listing will */
/* also have the lsb clear once debugging has */
/* started. */
/* We're careful never to overwrite a value with lsb 0. */
# if ALIGNMENT == 1
/* Fudge back pointer to be even. */
# define HIDE_BACK_PTR(p) HIDE_POINTER(~1 & (GC_word)(p))
# else
# define HIDE_BACK_PTR(p) HIDE_POINTER(p)
# endif
# ifdef KEEP_BACK_PTRS
GC_hidden_pointer oh_back_ptr;
# endif
# ifdef MAKE_BACK_GRAPH
GC_hidden_pointer oh_bg_ptr;
# endif
# if defined(ALIGN_DOUBLE) && \
(defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH))
word oh_dummy;
# endif
# endif
GC_CONST char * oh_string; /* object descriptor string */
word oh_int; /* object descriptor integers */
# ifdef NEED_CALLINFO
struct callinfo oh_ci[NFRAMES];
# endif
# ifndef SHORT_DBG_HDRS
word oh_sz; /* Original malloc arg. */
word oh_sf; /* start flag */
# endif /* SHORT_DBG_HDRS */
} oh;
/* The size of the above structure is assumed not to dealign things, */
/* and to be a multiple of the word length. */
#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. */
/* 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)
#else
# ifdef GC_ADD_CALLER
# define ADD_CALL_CHAIN(base, ra) ((oh *)(base)) -> oh_ci[0].ci_pc = (ra)
# define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
# else
# define ADD_CALL_CHAIN(base, ra)
# define PRINT_CALL_CHAIN(base)
# endif
#endif
# ifdef GC_ADD_CALLER
# define OPT_RA ra,
# else
# define OPT_RA
# endif
/* Check whether object with base pointer p has debugging info */
/* p is assumed to point to a legitimate object in our part */
/* of the heap. */
#ifdef SHORT_DBG_HDRS
# define GC_has_other_debug_info(p) TRUE
#else
GC_bool GC_has_other_debug_info(/* p */);
#endif
#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
# define GC_HAS_DEBUG_INFO(p) \
((*((word *)p) & 1) && GC_has_other_debug_info(p))
#else
# define GC_HAS_DEBUG_INFO(p) GC_has_other_debug_info(p)
#endif
/* Store debugging info into p. Return displaced pointer. */
/* Assumes we don't hold allocation lock. */
ptr_t GC_store_debug_info(/* p, sz, string, integer */);
#endif /* _DBG_MLC_H */
|