]> git.ipfire.org Git - thirdparty/gcc.git/blame - boehm-gc/reclaim.c
gc_ext_config.h.in: Added GC_PTHREAD_SYM_VERSION.
[thirdparty/gcc.git] / boehm-gc / reclaim.c
CommitLineData
73ffefd0
TT
1/*
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
20bbd3cd
TT
3 * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
73ffefd0
TT
6 *
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9 *
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
15 */
73ffefd0
TT
16
17#include <stdio.h>
9110a741 18#include "private/gc_priv.h"
73ffefd0
TT
19
20signed_word GC_mem_found = 0;
21 /* Number of words of memory reclaimed */
22
5a2586cf 23#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
9110a741
BM
24 word GC_fl_builder_count = 0;
25 /* Number of threads currently building free lists without */
26 /* holding GC lock. It is not safe to collect if this is */
27 /* nonzero. */
28#endif /* PARALLEL_MARK */
29
30c3de1f
JS
30/* We defer printing of leaked objects until we're done with the GC */
31/* cycle, since the routine for printing objects needs to run outside */
32/* the collector, e.g. without the allocation lock. */
33#define MAX_LEAKED 40
34ptr_t GC_leaked[MAX_LEAKED];
35unsigned GC_n_leaked = 0;
36
37GC_bool GC_have_errors = FALSE;
38
39void GC_add_leaked(leaked)
40ptr_t leaked;
73ffefd0 41{
30c3de1f
JS
42 if (GC_n_leaked < MAX_LEAKED) {
43 GC_have_errors = TRUE;
44 GC_leaked[GC_n_leaked++] = leaked;
45 /* Make sure it's not reclaimed this cycle */
46 GC_set_mark_bit(leaked);
73ffefd0 47 }
73ffefd0
TT
48}
49
30c3de1f
JS
50static GC_bool printing_errors = FALSE;
51/* Print all objects on the list after printing any smashed objs. */
52/* Clear both lists. */
53void GC_print_all_errors ()
54{
55 unsigned i;
56
57 LOCK();
58 if (printing_errors) {
59 UNLOCK();
60 return;
61 }
62 printing_errors = TRUE;
63 UNLOCK();
64 if (GC_debugging_started) GC_print_all_smashed();
65 for (i = 0; i < GC_n_leaked; ++i) {
66 ptr_t p = GC_leaked[i];
67 if (HDR(p) -> hb_obj_kind == PTRFREE) {
68 GC_err_printf0("Leaked atomic object at ");
69 } else {
70 GC_err_printf0("Leaked composite object at ");
71 }
72 GC_print_heap_obj(p);
73 GC_err_printf0("\n");
74 GC_free(p);
75 GC_leaked[i] = 0;
76 }
77 GC_n_leaked = 0;
78 printing_errors = FALSE;
79}
80
81
73ffefd0 82# define FOUND_FREE(hblk, word_no) \
20bbd3cd 83 { \
30c3de1f 84 GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
73ffefd0 85 }
73ffefd0
TT
86
87/*
88 * reclaim phase
89 *
90 */
91
92
93/*
94 * Test whether a block is completely empty, i.e. contains no marked
95 * objects. This does not require the block to be in physical
96 * memory.
97 */
98
99GC_bool GC_block_empty(hhdr)
100register hdr * hhdr;
101{
9110a741
BM
102 /* We treat hb_marks as an array of words here, even if it is */
103 /* actually an array of bytes. Since we only check for zero, there */
104 /* are no endian-ness issues. */
73ffefd0
TT
105 register word *p = (word *)(&(hhdr -> hb_marks[0]));
106 register word * plim =
9110a741 107 (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
73ffefd0
TT
108 while (p < plim) {
109 if (*p++) return(FALSE);
110 }
111 return(TRUE);
112}
113
20bbd3cd
TT
114/* The following functions sometimes return a DONT_KNOW value. */
115#define DONT_KNOW 2
116
117#ifdef SMALL_CONFIG
118# define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW
119# define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW
120# define GC_block_nearly_full(hhdr) DONT_KNOW
9110a741
BM
121#endif
122
123#if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES)
124
125# define GC_block_nearly_full1(hhdr, pat1) GC_block_nearly_full(hhdr)
126# define GC_block_nearly_full3(hhdr, pat1, pat2) GC_block_nearly_full(hhdr)
127
128
129GC_bool GC_block_nearly_full(hhdr)
130register hdr * hhdr;
131{
132 /* We again treat hb_marks as an array of words, even though it */
133 /* isn't. We first sum up all the words, resulting in a word */
134 /* containing 4 or 8 separate partial sums. */
135 /* We then sum the bytes in the word of partial sums. */
136 /* This is still endian independant. This fails if the partial */
137 /* sums can overflow. */
138# if (BYTES_TO_WORDS(MARK_BITS_SZ)) >= 256
139 --> potential overflow; fix the code
140# endif
141 register word *p = (word *)(&(hhdr -> hb_marks[0]));
142 register word * plim =
143 (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
144 word sum_vector = 0;
145 unsigned sum;
146 while (p < plim) {
147 sum_vector += *p;
148 ++p;
149 }
150 sum = 0;
151 while (sum_vector > 0) {
152 sum += sum_vector & 0xff;
153 sum_vector >>= 8;
154 }
155 return (sum > BYTES_TO_WORDS(7*HBLKSIZE/8)/(hhdr -> hb_sz));
156}
157#endif /* USE_MARK_BYTES */
158
159#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
20bbd3cd
TT
160
161/*
162 * Test whether nearly all of the mark words consist of the same
163 * repeating pattern.
164 */
165#define FULL_THRESHOLD (MARK_BITS_SZ/16)
166
167GC_bool GC_block_nearly_full1(hhdr, pat1)
168hdr *hhdr;
169word pat1;
170{
171 unsigned i;
172 unsigned misses = 0;
173 GC_ASSERT((MARK_BITS_SZ & 1) == 0);
174 for (i = 0; i < MARK_BITS_SZ; ++i) {
175 if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
176 if (++misses > FULL_THRESHOLD) return FALSE;
177 }
178 }
179 return TRUE;
180}
181
182/*
183 * Test whether the same repeating 3 word pattern occurs in nearly
184 * all the mark bit slots.
185 * This is used as a heuristic, so we're a bit sloppy and ignore
186 * the last one or two words.
187 */
188GC_bool GC_block_nearly_full3(hhdr, pat1, pat2, pat3)
189hdr *hhdr;
190word pat1, pat2, pat3;
191{
192 unsigned i;
193 unsigned misses = 0;
194
195 if (MARK_BITS_SZ < 4) {
196 return DONT_KNOW;
197 }
198 for (i = 0; i < MARK_BITS_SZ - 2; i += 3) {
199 if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
200 if (++misses > FULL_THRESHOLD) return FALSE;
201 }
202 if ((hhdr -> hb_marks[i+1] | ~pat2) != ONES) {
203 if (++misses > FULL_THRESHOLD) return FALSE;
204 }
205 if ((hhdr -> hb_marks[i+2] | ~pat3) != ONES) {
206 if (++misses > FULL_THRESHOLD) return FALSE;
207 }
208 }
209 return TRUE;
210}
211
212/* Check whether a small object block is nearly full by looking at only */
213/* the mark bits. */
214/* We manually precomputed the mark bit patterns that need to be */
215/* checked for, and we give up on the ones that are unlikely to occur, */
216/* or have period > 3. */
217/* This would be a lot easier with a mark bit per object instead of per */
218/* word, but that would rewuire computing object numbers in the mark */
219/* loop, which would require different data structures ... */
220GC_bool GC_block_nearly_full(hhdr)
221hdr *hhdr;
222{
223 int sz = hhdr -> hb_sz;
224
225# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
226 return DONT_KNOW; /* Shouldn't be used in any standard config. */
227# endif
20bbd3cd
TT
228# if CPP_WORDSZ == 32
229 switch(sz) {
230 case 1:
231 return GC_block_nearly_full1(hhdr, 0xffffffffl);
232 case 2:
233 return GC_block_nearly_full1(hhdr, 0x55555555l);
234 case 4:
235 return GC_block_nearly_full1(hhdr, 0x11111111l);
236 case 6:
237 return GC_block_nearly_full3(hhdr, 0x41041041l,
238 0x10410410l,
239 0x04104104l);
240 case 8:
241 return GC_block_nearly_full1(hhdr, 0x01010101l);
242 case 12:
243 return GC_block_nearly_full3(hhdr, 0x01001001l,
244 0x10010010l,
245 0x00100100l);
246 case 16:
247 return GC_block_nearly_full1(hhdr, 0x00010001l);
248 case 32:
249 return GC_block_nearly_full1(hhdr, 0x00000001l);
250 default:
251 return DONT_KNOW;
252 }
253# endif
254# if CPP_WORDSZ == 64
255 switch(sz) {
256 case 1:
257 return GC_block_nearly_full1(hhdr, 0xffffffffffffffffl);
258 case 2:
259 return GC_block_nearly_full1(hhdr, 0x5555555555555555l);
260 case 4:
261 return GC_block_nearly_full1(hhdr, 0x1111111111111111l);
262 case 6:
263 return GC_block_nearly_full3(hhdr, 0x1041041041041041l,
264 0x4104104104104104l,
265 0x0410410410410410l);
266 case 8:
267 return GC_block_nearly_full1(hhdr, 0x0101010101010101l);
268 case 12:
269 return GC_block_nearly_full3(hhdr, 0x1001001001001001l,
270 0x0100100100100100l,
271 0x0010010010010010l);
272 case 16:
273 return GC_block_nearly_full1(hhdr, 0x0001000100010001l);
274 case 32:
275 return GC_block_nearly_full1(hhdr, 0x0000000100000001l);
276 default:
277 return DONT_KNOW;
278 }
279# endif
280}
9110a741 281#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
20bbd3cd 282
9110a741
BM
283/* We keep track of reclaimed memory if we are either asked to, or */
284/* we are using the parallel marker. In the latter case, we assume */
285/* that most allocation goes through GC_malloc_many for scalability. */
286/* GC_malloc_many needs the count anyway. */
287# if defined(GATHERSTATS) || defined(PARALLEL_MARK)
73ffefd0 288# define INCR_WORDS(sz) n_words_found += (sz)
9110a741
BM
289# define COUNT_PARAM , count
290# define COUNT_ARG , count
291# define COUNT_DECL signed_word * count;
292# define NWORDS_DECL signed_word n_words_found = 0;
293# define COUNT_UPDATE *count += n_words_found;
294# define MEM_FOUND_ADDR , &GC_mem_found
73ffefd0
TT
295# else
296# define INCR_WORDS(sz)
9110a741
BM
297# define COUNT_PARAM
298# define COUNT_ARG
299# define COUNT_DECL
300# define NWORDS_DECL
301# define COUNT_UPDATE
302# define MEM_FOUND_ADDR
73ffefd0
TT
303# endif
304/*
305 * Restore unmarked small objects in h of size sz to the object
306 * free list. Returns the new list.
307 * Clears unmarked objects.
308 */
309/*ARGSUSED*/
9110a741 310ptr_t GC_reclaim_clear(hbp, hhdr, sz, list COUNT_PARAM)
73ffefd0
TT
311register struct hblk *hbp; /* ptr to current heap block */
312register hdr * hhdr;
73ffefd0
TT
313register ptr_t list;
314register word sz;
9110a741 315COUNT_DECL
73ffefd0
TT
316{
317 register int word_no;
318 register word *p, *q, *plim;
9110a741 319 NWORDS_DECL
73ffefd0 320
9110a741 321 GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
73ffefd0 322 p = (word *)(hbp->hb_body);
9110a741 323 word_no = 0;
73ffefd0
TT
324 plim = (word *)((((word)hbp) + HBLKSIZE)
325 - WORDS_TO_BYTES(sz));
326
327 /* go through all words in block */
328 while( p <= plim ) {
329 if( mark_bit_from_hdr(hhdr, word_no) ) {
330 p += sz;
331 } else {
73ffefd0
TT
332 INCR_WORDS(sz);
333 /* object is available - put on list */
334 obj_link(p) = list;
335 list = ((ptr_t)p);
336 /* Clear object, advance p to next object in the process */
337 q = p + sz;
9110a741
BM
338# ifdef USE_MARK_BYTES
339 GC_ASSERT(!(sz & 1)
340 && !((word)p & (2 * sizeof(word) - 1)));
341 p[1] = 0;
342 p += 2;
343 while (p < q) {
344 CLEAR_DOUBLE(p);
345 p += 2;
346 }
347# else
348 p++; /* Skip link field */
349 while (p < q) {
73ffefd0 350 *p++ = 0;
9110a741
BM
351 }
352# endif
73ffefd0
TT
353 }
354 word_no += sz;
355 }
9110a741 356 COUNT_UPDATE
73ffefd0
TT
357 return(list);
358}
359
9110a741 360#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
73ffefd0
TT
361
362/*
363 * A special case for 2 word composite objects (e.g. cons cells):
364 */
365/*ARGSUSED*/
9110a741 366ptr_t GC_reclaim_clear2(hbp, hhdr, list COUNT_PARAM)
73ffefd0
TT
367register struct hblk *hbp; /* ptr to current heap block */
368hdr * hhdr;
73ffefd0 369register ptr_t list;
9110a741 370COUNT_DECL
73ffefd0 371{
9110a741 372 register word * mark_word_addr = &(hhdr->hb_marks[0]);
73ffefd0 373 register word *p, *plim;
73ffefd0
TT
374 register word mark_word;
375 register int i;
9110a741 376 NWORDS_DECL
73ffefd0
TT
377# define DO_OBJ(start_displ) \
378 if (!(mark_word & ((word)1 << start_displ))) { \
73ffefd0
TT
379 p[start_displ] = (word)list; \
380 list = (ptr_t)(p+start_displ); \
381 p[start_displ+1] = 0; \
382 INCR_WORDS(2); \
383 }
384
385 p = (word *)(hbp->hb_body);
386 plim = (word *)(((word)hbp) + HBLKSIZE);
387
388 /* go through all words in block */
389 while( p < plim ) {
390 mark_word = *mark_word_addr++;
391 for (i = 0; i < WORDSZ; i += 8) {
392 DO_OBJ(0);
393 DO_OBJ(2);
394 DO_OBJ(4);
395 DO_OBJ(6);
396 p += 8;
397 mark_word >>= 8;
398 }
399 }
9110a741 400 COUNT_UPDATE
73ffefd0
TT
401 return(list);
402# undef DO_OBJ
403}
404
405/*
406 * Another special case for 4 word composite objects:
407 */
408/*ARGSUSED*/
9110a741 409ptr_t GC_reclaim_clear4(hbp, hhdr, list COUNT_PARAM)
73ffefd0
TT
410register struct hblk *hbp; /* ptr to current heap block */
411hdr * hhdr;
73ffefd0 412register ptr_t list;
9110a741 413COUNT_DECL
73ffefd0 414{
9110a741 415 register word * mark_word_addr = &(hhdr->hb_marks[0]);
73ffefd0 416 register word *p, *plim;
73ffefd0 417 register word mark_word;
9110a741 418 NWORDS_DECL
73ffefd0
TT
419# define DO_OBJ(start_displ) \
420 if (!(mark_word & ((word)1 << start_displ))) { \
73ffefd0
TT
421 p[start_displ] = (word)list; \
422 list = (ptr_t)(p+start_displ); \
423 p[start_displ+1] = 0; \
93002327 424 CLEAR_DOUBLE(p + start_displ + 2); \
73ffefd0
TT
425 INCR_WORDS(4); \
426 }
427
428 p = (word *)(hbp->hb_body);
429 plim = (word *)(((word)hbp) + HBLKSIZE);
430
431 /* go through all words in block */
432 while( p < plim ) {
433 mark_word = *mark_word_addr++;
434 DO_OBJ(0);
435 DO_OBJ(4);
436 DO_OBJ(8);
437 DO_OBJ(12);
438 DO_OBJ(16);
439 DO_OBJ(20);
440 DO_OBJ(24);
441 DO_OBJ(28);
442# if CPP_WORDSZ == 64
443 DO_OBJ(32);
444 DO_OBJ(36);
445 DO_OBJ(40);
446 DO_OBJ(44);
447 DO_OBJ(48);
448 DO_OBJ(52);
449 DO_OBJ(56);
450 DO_OBJ(60);
451# endif
452 p += WORDSZ;
453 }
9110a741 454 COUNT_UPDATE
73ffefd0
TT
455 return(list);
456# undef DO_OBJ
457}
458
9110a741 459#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
73ffefd0
TT
460
461/* The same thing, but don't clear objects: */
462/*ARGSUSED*/
9110a741 463ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_PARAM)
73ffefd0
TT
464register struct hblk *hbp; /* ptr to current heap block */
465register hdr * hhdr;
73ffefd0
TT
466register ptr_t list;
467register word sz;
9110a741 468COUNT_DECL
73ffefd0 469{
9110a741 470 register int word_no = 0;
73ffefd0 471 register word *p, *plim;
9110a741 472 NWORDS_DECL
73ffefd0
TT
473
474 p = (word *)(hbp->hb_body);
73ffefd0
TT
475 plim = (word *)((((word)hbp) + HBLKSIZE)
476 - WORDS_TO_BYTES(sz));
477
478 /* go through all words in block */
479 while( p <= plim ) {
480 if( !mark_bit_from_hdr(hhdr, word_no) ) {
73ffefd0
TT
481 INCR_WORDS(sz);
482 /* object is available - put on list */
483 obj_link(p) = list;
484 list = ((ptr_t)p);
485 }
486 p += sz;
487 word_no += sz;
488 }
9110a741 489 COUNT_UPDATE
73ffefd0
TT
490 return(list);
491}
492
20bbd3cd
TT
493/* Don't really reclaim objects, just check for unmarked ones: */
494/*ARGSUSED*/
495void GC_reclaim_check(hbp, hhdr, sz)
496register struct hblk *hbp; /* ptr to current heap block */
497register hdr * hhdr;
498register word sz;
499{
9110a741 500 register int word_no = 0;
20bbd3cd
TT
501 register word *p, *plim;
502# ifdef GATHERSTATS
503 register int n_words_found = 0;
504# endif
505
506 p = (word *)(hbp->hb_body);
20bbd3cd
TT
507 plim = (word *)((((word)hbp) + HBLKSIZE)
508 - WORDS_TO_BYTES(sz));
509
510 /* go through all words in block */
511 while( p <= plim ) {
512 if( !mark_bit_from_hdr(hhdr, word_no) ) {
513 FOUND_FREE(hbp, word_no);
514 }
515 p += sz;
516 word_no += sz;
517 }
518}
519
9110a741 520#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
73ffefd0
TT
521/*
522 * Another special case for 2 word atomic objects:
523 */
524/*ARGSUSED*/
9110a741 525ptr_t GC_reclaim_uninit2(hbp, hhdr, list COUNT_PARAM)
73ffefd0
TT
526register struct hblk *hbp; /* ptr to current heap block */
527hdr * hhdr;
73ffefd0 528register ptr_t list;
9110a741 529COUNT_DECL
73ffefd0 530{
9110a741 531 register word * mark_word_addr = &(hhdr->hb_marks[0]);
73ffefd0 532 register word *p, *plim;
73ffefd0
TT
533 register word mark_word;
534 register int i;
9110a741 535 NWORDS_DECL
73ffefd0
TT
536# define DO_OBJ(start_displ) \
537 if (!(mark_word & ((word)1 << start_displ))) { \
73ffefd0
TT
538 p[start_displ] = (word)list; \
539 list = (ptr_t)(p+start_displ); \
540 INCR_WORDS(2); \
541 }
542
543 p = (word *)(hbp->hb_body);
544 plim = (word *)(((word)hbp) + HBLKSIZE);
545
546 /* go through all words in block */
547 while( p < plim ) {
548 mark_word = *mark_word_addr++;
549 for (i = 0; i < WORDSZ; i += 8) {
550 DO_OBJ(0);
551 DO_OBJ(2);
552 DO_OBJ(4);
553 DO_OBJ(6);
554 p += 8;
555 mark_word >>= 8;
556 }
557 }
9110a741 558 COUNT_UPDATE
73ffefd0
TT
559 return(list);
560# undef DO_OBJ
561}
562
563/*
564 * Another special case for 4 word atomic objects:
565 */
566/*ARGSUSED*/
9110a741 567ptr_t GC_reclaim_uninit4(hbp, hhdr, list COUNT_PARAM)
73ffefd0
TT
568register struct hblk *hbp; /* ptr to current heap block */
569hdr * hhdr;
73ffefd0 570register ptr_t list;
9110a741 571COUNT_DECL
73ffefd0 572{
9110a741 573 register word * mark_word_addr = &(hhdr->hb_marks[0]);
73ffefd0 574 register word *p, *plim;
73ffefd0 575 register word mark_word;
9110a741 576 NWORDS_DECL
73ffefd0
TT
577# define DO_OBJ(start_displ) \
578 if (!(mark_word & ((word)1 << start_displ))) { \
73ffefd0
TT
579 p[start_displ] = (word)list; \
580 list = (ptr_t)(p+start_displ); \
581 INCR_WORDS(4); \
582 }
583
584 p = (word *)(hbp->hb_body);
585 plim = (word *)(((word)hbp) + HBLKSIZE);
586
587 /* go through all words in block */
588 while( p < plim ) {
589 mark_word = *mark_word_addr++;
590 DO_OBJ(0);
591 DO_OBJ(4);
592 DO_OBJ(8);
593 DO_OBJ(12);
594 DO_OBJ(16);
595 DO_OBJ(20);
596 DO_OBJ(24);
597 DO_OBJ(28);
598# if CPP_WORDSZ == 64
599 DO_OBJ(32);
600 DO_OBJ(36);
601 DO_OBJ(40);
602 DO_OBJ(44);
603 DO_OBJ(48);
604 DO_OBJ(52);
605 DO_OBJ(56);
606 DO_OBJ(60);
607# endif
608 p += WORDSZ;
609 }
9110a741 610 COUNT_UPDATE
73ffefd0
TT
611 return(list);
612# undef DO_OBJ
613}
614
615/* Finally the one word case, which never requires any clearing: */
616/*ARGSUSED*/
9110a741 617ptr_t GC_reclaim1(hbp, hhdr, list COUNT_PARAM)
73ffefd0
TT
618register struct hblk *hbp; /* ptr to current heap block */
619hdr * hhdr;
73ffefd0 620register ptr_t list;
9110a741 621COUNT_DECL
73ffefd0 622{
9110a741 623 register word * mark_word_addr = &(hhdr->hb_marks[0]);
73ffefd0 624 register word *p, *plim;
73ffefd0
TT
625 register word mark_word;
626 register int i;
9110a741 627 NWORDS_DECL
73ffefd0
TT
628# define DO_OBJ(start_displ) \
629 if (!(mark_word & ((word)1 << start_displ))) { \
73ffefd0
TT
630 p[start_displ] = (word)list; \
631 list = (ptr_t)(p+start_displ); \
632 INCR_WORDS(1); \
633 }
634
635 p = (word *)(hbp->hb_body);
636 plim = (word *)(((word)hbp) + HBLKSIZE);
637
638 /* go through all words in block */
639 while( p < plim ) {
640 mark_word = *mark_word_addr++;
641 for (i = 0; i < WORDSZ; i += 4) {
642 DO_OBJ(0);
643 DO_OBJ(1);
644 DO_OBJ(2);
645 DO_OBJ(3);
646 p += 4;
647 mark_word >>= 4;
648 }
649 }
9110a741 650 COUNT_UPDATE
73ffefd0
TT
651 return(list);
652# undef DO_OBJ
653}
654
9110a741 655#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
73ffefd0
TT
656
657/*
9110a741
BM
658 * Generic procedure to rebuild a free list in hbp.
659 * Also called directly from GC_malloc_many.
73ffefd0 660 */
9110a741
BM
661ptr_t GC_reclaim_generic(hbp, hhdr, sz, init, list COUNT_PARAM)
662struct hblk *hbp; /* ptr to current heap block */
663hdr * hhdr;
664GC_bool init;
665ptr_t list;
666word sz;
667COUNT_DECL
73ffefd0 668{
9110a741 669 ptr_t result = list;
73ffefd0 670
9110a741 671 GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
79f777fd 672 GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
9110a741 673 if (init) {
73ffefd0 674 switch(sz) {
9110a741 675# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
73ffefd0 676 case 1:
9110a741
BM
677 /* We now issue the hint even if GC_nearly_full returned */
678 /* DONT_KNOW. */
9110a741 679 result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
73ffefd0
TT
680 break;
681 case 2:
9110a741 682 result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG);
73ffefd0
TT
683 break;
684 case 4:
9110a741 685 result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG);
73ffefd0 686 break;
9110a741 687# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
73ffefd0 688 default:
9110a741 689 result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG);
73ffefd0
TT
690 break;
691 }
692 } else {
79f777fd 693 GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
73ffefd0 694 switch(sz) {
9110a741 695# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
73ffefd0 696 case 1:
9110a741 697 result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
73ffefd0
TT
698 break;
699 case 2:
9110a741 700 result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG);
73ffefd0
TT
701 break;
702 case 4:
9110a741 703 result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG);
73ffefd0 704 break;
9110a741 705# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
73ffefd0 706 default:
9110a741 707 result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG);
73ffefd0
TT
708 break;
709 }
710 }
9110a741
BM
711 if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);
712 return result;
713}
714
715/*
716 * Restore unmarked small objects in the block pointed to by hbp
717 * to the appropriate object free list.
718 * If entirely empty blocks are to be completely deallocated, then
719 * caller should perform that check.
720 */
721void GC_reclaim_small_nonempty_block(hbp, report_if_found COUNT_PARAM)
722register struct hblk *hbp; /* ptr to current heap block */
723int report_if_found; /* Abort if a reclaimable object is found */
724COUNT_DECL
725{
726 hdr *hhdr = HDR(hbp);
727 word sz = hhdr -> hb_sz;
728 int kind = hhdr -> hb_obj_kind;
729 struct obj_kind * ok = &GC_obj_kinds[kind];
730 ptr_t * flh = &(ok -> ok_freelist[sz]);
731
732 hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
733
734 if (report_if_found) {
735 GC_reclaim_check(hbp, hhdr, sz);
736 } else {
4c7726b1
BM
737 *flh = GC_reclaim_generic(hbp, hhdr, sz,
738 (ok -> ok_init || GC_debugging_started),
9110a741
BM
739 *flh MEM_FOUND_ADDR);
740 }
73ffefd0
TT
741}
742
743/*
744 * Restore an unmarked large object or an entirely empty blocks of small objects
745 * to the heap block free list.
746 * Otherwise enqueue the block for later processing
747 * by GC_reclaim_small_nonempty_block.
20bbd3cd
TT
748 * If report_if_found is TRUE, then process any block immediately, and
749 * simply report free objects; do not actually reclaim them.
73ffefd0 750 */
9110a741
BM
751# if defined(__STDC__) || defined(__cplusplus)
752 void GC_reclaim_block(register struct hblk *hbp, word report_if_found)
753# else
754 void GC_reclaim_block(hbp, report_if_found)
755 register struct hblk *hbp; /* ptr to current heap block */
756 word report_if_found; /* Abort if a reclaimable object is found */
757# endif
73ffefd0
TT
758{
759 register hdr * hhdr;
760 register word sz; /* size of objects in current block */
761 register struct obj_kind * ok;
762 struct hblk ** rlh;
763
764 hhdr = HDR(hbp);
765 sz = hhdr -> hb_sz;
766 ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
767
768 if( sz > MAXOBJSZ ) { /* 1 big object */
9110a741 769 if( !mark_bit_from_hdr(hhdr, 0) ) {
20bbd3cd 770 if (report_if_found) {
9110a741 771 FOUND_FREE(hbp, 0);
20bbd3cd 772 } else {
9110a741
BM
773 word blocks = OBJ_SZ_TO_BLOCKS(sz);
774 if (blocks > 1) {
775 GC_large_allocd_bytes -= blocks * HBLKSIZE;
776 }
20bbd3cd 777# ifdef GATHERSTATS
73ffefd0 778 GC_mem_found += sz;
20bbd3cd
TT
779# endif
780 GC_freehblk(hbp);
781 }
73ffefd0
TT
782 }
783 } else {
784 GC_bool empty = GC_block_empty(hhdr);
20bbd3cd 785 if (report_if_found) {
9110a741
BM
786 GC_reclaim_small_nonempty_block(hbp, (int)report_if_found
787 MEM_FOUND_ADDR);
73ffefd0
TT
788 } else if (empty) {
789# ifdef GATHERSTATS
790 GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
791# endif
792 GC_freehblk(hbp);
9110a741 793 } else if (TRUE != GC_block_nearly_full(hhdr)){
73ffefd0
TT
794 /* group of smaller objects, enqueue the real work */
795 rlh = &(ok -> ok_reclaim_list[sz]);
796 hhdr -> hb_next = *rlh;
797 *rlh = hbp;
9110a741
BM
798 } /* else not worth salvaging. */
799 /* We used to do the nearly_full check later, but we */
800 /* already have the right cache context here. Also */
801 /* doing it here avoids some silly lock contention in */
802 /* GC_malloc_many. */
73ffefd0
TT
803 }
804}
805
806#if !defined(NO_DEBUGGING)
807/* Routines to gather and print heap block info */
808/* intended for debugging. Otherwise should be called */
809/* with lock. */
4c7726b1
BM
810
811struct Print_stats
812{
813 size_t number_of_blocks;
814 size_t total_bytes;
815};
73ffefd0 816
9110a741
BM
817#ifdef USE_MARK_BYTES
818
819/* Return the number of set mark bits in the given header */
820int GC_n_set_marks(hhdr)
821hdr * hhdr;
822{
823 register int result = 0;
824 register int i;
825
826 for (i = 0; i < MARK_BITS_SZ; i++) {
827 result += hhdr -> hb_marks[i];
828 }
829 return(result);
830}
831
832#else
833
73ffefd0
TT
834/* Number of set bits in a word. Not performance critical. */
835static int set_bits(n)
836word n;
837{
838 register word m = n;
839 register int result = 0;
840
841 while (m > 0) {
842 if (m & 1) result++;
843 m >>= 1;
844 }
845 return(result);
846}
847
848/* Return the number of set mark bits in the given header */
849int GC_n_set_marks(hhdr)
850hdr * hhdr;
851{
852 register int result = 0;
853 register int i;
854
855 for (i = 0; i < MARK_BITS_SZ; i++) {
856 result += set_bits(hhdr -> hb_marks[i]);
857 }
858 return(result);
859}
860
9110a741
BM
861#endif /* !USE_MARK_BYTES */
862
73ffefd0 863/*ARGSUSED*/
9110a741
BM
864# if defined(__STDC__) || defined(__cplusplus)
865 void GC_print_block_descr(struct hblk *h, word dummy)
866# else
867 void GC_print_block_descr(h, dummy)
868 struct hblk *h;
869 word dummy;
870# endif
73ffefd0
TT
871{
872 register hdr * hhdr = HDR(h);
873 register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
4c7726b1 874 struct Print_stats *ps;
73ffefd0
TT
875
876 GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),
877 (unsigned long)bytes,
878 (unsigned long)(GC_n_set_marks(hhdr)));
9110a741 879 bytes += HBLKSIZE-1;
73ffefd0 880 bytes &= ~(HBLKSIZE-1);
4c7726b1
BM
881
882 ps = (struct Print_stats *)dummy;
883 ps->total_bytes += bytes;
884 ps->number_of_blocks++;
73ffefd0
TT
885}
886
887void GC_print_block_list()
888{
4c7726b1
BM
889 struct Print_stats pstats;
890
54f28c21 891 GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN);
4c7726b1
BM
892 pstats.number_of_blocks = 0;
893 pstats.total_bytes = 0;
894 GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
73ffefd0 895 GC_printf2("\nblocks = %lu, bytes = %lu\n",
4c7726b1
BM
896 (unsigned long)pstats.number_of_blocks,
897 (unsigned long)pstats.total_bytes);
73ffefd0
TT
898}
899
900#endif /* NO_DEBUGGING */
901
4d6ac542
HB
902/*
903 * Clear all obj_link pointers in the list of free objects *flp.
904 * Clear *flp.
905 * This must be done before dropping a list of free gcj-style objects,
906 * since may otherwise end up with dangling "descriptor" pointers.
30c3de1f 907 * It may help for other pointer-containing objects.
4d6ac542
HB
908 */
909void GC_clear_fl_links(flp)
910ptr_t *flp;
911{
912 ptr_t next = *flp;
913
914 while (0 != next) {
915 *flp = 0;
916 flp = &(obj_link(next));
917 next = *flp;
918 }
919}
920
73ffefd0 921/*
20bbd3cd
TT
922 * Perform GC_reclaim_block on the entire heap, after first clearing
923 * small object free lists (if we are not just looking for leaks).
73ffefd0 924 */
20bbd3cd
TT
925void GC_start_reclaim(report_if_found)
926int report_if_found; /* Abort if a GC_reclaimable object is found */
73ffefd0
TT
927{
928 int kind;
929
5a2586cf
TT
930# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
931 GC_ASSERT(0 == GC_fl_builder_count);
932# endif
73ffefd0
TT
933 /* Clear reclaim- and free-lists */
934 for (kind = 0; kind < GC_n_kinds; kind++) {
4d6ac542
HB
935 ptr_t *fop;
936 ptr_t *lim;
937 struct hblk ** rlp;
938 struct hblk ** rlim;
939 struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
940 GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0);
73ffefd0
TT
941
942 if (rlist == 0) continue; /* This kind not used. */
20bbd3cd 943 if (!report_if_found) {
73ffefd0
TT
944 lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
945 for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
4d6ac542
HB
946 if (*fop != 0) {
947 if (should_clobber) {
948 GC_clear_fl_links(fop);
949 } else {
950 *fop = 0;
951 }
952 }
73ffefd0
TT
953 }
954 } /* otherwise free list objects are marked, */
955 /* and its safe to leave them */
956 rlim = rlist + MAXOBJSZ+1;
957 for( rlp = rlist; rlp < rlim; rlp++ ) {
958 *rlp = 0;
959 }
960 }
961
962# ifdef PRINTBLOCKS
963 GC_printf0("GC_reclaim: current block sizes:\n");
964 GC_print_block_list();
965# endif
966
967 /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
968 /* or enqueue the block for later processing. */
20bbd3cd 969 GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
93002327
BM
970
971# ifdef EAGER_SWEEP
972 /* This is a very stupid thing to do. We make it possible anyway, */
973 /* so that you can convince yourself that it really is very stupid. */
974 GC_reclaim_all((GC_stop_func)0, FALSE);
975# endif
5a2586cf
TT
976# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
977 GC_ASSERT(0 == GC_fl_builder_count);
978# endif
73ffefd0
TT
979
980}
981
982/*
983 * Sweep blocks of the indicated object size and kind until either the
984 * appropriate free list is nonempty, or there are no more blocks to
985 * sweep.
986 */
987void GC_continue_reclaim(sz, kind)
988word sz; /* words */
989int kind;
990{
991 register hdr * hhdr;
992 register struct hblk * hbp;
993 register struct obj_kind * ok = &(GC_obj_kinds[kind]);
994 struct hblk ** rlh = ok -> ok_reclaim_list;
995 ptr_t *flh = &(ok -> ok_freelist[sz]);
996
997 if (rlh == 0) return; /* No blocks of this kind. */
998 rlh += sz;
999 while ((hbp = *rlh) != 0) {
1000 hhdr = HDR(hbp);
1001 *rlh = hhdr -> hb_next;
9110a741 1002 GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
73ffefd0
TT
1003 if (*flh != 0) break;
1004 }
1005}
1006
1007/*
1008 * Reclaim all small blocks waiting to be reclaimed.
1009 * Abort and return FALSE when/if (*stop_func)() returns TRUE.
1010 * If this returns TRUE, then it's safe to restart the world
1011 * with incorrectly cleared mark bits.
93002327 1012 * If ignore_old is TRUE, then reclaim only blocks that have been
73ffefd0
TT
1013 * recently reclaimed, and discard the rest.
1014 * Stop_func may be 0.
1015 */
1016GC_bool GC_reclaim_all(stop_func, ignore_old)
1017GC_stop_func stop_func;
1018GC_bool ignore_old;
1019{
1020 register word sz;
1021 register int kind;
1022 register hdr * hhdr;
1023 register struct hblk * hbp;
1024 register struct obj_kind * ok;
1025 struct hblk ** rlp;
1026 struct hblk ** rlh;
1027# ifdef PRINTTIMES
1028 CLOCK_TYPE start_time;
1029 CLOCK_TYPE done_time;
1030
1031 GET_TIME(start_time);
1032# endif
1033
1034 for (kind = 0; kind < GC_n_kinds; kind++) {
1035 ok = &(GC_obj_kinds[kind]);
1036 rlp = ok -> ok_reclaim_list;
1037 if (rlp == 0) continue;
1038 for (sz = 1; sz <= MAXOBJSZ; sz++) {
1039 rlh = rlp + sz;
1040 while ((hbp = *rlh) != 0) {
1041 if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
1042 return(FALSE);
1043 }
1044 hhdr = HDR(hbp);
1045 *rlh = hhdr -> hb_next;
1046 if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
1047 /* It's likely we'll need it this time, too */
1048 /* It's been touched recently, so this */
1049 /* shouldn't trigger paging. */
9110a741 1050 GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
73ffefd0
TT
1051 }
1052 }
1053 }
1054 }
1055# ifdef PRINTTIMES
1056 GET_TIME(done_time);
1057 GC_printf1("Disposing of reclaim lists took %lu msecs\n",
1058 MS_TIME_DIFF(done_time,start_time));
1059# endif
1060 return(TRUE);
1061}