OSDN Git Service

boehm-gc/
[pf3gnuchains/gcc-fork.git] / boehm-gc / reclaim.c
1 /* 
2  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
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.
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  */
16
17 #include <stdio.h>
18 #include "private/gc_priv.h"
19
20 signed_word GC_mem_found = 0;
21                         /* Number of words of memory reclaimed     */
22
23 #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
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
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
34 ptr_t GC_leaked[MAX_LEAKED];
35 unsigned GC_n_leaked = 0;
36
37 GC_bool GC_have_errors = FALSE;
38
39 void GC_add_leaked(leaked)
40 ptr_t leaked;
41 {
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);
47     }
48 }
49
50 static GC_bool printing_errors = FALSE;
51 /* Print all objects on the list after printing any smashed objs.       */
52 /* Clear both lists.                                                    */
53 void 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
82 #   define FOUND_FREE(hblk, word_no) \
83       { \
84          GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
85       }
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  
99 GC_bool GC_block_empty(hhdr)
100 register hdr * hhdr;
101 {
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.                                       */
105     register word *p = (word *)(&(hhdr -> hb_marks[0]));
106     register word * plim =
107             (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
108     while (p < plim) {
109         if (*p++) return(FALSE);
110     }
111     return(TRUE);
112 }
113
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
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  
129 GC_bool GC_block_nearly_full(hhdr)
130 register 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)
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
167 GC_bool GC_block_nearly_full1(hhdr, pat1)
168 hdr *hhdr;
169 word 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  */
188 GC_bool GC_block_nearly_full3(hhdr, pat1, pat2, pat3)
189 hdr *hhdr;
190 word 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 ...              */
220 GC_bool GC_block_nearly_full(hhdr)
221 hdr *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
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 }
281 #endif /* !SMALL_CONFIG  && !USE_MARK_BYTES */
282
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)
288 #   define INCR_WORDS(sz) n_words_found += (sz)
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
295 # else
296 #   define INCR_WORDS(sz)
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
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*/
310 ptr_t GC_reclaim_clear(hbp, hhdr, sz, list COUNT_PARAM)
311 register struct hblk *hbp;      /* ptr to current heap block            */
312 register hdr * hhdr;
313 register ptr_t list;
314 register word sz;
315 COUNT_DECL
316 {
317     register int word_no;
318     register word *p, *q, *plim;
319     NWORDS_DECL
320     
321     GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
322     p = (word *)(hbp->hb_body);
323     word_no = 0;
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 {
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;
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) {
350                         *p++ = 0;
351                       }
352 #                   endif
353             }
354             word_no += sz;
355         }
356     COUNT_UPDATE
357     return(list);
358 }
359
360 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
361
362 /*
363  * A special case for 2 word composite objects (e.g. cons cells):
364  */
365 /*ARGSUSED*/
366 ptr_t GC_reclaim_clear2(hbp, hhdr, list COUNT_PARAM)
367 register struct hblk *hbp;      /* ptr to current heap block            */
368 hdr * hhdr;
369 register ptr_t list;
370 COUNT_DECL
371 {
372     register word * mark_word_addr = &(hhdr->hb_marks[0]);
373     register word *p, *plim;
374     register word mark_word;
375     register int i;
376     NWORDS_DECL
377 #   define DO_OBJ(start_displ) \
378         if (!(mark_word & ((word)1 << start_displ))) { \
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         }               
400     COUNT_UPDATE
401     return(list);
402 #   undef DO_OBJ
403 }
404
405 /*
406  * Another special case for 4 word composite objects:
407  */
408 /*ARGSUSED*/
409 ptr_t GC_reclaim_clear4(hbp, hhdr, list COUNT_PARAM)
410 register struct hblk *hbp;      /* ptr to current heap block            */
411 hdr * hhdr;
412 register ptr_t list;
413 COUNT_DECL
414 {
415     register word * mark_word_addr = &(hhdr->hb_marks[0]);
416     register word *p, *plim;
417     register word mark_word;
418     NWORDS_DECL
419 #   define DO_OBJ(start_displ) \
420         if (!(mark_word & ((word)1 << start_displ))) { \
421             p[start_displ] = (word)list; \
422             list = (ptr_t)(p+start_displ); \
423             p[start_displ+1] = 0; \
424             CLEAR_DOUBLE(p + start_displ + 2); \
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         }               
454     COUNT_UPDATE
455     return(list);
456 #   undef DO_OBJ
457 }
458
459 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
460
461 /* The same thing, but don't clear objects: */
462 /*ARGSUSED*/
463 ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_PARAM)
464 register struct hblk *hbp;      /* ptr to current heap block            */
465 register hdr * hhdr;
466 register ptr_t list;
467 register word sz;
468 COUNT_DECL
469 {
470     register int word_no = 0;
471     register word *p, *plim;
472     NWORDS_DECL
473     
474     p = (word *)(hbp->hb_body);
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) ) {
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         }
489     COUNT_UPDATE
490     return(list);
491 }
492
493 /* Don't really reclaim objects, just check for unmarked ones: */
494 /*ARGSUSED*/
495 void GC_reclaim_check(hbp, hhdr, sz)
496 register struct hblk *hbp;      /* ptr to current heap block            */
497 register hdr * hhdr;
498 register word sz;
499 {
500     register int word_no = 0;
501     register word *p, *plim;
502 #   ifdef GATHERSTATS
503         register int n_words_found = 0;
504 #   endif
505     
506     p = (word *)(hbp->hb_body);
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
520 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
521 /*
522  * Another special case for 2 word atomic objects:
523  */
524 /*ARGSUSED*/
525 ptr_t GC_reclaim_uninit2(hbp, hhdr, list COUNT_PARAM)
526 register struct hblk *hbp;      /* ptr to current heap block            */
527 hdr * hhdr;
528 register ptr_t list;
529 COUNT_DECL
530 {
531     register word * mark_word_addr = &(hhdr->hb_marks[0]);
532     register word *p, *plim;
533     register word mark_word;
534     register int i;
535     NWORDS_DECL
536 #   define DO_OBJ(start_displ) \
537         if (!(mark_word & ((word)1 << start_displ))) { \
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         }               
558     COUNT_UPDATE
559     return(list);
560 #   undef DO_OBJ
561 }
562
563 /*
564  * Another special case for 4 word atomic objects:
565  */
566 /*ARGSUSED*/
567 ptr_t GC_reclaim_uninit4(hbp, hhdr, list COUNT_PARAM)
568 register struct hblk *hbp;      /* ptr to current heap block            */
569 hdr * hhdr;
570 register ptr_t list;
571 COUNT_DECL
572 {
573     register word * mark_word_addr = &(hhdr->hb_marks[0]);
574     register word *p, *plim;
575     register word mark_word;
576     NWORDS_DECL
577 #   define DO_OBJ(start_displ) \
578         if (!(mark_word & ((word)1 << start_displ))) { \
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         }               
610     COUNT_UPDATE
611     return(list);
612 #   undef DO_OBJ
613 }
614
615 /* Finally the one word case, which never requires any clearing: */
616 /*ARGSUSED*/
617 ptr_t GC_reclaim1(hbp, hhdr, list COUNT_PARAM)
618 register struct hblk *hbp;      /* ptr to current heap block            */
619 hdr * hhdr;
620 register ptr_t list;
621 COUNT_DECL
622 {
623     register word * mark_word_addr = &(hhdr->hb_marks[0]);
624     register word *p, *plim;
625     register word mark_word;
626     register int i;
627     NWORDS_DECL
628 #   define DO_OBJ(start_displ) \
629         if (!(mark_word & ((word)1 << start_displ))) { \
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         }               
650     COUNT_UPDATE
651     return(list);
652 #   undef DO_OBJ
653 }
654
655 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
656
657 /*
658  * Generic procedure to rebuild a free list in hbp.
659  * Also called directly from GC_malloc_many.
660  */
661 ptr_t GC_reclaim_generic(hbp, hhdr, sz, init, list COUNT_PARAM)
662 struct hblk *hbp;       /* ptr to current heap block            */
663 hdr * hhdr;
664 GC_bool init;
665 ptr_t list;
666 word sz;
667 COUNT_DECL
668 {
669     ptr_t result = list;
670
671     GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
672     GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
673     if (init) {
674       switch(sz) {
675 #      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
676         case 1:
677             /* We now issue the hint even if GC_nearly_full returned    */
678             /* DONT_KNOW.                                               */
679             result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
680             break;
681         case 2:
682             result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG);
683             break;
684         case 4:
685             result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG);
686             break;
687 #      endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
688         default:
689             result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG);
690             break;
691       }
692     } else {
693       GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
694       switch(sz) {
695 #      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
696         case 1:
697             result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
698             break;
699         case 2:
700             result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG);
701             break;
702         case 4:
703             result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG);
704             break;
705 #      endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
706         default:
707             result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG);
708             break;
709       }
710     } 
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  */
721 void GC_reclaim_small_nonempty_block(hbp, report_if_found COUNT_PARAM)
722 register struct hblk *hbp;      /* ptr to current heap block            */
723 int report_if_found;            /* Abort if a reclaimable object is found */
724 COUNT_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 {
737         *flh = GC_reclaim_generic(hbp, hhdr, sz,
738                                   (ok -> ok_init || GC_debugging_started),
739                                   *flh MEM_FOUND_ADDR);
740     }
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.
748  * If report_if_found is TRUE, then process any block immediately, and
749  * simply report free objects; do not actually reclaim them.
750  */
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
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 */
769         if( !mark_bit_from_hdr(hhdr, 0) ) {
770             if (report_if_found) {
771               FOUND_FREE(hbp, 0);
772             } else {
773               word blocks = OBJ_SZ_TO_BLOCKS(sz);
774               if (blocks > 1) {
775                 GC_large_allocd_bytes -= blocks * HBLKSIZE;
776               }
777 #             ifdef GATHERSTATS
778                 GC_mem_found += sz;
779 #             endif
780               GC_freehblk(hbp);
781             }
782         }
783     } else {
784         GC_bool empty = GC_block_empty(hhdr);
785         if (report_if_found) {
786           GC_reclaim_small_nonempty_block(hbp, (int)report_if_found
787                                           MEM_FOUND_ADDR);
788         } else if (empty) {
789 #         ifdef GATHERSTATS
790             GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
791 #         endif
792           GC_freehblk(hbp);
793         } else if (TRUE != GC_block_nearly_full(hhdr)){
794           /* group of smaller objects, enqueue the real work */
795           rlh = &(ok -> ok_reclaim_list[sz]);
796           hhdr -> hb_next = *rlh;
797           *rlh = hbp;
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.                                      */
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.                                           */
810
811 struct Print_stats
812 {
813         size_t number_of_blocks;
814         size_t total_bytes;
815 };
816
817 #ifdef USE_MARK_BYTES
818
819 /* Return the number of set mark bits in the given header       */
820 int GC_n_set_marks(hhdr)
821 hdr * 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
834 /* Number of set bits in a word.  Not performance critical.     */
835 static int set_bits(n)
836 word 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       */
849 int GC_n_set_marks(hhdr)
850 hdr * 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
861 #endif /* !USE_MARK_BYTES  */
862
863 /*ARGSUSED*/
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
871 {
872     register hdr * hhdr = HDR(h);
873     register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
874     struct Print_stats *ps;
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)));
879     bytes += HBLKSIZE-1;
880     bytes &= ~(HBLKSIZE-1);
881
882     ps = (struct Print_stats *)dummy;
883     ps->total_bytes += bytes;
884     ps->number_of_blocks++;
885 }
886
887 void GC_print_block_list()
888 {
889     struct Print_stats pstats;
890
891     GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN);
892     pstats.number_of_blocks = 0;
893     pstats.total_bytes = 0;
894     GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
895     GC_printf2("\nblocks = %lu, bytes = %lu\n",
896                (unsigned long)pstats.number_of_blocks,
897                (unsigned long)pstats.total_bytes);
898 }
899
900 #endif /* NO_DEBUGGING */
901
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.
907  * It may help for other pointer-containing objects.
908  */
909 void GC_clear_fl_links(flp)
910 ptr_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
921 /*
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).
924  */
925 void GC_start_reclaim(report_if_found)
926 int report_if_found;            /* Abort if a GC_reclaimable object is found */
927 {
928     int kind;
929     
930 #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
931       GC_ASSERT(0 == GC_fl_builder_count);
932 #   endif
933     /* Clear reclaim- and free-lists */
934       for (kind = 0; kind < GC_n_kinds; kind++) {
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);
941         
942         if (rlist == 0) continue;       /* This kind not used.  */
943         if (!report_if_found) {
944             lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
945             for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
946               if (*fop != 0) {
947                 if (should_clobber) {
948                   GC_clear_fl_links(fop);
949                 } else {
950                   *fop = 0;
951                 }
952               }
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.                            */
969     GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
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
976 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
977     GC_ASSERT(0 == GC_fl_builder_count);
978 # endif
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  */
987 void GC_continue_reclaim(sz, kind)
988 word sz;        /* words */
989 int 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;
1002         GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
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.
1012  * If ignore_old is TRUE, then reclaim only blocks that have been 
1013  * recently reclaimed, and discard the rest.
1014  * Stop_func may be 0.
1015  */
1016 GC_bool GC_reclaim_all(stop_func, ignore_old)
1017 GC_stop_func stop_func;
1018 GC_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.                */
1050                     GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
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 }