]>
Commit | Line | Data |
---|---|---|
73ffefd0 TT |
1 | /* |
2 | * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers | |
3 | * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. | |
85f29b3b | 4 | * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. |
abdbd4a8 | 5 | * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. |
85f29b3b | 6 | * |
73ffefd0 TT |
7 | * |
8 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED | |
9 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. | |
10 | * | |
11 | * Permission is hereby granted to use or copy this program | |
12 | * for any purpose, provided the above notices are retained on all copies. | |
13 | * Permission to modify the code and to distribute modified code is granted, | |
14 | * provided the above notices are retained, and a notice that the code was | |
15 | * modified is included with the above copyright notice. | |
16 | */ | |
73ffefd0 TT |
17 | |
18 | ||
19 | # ifndef GC_PRIVATE_H | |
20 | # define GC_PRIVATE_H | |
21 | ||
5909b034 BM |
22 | /* Autoconf definitions. */ |
23 | /* FIXME: This should really be included directly from each .c file. */ | |
24 | #include <gc_config.h> | |
25 | ||
73ffefd0 TT |
26 | #if defined(mips) && defined(SYSTYPE_BSD) && defined(sony_news) |
27 | /* sony RISC NEWS, NEWSOS 4 */ | |
28 | # define BSD_TIME | |
29 | /* typedef long ptrdiff_t; -- necessary on some really old systems */ | |
30 | #endif | |
31 | ||
32 | #if defined(mips) && defined(SYSTYPE_BSD43) | |
33 | /* MIPS RISCOS 4 */ | |
34 | # define BSD_TIME | |
35 | #endif | |
36 | ||
30c3de1f JS |
37 | #ifdef DGUX |
38 | # include <sys/types.h> | |
39 | # include <sys/time.h> | |
40 | # include <sys/resource.h> | |
41 | #endif /* DGUX */ | |
42 | ||
73ffefd0 TT |
43 | #ifdef BSD_TIME |
44 | # include <sys/types.h> | |
45 | # include <sys/time.h> | |
46 | # include <sys/resource.h> | |
47 | #endif /* BSD_TIME */ | |
48 | ||
30c3de1f JS |
49 | # ifndef _GC_H |
50 | # include "../gc.h" | |
73ffefd0 TT |
51 | # endif |
52 | ||
abdbd4a8 BM |
53 | # ifndef GC_MARK_H |
54 | # include "../gc_mark.h" | |
55 | # endif | |
73ffefd0 | 56 | |
abdbd4a8 BM |
57 | typedef GC_word word; |
58 | typedef GC_signed_word signed_word; | |
73ffefd0 TT |
59 | |
60 | typedef int GC_bool; | |
61 | # define TRUE 1 | |
62 | # define FALSE 0 | |
63 | ||
64 | typedef char * ptr_t; /* A generic pointer to which we can add */ | |
65 | /* byte displacements. */ | |
66 | /* Preferably identical to caddr_t, if it */ | |
67 | /* exists. */ | |
68 | ||
c62b9064 HB |
69 | # ifndef GCCONFIG_H |
70 | # include "gcconfig.h" | |
71 | # endif | |
72 | ||
abdbd4a8 BM |
73 | # ifndef HEADERS_H |
74 | # include "gc_hdrs.h" | |
75 | # endif | |
76 | ||
73ffefd0 TT |
77 | #if defined(__STDC__) |
78 | # include <stdlib.h> | |
79 | # if !(defined( sony_news ) ) | |
80 | # include <stddef.h> | |
81 | # endif | |
82 | # define VOLATILE volatile | |
73ffefd0 TT |
83 | #else |
84 | # ifdef MSWIN32 | |
85 | # include <stdlib.h> | |
86 | # endif | |
87 | # define VOLATILE | |
73ffefd0 TT |
88 | #endif |
89 | ||
abdbd4a8 BM |
90 | #if 0 /* defined(__GNUC__) doesn't work yet */ |
91 | # define EXPECT(expr, outcome) __builtin_expect(expr,outcome) | |
92 | /* Equivalent to (expr), but predict that usually (expr)==outcome. */ | |
93 | #else | |
94 | # define EXPECT(expr, outcome) (expr) | |
95 | #endif /* __GNUC__ */ | |
96 | ||
97 | # ifndef GC_LOCKS_H | |
98 | # include "gc_locks.h" | |
99 | # endif | |
85f29b3b | 100 | |
abdbd4a8 BM |
101 | # ifdef STACK_GROWS_DOWN |
102 | # define COOLER_THAN > | |
103 | # define HOTTER_THAN < | |
104 | # define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \ | |
105 | else {(x) = (word)ONES;} | |
106 | # define MAKE_HOTTER(x,y) (x) -= (y) | |
107 | # else | |
108 | # define COOLER_THAN < | |
109 | # define HOTTER_THAN > | |
110 | # define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;} | |
111 | # define MAKE_HOTTER(x,y) (x) += (y) | |
112 | # endif | |
113 | ||
114 | #if defined(AMIGA) && defined(__SASC) | |
73ffefd0 TT |
115 | # define GC_FAR __far |
116 | #else | |
117 | # define GC_FAR | |
118 | #endif | |
119 | ||
56293c2b | 120 | |
73ffefd0 TT |
121 | /*********************************/ |
122 | /* */ | |
123 | /* Definitions for conservative */ | |
124 | /* collector */ | |
125 | /* */ | |
126 | /*********************************/ | |
127 | ||
128 | /*********************************/ | |
129 | /* */ | |
130 | /* Easily changeable parameters */ | |
131 | /* */ | |
132 | /*********************************/ | |
133 | ||
abdbd4a8 BM |
134 | /* #define STUBBORN_ALLOC */ |
135 | /* Enable stubborm allocation, and thus a limited */ | |
136 | /* form of incremental collection w/o dirty bits. */ | |
73ffefd0 TT |
137 | |
138 | /* #define ALL_INTERIOR_POINTERS */ | |
139 | /* Forces all pointers into the interior of an */ | |
140 | /* object to be considered valid. Also causes the */ | |
141 | /* sizes of all objects to be inflated by at least */ | |
142 | /* one byte. This should suffice to guarantee */ | |
143 | /* that in the presence of a compiler that does */ | |
144 | /* not perform garbage-collector-unsafe */ | |
145 | /* optimizations, all portable, strictly ANSI */ | |
146 | /* conforming C programs should be safely usable */ | |
147 | /* with malloc replaced by GC_malloc and free */ | |
148 | /* calls removed. There are several disadvantages: */ | |
149 | /* 1. There are probably no interesting, portable, */ | |
150 | /* strictly ANSI conforming C programs. */ | |
151 | /* 2. This option makes it hard for the collector */ | |
152 | /* to allocate space that is not ``pointed to'' */ | |
153 | /* by integers, etc. Under SunOS 4.X with a */ | |
154 | /* statically linked libc, we empiricaly */ | |
155 | /* observed that it would be difficult to */ | |
156 | /* allocate individual objects larger than 100K. */ | |
157 | /* Even if only smaller objects are allocated, */ | |
158 | /* more swap space is likely to be needed. */ | |
159 | /* Fortunately, much of this will never be */ | |
160 | /* touched. */ | |
161 | /* If you can easily avoid using this option, do. */ | |
162 | /* If not, try to keep individual objects small. */ | |
abdbd4a8 BM |
163 | /* This is now really controlled at startup, */ |
164 | /* through GC_all_interior_pointers. */ | |
73ffefd0 TT |
165 | |
166 | #define PRINTSTATS /* Print garbage collection statistics */ | |
167 | /* For less verbose output, undefine in reclaim.c */ | |
168 | ||
169 | #define PRINTTIMES /* Print the amount of time consumed by each garbage */ | |
170 | /* collection. */ | |
171 | ||
172 | #define PRINTBLOCKS /* Print object sizes associated with heap blocks, */ | |
173 | /* whether the objects are atomic or composite, and */ | |
174 | /* whether or not the block was found to be empty */ | |
175 | /* during the reclaim phase. Typically generates */ | |
176 | /* about one screenful per garbage collection. */ | |
177 | #undef PRINTBLOCKS | |
178 | ||
179 | #ifdef SILENT | |
180 | # ifdef PRINTSTATS | |
181 | # undef PRINTSTATS | |
182 | # endif | |
183 | # ifdef PRINTTIMES | |
184 | # undef PRINTTIMES | |
185 | # endif | |
186 | # ifdef PRINTNBLOCKS | |
187 | # undef PRINTNBLOCKS | |
188 | # endif | |
189 | #endif | |
190 | ||
191 | #if defined(PRINTSTATS) && !defined(GATHERSTATS) | |
192 | # define GATHERSTATS | |
193 | #endif | |
194 | ||
abdbd4a8 BM |
195 | #if defined(PRINTSTATS) || !defined(SMALL_CONFIG) |
196 | # define CONDPRINT /* Print some things if GC_print_stats is set */ | |
73ffefd0 TT |
197 | #endif |
198 | ||
abdbd4a8 BM |
199 | #define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers() |
200 | ||
73ffefd0 TT |
201 | #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */ |
202 | /* free lists are actually maintained. This applies */ | |
203 | /* only to the top level routines in misc.c, not to */ | |
204 | /* user generated code that calls GC_allocobj and */ | |
205 | /* GC_allocaobj directly. */ | |
206 | /* Slows down average programs slightly. May however */ | |
207 | /* substantially reduce fragmentation if allocation */ | |
208 | /* request sizes are widely scattered. */ | |
209 | /* May save significant amounts of space for obj_map */ | |
210 | /* entries. */ | |
211 | ||
abdbd4a8 BM |
212 | #if defined(USE_MARK_BYTES) && !defined(ALIGN_DOUBLE) |
213 | # define ALIGN_DOUBLE | |
214 | /* We use one byte for every 2 words, which doesn't allow for */ | |
215 | /* odd numbered words to have mark bits. */ | |
216 | #endif | |
217 | ||
45597167 | 218 | #if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE) |
30c3de1f | 219 | /* GCJ's Hashtable synchronization code requires 64-bit alignment. */ |
45597167 BM |
220 | # define ALIGN_DOUBLE |
221 | #endif | |
222 | ||
73ffefd0 TT |
223 | /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ |
224 | # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) | |
225 | # define MERGE_SIZES | |
226 | # endif | |
227 | ||
abdbd4a8 BM |
228 | #if !defined(DONT_ADD_BYTE_AT_END) |
229 | # define EXTRA_BYTES GC_all_interior_pointers | |
230 | #else | |
231 | # define EXTRA_BYTES 0 | |
73ffefd0 TT |
232 | #endif |
233 | ||
234 | ||
235 | # ifndef LARGE_CONFIG | |
abdbd4a8 BM |
236 | # define MINHINCR 16 /* Minimum heap increment, in blocks of HBLKSIZE */ |
237 | /* Must be multiple of largest page size. */ | |
238 | # define MAXHINCR 2048 /* Maximum heap increment, in blocks */ | |
73ffefd0 TT |
239 | # else |
240 | # define MINHINCR 64 | |
241 | # define MAXHINCR 4096 | |
242 | # endif | |
243 | ||
244 | # define TIME_LIMIT 50 /* We try to keep pause times from exceeding */ | |
245 | /* this by much. In milliseconds. */ | |
246 | ||
247 | # define BL_LIMIT GC_black_list_spacing | |
248 | /* If we need a block of N bytes, and we have */ | |
249 | /* a block of N + BL_LIMIT bytes available, */ | |
250 | /* and N > BL_LIMIT, */ | |
251 | /* but all possible positions in it are */ | |
252 | /* blacklisted, we just use it anyway (and */ | |
253 | /* print a warning, if warnings are enabled). */ | |
254 | /* This risks subsequently leaking the block */ | |
255 | /* due to a false reference. But not using */ | |
256 | /* the block risks unreasonable immediate */ | |
257 | /* heap growth. */ | |
258 | ||
259 | /*********************************/ | |
260 | /* */ | |
261 | /* Stack saving for debugging */ | |
262 | /* */ | |
263 | /*********************************/ | |
264 | ||
73ffefd0 TT |
265 | #ifdef NEED_CALLINFO |
266 | struct callinfo { | |
abdbd4a8 | 267 | word ci_pc; /* Caller, not callee, pc */ |
73ffefd0 TT |
268 | # if NARGS > 0 |
269 | word ci_arg[NARGS]; /* bit-wise complement to avoid retention */ | |
270 | # endif | |
271 | # if defined(ALIGN_DOUBLE) && (NFRAMES * (NARGS + 1)) % 2 == 1 | |
272 | /* Likely alignment problem. */ | |
273 | word ci_dummy; | |
274 | # endif | |
275 | }; | |
276 | #endif | |
277 | ||
54f28c21 BM |
278 | #ifdef SAVE_CALL_CHAIN |
279 | ||
280 | /* Fill in the pc and argument information for up to NFRAMES of my */ | |
281 | /* callers. Ignore my frame and my callers frame. */ | |
282 | void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES])); | |
283 | ||
284 | void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES])); | |
285 | ||
286 | #endif | |
287 | ||
73ffefd0 TT |
288 | |
289 | /*********************************/ | |
290 | /* */ | |
291 | /* OS interface routines */ | |
292 | /* */ | |
293 | /*********************************/ | |
294 | ||
295 | #ifdef BSD_TIME | |
296 | # undef CLOCK_TYPE | |
297 | # undef GET_TIME | |
298 | # undef MS_TIME_DIFF | |
299 | # define CLOCK_TYPE struct timeval | |
300 | # define GET_TIME(x) { struct rusage rusage; \ | |
301 | getrusage (RUSAGE_SELF, &rusage); \ | |
302 | x = rusage.ru_utime; } | |
303 | # define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \ | |
304 | + (double) (a.tv_usec - b.tv_usec) / 1000.0) | |
305 | #else /* !BSD_TIME */ | |
abdbd4a8 | 306 | # if defined(MSWIN32) || defined(MSWINCE) |
56293c2b BM |
307 | # include <windows.h> |
308 | # include <winbase.h> | |
309 | # define CLOCK_TYPE DWORD | |
310 | # define GET_TIME(x) x = GetTickCount() | |
311 | # define MS_TIME_DIFF(a,b) ((long)((a)-(b))) | |
abdbd4a8 | 312 | # else /* !MSWIN32, !MSWINCE, !BSD_TIME */ |
73ffefd0 TT |
313 | # include <time.h> |
314 | # if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) | |
315 | clock_t clock(); /* Not in time.h, where it belongs */ | |
316 | # endif | |
317 | # if defined(FREEBSD) && !defined(CLOCKS_PER_SEC) | |
318 | # include <machine/limits.h> | |
319 | # define CLOCKS_PER_SEC CLK_TCK | |
320 | # endif | |
321 | # if !defined(CLOCKS_PER_SEC) | |
322 | # define CLOCKS_PER_SEC 1000000 | |
323 | /* | |
324 | * This is technically a bug in the implementation. ANSI requires that | |
325 | * CLOCKS_PER_SEC be defined. But at least under SunOS4.1.1, it isn't. | |
326 | * Also note that the combination of ANSI C and POSIX is incredibly gross | |
327 | * here. The type clock_t is used by both clock() and times(). But on | |
328 | * some machines these use different notions of a clock tick, CLOCKS_PER_SEC | |
329 | * seems to apply only to clock. Hence we use it here. On many machines, | |
330 | * including SunOS, clock actually uses units of microseconds (which are | |
331 | * not really clock ticks). | |
332 | */ | |
333 | # endif | |
334 | # define CLOCK_TYPE clock_t | |
335 | # define GET_TIME(x) x = clock() | |
336 | # define MS_TIME_DIFF(a,b) ((unsigned long) \ | |
337 | (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC)) | |
56293c2b | 338 | # endif /* !MSWIN32 */ |
73ffefd0 TT |
339 | #endif /* !BSD_TIME */ |
340 | ||
341 | /* We use bzero and bcopy internally. They may not be available. */ | |
342 | # if defined(SPARC) && defined(SUNOS4) | |
343 | # define BCOPY_EXISTS | |
344 | # endif | |
345 | # if defined(M68K) && defined(AMIGA) | |
346 | # define BCOPY_EXISTS | |
347 | # endif | |
348 | # if defined(M68K) && defined(NEXT) | |
349 | # define BCOPY_EXISTS | |
350 | # endif | |
351 | # if defined(VAX) | |
352 | # define BCOPY_EXISTS | |
353 | # endif | |
354 | # if defined(AMIGA) | |
355 | # include <string.h> | |
356 | # define BCOPY_EXISTS | |
357 | # endif | |
30c3de1f JS |
358 | # if defined(DARWIN) |
359 | # include <string.h> | |
abdbd4a8 BM |
360 | # define BCOPY_EXISTS |
361 | # endif | |
73ffefd0 TT |
362 | |
363 | # ifndef BCOPY_EXISTS | |
364 | # include <string.h> | |
365 | # define BCOPY(x,y,n) memcpy(y, x, (size_t)(n)) | |
366 | # define BZERO(x,n) memset(x, 0, (size_t)(n)) | |
367 | # else | |
368 | # define BCOPY(x,y,n) bcopy((char *)(x),(char *)(y),(int)(n)) | |
369 | # define BZERO(x,n) bzero((char *)(x),(int)(n)) | |
370 | # endif | |
371 | ||
73ffefd0 TT |
372 | /* Delay any interrupts or signals that may abort this thread. Data */ |
373 | /* structures are in a consistent state outside this pair of calls. */ | |
374 | /* ANSI C allows both to be empty (though the standard isn't very */ | |
375 | /* clear on that point). Standard malloc implementations are usually */ | |
376 | /* neither interruptable nor thread-safe, and thus correspond to */ | |
377 | /* empty definitions. */ | |
4c7726b1 BM |
378 | /* It probably doesn't make any sense to declare these to be nonempty */ |
379 | /* if the code is being optimized, since signal safety relies on some */ | |
380 | /* ordering constraints that are typically not obeyed by optimizing */ | |
381 | /* compilers. */ | |
73ffefd0 TT |
382 | # ifdef PCR |
383 | # define DISABLE_SIGNALS() \ | |
384 | PCR_Th_SetSigMask(PCR_allSigsBlocked,&GC_old_sig_mask) | |
385 | # define ENABLE_SIGNALS() \ | |
386 | PCR_Th_SetSigMask(&GC_old_sig_mask, NIL) | |
387 | # else | |
4c7726b1 | 388 | # if defined(THREADS) || defined(AMIGA) \ |
abdbd4a8 | 389 | || defined(MSWIN32) || defined(MSWINCE) || defined(MACOS) \ |
4c7726b1 | 390 | || defined(DJGPP) || defined(NO_SIGNALS) |
73ffefd0 | 391 | /* Also useful for debugging. */ |
4c7726b1 | 392 | /* Should probably use thr_sigsetmask for GC_SOLARIS_THREADS. */ |
73ffefd0 TT |
393 | # define DISABLE_SIGNALS() |
394 | # define ENABLE_SIGNALS() | |
395 | # else | |
396 | # define DISABLE_SIGNALS() GC_disable_signals() | |
397 | void GC_disable_signals(); | |
398 | # define ENABLE_SIGNALS() GC_enable_signals() | |
399 | void GC_enable_signals(); | |
400 | # endif | |
401 | # endif | |
402 | ||
403 | /* | |
404 | * Stop and restart mutator threads. | |
405 | */ | |
406 | # ifdef PCR | |
407 | # include "th/PCR_ThCtl.h" | |
408 | # define STOP_WORLD() \ | |
409 | PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_stopNormal, \ | |
410 | PCR_allSigsBlocked, \ | |
411 | PCR_waitForever) | |
412 | # define START_WORLD() \ | |
413 | PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_null, \ | |
414 | PCR_allSigsBlocked, \ | |
415 | PCR_waitForever); | |
416 | # else | |
4c7726b1 BM |
417 | # if defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) \ |
418 | || defined(GC_PTHREADS) | |
73ffefd0 TT |
419 | void GC_stop_world(); |
420 | void GC_start_world(); | |
421 | # define STOP_WORLD() GC_stop_world() | |
422 | # define START_WORLD() GC_start_world() | |
423 | # else | |
424 | # define STOP_WORLD() | |
425 | # define START_WORLD() | |
426 | # endif | |
427 | # endif | |
428 | ||
429 | /* Abandon ship */ | |
430 | # ifdef PCR | |
431 | # define ABORT(s) PCR_Base_Panic(s) | |
432 | # else | |
433 | # ifdef SMALL_CONFIG | |
434 | # define ABORT(msg) abort(); | |
435 | # else | |
30c3de1f | 436 | GC_API void GC_abort GC_PROTO((GC_CONST char * msg)); |
73ffefd0 TT |
437 | # define ABORT(msg) GC_abort(msg); |
438 | # endif | |
439 | # endif | |
440 | ||
441 | /* Exit abnormally, but without making a mess (e.g. out of memory) */ | |
442 | # ifdef PCR | |
443 | # define EXIT() PCR_Base_Exit(1,PCR_waitForever) | |
444 | # else | |
445 | # define EXIT() (void)exit(1) | |
446 | # endif | |
447 | ||
448 | /* Print warning message, e.g. almost out of memory. */ | |
787bf7e3 | 449 | # define WARN(msg,arg) (*GC_current_warn_proc)("GC Warning: " msg, (GC_word)(arg)) |
73ffefd0 TT |
450 | extern GC_warn_proc GC_current_warn_proc; |
451 | ||
abdbd4a8 BM |
452 | /* Get environment entry */ |
453 | #if !defined(NO_GETENV) | |
aa44273b HB |
454 | # if defined(EMPTY_GETENV_RESULTS) |
455 | /* Workaround for a reputed Wine bug. */ | |
456 | static inline char * fixed_getenv(const char *name) | |
457 | { | |
458 | char * tmp = getenv(name); | |
459 | if (tmp == 0 || strlen(tmp) == 0) | |
460 | return 0; | |
461 | return tmp; | |
462 | } | |
463 | # define GETENV(name) fixed_getenv(name) | |
464 | # else | |
465 | # define GETENV(name) getenv(name) | |
466 | # endif | |
abdbd4a8 BM |
467 | #else |
468 | # define GETENV(name) 0 | |
469 | #endif | |
470 | ||
583cb3d3 AT |
471 | #if defined(DARWIN) |
472 | # if defined(POWERPC) | |
473 | # if CPP_WORDSZ == 32 | |
474 | # define GC_THREAD_STATE_T ppc_thread_state_t | |
6656fda3 AT |
475 | # define GC_MACH_THREAD_STATE PPC_THREAD_STATE |
476 | # define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT | |
583cb3d3 AT |
477 | # define GC_MACH_HEADER mach_header |
478 | # define GC_MACH_SECTION section | |
6656fda3 | 479 | # define GC_GETSECTBYNAME getsectbynamefromheader |
583cb3d3 AT |
480 | # else |
481 | # define GC_THREAD_STATE_T ppc_thread_state64_t | |
6656fda3 AT |
482 | # define GC_MACH_THREAD_STATE PPC_THREAD_STATE64 |
483 | # define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT | |
583cb3d3 AT |
484 | # define GC_MACH_HEADER mach_header_64 |
485 | # define GC_MACH_SECTION section_64 | |
6656fda3 | 486 | # define GC_GETSECTBYNAME getsectbynamefromheader_64 |
583cb3d3 | 487 | # endif |
583cb3d3 AT |
488 | # elif defined(I386) || defined(X86_64) |
489 | # if CPP_WORDSZ == 32 | |
490 | # define GC_THREAD_STATE_T x86_thread_state32_t | |
491 | # define GC_MACH_THREAD_STATE x86_THREAD_STATE32 | |
492 | # define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT | |
493 | # define GC_MACH_HEADER mach_header | |
494 | # define GC_MACH_SECTION section | |
6656fda3 | 495 | # define GC_GETSECTBYNAME getsectbynamefromheader |
583cb3d3 AT |
496 | # else |
497 | # define GC_THREAD_STATE_T x86_thread_state64_t | |
498 | # define GC_MACH_THREAD_STATE x86_THREAD_STATE64 | |
499 | # define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT | |
500 | # define GC_MACH_HEADER mach_header_64 | |
501 | # define GC_MACH_SECTION section_64 | |
6656fda3 | 502 | # define GC_GETSECTBYNAME getsectbynamefromheader_64 |
583cb3d3 AT |
503 | # endif |
504 | # else | |
505 | # error define GC_THREAD_STATE_T | |
506 | # define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE | |
507 | # define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT | |
508 | # endif | |
d88c6456 AT |
509 | /* Try to work out the right way to access thread state structure members. |
510 | The structure has changed its definition in different Darwin versions. | |
511 | This now defaults to the (older) names without __, thus hopefully, | |
512 | not breaking any existing Makefile.direct builds. */ | |
513 | # if defined (HAS_PPC_THREAD_STATE___R0) \ | |
514 | || defined (HAS_PPC_THREAD_STATE64___R0) \ | |
515 | || defined (HAS_X86_THREAD_STATE32___EAX) \ | |
516 | || defined (HAS_X86_THREAD_STATE64___RAX) | |
517 | # define THREAD_FLD(x) __ ## x | |
518 | # else | |
519 | # define THREAD_FLD(x) x | |
520 | # endif | |
583cb3d3 | 521 | #endif |
73ffefd0 TT |
522 | /*********************************/ |
523 | /* */ | |
524 | /* Word-size-dependent defines */ | |
525 | /* */ | |
526 | /*********************************/ | |
527 | ||
528 | #if CPP_WORDSZ == 32 | |
529 | # define WORDS_TO_BYTES(x) ((x)<<2) | |
530 | # define BYTES_TO_WORDS(x) ((x)>>2) | |
531 | # define LOGWL ((word)5) /* log[2] of CPP_WORDSZ */ | |
532 | # define modWORDSZ(n) ((n) & 0x1f) /* n mod size of word */ | |
533 | # if ALIGNMENT != 4 | |
534 | # define UNALIGNED | |
535 | # endif | |
536 | #endif | |
537 | ||
538 | #if CPP_WORDSZ == 64 | |
539 | # define WORDS_TO_BYTES(x) ((x)<<3) | |
540 | # define BYTES_TO_WORDS(x) ((x)>>3) | |
541 | # define LOGWL ((word)6) /* log[2] of CPP_WORDSZ */ | |
542 | # define modWORDSZ(n) ((n) & 0x3f) /* n mod size of word */ | |
543 | # if ALIGNMENT != 8 | |
544 | # define UNALIGNED | |
545 | # endif | |
546 | #endif | |
547 | ||
548 | #define WORDSZ ((word)CPP_WORDSZ) | |
549 | #define SIGNB ((word)1 << (WORDSZ-1)) | |
550 | #define BYTES_PER_WORD ((word)(sizeof (word))) | |
abdbd4a8 | 551 | #define ONES ((word)(signed_word)(-1)) |
73ffefd0 TT |
552 | #define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */ |
553 | ||
554 | /*********************/ | |
555 | /* */ | |
556 | /* Size Parameters */ | |
557 | /* */ | |
558 | /*********************/ | |
559 | ||
560 | /* heap block size, bytes. Should be power of 2 */ | |
561 | ||
562 | #ifndef HBLKSIZE | |
563 | # ifdef SMALL_CONFIG | |
564 | # define CPP_LOG_HBLKSIZE 10 | |
565 | # else | |
4c7726b1 BM |
566 | # if (CPP_WORDSZ == 32) || (defined(HPUX) && defined(HP_PA)) |
567 | /* HPUX/PA seems to use 4K pages with the 64 bit ABI */ | |
73ffefd0 TT |
568 | # define CPP_LOG_HBLKSIZE 12 |
569 | # else | |
570 | # define CPP_LOG_HBLKSIZE 13 | |
571 | # endif | |
572 | # endif | |
573 | #else | |
574 | # if HBLKSIZE == 512 | |
575 | # define CPP_LOG_HBLKSIZE 9 | |
576 | # endif | |
577 | # if HBLKSIZE == 1024 | |
578 | # define CPP_LOG_HBLKSIZE 10 | |
579 | # endif | |
580 | # if HBLKSIZE == 2048 | |
581 | # define CPP_LOG_HBLKSIZE 11 | |
582 | # endif | |
583 | # if HBLKSIZE == 4096 | |
584 | # define CPP_LOG_HBLKSIZE 12 | |
585 | # endif | |
586 | # if HBLKSIZE == 8192 | |
587 | # define CPP_LOG_HBLKSIZE 13 | |
588 | # endif | |
589 | # if HBLKSIZE == 16384 | |
590 | # define CPP_LOG_HBLKSIZE 14 | |
591 | # endif | |
592 | # ifndef CPP_LOG_HBLKSIZE | |
593 | --> fix HBLKSIZE | |
594 | # endif | |
595 | # undef HBLKSIZE | |
596 | #endif | |
597 | # define CPP_HBLKSIZE (1 << CPP_LOG_HBLKSIZE) | |
598 | # define LOG_HBLKSIZE ((word)CPP_LOG_HBLKSIZE) | |
599 | # define HBLKSIZE ((word)CPP_HBLKSIZE) | |
600 | ||
601 | ||
602 | /* max size objects supported by freelist (larger objects may be */ | |
603 | /* allocated, but less efficiently) */ | |
604 | ||
abdbd4a8 BM |
605 | #define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2) |
606 | #define MAXOBJBYTES ((word)CPP_MAXOBJBYTES) | |
4109fe85 | 607 | #define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_MAXOBJBYTES) |
73ffefd0 TT |
608 | #define MAXOBJSZ ((word)CPP_MAXOBJSZ) |
609 | ||
610 | # define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE) | |
611 | ||
612 | # define HBLK_PTR_DIFF(p,q) divHBLKSZ((ptr_t)p - (ptr_t)q) | |
613 | /* Equivalent to subtracting 2 hblk pointers. */ | |
614 | /* We do it this way because a compiler should */ | |
615 | /* find it hard to use an integer division */ | |
616 | /* instead of a shift. The bundled SunOS 4.1 */ | |
617 | /* o.w. sometimes pessimizes the subtraction to */ | |
618 | /* involve a call to .div. */ | |
619 | ||
620 | # define modHBLKSZ(n) ((n) & (HBLKSIZE-1)) | |
621 | ||
622 | # define HBLKPTR(objptr) ((struct hblk *)(((word) (objptr)) & ~(HBLKSIZE-1))) | |
623 | ||
624 | # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1)) | |
625 | ||
626 | /* Round up byte allocation requests to integral number of words, etc. */ | |
abdbd4a8 BM |
627 | # define ROUNDED_UP_WORDS(n) \ |
628 | BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1 + EXTRA_BYTES)) | |
629 | # ifdef ALIGN_DOUBLE | |
73ffefd0 | 630 | # define ALIGNED_WORDS(n) \ |
abdbd4a8 BM |
631 | (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1 + EXTRA_BYTES) & ~1) |
632 | # else | |
73ffefd0 | 633 | # define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n) |
abdbd4a8 | 634 | # endif |
4109fe85 | 635 | # define SMALL_OBJ(bytes) ((bytes) <= (MAXOBJBYTES - EXTRA_BYTES)) |
abdbd4a8 BM |
636 | # define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES) |
637 | # ifndef MIN_WORDS | |
638 | /* MIN_WORDS is the size of the smallest allocated object. */ | |
639 | /* 1 and 2 are the only valid values. */ | |
640 | /* 2 must be used if: */ | |
641 | /* - GC_gcj_malloc can be used for objects of requested */ | |
642 | /* size smaller than 2 words, or */ | |
643 | /* - USE_MARK_BYTES is defined. */ | |
644 | # if defined(USE_MARK_BYTES) || defined(GC_GCJ_SUPPORT) | |
645 | # define MIN_WORDS 2 /* Smallest allocated object. */ | |
646 | # else | |
647 | # define MIN_WORDS 1 | |
73ffefd0 | 648 | # endif |
73ffefd0 TT |
649 | # endif |
650 | ||
651 | ||
652 | /* | |
653 | * Hash table representation of sets of pages. This assumes it is | |
654 | * OK to add spurious entries to sets. | |
655 | * Used by black-listing code, and perhaps by dirty bit maintenance code. | |
656 | */ | |
657 | ||
658 | # ifdef LARGE_CONFIG | |
30c3de1f JS |
659 | # define LOG_PHT_ENTRIES 20 /* Collisions likely at 1M blocks, */ |
660 | /* which is >= 4GB. Each table takes */ | |
661 | /* 128KB, some of which may never be */ | |
662 | /* touched. */ | |
73ffefd0 | 663 | # else |
abdbd4a8 BM |
664 | # ifdef SMALL_CONFIG |
665 | # define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ | |
666 | /* to more than 16K hblks = 64MB. */ | |
667 | /* Each hash table occupies 2K bytes. */ | |
668 | # else /* default "medium" configuration */ | |
669 | # define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */ | |
30c3de1f | 670 | /* to more than 64K hblks >= 256MB. */ |
abdbd4a8 | 671 | /* Each hash table occupies 8K bytes. */ |
4109fe85 BM |
672 | /* Even for somewhat smaller heaps, */ |
673 | /* say half that, collisions may be an */ | |
674 | /* issue because we blacklist */ | |
675 | /* addresses outside the heap. */ | |
abdbd4a8 | 676 | # endif |
73ffefd0 TT |
677 | # endif |
678 | # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES) | |
679 | # define PHT_SIZE (PHT_ENTRIES >> LOGWL) | |
680 | typedef word page_hash_table[PHT_SIZE]; | |
681 | ||
682 | # define PHT_HASH(addr) ((((word)(addr)) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1)) | |
683 | ||
684 | # define get_pht_entry_from_index(bl, index) \ | |
685 | (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1) | |
686 | # define set_pht_entry_from_index(bl, index) \ | |
687 | (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index) | |
688 | # define clear_pht_entry_from_index(bl, index) \ | |
689 | (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index)) | |
abdbd4a8 BM |
690 | /* And a dumb but thread-safe version of set_pht_entry_from_index. */ |
691 | /* This sets (many) extra bits. */ | |
692 | # define set_pht_entry_from_index_safe(bl, index) \ | |
693 | (bl)[divWORDSZ(index)] = ONES | |
73ffefd0 TT |
694 | |
695 | ||
696 | ||
697 | /********************************************/ | |
698 | /* */ | |
699 | /* H e a p B l o c k s */ | |
700 | /* */ | |
701 | /********************************************/ | |
702 | ||
703 | /* heap block header */ | |
704 | #define HBLKMASK (HBLKSIZE-1) | |
705 | ||
abdbd4a8 | 706 | #define BITS_PER_HBLK (CPP_HBLKSIZE * 8) |
73ffefd0 TT |
707 | |
708 | #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ) | |
709 | /* upper bound */ | |
abdbd4a8 BM |
710 | /* We allocate 1 bit/word, unless USE_MARK_BYTES */ |
711 | /* is defined. Only the first word */ | |
73ffefd0 TT |
712 | /* in each object is actually marked. */ |
713 | ||
abdbd4a8 BM |
714 | # ifdef USE_MARK_BYTES |
715 | # define MARK_BITS_SZ (MARK_BITS_PER_HBLK/2) | |
716 | /* Unlike the other case, this is in units of bytes. */ | |
717 | /* We actually allocate only every second mark bit, since we */ | |
718 | /* force all objects to be doubleword aligned. */ | |
719 | /* However, each mark bit is allocated as a byte. */ | |
73ffefd0 | 720 | # else |
abdbd4a8 | 721 | # define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ) |
73ffefd0 | 722 | # endif |
abdbd4a8 BM |
723 | |
724 | /* We maintain layout maps for heap blocks containing objects of a given */ | |
725 | /* size. Each entry in this map describes a byte offset and has the */ | |
726 | /* following type. */ | |
727 | typedef unsigned char map_entry_type; | |
73ffefd0 TT |
728 | |
729 | struct hblkhdr { | |
730 | word hb_sz; /* If in use, size in words, of objects in the block. */ | |
731 | /* if free, the size in bytes of the whole block */ | |
732 | struct hblk * hb_next; /* Link field for hblk free list */ | |
733 | /* and for lists of chunks waiting to be */ | |
734 | /* reclaimed. */ | |
85f29b3b | 735 | struct hblk * hb_prev; /* Backwards link for free list. */ |
73ffefd0 TT |
736 | word hb_descr; /* object descriptor for marking. See */ |
737 | /* mark.h. */ | |
abdbd4a8 BM |
738 | map_entry_type * hb_map; |
739 | /* A pointer to a pointer validity map of the block. */ | |
73ffefd0 TT |
740 | /* See GC_obj_map. */ |
741 | /* Valid for all blocks with headers. */ | |
742 | /* Free blocks point to GC_invalid_map. */ | |
743 | unsigned char hb_obj_kind; | |
744 | /* Kind of objects in the block. Each kind */ | |
745 | /* identifies a mark procedure and a set of */ | |
746 | /* list headers. Sometimes called regions. */ | |
747 | unsigned char hb_flags; | |
748 | # define IGNORE_OFF_PAGE 1 /* Ignore pointers that do not */ | |
749 | /* point to the first page of */ | |
750 | /* this object. */ | |
85f29b3b TT |
751 | # define WAS_UNMAPPED 2 /* This is a free block, which has */ |
752 | /* been unmapped from the address */ | |
753 | /* space. */ | |
754 | /* GC_remap must be invoked on it */ | |
755 | /* before it can be reallocated. */ | |
756 | /* Only set with USE_MUNMAP. */ | |
73ffefd0 TT |
757 | unsigned short hb_last_reclaimed; |
758 | /* Value of GC_gc_no when block was */ | |
759 | /* last allocated or swept. May wrap. */ | |
85f29b3b | 760 | /* For a free block, this is maintained */ |
abdbd4a8 | 761 | /* only for USE_MUNMAP, and indicates */ |
85f29b3b TT |
762 | /* when the header was allocated, or */ |
763 | /* when the size of the block last */ | |
764 | /* changed. */ | |
abdbd4a8 BM |
765 | # ifdef USE_MARK_BYTES |
766 | union { | |
767 | char _hb_marks[MARK_BITS_SZ]; | |
768 | /* The i'th byte is 1 if the object */ | |
769 | /* starting at word 2i is marked, 0 o.w. */ | |
770 | word dummy; /* Force word alignment of mark bytes. */ | |
771 | } _mark_byte_union; | |
772 | # define hb_marks _mark_byte_union._hb_marks | |
773 | # else | |
774 | word hb_marks[MARK_BITS_SZ]; | |
73ffefd0 TT |
775 | /* Bit i in the array refers to the */ |
776 | /* object starting at the ith word (header */ | |
777 | /* INCLUDED) in the heap block. */ | |
778 | /* The lsb of word 0 is numbered 0. */ | |
85f29b3b TT |
779 | /* Unused bits are invalid, and are */ |
780 | /* occasionally set, e.g for uncollectable */ | |
781 | /* objects. */ | |
abdbd4a8 | 782 | # endif /* !USE_MARK_BYTES */ |
73ffefd0 TT |
783 | }; |
784 | ||
785 | /* heap block body */ | |
786 | ||
abdbd4a8 | 787 | # define BODY_SZ (HBLKSIZE/sizeof(word)) |
73ffefd0 TT |
788 | |
789 | struct hblk { | |
73ffefd0 TT |
790 | word hb_body[BODY_SZ]; |
791 | }; | |
792 | ||
79f777fd BM |
793 | # define HBLK_IS_FREE(hdr) ((hdr) -> hb_map == GC_invalid_map) |
794 | ||
73ffefd0 | 795 | # define OBJ_SZ_TO_BLOCKS(sz) \ |
abdbd4a8 | 796 | divHBLKSZ(WORDS_TO_BYTES(sz) + HBLKSIZE-1) |
73ffefd0 TT |
797 | /* Size of block (in units of HBLKSIZE) needed to hold objects of */ |
798 | /* given sz (in words). */ | |
799 | ||
800 | /* Object free list link */ | |
801 | # define obj_link(p) (*(ptr_t *)(p)) | |
802 | ||
56ba54b4 TT |
803 | # define LOG_MAX_MARK_PROCS 6 |
804 | # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS) | |
805 | ||
806 | /* Root sets. Logically private to mark_rts.c. But we don't want the */ | |
807 | /* tables scanned, so we put them here. */ | |
808 | /* MAX_ROOT_SETS is the maximum number of ranges that can be */ | |
809 | /* registered as static roots. */ | |
810 | # ifdef LARGE_CONFIG | |
811 | # define MAX_ROOT_SETS 4096 | |
812 | # else | |
39bfe5c7 BM |
813 | /* GCJ LOCAL: MAX_ROOT_SETS increased to permit more shared */ |
814 | /* libraries to be loaded. */ | |
815 | # define MAX_ROOT_SETS 1024 | |
56ba54b4 TT |
816 | # endif |
817 | ||
818 | # define MAX_EXCLUSIONS (MAX_ROOT_SETS/4) | |
819 | /* Maximum number of segments that can be excluded from root sets. */ | |
820 | ||
821 | /* | |
822 | * Data structure for excluded static roots. | |
823 | */ | |
824 | struct exclusion { | |
825 | ptr_t e_start; | |
826 | ptr_t e_end; | |
827 | }; | |
828 | ||
829 | /* Data structure for list of root sets. */ | |
830 | /* We keep a hash table, so that we can filter out duplicate additions. */ | |
831 | /* Under Win32, we need to do a better job of filtering overlaps, so */ | |
832 | /* we resort to sequential search, and pay the price. */ | |
833 | struct roots { | |
834 | ptr_t r_start; | |
835 | ptr_t r_end; | |
045a52c8 | 836 | # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) |
56ba54b4 TT |
837 | struct roots * r_next; |
838 | # endif | |
839 | GC_bool r_tmp; | |
840 | /* Delete before registering new dynamic libraries */ | |
841 | }; | |
842 | ||
045a52c8 | 843 | #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) |
56ba54b4 TT |
844 | /* Size of hash table index to roots. */ |
845 | # define LOG_RT_SIZE 6 | |
846 | # define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */ | |
847 | #endif | |
848 | ||
849 | /* Lists of all heap blocks and free lists */ | |
850 | /* as well as other random data structures */ | |
851 | /* that should not be scanned by the */ | |
852 | /* collector. */ | |
73ffefd0 TT |
853 | /* These are grouped together in a struct */ |
854 | /* so that they can be easily skipped by the */ | |
855 | /* GC_mark routine. */ | |
856 | /* The ordering is weird to make GC_malloc */ | |
857 | /* faster by keeping the important fields */ | |
858 | /* sufficiently close together that a */ | |
859 | /* single load of a base register will do. */ | |
860 | /* Scalars that could easily appear to */ | |
861 | /* be pointers are also put here. */ | |
862 | /* The main fields should precede any */ | |
863 | /* conditionally included fields, so that */ | |
864 | /* gc_inl.h will work even if a different set */ | |
865 | /* of macros is defined when the client is */ | |
866 | /* compiled. */ | |
867 | ||
868 | struct _GC_arrays { | |
869 | word _heapsize; | |
870 | word _max_heapsize; | |
56293c2b | 871 | word _requested_heapsize; /* Heap size due to explicit expansion */ |
73ffefd0 TT |
872 | ptr_t _last_heap_addr; |
873 | ptr_t _prev_heap_addr; | |
85f29b3b TT |
874 | word _large_free_bytes; |
875 | /* Total bytes contained in blocks on large object free */ | |
876 | /* list. */ | |
abdbd4a8 BM |
877 | word _large_allocd_bytes; |
878 | /* Total number of bytes in allocated large objects blocks. */ | |
879 | /* For the purposes of this counter and the next one only, a */ | |
880 | /* large object is one that occupies a block of at least */ | |
881 | /* 2*HBLKSIZE. */ | |
882 | word _max_large_allocd_bytes; | |
883 | /* Maximum number of bytes that were ever allocated in */ | |
884 | /* large object blocks. This is used to help decide when it */ | |
885 | /* is safe to split up a large block. */ | |
73ffefd0 TT |
886 | word _words_allocd_before_gc; |
887 | /* Number of words allocated before this */ | |
888 | /* collection cycle. */ | |
abdbd4a8 BM |
889 | # ifndef SEPARATE_GLOBALS |
890 | word _words_allocd; | |
73ffefd0 | 891 | /* Number of words allocated during this collection cycle */ |
abdbd4a8 | 892 | # endif |
73ffefd0 TT |
893 | word _words_wasted; |
894 | /* Number of words wasted due to internal fragmentation */ | |
895 | /* in large objects, or due to dropping blacklisted */ | |
896 | /* blocks, since last gc. Approximate. */ | |
897 | word _words_finalized; | |
898 | /* Approximate number of words in objects (and headers) */ | |
899 | /* That became ready for finalization in the last */ | |
900 | /* collection. */ | |
901 | word _non_gc_bytes_at_gc; | |
902 | /* Number of explicitly managed bytes of storage */ | |
903 | /* at last collection. */ | |
904 | word _mem_freed; | |
905 | /* Number of explicitly deallocated words of memory */ | |
906 | /* since last collection. */ | |
30c3de1f JS |
907 | word _finalizer_mem_freed; |
908 | /* Words of memory explicitly deallocated while */ | |
909 | /* finalizers were running. Used to approximate mem. */ | |
910 | /* explicitly deallocated by finalizers. */ | |
56293c2b BM |
911 | ptr_t _scratch_end_ptr; |
912 | ptr_t _scratch_last_end_ptr; | |
913 | /* Used by headers.c, and can easily appear to point to */ | |
914 | /* heap. */ | |
abdbd4a8 | 915 | GC_mark_proc _mark_procs[MAX_MARK_PROCS]; |
56ba54b4 TT |
916 | /* Table of user-defined mark procedures. There is */ |
917 | /* a small number of these, which can be referenced */ | |
918 | /* by DS_PROC mark descriptors. See gc_mark.h. */ | |
abdbd4a8 BM |
919 | |
920 | # ifndef SEPARATE_GLOBALS | |
921 | ptr_t _objfreelist[MAXOBJSZ+1]; | |
73ffefd0 | 922 | /* free list for objects */ |
abdbd4a8 | 923 | ptr_t _aobjfreelist[MAXOBJSZ+1]; |
73ffefd0 | 924 | /* free list for atomic objs */ |
abdbd4a8 | 925 | # endif |
73ffefd0 TT |
926 | |
927 | ptr_t _uobjfreelist[MAXOBJSZ+1]; | |
928 | /* uncollectable but traced objs */ | |
929 | /* objects on this and auobjfreelist */ | |
930 | /* are always marked, except during */ | |
931 | /* garbage collections. */ | |
932 | # ifdef ATOMIC_UNCOLLECTABLE | |
933 | ptr_t _auobjfreelist[MAXOBJSZ+1]; | |
934 | # endif | |
935 | /* uncollectable but traced objs */ | |
936 | ||
937 | # ifdef GATHERSTATS | |
938 | word _composite_in_use; | |
939 | /* Number of words in accessible composite */ | |
940 | /* objects. */ | |
941 | word _atomic_in_use; | |
942 | /* Number of words in accessible atomic */ | |
943 | /* objects. */ | |
944 | # endif | |
85f29b3b TT |
945 | # ifdef USE_MUNMAP |
946 | word _unmapped_bytes; | |
947 | # endif | |
73ffefd0 TT |
948 | # ifdef MERGE_SIZES |
949 | unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)]; | |
950 | /* Number of words to allocate for a given allocation request in */ | |
951 | /* bytes. */ | |
952 | # endif | |
953 | ||
954 | # ifdef STUBBORN_ALLOC | |
955 | ptr_t _sobjfreelist[MAXOBJSZ+1]; | |
956 | # endif | |
957 | /* free list for immutable objects */ | |
abdbd4a8 | 958 | map_entry_type * _obj_map[MAXOBJSZ+1]; |
73ffefd0 TT |
959 | /* If not NIL, then a pointer to a map of valid */ |
960 | /* object addresses. _obj_map[sz][i] is j if the */ | |
961 | /* address block_start+i is a valid pointer */ | |
abdbd4a8 BM |
962 | /* to an object at block_start + */ |
963 | /* WORDS_TO_BYTES(BYTES_TO_WORDS(i) - j) */ | |
964 | /* I.e. j is a word displacement from the */ | |
965 | /* object beginning. */ | |
966 | /* The entry is OBJ_INVALID if the corresponding */ | |
967 | /* address is not a valid pointer. It is */ | |
968 | /* OFFSET_TOO_BIG if the value j would be too */ | |
969 | /* large to fit in the entry. (Note that the */ | |
970 | /* size of these entries matters, both for */ | |
30c3de1f | 971 | /* space consumption and for cache utilization.) */ |
abdbd4a8 BM |
972 | # define OFFSET_TOO_BIG 0xfe |
973 | # define OBJ_INVALID 0xff | |
974 | # define MAP_ENTRY(map, bytes) (map)[bytes] | |
975 | # define MAP_ENTRIES HBLKSIZE | |
976 | # define MAP_SIZE MAP_ENTRIES | |
977 | # define CPP_MAX_OFFSET (OFFSET_TOO_BIG - 1) | |
978 | # define MAX_OFFSET ((word)CPP_MAX_OFFSET) | |
979 | /* The following are used only if GC_all_interior_ptrs != 0 */ | |
73ffefd0 TT |
980 | # define VALID_OFFSET_SZ \ |
981 | (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \ | |
982 | CPP_MAX_OFFSET+1 \ | |
983 | : WORDS_TO_BYTES(CPP_MAXOBJSZ)+1) | |
984 | char _valid_offsets[VALID_OFFSET_SZ]; | |
985 | /* GC_valid_offsets[i] == TRUE ==> i */ | |
986 | /* is registered as a displacement. */ | |
73ffefd0 TT |
987 | char _modws_valid_offsets[sizeof(word)]; |
988 | /* GC_valid_offsets[i] ==> */ | |
989 | /* GC_modws_valid_offsets[i%sizeof(word)] */ | |
4109fe85 BM |
990 | # define OFFSET_VALID(displ) \ |
991 | (GC_all_interior_pointers || GC_valid_offsets[displ]) | |
73ffefd0 | 992 | # ifdef STUBBORN_ALLOC |
56ba54b4 | 993 | page_hash_table _changed_pages; |
73ffefd0 TT |
994 | /* Stubborn object pages that were changes since last call to */ |
995 | /* GC_read_changed. */ | |
56ba54b4 | 996 | page_hash_table _prev_changed_pages; |
73ffefd0 TT |
997 | /* Stubborn object pages that were changes before last call to */ |
998 | /* GC_read_changed. */ | |
999 | # endif | |
1000 | # if defined(PROC_VDB) || defined(MPROTECT_VDB) | |
56ba54b4 | 1001 | page_hash_table _grungy_pages; /* Pages that were dirty at last */ |
73ffefd0 TT |
1002 | /* GC_read_dirty. */ |
1003 | # endif | |
56ba54b4 TT |
1004 | # ifdef MPROTECT_VDB |
1005 | VOLATILE page_hash_table _dirty_pages; | |
1006 | /* Pages dirtied since last GC_read_dirty. */ | |
1007 | # endif | |
1008 | # ifdef PROC_VDB | |
1009 | page_hash_table _written_pages; /* Pages ever dirtied */ | |
1010 | # endif | |
73ffefd0 TT |
1011 | # ifdef LARGE_CONFIG |
1012 | # if CPP_WORDSZ > 32 | |
1013 | # define MAX_HEAP_SECTS 4096 /* overflows at roughly 64 GB */ | |
1014 | # else | |
1015 | # define MAX_HEAP_SECTS 768 /* Separately added heap sections. */ | |
1016 | # endif | |
1017 | # else | |
abdbd4a8 | 1018 | # ifdef SMALL_CONFIG |
4109fe85 | 1019 | # define MAX_HEAP_SECTS 128 /* Roughly 256MB (128*2048*1K) */ |
abdbd4a8 BM |
1020 | # else |
1021 | # define MAX_HEAP_SECTS 384 /* Roughly 3GB */ | |
1022 | # endif | |
73ffefd0 TT |
1023 | # endif |
1024 | struct HeapSect { | |
1025 | ptr_t hs_start; word hs_bytes; | |
1026 | } _heap_sects[MAX_HEAP_SECTS]; | |
045a52c8 | 1027 | # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) |
73ffefd0 TT |
1028 | ptr_t _heap_bases[MAX_HEAP_SECTS]; |
1029 | /* Start address of memory regions obtained from kernel. */ | |
abdbd4a8 BM |
1030 | # endif |
1031 | # ifdef MSWINCE | |
1032 | word _heap_lengths[MAX_HEAP_SECTS]; | |
1033 | /* Commited lengths of memory regions obtained from kernel. */ | |
73ffefd0 | 1034 | # endif |
56ba54b4 | 1035 | struct roots _static_roots[MAX_ROOT_SETS]; |
045a52c8 | 1036 | # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) |
56ba54b4 TT |
1037 | struct roots * _root_index[RT_SIZE]; |
1038 | # endif | |
1039 | struct exclusion _excl_table[MAX_EXCLUSIONS]; | |
73ffefd0 TT |
1040 | /* Block header index; see gc_headers.h */ |
1041 | bottom_index * _all_nils; | |
1042 | bottom_index * _top_index [TOP_SZ]; | |
1043 | #ifdef SAVE_CALL_CHAIN | |
1044 | struct callinfo _last_stack[NFRAMES]; /* Stack at last garbage collection.*/ | |
1045 | /* Useful for debugging mysterious */ | |
1046 | /* object disappearances. */ | |
1047 | /* In the multithreaded case, we */ | |
1048 | /* currently only save the calling */ | |
1049 | /* stack. */ | |
1050 | #endif | |
1051 | }; | |
1052 | ||
1053 | GC_API GC_FAR struct _GC_arrays GC_arrays; | |
1054 | ||
abdbd4a8 BM |
1055 | # ifndef SEPARATE_GLOBALS |
1056 | # define GC_objfreelist GC_arrays._objfreelist | |
1057 | # define GC_aobjfreelist GC_arrays._aobjfreelist | |
1058 | # define GC_words_allocd GC_arrays._words_allocd | |
1059 | # endif | |
73ffefd0 TT |
1060 | # define GC_uobjfreelist GC_arrays._uobjfreelist |
1061 | # ifdef ATOMIC_UNCOLLECTABLE | |
1062 | # define GC_auobjfreelist GC_arrays._auobjfreelist | |
1063 | # endif | |
1064 | # define GC_sobjfreelist GC_arrays._sobjfreelist | |
1065 | # define GC_valid_offsets GC_arrays._valid_offsets | |
1066 | # define GC_modws_valid_offsets GC_arrays._modws_valid_offsets | |
1067 | # ifdef STUBBORN_ALLOC | |
1068 | # define GC_changed_pages GC_arrays._changed_pages | |
1069 | # define GC_prev_changed_pages GC_arrays._prev_changed_pages | |
1070 | # endif | |
1071 | # define GC_obj_map GC_arrays._obj_map | |
1072 | # define GC_last_heap_addr GC_arrays._last_heap_addr | |
1073 | # define GC_prev_heap_addr GC_arrays._prev_heap_addr | |
73ffefd0 | 1074 | # define GC_words_wasted GC_arrays._words_wasted |
85f29b3b | 1075 | # define GC_large_free_bytes GC_arrays._large_free_bytes |
abdbd4a8 BM |
1076 | # define GC_large_allocd_bytes GC_arrays._large_allocd_bytes |
1077 | # define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes | |
73ffefd0 TT |
1078 | # define GC_words_finalized GC_arrays._words_finalized |
1079 | # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc | |
1080 | # define GC_mem_freed GC_arrays._mem_freed | |
30c3de1f | 1081 | # define GC_finalizer_mem_freed GC_arrays._finalizer_mem_freed |
56293c2b BM |
1082 | # define GC_scratch_end_ptr GC_arrays._scratch_end_ptr |
1083 | # define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr | |
56ba54b4 | 1084 | # define GC_mark_procs GC_arrays._mark_procs |
73ffefd0 TT |
1085 | # define GC_heapsize GC_arrays._heapsize |
1086 | # define GC_max_heapsize GC_arrays._max_heapsize | |
56293c2b | 1087 | # define GC_requested_heapsize GC_arrays._requested_heapsize |
73ffefd0 TT |
1088 | # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc |
1089 | # define GC_heap_sects GC_arrays._heap_sects | |
1090 | # define GC_last_stack GC_arrays._last_stack | |
85f29b3b TT |
1091 | # ifdef USE_MUNMAP |
1092 | # define GC_unmapped_bytes GC_arrays._unmapped_bytes | |
1093 | # endif | |
045a52c8 | 1094 | # if defined(MSWIN32) || defined(MSWINCE) || defined (CYGWIN32) |
73ffefd0 TT |
1095 | # define GC_heap_bases GC_arrays._heap_bases |
1096 | # endif | |
abdbd4a8 BM |
1097 | # ifdef MSWINCE |
1098 | # define GC_heap_lengths GC_arrays._heap_lengths | |
1099 | # endif | |
56ba54b4 TT |
1100 | # define GC_static_roots GC_arrays._static_roots |
1101 | # define GC_root_index GC_arrays._root_index | |
1102 | # define GC_excl_table GC_arrays._excl_table | |
73ffefd0 TT |
1103 | # define GC_all_nils GC_arrays._all_nils |
1104 | # define GC_top_index GC_arrays._top_index | |
1105 | # if defined(PROC_VDB) || defined(MPROTECT_VDB) | |
1106 | # define GC_grungy_pages GC_arrays._grungy_pages | |
1107 | # endif | |
56ba54b4 TT |
1108 | # ifdef MPROTECT_VDB |
1109 | # define GC_dirty_pages GC_arrays._dirty_pages | |
1110 | # endif | |
1111 | # ifdef PROC_VDB | |
1112 | # define GC_written_pages GC_arrays._written_pages | |
1113 | # endif | |
73ffefd0 TT |
1114 | # ifdef GATHERSTATS |
1115 | # define GC_composite_in_use GC_arrays._composite_in_use | |
1116 | # define GC_atomic_in_use GC_arrays._atomic_in_use | |
1117 | # endif | |
1118 | # ifdef MERGE_SIZES | |
1119 | # define GC_size_map GC_arrays._size_map | |
1120 | # endif | |
1121 | ||
1122 | # define beginGC_arrays ((ptr_t)(&GC_arrays)) | |
1123 | # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays)) | |
1124 | ||
56293c2b BM |
1125 | #define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes) |
1126 | ||
56ba54b4 | 1127 | /* Object kinds: */ |
73ffefd0 TT |
1128 | # define MAXOBJKINDS 16 |
1129 | ||
73ffefd0 TT |
1130 | extern struct obj_kind { |
1131 | ptr_t *ok_freelist; /* Array of free listheaders for this kind of object */ | |
1132 | /* Point either to GC_arrays or to storage allocated */ | |
1133 | /* with GC_scratch_alloc. */ | |
1134 | struct hblk **ok_reclaim_list; | |
1135 | /* List headers for lists of blocks waiting to be */ | |
1136 | /* swept. */ | |
1137 | word ok_descriptor; /* Descriptor template for objects in this */ | |
1138 | /* block. */ | |
1139 | GC_bool ok_relocate_descr; | |
1140 | /* Add object size in bytes to descriptor */ | |
1141 | /* template to obtain descriptor. Otherwise */ | |
1142 | /* template is used as is. */ | |
56ba54b4 | 1143 | GC_bool ok_init; /* Clear objects before putting them on the free list. */ |
73ffefd0 | 1144 | } GC_obj_kinds[MAXOBJKINDS]; |
56ba54b4 | 1145 | |
abdbd4a8 BM |
1146 | # define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds)) |
1147 | # define endGC_obj_kinds (beginGC_obj_kinds + (sizeof GC_obj_kinds)) | |
56ba54b4 | 1148 | |
abdbd4a8 BM |
1149 | /* Variables that used to be in GC_arrays, but need to be accessed by */ |
1150 | /* inline allocation code. If they were in GC_arrays, the inlined */ | |
1151 | /* allocation code would include GC_arrays offsets (as it did), which */ | |
1152 | /* introduce maintenance problems. */ | |
1153 | ||
1154 | #ifdef SEPARATE_GLOBALS | |
1155 | word GC_words_allocd; | |
1156 | /* Number of words allocated during this collection cycle */ | |
1157 | ptr_t GC_objfreelist[MAXOBJSZ+1]; | |
1158 | /* free list for NORMAL objects */ | |
1159 | # define beginGC_objfreelist ((ptr_t)(&GC_objfreelist)) | |
1160 | # define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist)) | |
1161 | ||
1162 | ptr_t GC_aobjfreelist[MAXOBJSZ+1]; | |
1163 | /* free list for atomic (PTRFREE) objs */ | |
1164 | # define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist)) | |
1165 | # define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist)) | |
1166 | #endif | |
56ba54b4 | 1167 | |
73ffefd0 TT |
1168 | /* Predefined kinds: */ |
1169 | # define PTRFREE 0 | |
1170 | # define NORMAL 1 | |
1171 | # define UNCOLLECTABLE 2 | |
1172 | # ifdef ATOMIC_UNCOLLECTABLE | |
1173 | # define AUNCOLLECTABLE 3 | |
1174 | # define STUBBORN 4 | |
1175 | # define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE) | |
1176 | # else | |
1177 | # define STUBBORN 3 | |
1178 | # define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE) | |
1179 | # endif | |
1180 | ||
1181 | extern int GC_n_kinds; | |
1182 | ||
56ba54b4 TT |
1183 | GC_API word GC_fo_entries; |
1184 | ||
73ffefd0 TT |
1185 | extern word GC_n_heap_sects; /* Number of separately added heap */ |
1186 | /* sections. */ | |
1187 | ||
1188 | extern word GC_page_size; | |
1189 | ||
045a52c8 | 1190 | # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) |
abdbd4a8 BM |
1191 | struct _SYSTEM_INFO; |
1192 | extern struct _SYSTEM_INFO GC_sysinfo; | |
1193 | extern word GC_n_heap_bases; /* See GC_heap_bases. */ | |
73ffefd0 TT |
1194 | # endif |
1195 | ||
1196 | extern word GC_total_stack_black_listed; | |
1197 | /* Number of bytes on stack blacklist. */ | |
1198 | ||
1199 | extern word GC_black_list_spacing; | |
1200 | /* Average number of bytes between blacklisted */ | |
1201 | /* blocks. Approximate. */ | |
1202 | /* Counts only blocks that are */ | |
1203 | /* "stack-blacklisted", i.e. that are */ | |
1204 | /* problematic in the interior of an object. */ | |
1205 | ||
abdbd4a8 | 1206 | extern map_entry_type * GC_invalid_map; |
73ffefd0 TT |
1207 | /* Pointer to the nowhere valid hblk map */ |
1208 | /* Blocks pointing to this map are free. */ | |
1209 | ||
85f29b3b | 1210 | extern struct hblk * GC_hblkfreelist[]; |
73ffefd0 TT |
1211 | /* List of completely empty heap blocks */ |
1212 | /* Linked through hb_next field of */ | |
1213 | /* header structure associated with */ | |
1214 | /* block. */ | |
1215 | ||
73ffefd0 TT |
1216 | extern GC_bool GC_objects_are_marked; /* There are marked objects in */ |
1217 | /* the heap. */ | |
1218 | ||
56ba54b4 TT |
1219 | #ifndef SMALL_CONFIG |
1220 | extern GC_bool GC_incremental; | |
1221 | /* Using incremental/generational collection. */ | |
30c3de1f JS |
1222 | # define TRUE_INCREMENTAL \ |
1223 | (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) | |
1224 | /* True incremental, not just generational, mode */ | |
56ba54b4 | 1225 | #else |
179977c1 | 1226 | # define GC_incremental FALSE |
56ba54b4 | 1227 | /* Hopefully allow optimizer to remove some code. */ |
30c3de1f | 1228 | # define TRUE_INCREMENTAL FALSE |
56ba54b4 | 1229 | #endif |
73ffefd0 TT |
1230 | |
1231 | extern GC_bool GC_dirty_maintained; | |
1232 | /* Dirty bits are being maintained, */ | |
1233 | /* either for incremental collection, */ | |
1234 | /* or to limit the root set. */ | |
1235 | ||
73ffefd0 TT |
1236 | extern word GC_root_size; /* Total size of registered root sections */ |
1237 | ||
1238 | extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */ | |
1239 | ||
787bf7e3 HB |
1240 | extern long GC_large_alloc_warn_interval; |
1241 | /* Interval between unsuppressed warnings. */ | |
1242 | ||
1243 | extern long GC_large_alloc_warn_suppressed; | |
1244 | /* Number of warnings suppressed so far. */ | |
1245 | ||
30c3de1f JS |
1246 | #ifdef THREADS |
1247 | extern GC_bool GC_world_stopped; | |
1248 | #endif | |
1249 | ||
73ffefd0 TT |
1250 | /* Operations */ |
1251 | # ifndef abs | |
1252 | # define abs(x) ((x) < 0? (-(x)) : (x)) | |
1253 | # endif | |
1254 | ||
1255 | ||
1256 | /* Marks are in a reserved area in */ | |
1257 | /* each heap block. Each word has one mark bit associated */ | |
1258 | /* with it. Only those corresponding to the beginning of an */ | |
1259 | /* object are used. */ | |
1260 | ||
abdbd4a8 BM |
1261 | /* Set mark bit correctly, even if mark bits may be concurrently */ |
1262 | /* accessed. */ | |
1263 | #ifdef PARALLEL_MARK | |
1264 | # define OR_WORD(addr, bits) \ | |
1265 | { word old; \ | |
1266 | do { \ | |
1267 | old = *((volatile word *)addr); \ | |
1268 | } while (!GC_compare_and_exchange((addr), old, old | (bits))); \ | |
1269 | } | |
1270 | # define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ | |
1271 | { word old; \ | |
1272 | word my_bits = (bits); \ | |
1273 | do { \ | |
1274 | old = *((volatile word *)addr); \ | |
1275 | if (old & my_bits) goto exit_label; \ | |
1276 | } while (!GC_compare_and_exchange((addr), old, old | my_bits)); \ | |
1277 | } | |
1278 | #else | |
1279 | # define OR_WORD(addr, bits) *(addr) |= (bits) | |
1280 | # define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ | |
1281 | { \ | |
1282 | word old = *(addr); \ | |
1283 | word my_bits = (bits); \ | |
1284 | if (old & my_bits) goto exit_label; \ | |
1285 | *(addr) = (old | my_bits); \ | |
1286 | } | |
1287 | #endif | |
73ffefd0 TT |
1288 | |
1289 | /* Mark bit operations */ | |
1290 | ||
1291 | /* | |
1292 | * Retrieve, set, clear the mark bit corresponding | |
1293 | * to the nth word in a given heap block. | |
1294 | * | |
1295 | * (Recall that bit n corresponds to object beginning at word n | |
1296 | * relative to the beginning of the block, including unused words) | |
1297 | */ | |
1298 | ||
abdbd4a8 BM |
1299 | #ifdef USE_MARK_BYTES |
1300 | # define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n) >> 1]) | |
1301 | # define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 1 | |
1302 | # define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 0 | |
1303 | #else /* !USE_MARK_BYTES */ | |
73ffefd0 TT |
1304 | # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ |
1305 | >> (modWORDSZ(n))) & (word)1) | |
abdbd4a8 BM |
1306 | # define set_mark_bit_from_hdr(hhdr,n) \ |
1307 | OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ | |
1308 | (word)1 << modWORDSZ(n)) | |
73ffefd0 TT |
1309 | # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ |
1310 | &= ~((word)1 << modWORDSZ(n)) | |
abdbd4a8 | 1311 | #endif /* !USE_MARK_BYTES */ |
73ffefd0 TT |
1312 | |
1313 | /* Important internal collector routines */ | |
1314 | ||
abdbd4a8 BM |
1315 | ptr_t GC_approx_sp GC_PROTO((void)); |
1316 | ||
1317 | GC_bool GC_should_collect GC_PROTO((void)); | |
1318 | ||
1319 | void GC_apply_to_all_blocks GC_PROTO(( \ | |
1320 | void (*fn) GC_PROTO((struct hblk *h, word client_data)), \ | |
1321 | word client_data)); | |
1322 | /* Invoke fn(hbp, client_data) for each */ | |
1323 | /* allocated heap block. */ | |
1324 | struct hblk * GC_next_used_block GC_PROTO((struct hblk * h)); | |
1325 | /* Return first in-use block >= h */ | |
1326 | struct hblk * GC_prev_block GC_PROTO((struct hblk * h)); | |
1327 | /* Return last block <= h. Returned block */ | |
1328 | /* is managed by GC, but may or may not be in */ | |
85f29b3b | 1329 | /* use. */ |
abdbd4a8 BM |
1330 | void GC_mark_init GC_PROTO((void)); |
1331 | void GC_clear_marks GC_PROTO((void)); /* Clear mark bits for all heap objects. */ | |
1332 | void GC_invalidate_mark_state GC_PROTO((void)); | |
1333 | /* Tell the marker that marked */ | |
1334 | /* objects may point to unmarked */ | |
1335 | /* ones, and roots may point to */ | |
1336 | /* unmarked objects. */ | |
1337 | /* Reset mark stack. */ | |
1338 | GC_bool GC_mark_stack_empty GC_PROTO((void)); | |
1339 | GC_bool GC_mark_some GC_PROTO((ptr_t cold_gc_frame)); | |
1340 | /* Perform about one pages worth of marking */ | |
1341 | /* work of whatever kind is needed. Returns */ | |
1342 | /* quickly if no collection is in progress. */ | |
1343 | /* Return TRUE if mark phase finished. */ | |
1344 | void GC_initiate_gc GC_PROTO((void)); | |
1345 | /* initiate collection. */ | |
1346 | /* If the mark state is invalid, this */ | |
1347 | /* becomes full colleection. Otherwise */ | |
1348 | /* it's partial. */ | |
1349 | void GC_push_all GC_PROTO((ptr_t bottom, ptr_t top)); | |
1350 | /* Push everything in a range */ | |
1351 | /* onto mark stack. */ | |
1352 | void GC_push_selected GC_PROTO(( \ | |
1353 | ptr_t bottom, \ | |
1354 | ptr_t top, \ | |
1355 | int (*dirty_fn) GC_PROTO((struct hblk *h)), \ | |
1356 | void (*push_fn) GC_PROTO((ptr_t bottom, ptr_t top)) )); | |
1357 | /* Push all pages h in [b,t) s.t. */ | |
1358 | /* select_fn(h) != 0 onto mark stack. */ | |
73ffefd0 | 1359 | #ifndef SMALL_CONFIG |
abdbd4a8 | 1360 | void GC_push_conditional GC_PROTO((ptr_t b, ptr_t t, GC_bool all)); |
73ffefd0 TT |
1361 | #else |
1362 | # define GC_push_conditional(b, t, all) GC_push_all(b, t) | |
1363 | #endif | |
1364 | /* Do either of the above, depending */ | |
1365 | /* on the third arg. */ | |
abdbd4a8 BM |
1366 | void GC_push_all_stack GC_PROTO((ptr_t b, ptr_t t)); |
1367 | /* As above, but consider */ | |
73ffefd0 | 1368 | /* interior pointers as valid */ |
abdbd4a8 BM |
1369 | void GC_push_all_eager GC_PROTO((ptr_t b, ptr_t t)); |
1370 | /* Same as GC_push_all_stack, but */ | |
56ba54b4 TT |
1371 | /* ensures that stack is scanned */ |
1372 | /* immediately, not just scheduled */ | |
1373 | /* for scanning. */ | |
1374 | #ifndef THREADS | |
abdbd4a8 BM |
1375 | void GC_push_all_stack_partially_eager GC_PROTO(( \ |
1376 | ptr_t bottom, ptr_t top, ptr_t cold_gc_frame )); | |
56ba54b4 TT |
1377 | /* Similar to GC_push_all_eager, but only the */ |
1378 | /* part hotter than cold_gc_frame is scanned */ | |
abdbd4a8 | 1379 | /* immediately. Needed to ensure that callee- */ |
56ba54b4 TT |
1380 | /* save registers are not missed. */ |
1381 | #else | |
1382 | /* In the threads case, we push part of the current thread stack */ | |
1383 | /* with GC_push_all_eager when we push the registers. This gets the */ | |
1384 | /* callee-save registers that may disappear. The remainder of the */ | |
1385 | /* stacks are scheduled for scanning in *GC_push_other_roots, which */ | |
1386 | /* is thread-package-specific. */ | |
1387 | #endif | |
abdbd4a8 BM |
1388 | void GC_push_current_stack GC_PROTO((ptr_t cold_gc_frame)); |
1389 | /* Push enough of the current stack eagerly to */ | |
1390 | /* ensure that callee-save registers saved in */ | |
1391 | /* GC frames are scanned. */ | |
1392 | /* In the non-threads case, schedule entire */ | |
1393 | /* stack for scanning. */ | |
1394 | void GC_push_roots GC_PROTO((GC_bool all, ptr_t cold_gc_frame)); | |
1395 | /* Push all or dirty roots. */ | |
1396 | extern void (*GC_push_other_roots) GC_PROTO((void)); | |
1397 | /* Push system or application specific roots */ | |
1398 | /* onto the mark stack. In some environments */ | |
1399 | /* (e.g. threads environments) this is */ | |
1400 | /* predfined to be non-zero. A client supplied */ | |
1401 | /* replacement should also call the original */ | |
1402 | /* function. */ | |
1403 | extern void GC_push_gc_structures GC_PROTO((void)); | |
1404 | /* Push GC internal roots. These are normally */ | |
1405 | /* included in the static data segment, and */ | |
1406 | /* Thus implicitly pushed. But we must do this */ | |
1407 | /* explicitly if normal root processing is */ | |
1408 | /* disabled. Calls the following: */ | |
1409 | extern void GC_push_finalizer_structures GC_PROTO((void)); | |
1410 | extern void GC_push_stubborn_structures GC_PROTO((void)); | |
1411 | # ifdef THREADS | |
1412 | extern void GC_push_thread_structures GC_PROTO((void)); | |
1413 | # endif | |
1414 | extern void (*GC_start_call_back) GC_PROTO((void)); | |
1415 | /* Called at start of full collections. */ | |
1416 | /* Not called if 0. Called with allocation */ | |
1417 | /* lock held. */ | |
1418 | /* 0 by default. */ | |
1419 | # if defined(USE_GENERIC_PUSH_REGS) | |
1420 | void GC_generic_push_regs GC_PROTO((ptr_t cold_gc_frame)); | |
1421 | # else | |
1422 | void GC_push_regs GC_PROTO((void)); | |
30c3de1f JS |
1423 | # endif |
1424 | # if defined(SPARC) || defined(IA64) | |
1425 | /* Cause all stacked registers to be saved in memory. Return a */ | |
1426 | /* pointer to the top of the corresponding memory stack. */ | |
1427 | word GC_save_regs_in_stack GC_PROTO((void)); | |
abdbd4a8 BM |
1428 | # endif |
1429 | /* Push register contents onto mark stack. */ | |
1430 | /* If NURSERY is defined, the default push */ | |
1431 | /* action can be overridden with GC_push_proc */ | |
85f29b3b TT |
1432 | |
1433 | # ifdef NURSERY | |
1434 | extern void (*GC_push_proc)(ptr_t); | |
1435 | # endif | |
abdbd4a8 BM |
1436 | # if defined(MSWIN32) || defined(MSWINCE) |
1437 | void __cdecl GC_push_one GC_PROTO((word p)); | |
73ffefd0 | 1438 | # else |
abdbd4a8 BM |
1439 | void GC_push_one GC_PROTO((word p)); |
1440 | /* If p points to an object, mark it */ | |
73ffefd0 | 1441 | /* and push contents on the mark stack */ |
abdbd4a8 BM |
1442 | /* Pointer recognition test always */ |
1443 | /* accepts interior pointers, i.e. this */ | |
1444 | /* is appropriate for pointers found on */ | |
1445 | /* stack. */ | |
1446 | # endif | |
1447 | # if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS) | |
1448 | void GC_mark_and_push_stack GC_PROTO((word p, ptr_t source)); | |
1449 | /* Ditto, omits plausibility test */ | |
1450 | # else | |
1451 | void GC_mark_and_push_stack GC_PROTO((word p)); | |
73ffefd0 | 1452 | # endif |
abdbd4a8 | 1453 | void GC_push_marked GC_PROTO((struct hblk * h, hdr * hhdr)); |
73ffefd0 TT |
1454 | /* Push contents of all marked objects in h onto */ |
1455 | /* mark stack. */ | |
1456 | #ifdef SMALL_CONFIG | |
1457 | # define GC_push_next_marked_dirty(h) GC_push_next_marked(h) | |
1458 | #else | |
abdbd4a8 | 1459 | struct hblk * GC_push_next_marked_dirty GC_PROTO((struct hblk * h)); |
73ffefd0 TT |
1460 | /* Invoke GC_push_marked on next dirty block above h. */ |
1461 | /* Return a pointer just past the end of this block. */ | |
1462 | #endif /* !SMALL_CONFIG */ | |
abdbd4a8 BM |
1463 | struct hblk * GC_push_next_marked GC_PROTO((struct hblk * h)); |
1464 | /* Ditto, but also mark from clean pages. */ | |
1465 | struct hblk * GC_push_next_marked_uncollectable GC_PROTO((struct hblk * h)); | |
1466 | /* Ditto, but mark only from uncollectable pages. */ | |
1467 | GC_bool GC_stopped_mark GC_PROTO((GC_stop_func stop_func)); | |
1468 | /* Stop world and mark from all roots */ | |
1469 | /* and rescuers. */ | |
1470 | void GC_clear_hdr_marks GC_PROTO((hdr * hhdr)); | |
1471 | /* Clear the mark bits in a header */ | |
1472 | void GC_set_hdr_marks GC_PROTO((hdr * hhdr)); | |
1473 | /* Set the mark bits in a header */ | |
5a2586cf TT |
1474 | void GC_set_fl_marks GC_PROTO((ptr_t p)); |
1475 | /* Set all mark bits associated with */ | |
1476 | /* a free list. */ | |
abdbd4a8 | 1477 | void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp)); |
30c3de1f | 1478 | void GC_remove_roots_inner GC_PROTO((char * b, char * e)); |
abdbd4a8 BM |
1479 | GC_bool GC_is_static_root GC_PROTO((ptr_t p)); |
1480 | /* Is the address p in one of the registered static */ | |
1481 | /* root sections? */ | |
045a52c8 | 1482 | # if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) || defined(CYGWIN32) |
abdbd4a8 BM |
1483 | GC_bool GC_is_tmp_root GC_PROTO((ptr_t p)); |
1484 | /* Is the address p in one of the temporary static */ | |
73ffefd0 | 1485 | /* root sections? */ |
abdbd4a8 BM |
1486 | # endif |
1487 | void GC_register_dynamic_libraries GC_PROTO((void)); | |
1488 | /* Add dynamic library data sections to the root set. */ | |
4109fe85 | 1489 | |
ebcc6a7e | 1490 | GC_bool GC_register_main_static_data GC_PROTO((void)); |
30c3de1f JS |
1491 | /* We need to register the main data segment. Returns */ |
1492 | /* TRUE unless this is done implicitly as part of */ | |
1493 | /* dynamic library registration. */ | |
abdbd4a8 | 1494 | |
73ffefd0 | 1495 | /* Machine dependent startup routines */ |
abdbd4a8 BM |
1496 | ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */ |
1497 | #ifdef IA64 | |
1498 | ptr_t GC_get_register_stack_base GC_PROTO((void)); | |
1499 | /* Cold end of register stack. */ | |
1500 | #endif | |
1501 | void GC_register_data_segments GC_PROTO((void)); | |
1502 | ||
73ffefd0 | 1503 | /* Black listing: */ |
abdbd4a8 BM |
1504 | void GC_bl_init GC_PROTO((void)); |
1505 | # ifdef PRINT_BLACK_LIST | |
1506 | void GC_add_to_black_list_normal GC_PROTO((word p, ptr_t source)); | |
73ffefd0 TT |
1507 | /* Register bits as a possible future false */ |
1508 | /* reference from the heap or static data */ | |
73ffefd0 | 1509 | # define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ |
abdbd4a8 | 1510 | if (GC_all_interior_pointers) { \ |
5a2586cf | 1511 | GC_add_to_black_list_stack(bits, (ptr_t)(source)); \ |
abdbd4a8 | 1512 | } else { \ |
5a2586cf | 1513 | GC_add_to_black_list_normal(bits, (ptr_t)(source)); \ |
abdbd4a8 | 1514 | } |
73ffefd0 | 1515 | # else |
abdbd4a8 | 1516 | void GC_add_to_black_list_normal GC_PROTO((word p)); |
73ffefd0 | 1517 | # define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ |
abdbd4a8 BM |
1518 | if (GC_all_interior_pointers) { \ |
1519 | GC_add_to_black_list_stack(bits); \ | |
1520 | } else { \ | |
1521 | GC_add_to_black_list_normal(bits); \ | |
1522 | } | |
73ffefd0 TT |
1523 | # endif |
1524 | ||
abdbd4a8 BM |
1525 | # ifdef PRINT_BLACK_LIST |
1526 | void GC_add_to_black_list_stack GC_PROTO((word p, ptr_t source)); | |
1527 | # else | |
1528 | void GC_add_to_black_list_stack GC_PROTO((word p)); | |
1529 | # endif | |
1530 | struct hblk * GC_is_black_listed GC_PROTO((struct hblk * h, word len)); | |
1531 | /* If there are likely to be false references */ | |
1532 | /* to a block starting at h of the indicated */ | |
1533 | /* length, then return the next plausible */ | |
1534 | /* starting location for h that might avoid */ | |
1535 | /* these false references. */ | |
1536 | void GC_promote_black_lists GC_PROTO((void)); | |
1537 | /* Declare an end to a black listing phase. */ | |
1538 | void GC_unpromote_black_lists GC_PROTO((void)); | |
1539 | /* Approximately undo the effect of the above. */ | |
1540 | /* This actually loses some information, but */ | |
1541 | /* only in a reasonably safe way. */ | |
1542 | word GC_number_stack_black_listed GC_PROTO(( \ | |
1543 | struct hblk *start, struct hblk *endp1)); | |
1544 | /* Return the number of (stack) blacklisted */ | |
1545 | /* blocks in the range for statistical */ | |
1546 | /* purposes. */ | |
1547 | ||
1548 | ptr_t GC_scratch_alloc GC_PROTO((word bytes)); | |
1549 | /* GC internal memory allocation for */ | |
1550 | /* small objects. Deallocation is not */ | |
1551 | /* possible. */ | |
1552 | ||
73ffefd0 | 1553 | /* Heap block layout maps: */ |
abdbd4a8 BM |
1554 | void GC_invalidate_map GC_PROTO((hdr * hhdr)); |
1555 | /* Remove the object map associated */ | |
1556 | /* with the block. This identifies */ | |
1557 | /* the block as invalid to the mark */ | |
1558 | /* routines. */ | |
1559 | GC_bool GC_add_map_entry GC_PROTO((word sz)); | |
1560 | /* Add a heap block map for objects of */ | |
1561 | /* size sz to obj_map. */ | |
1562 | /* Return FALSE on failure. */ | |
1563 | void GC_register_displacement_inner GC_PROTO((word offset)); | |
1564 | /* Version of GC_register_displacement */ | |
1565 | /* that assumes lock is already held */ | |
1566 | /* and signals are already disabled. */ | |
1567 | ||
73ffefd0 | 1568 | /* hblk allocation: */ |
abdbd4a8 BM |
1569 | void GC_new_hblk GC_PROTO((word size_in_words, int kind)); |
1570 | /* Allocate a new heap block, and build */ | |
1571 | /* a free list in it. */ | |
1572 | ||
1573 | ptr_t GC_build_fl GC_PROTO((struct hblk *h, word sz, | |
1574 | GC_bool clear, ptr_t list)); | |
1575 | /* Build a free list for objects of */ | |
1576 | /* size sz in block h. Append list to */ | |
1577 | /* end of the free lists. Possibly */ | |
1578 | /* clear objects on the list. Normally */ | |
1579 | /* called by GC_new_hblk, but also */ | |
1580 | /* called explicitly without GC lock. */ | |
1581 | ||
1582 | struct hblk * GC_allochblk GC_PROTO(( \ | |
1583 | word size_in_words, int kind, unsigned flags)); | |
1584 | /* Allocate a heap block, inform */ | |
73ffefd0 TT |
1585 | /* the marker that block is valid */ |
1586 | /* for objects of indicated size. */ | |
abdbd4a8 BM |
1587 | |
1588 | ptr_t GC_alloc_large GC_PROTO((word lw, int k, unsigned flags)); | |
1589 | /* Allocate a large block of size lw words. */ | |
1590 | /* The block is not cleared. */ | |
1591 | /* Flags is 0 or IGNORE_OFF_PAGE. */ | |
1592 | /* Calls GC_allchblk to do the actual */ | |
1593 | /* allocation, but also triggers GC and/or */ | |
1594 | /* heap expansion as appropriate. */ | |
1595 | /* Does not update GC_words_allocd, but does */ | |
1596 | /* other accounting. */ | |
1597 | ||
1598 | ptr_t GC_alloc_large_and_clear GC_PROTO((word lw, int k, unsigned flags)); | |
1599 | /* As above, but clear block if appropriate */ | |
1600 | /* for kind k. */ | |
1601 | ||
1602 | void GC_freehblk GC_PROTO((struct hblk * p)); | |
1603 | /* Deallocate a heap block and mark it */ | |
1604 | /* as invalid. */ | |
1605 | ||
73ffefd0 | 1606 | /* Misc GC: */ |
abdbd4a8 BM |
1607 | void GC_init_inner GC_PROTO((void)); |
1608 | GC_bool GC_expand_hp_inner GC_PROTO((word n)); | |
1609 | void GC_start_reclaim GC_PROTO((int abort_if_found)); | |
1610 | /* Restore unmarked objects to free */ | |
1611 | /* lists, or (if abort_if_found is */ | |
1612 | /* TRUE) report them. */ | |
1613 | /* Sweeping of small object pages is */ | |
1614 | /* largely deferred. */ | |
1615 | void GC_continue_reclaim GC_PROTO((word sz, int kind)); | |
1616 | /* Sweep pages of the given size and */ | |
1617 | /* kind, as long as possible, and */ | |
1618 | /* as long as the corr. free list is */ | |
1619 | /* empty. */ | |
1620 | void GC_reclaim_or_delete_all GC_PROTO((void)); | |
1621 | /* Arrange for all reclaim lists to be */ | |
1622 | /* empty. Judiciously choose between */ | |
1623 | /* sweeping and discarding each page. */ | |
1624 | GC_bool GC_reclaim_all GC_PROTO((GC_stop_func stop_func, GC_bool ignore_old)); | |
1625 | /* Reclaim all blocks. Abort (in a */ | |
1626 | /* consistent state) if f returns TRUE. */ | |
1627 | GC_bool GC_block_empty GC_PROTO((hdr * hhdr)); | |
1628 | /* Block completely unmarked? */ | |
1629 | GC_bool GC_never_stop_func GC_PROTO((void)); | |
1630 | /* Returns FALSE. */ | |
1631 | GC_bool GC_try_to_collect_inner GC_PROTO((GC_stop_func f)); | |
1632 | ||
73ffefd0 TT |
1633 | /* Collect; caller must have acquired */ |
1634 | /* lock and disabled signals. */ | |
1635 | /* Collection is aborted if f returns */ | |
1636 | /* TRUE. Returns TRUE if it completes */ | |
1637 | /* successfully. */ | |
1638 | # define GC_gcollect_inner() \ | |
1639 | (void) GC_try_to_collect_inner(GC_never_stop_func) | |
abdbd4a8 BM |
1640 | void GC_finish_collection GC_PROTO((void)); |
1641 | /* Finish collection. Mark bits are */ | |
1642 | /* consistent and lock is still held. */ | |
1643 | GC_bool GC_collect_or_expand GC_PROTO(( \ | |
1644 | word needed_blocks, GC_bool ignore_off_page)); | |
1645 | /* Collect or expand heap in an attempt */ | |
1646 | /* make the indicated number of free */ | |
1647 | /* blocks available. Should be called */ | |
1648 | /* until the blocks are available or */ | |
1649 | /* until it fails by returning FALSE. */ | |
abdbd4a8 | 1650 | |
30c3de1f JS |
1651 | extern GC_bool GC_is_initialized; /* GC_init() has been run. */ |
1652 | ||
abdbd4a8 BM |
1653 | #if defined(MSWIN32) || defined(MSWINCE) |
1654 | void GC_deinit GC_PROTO((void)); | |
1655 | /* Free any resources allocated by */ | |
1656 | /* GC_init */ | |
1657 | #endif | |
1658 | ||
1659 | void GC_collect_a_little_inner GC_PROTO((int n)); | |
1660 | /* Do n units worth of garbage */ | |
1661 | /* collection work, if appropriate. */ | |
1662 | /* A unit is an amount appropriate for */ | |
1663 | /* HBLKSIZE bytes of allocation. */ | |
4109fe85 | 1664 | /* ptr_t GC_generic_malloc GC_PROTO((word lb, int k)); */ |
abdbd4a8 BM |
1665 | /* Allocate an object of the given */ |
1666 | /* kind. By default, there are only */ | |
1667 | /* a few kinds: composite(pointerfree), */ | |
73ffefd0 TT |
1668 | /* atomic, uncollectable, etc. */ |
1669 | /* We claim it's possible for clever */ | |
1670 | /* client code that understands GC */ | |
1671 | /* internals to add more, e.g. to */ | |
1672 | /* communicate object layout info */ | |
1673 | /* to the collector. */ | |
4109fe85 | 1674 | /* The actual decl is in gc_mark.h. */ |
abdbd4a8 BM |
1675 | ptr_t GC_generic_malloc_ignore_off_page GC_PROTO((size_t b, int k)); |
1676 | /* As above, but pointers past the */ | |
1677 | /* first page of the resulting object */ | |
1678 | /* are ignored. */ | |
1679 | ptr_t GC_generic_malloc_inner GC_PROTO((word lb, int k)); | |
1680 | /* Ditto, but I already hold lock, etc. */ | |
e5fa845c UW |
1681 | ptr_t GC_generic_malloc_words_small_inner GC_PROTO((word lw, int k)); |
1682 | /* Analogous to the above, but assumes */ | |
1683 | /* a small object size, and bypasses */ | |
1684 | /* MERGE_SIZES mechanism. */ | |
abdbd4a8 BM |
1685 | ptr_t GC_generic_malloc_words_small GC_PROTO((size_t lw, int k)); |
1686 | /* As above, but size in units of words */ | |
1687 | /* Bypasses MERGE_SIZES. Assumes */ | |
1688 | /* words <= MAXOBJSZ. */ | |
1689 | ptr_t GC_generic_malloc_inner_ignore_off_page GC_PROTO((size_t lb, int k)); | |
1690 | /* Allocate an object, where */ | |
1691 | /* the client guarantees that there */ | |
1692 | /* will always be a pointer to the */ | |
1693 | /* beginning of the object while the */ | |
1694 | /* object is live. */ | |
1695 | ptr_t GC_allocobj GC_PROTO((word sz, int kind)); | |
1696 | /* Make the indicated */ | |
1697 | /* free list nonempty, and return its */ | |
1698 | /* head. */ | |
30c3de1f JS |
1699 | |
1700 | void GC_free_inner(GC_PTR p); | |
abdbd4a8 BM |
1701 | |
1702 | void GC_init_headers GC_PROTO((void)); | |
1703 | struct hblkhdr * GC_install_header GC_PROTO((struct hblk *h)); | |
1704 | /* Install a header for block h. */ | |
1705 | /* Return 0 on failure, or the header */ | |
1706 | /* otherwise. */ | |
1707 | GC_bool GC_install_counts GC_PROTO((struct hblk * h, word sz)); | |
1708 | /* Set up forwarding counts for block */ | |
1709 | /* h of size sz. */ | |
1710 | /* Return FALSE on failure. */ | |
1711 | void GC_remove_header GC_PROTO((struct hblk * h)); | |
1712 | /* Remove the header for block h. */ | |
1713 | void GC_remove_counts GC_PROTO((struct hblk * h, word sz)); | |
1714 | /* Remove forwarding counts for h. */ | |
1715 | hdr * GC_find_header GC_PROTO((ptr_t h)); /* Debugging only. */ | |
1716 | ||
1717 | void GC_finalize GC_PROTO((void)); | |
1718 | /* Perform all indicated finalization actions */ | |
1719 | /* on unmarked objects. */ | |
1720 | /* Unreachable finalizable objects are enqueued */ | |
1721 | /* for processing by GC_invoke_finalizers. */ | |
1722 | /* Invoked with lock. */ | |
1723 | ||
1724 | void GC_notify_or_invoke_finalizers GC_PROTO((void)); | |
1725 | /* If GC_finalize_on_demand is not set, invoke */ | |
1726 | /* eligible finalizers. Otherwise: */ | |
1727 | /* Call *GC_finalizer_notifier if there are */ | |
1728 | /* finalizers to be run, and we haven't called */ | |
1729 | /* this procedure yet this GC cycle. */ | |
30c3de1f JS |
1730 | |
1731 | GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data)); | |
1732 | GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data)); | |
1733 | /* Auxiliary fns to make finalization work */ | |
1734 | /* correctly with displaced pointers introduced */ | |
1735 | /* by the debugging allocators. */ | |
abdbd4a8 BM |
1736 | |
1737 | void GC_add_to_heap GC_PROTO((struct hblk *p, word bytes)); | |
1738 | /* Add a HBLKSIZE aligned chunk to the heap. */ | |
1739 | ||
1740 | void GC_print_obj GC_PROTO((ptr_t p)); | |
1741 | /* P points to somewhere inside an object with */ | |
1742 | /* debugging info. Print a human readable */ | |
1743 | /* description of the object to stderr. */ | |
1744 | extern void (*GC_check_heap) GC_PROTO((void)); | |
1745 | /* Check that all objects in the heap with */ | |
30c3de1f JS |
1746 | /* debugging info are intact. */ |
1747 | /* Add any that are not to GC_smashed list. */ | |
1748 | extern void (*GC_print_all_smashed) GC_PROTO((void)); | |
1749 | /* Print GC_smashed if it's not empty. */ | |
1750 | /* Clear GC_smashed list. */ | |
1751 | extern void GC_print_all_errors GC_PROTO((void)); | |
1752 | /* Print smashed and leaked objects, if any. */ | |
1753 | /* Clear the lists of such objects. */ | |
abdbd4a8 BM |
1754 | extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p)); |
1755 | /* If possible print s followed by a more */ | |
1756 | /* detailed description of the object */ | |
1757 | /* referred to by p. */ | |
30c3de1f JS |
1758 | #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) |
1759 | void GC_print_address_map GC_PROTO((void)); | |
1760 | /* Print an address map of the process. */ | |
1761 | #endif | |
abdbd4a8 | 1762 | |
30c3de1f JS |
1763 | extern GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ |
1764 | /* Call error printing routine */ | |
1765 | /* occasionally. */ | |
abdbd4a8 BM |
1766 | extern GC_bool GC_print_stats; /* Produce at least some logging output */ |
1767 | /* Set from environment variable. */ | |
1768 | ||
30c3de1f JS |
1769 | #ifndef NO_DEBUGGING |
1770 | extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */ | |
1771 | # define COND_DUMP if (GC_dump_regularly) GC_dump(); | |
1772 | #else | |
1773 | # define COND_DUMP | |
1774 | #endif | |
1775 | ||
4109fe85 BM |
1776 | #ifdef KEEP_BACK_PTRS |
1777 | extern long GC_backtraces; | |
3c1cbf58 HB |
1778 | void GC_generate_random_backtrace_no_gc(void); |
1779 | #endif | |
1780 | ||
1781 | extern GC_bool GC_print_back_height; | |
1782 | ||
1783 | #ifdef MAKE_BACK_GRAPH | |
1784 | void GC_print_back_graph_stats(void); | |
4109fe85 BM |
1785 | #endif |
1786 | ||
abdbd4a8 BM |
1787 | /* Macros used for collector internal allocation. */ |
1788 | /* These assume the collector lock is held. */ | |
1789 | #ifdef DBG_HDRS_ALL | |
1790 | extern GC_PTR GC_debug_generic_malloc_inner(size_t lb, int k); | |
1791 | extern GC_PTR GC_debug_generic_malloc_inner_ignore_off_page(size_t lb, | |
1792 | int k); | |
1793 | # define GC_INTERNAL_MALLOC GC_debug_generic_malloc_inner | |
1794 | # define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \ | |
1795 | GC_debug_generic_malloc_inner_ignore_off_page | |
1796 | # ifdef THREADS | |
1797 | # define GC_INTERNAL_FREE GC_debug_free_inner | |
1798 | # else | |
1799 | # define GC_INTERNAL_FREE GC_debug_free | |
1800 | # endif | |
1801 | #else | |
1802 | # define GC_INTERNAL_MALLOC GC_generic_malloc_inner | |
1803 | # define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \ | |
1804 | GC_generic_malloc_inner_ignore_off_page | |
1805 | # ifdef THREADS | |
1806 | # define GC_INTERNAL_FREE GC_free_inner | |
1807 | # else | |
1808 | # define GC_INTERNAL_FREE GC_free | |
1809 | # endif | |
1810 | #endif | |
1811 | ||
85f29b3b TT |
1812 | /* Memory unmapping: */ |
1813 | #ifdef USE_MUNMAP | |
1814 | void GC_unmap_old(void); | |
1815 | void GC_merge_unmapped(void); | |
1816 | void GC_unmap(ptr_t start, word bytes); | |
1817 | void GC_remap(ptr_t start, word bytes); | |
1818 | void GC_unmap_gap(ptr_t start1, word bytes1, ptr_t start2, word bytes2); | |
1819 | #endif | |
1820 | ||
73ffefd0 TT |
1821 | /* Virtual dirty bit implementation: */ |
1822 | /* Each implementation exports the following: */ | |
abdbd4a8 BM |
1823 | void GC_read_dirty GC_PROTO((void)); |
1824 | /* Retrieve dirty bits. */ | |
1825 | GC_bool GC_page_was_dirty GC_PROTO((struct hblk *h)); | |
1826 | /* Read retrieved dirty bits. */ | |
1827 | GC_bool GC_page_was_ever_dirty GC_PROTO((struct hblk *h)); | |
1828 | /* Could the page contain valid heap pointers? */ | |
1829 | void GC_is_fresh GC_PROTO((struct hblk *h, word n)); | |
1830 | /* Assert the region currently contains no */ | |
1831 | /* valid pointers. */ | |
79f777fd BM |
1832 | void GC_remove_protection GC_PROTO((struct hblk *h, word nblocks, |
1833 | GC_bool pointerfree)); | |
1834 | /* h is about to be writteni or allocated. Ensure */ | |
1835 | /* that it's not write protected by the virtual */ | |
1836 | /* dirty bit implementation. */ | |
1837 | ||
abdbd4a8 BM |
1838 | void GC_dirty_init GC_PROTO((void)); |
1839 | ||
73ffefd0 | 1840 | /* Slow/general mark bit manipulation: */ |
abdbd4a8 BM |
1841 | GC_API GC_bool GC_is_marked GC_PROTO((ptr_t p)); |
1842 | void GC_clear_mark_bit GC_PROTO((ptr_t p)); | |
1843 | void GC_set_mark_bit GC_PROTO((ptr_t p)); | |
1844 | ||
73ffefd0 | 1845 | /* Stubborn objects: */ |
abdbd4a8 BM |
1846 | void GC_read_changed GC_PROTO((void)); /* Analogous to GC_read_dirty */ |
1847 | GC_bool GC_page_was_changed GC_PROTO((struct hblk * h)); | |
1848 | /* Analogous to GC_page_was_dirty */ | |
1849 | void GC_clean_changing_list GC_PROTO((void)); | |
1850 | /* Collect obsolete changing list entries */ | |
1851 | void GC_stubborn_init GC_PROTO((void)); | |
1852 | ||
73ffefd0 | 1853 | /* Debugging print routines: */ |
abdbd4a8 BM |
1854 | void GC_print_block_list GC_PROTO((void)); |
1855 | void GC_print_hblkfreelist GC_PROTO((void)); | |
1856 | void GC_print_heap_sects GC_PROTO((void)); | |
1857 | void GC_print_static_roots GC_PROTO((void)); | |
30c3de1f | 1858 | void GC_print_finalization_stats GC_PROTO((void)); |
abdbd4a8 | 1859 | void GC_dump GC_PROTO((void)); |
73ffefd0 | 1860 | |
85f29b3b TT |
1861 | #ifdef KEEP_BACK_PTRS |
1862 | void GC_store_back_pointer(ptr_t source, ptr_t dest); | |
1863 | void GC_marked_for_finalization(ptr_t dest); | |
1864 | # define GC_STORE_BACK_PTR(source, dest) GC_store_back_pointer(source, dest) | |
1865 | # define GC_MARKED_FOR_FINALIZATION(dest) GC_marked_for_finalization(dest) | |
1866 | #else | |
1867 | # define GC_STORE_BACK_PTR(source, dest) | |
1868 | # define GC_MARKED_FOR_FINALIZATION(dest) | |
1869 | #endif | |
1870 | ||
73ffefd0 TT |
1871 | /* Make arguments appear live to compiler */ |
1872 | # ifdef __WATCOMC__ | |
5a2586cf | 1873 | void GC_noop(void*, ...); |
73ffefd0 | 1874 | # else |
5a2586cf TT |
1875 | # ifdef __DMC__ |
1876 | GC_API void GC_noop(...); | |
1877 | # else | |
1878 | GC_API void GC_noop(); | |
1879 | # endif | |
73ffefd0 TT |
1880 | # endif |
1881 | ||
5a2586cf | 1882 | void GC_noop1 GC_PROTO((word)); |
73ffefd0 TT |
1883 | |
1884 | /* Logging and diagnostic output: */ | |
abdbd4a8 | 1885 | GC_API void GC_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long)); |
73ffefd0 TT |
1886 | /* A version of printf that doesn't allocate, */ |
1887 | /* is restricted to long arguments, and */ | |
1888 | /* (unfortunately) doesn't use varargs for */ | |
1889 | /* portability. Restricted to 6 args and */ | |
1890 | /* 1K total output length. */ | |
1891 | /* (We use sprintf. Hopefully that doesn't */ | |
1892 | /* allocate for long arguments.) */ | |
1893 | # define GC_printf0(f) GC_printf(f, 0l, 0l, 0l, 0l, 0l, 0l) | |
1894 | # define GC_printf1(f,a) GC_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l) | |
1895 | # define GC_printf2(f,a,b) GC_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l) | |
1896 | # define GC_printf3(f,a,b,c) GC_printf(f, (long)a, (long)b, (long)c, 0l, 0l, 0l) | |
1897 | # define GC_printf4(f,a,b,c,d) GC_printf(f, (long)a, (long)b, (long)c, \ | |
1898 | (long)d, 0l, 0l) | |
1899 | # define GC_printf5(f,a,b,c,d,e) GC_printf(f, (long)a, (long)b, (long)c, \ | |
1900 | (long)d, (long)e, 0l) | |
1901 | # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \ | |
1902 | (long)d, (long)e, (long)g) | |
1903 | ||
abdbd4a8 | 1904 | GC_API void GC_err_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long)); |
73ffefd0 TT |
1905 | # define GC_err_printf0(f) GC_err_puts(f) |
1906 | # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l) | |
1907 | # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l) | |
1908 | # define GC_err_printf3(f,a,b,c) GC_err_printf(f, (long)a, (long)b, (long)c, \ | |
1909 | 0l, 0l, 0l) | |
1910 | # define GC_err_printf4(f,a,b,c,d) GC_err_printf(f, (long)a, (long)b, \ | |
1911 | (long)c, (long)d, 0l, 0l) | |
1912 | # define GC_err_printf5(f,a,b,c,d,e) GC_err_printf(f, (long)a, (long)b, \ | |
1913 | (long)c, (long)d, \ | |
1914 | (long)e, 0l) | |
1915 | # define GC_err_printf6(f,a,b,c,d,e,g) GC_err_printf(f, (long)a, (long)b, \ | |
1916 | (long)c, (long)d, \ | |
1917 | (long)e, (long)g) | |
1918 | /* Ditto, writes to stderr. */ | |
1919 | ||
abdbd4a8 | 1920 | void GC_err_puts GC_PROTO((GC_CONST char *s)); |
73ffefd0 TT |
1921 | /* Write s to stderr, don't buffer, don't add */ |
1922 | /* newlines, don't ... */ | |
1923 | ||
abdbd4a8 BM |
1924 | #if defined(LINUX) && !defined(SMALL_CONFIG) |
1925 | void GC_err_write GC_PROTO((GC_CONST char *buf, size_t len)); | |
1926 | /* Write buf to stderr, don't buffer, don't add */ | |
1927 | /* newlines, don't ... */ | |
1928 | #endif | |
1929 | ||
73ffefd0 | 1930 | |
abdbd4a8 | 1931 | # ifdef GC_ASSERTIONS |
85f29b3b TT |
1932 | # define GC_ASSERT(expr) if(!(expr)) {\ |
1933 | GC_err_printf2("Assertion failure: %s:%ld\n", \ | |
1934 | __FILE__, (unsigned long)__LINE__); \ | |
1935 | ABORT("assertion failure"); } | |
abdbd4a8 | 1936 | # else |
85f29b3b | 1937 | # define GC_ASSERT(expr) |
abdbd4a8 BM |
1938 | # endif |
1939 | ||
30c3de1f JS |
1940 | /* Check a compile time assertion at compile time. The error */ |
1941 | /* message for failure is a bit baroque, but ... */ | |
1942 | #if defined(mips) && !defined(__GNUC__) | |
1943 | /* DOB: MIPSPro C gets an internal error taking the sizeof an array type. | |
1944 | This code works correctly (ugliness is to avoid "unused var" warnings) */ | |
1945 | # define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0) | |
1946 | #else | |
1947 | # define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1]) | |
1948 | #endif | |
1949 | ||
5a2586cf | 1950 | # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) |
abdbd4a8 BM |
1951 | /* We need additional synchronization facilities from the thread */ |
1952 | /* support. We believe these are less performance critical */ | |
1953 | /* than the main garbage collector lock; standard pthreads-based */ | |
1954 | /* implementations should be sufficient. */ | |
1955 | ||
1956 | /* The mark lock and condition variable. If the GC lock is also */ | |
1957 | /* acquired, the GC lock must be acquired first. The mark lock is */ | |
1958 | /* used to both protect some variables used by the parallel */ | |
1959 | /* marker, and to protect GC_fl_builder_count, below. */ | |
1960 | /* GC_notify_all_marker() is called when */ | |
1961 | /* the state of the parallel marker changes */ | |
1962 | /* in some significant way (see gc_mark.h for details). The */ | |
1963 | /* latter set of events includes incrementing GC_mark_no. */ | |
1964 | /* GC_notify_all_builder() is called when GC_fl_builder_count */ | |
1965 | /* reaches 0. */ | |
1966 | ||
1967 | extern void GC_acquire_mark_lock(); | |
1968 | extern void GC_release_mark_lock(); | |
abdbd4a8 | 1969 | extern void GC_notify_all_builder(); |
abdbd4a8 BM |
1970 | /* extern void GC_wait_builder(); */ |
1971 | extern void GC_wait_for_reclaim(); | |
1972 | ||
1973 | extern word GC_fl_builder_count; /* Protected by mark lock. */ | |
5a2586cf TT |
1974 | # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ |
1975 | # ifdef PARALLEL_MARK | |
1976 | extern void GC_notify_all_marker(); | |
1977 | extern void GC_wait_marker(); | |
abdbd4a8 BM |
1978 | extern word GC_mark_no; /* Protected by mark lock. */ |
1979 | ||
1980 | extern void GC_help_marker(word my_mark_no); | |
1981 | /* Try to help out parallel marker for mark cycle */ | |
1982 | /* my_mark_no. Returns if the mark cycle finishes or */ | |
1983 | /* was already done, or there was nothing to do for */ | |
1984 | /* some other reason. */ | |
1985 | # endif /* PARALLEL_MARK */ | |
85f29b3b | 1986 | |
4c7726b1 | 1987 | # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) |
5a2586cf TT |
1988 | /* We define the thread suspension signal here, so that we can refer */ |
1989 | /* to it in the dirty bit implementation, if necessary. Ideally we */ | |
1990 | /* would allocate a (real-time ?) signal using the standard mechanism.*/ | |
1991 | /* unfortunately, there is no standard mechanism. (There is one */ | |
1992 | /* in Linux glibc, but it's not exported.) Thus we continue to use */ | |
1993 | /* the same hard-coded signals we've always used. */ | |
1994 | # if !defined(SIG_SUSPEND) | |
30c3de1f | 1995 | # if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS) |
5a2586cf TT |
1996 | # if defined(SPARC) && !defined(SIGPWR) |
1997 | /* SPARC/Linux doesn't properly define SIGPWR in <signal.h>. | |
1998 | * It is aliased to SIGLOST in asm/signal.h, though. */ | |
1999 | # define SIG_SUSPEND SIGLOST | |
2000 | # else | |
4c7726b1 | 2001 | /* Linuxthreads itself uses SIGUSR1 and SIGUSR2. */ |
5a2586cf TT |
2002 | # define SIG_SUSPEND SIGPWR |
2003 | # endif | |
4c7726b1 | 2004 | # else /* !GC_LINUX_THREADS */ |
61039cd0 MM |
2005 | # if defined(_SIGRTMIN) |
2006 | # define SIG_SUSPEND _SIGRTMIN + 6 | |
2007 | # else | |
2008 | # define SIG_SUSPEND SIGRTMIN + 6 | |
2009 | # endif | |
5a2586cf TT |
2010 | # endif |
2011 | # endif /* !SIG_SUSPEND */ | |
2012 | ||
2013 | # endif | |
2014 | ||
73ffefd0 | 2015 | # endif /* GC_PRIVATE_H */ |