OSDN Git Service

Merged GC 5.0alpha4 with local changes, plus:
[pf3gnuchains/gcc-fork.git] / boehm-gc / gc_mark.h
1 /*
2  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
3  *
4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  *
7  * Permission is hereby granted to use or copy this program
8  * for any purpose,  provided the above notices are retained on all copies.
9  * Permission to modify the code and to distribute modified code is granted,
10  * provided the above notices are retained, and a notice that the code was
11  * modified is included with the above copyright notice.
12  *
13  */
14 /* Boehm, November 7, 1994 4:56 pm PST */
15
16 /*
17  * Declarations of mark stack.  Needed by marker and client supplied mark
18  * routines.  To be included after gc_priv.h.
19  */
20 #ifndef GC_MARK_H
21 # define GC_MARK_H
22
23 /* A client supplied mark procedure.  Returns new mark stack pointer.   */
24 /* Primary effect should be to push new entries on the mark stack.      */
25 /* Mark stack pointer values are passed and returned explicitly.        */
26 /* Global variables decribing mark stack are not necessarily valid.     */
27 /* (This usually saves a few cycles by keeping things in registers.)    */
28 /* Assumed to scan about PROC_BYTES on average.  If it needs to do      */
29 /* much more work than that, it should do it in smaller pieces by       */
30 /* pushing itself back on the mark stack.                               */
31 /* Note that it should always do some work (defined as marking some     */
32 /* objects) before pushing more than one entry on the mark stack.       */
33 /* This is required to ensure termination in the event of mark stack    */
34 /* overflows.                                                           */
35 /* This procedure is always called with at least one empty entry on the */
36 /* mark stack.                                                          */
37 /* Currently we require that mark procedures look for pointers in a     */
38 /* subset of the places the conservative marker would.  It must be safe */
39 /* to invoke the normal mark procedure instead.                         */
40 # define PROC_BYTES 100
41 /* The real declarations of the following are in gc_priv.h, so that     */
42 /* we can avoid scanning the following table.                           */
43 /*
44 typedef struct ms_entry * (*mark_proc)(   word * addr, mark_stack_ptr,
45                                           mark_stack_limit, env   );
46                                           
47 # define LOG_MAX_MARK_PROCS 6
48 # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
49 extern mark_proc GC_mark_procs[MAX_MARK_PROCS];
50 */
51
52 extern word GC_n_mark_procs;
53
54 /* Object descriptors on mark stack or in objects.  Low order two       */
55 /* bits are tags distinguishing among the following 4 possibilities     */
56 /* for the high order 30 bits.                                          */
57 #define DS_TAG_BITS 2
58 #define DS_TAGS   ((1 << DS_TAG_BITS) - 1)
59 #define DS_LENGTH 0     /* The entire word is a length in bytes that    */
60                         /* must be a multiple of 4.                     */
61 #define DS_BITMAP 1     /* 30 bits are a bitmap describing pointer      */
62                         /* fields.  The msb is 1 iff the first word     */
63                         /* is a pointer.                                */
64                         /* (This unconventional ordering sometimes      */
65                         /* makes the marker slightly faster.)           */
66                         /* Zeroes indicate definite nonpointers.  Ones  */
67                         /* indicate possible pointers.                  */
68                         /* Only usable if pointers are word aligned.    */
69 #   define BITMAP_BITS (WORDSZ - DS_TAG_BITS)
70 #define DS_PROC   2
71                         /* The objects referenced by this object can be */
72                         /* pushed on the mark stack by invoking         */
73                         /* PROC(descr).  ENV(descr) is passed as the    */
74                         /* last argument.                               */
75 #   define PROC(descr) \
76                 (GC_mark_procs[((descr) >> DS_TAG_BITS) & (MAX_MARK_PROCS-1)])
77 #   define ENV(descr) \
78                 ((descr) >> (DS_TAG_BITS + LOG_MAX_MARK_PROCS))
79 #   define MAX_ENV \
80               (((word)1 << (WORDSZ - DS_TAG_BITS - LOG_MAX_MARK_PROCS)) - 1)
81 #   define MAKE_PROC(proc_index, env) \
82             (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS) \
83             | DS_PROC)
84 #define DS_PER_OBJECT 3 /* The real descriptor is at the                */
85                         /* byte displacement from the beginning of the  */
86                         /* object given by descr & ~DS_TAGS             */
87                         
88 typedef struct ms_entry {
89     word * mse_start;   /* First word of object */
90     word mse_descr;     /* Descriptor; low order two bits are tags,     */
91                         /* identifying the upper 30 bits as one of the  */
92                         /* following:                                   */
93 } mse;
94
95 extern word GC_mark_stack_size;
96
97 extern mse * GC_mark_stack_top;
98
99 extern mse * GC_mark_stack;
100
101 word GC_find_start();
102
103 mse * GC_signal_mark_stack_overflow();
104
105 # ifdef GATHERSTATS
106 #   define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
107 #   define ADD_TO_COMPOSITE(sz) GC_composite_in_use += (sz)
108 # else
109 #   define ADD_TO_ATOMIC(sz)
110 #   define ADD_TO_COMPOSITE(sz)
111 # endif
112
113 /* Push the object obj with corresponding heap block header hhdr onto   */
114 /* the mark stack.                                                      */
115 # define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \
116 { \
117     register word _descr = (hhdr) -> hb_descr; \
118         \
119     if (_descr == 0) { \
120         ADD_TO_ATOMIC((hhdr) -> hb_sz); \
121     } else { \
122         ADD_TO_COMPOSITE((hhdr) -> hb_sz); \
123         mark_stack_top++; \
124         if (mark_stack_top >= mark_stack_limit) { \
125           mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \
126         } \
127         mark_stack_top -> mse_start = (obj); \
128         mark_stack_top -> mse_descr = _descr; \
129     } \
130 }
131
132 #ifdef PRINT_BLACK_LIST
133 #   define GC_FIND_START(current, hhdr, source) \
134         GC_find_start(current, hhdr, source)
135 #else
136 #   define GC_FIND_START(current, hhdr, source) \
137         GC_find_start(current, hhdr)
138 #endif
139
140 /* Push the contents of current onto the mark stack if it is a valid    */
141 /* ptr to a currently unmarked object.  Mark it.                        */
142 /* If we assumed a standard-conforming compiler, we could probably      */
143 /* generate the exit_label transparently.                               */
144 # define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
145                        source, exit_label) \
146 { \
147     register int displ;  /* Displacement in block; first bytes, then words */ \
148     register hdr * hhdr; \
149     register map_entry_type map_entry; \
150     \
151     GET_HDR(current,hhdr); \
152     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
153          current = GC_FIND_START(current, hhdr, (word)source); \
154          if (current == 0) goto exit_label; \
155          hhdr = HDR(current); \
156     } \
157     displ = HBLKDISPL(current); \
158     map_entry = MAP_ENTRY((hhdr -> hb_map), displ); \
159     if (map_entry == OBJ_INVALID) { \
160         GC_ADD_TO_BLACK_LIST_NORMAL(current, source); goto exit_label; \
161     } \
162     displ = BYTES_TO_WORDS(displ); \
163     displ -= map_entry; \
164         \
165     { \
166         register word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(displ); \
167         register word mark_word = *mark_word_addr; \
168         register word mark_bit = (word)1 << modWORDSZ(displ); \
169           \
170         if (mark_word & mark_bit) { \
171               /* Mark bit is already set */ \
172               goto exit_label; \
173         } \
174         GC_STORE_BACK_PTR((ptr_t)source, (ptr_t)HBLKPTR(current) \
175                                       + WORDS_TO_BYTES(displ)); \
176         *mark_word_addr = mark_word | mark_bit; \
177     } \
178     PUSH_OBJ(((word *)(HBLKPTR(current)) + displ), hhdr, \
179              mark_stack_top, mark_stack_limit) \
180   exit_label: ; \
181 }
182
183 #ifdef PRINT_BLACK_LIST
184 #   define PUSH_ONE_CHECKED(p, ip, source) \
185         GC_push_one_checked(p, ip, (ptr_t)(source))
186 #else
187 #   define PUSH_ONE_CHECKED(p, ip, source) \
188         GC_push_one_checked(p, ip)
189 #endif
190
191 /*
192  * Push a single value onto mark stack. Mark from the object pointed to by p.
193  * P is considered valid even if it is an interior pointer.
194  * Previously marked objects are not pushed.  Hence we make progress even
195  * if the mark stack overflows.
196  */
197 # define GC_PUSH_ONE_STACK(p, source) \
198     if ((ptr_t)(p) >= GC_least_plausible_heap_addr      \
199          && (ptr_t)(p) < GC_greatest_plausible_heap_addr) {     \
200          PUSH_ONE_CHECKED(p, TRUE, source);     \
201     }
202
203 /*
204  * As above, but interior pointer recognition as for
205  * normal for heap pointers.
206  */
207 # ifdef ALL_INTERIOR_POINTERS
208 #   define AIP TRUE
209 # else
210 #   define AIP FALSE
211 # endif
212 # define GC_PUSH_ONE_HEAP(p,source) \
213     if ((ptr_t)(p) >= GC_least_plausible_heap_addr      \
214          && (ptr_t)(p) < GC_greatest_plausible_heap_addr) {     \
215          PUSH_ONE_CHECKED(p,AIP,source);        \
216     }
217
218 /*
219  * Mark from one finalizable object using the specified
220  * mark proc. May not mark the object pointed to by 
221  * real_ptr. That is the job of the caller, if appropriate
222  */
223 # define GC_MARK_FO(real_ptr, mark_proc) \
224 { \
225     (*(mark_proc))(real_ptr); \
226     while (!GC_mark_stack_empty()) GC_mark_from_mark_stack(); \
227     if (GC_mark_state != MS_NONE) { \
228         GC_set_mark_bit(real_ptr); \
229         while (!GC_mark_some((ptr_t)0)); \
230     } \
231 }
232
233 extern GC_bool GC_mark_stack_too_small;
234                                 /* We need a larger mark stack.  May be */
235                                 /* set by client supplied mark routines.*/
236
237 typedef int mark_state_t;       /* Current state of marking, as follows:*/
238                                 /* Used to remember where we are during */
239                                 /* concurrent marking.                  */
240
241                                 /* We say something is dirty if it was  */
242                                 /* written since the last time we       */
243                                 /* retrieved dirty bits.  We say it's   */
244                                 /* grungy if it was marked dirty in the */
245                                 /* last set of bits we retrieved.       */
246                                 
247                                 /* Invariant I: all roots and marked    */
248                                 /* objects p are either dirty, or point */
249                                 /* to objects q that are either marked  */
250                                 /* or a pointer to q appears in a range */
251                                 /* on the mark stack.                   */
252
253 # define MS_NONE 0              /* No marking in progress. I holds.     */
254                                 /* Mark stack is empty.                 */
255
256 # define MS_PUSH_RESCUERS 1     /* Rescuing objects are currently       */
257                                 /* being pushed.  I holds, except       */
258                                 /* that grungy roots may point to       */
259                                 /* unmarked objects, as may marked      */
260                                 /* grungy objects above scan_ptr.       */
261
262 # define MS_PUSH_UNCOLLECTABLE 2
263                                 /* I holds, except that marked          */
264                                 /* uncollectable objects above scan_ptr */
265                                 /* may point to unmarked objects.       */
266                                 /* Roots may point to unmarked objects  */
267
268 # define MS_ROOTS_PUSHED 3      /* I holds, mark stack may be nonempty  */
269
270 # define MS_PARTIALLY_INVALID 4 /* I may not hold, e.g. because of M.S. */
271                                 /* overflow.  However marked heap       */
272                                 /* objects below scan_ptr point to      */
273                                 /* marked or stacked objects.           */
274
275 # define MS_INVALID 5           /* I may not hold.                      */
276
277 extern mark_state_t GC_mark_state;
278
279 #endif  /* GC_MARK_H */
280