Only include vectors.h in those files, where it is actually needed.
[bpt/guile.git] / libguile / gc.c
1 /* Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 \f
46 #include <stdio.h>
47 #include "_scm.h"
48 #include "stime.h"
49 #include "stackchk.h"
50 #include "struct.h"
51 #include "weaks.h"
52 #include "guardians.h"
53 #include "smob.h"
54 #include "unif.h"
55 #include "async.h"
56 #include "vectors.h"
57
58 #include "validate.h"
59 #include "gc.h"
60
61 #ifdef HAVE_MALLOC_H
62 #include <malloc.h>
63 #endif
64
65 #ifdef HAVE_UNISTD_H
66 #include <unistd.h>
67 #endif
68
69 #ifdef __STDC__
70 #include <stdarg.h>
71 #define var_start(x, y) va_start(x, y)
72 #else
73 #include <varargs.h>
74 #define var_start(x, y) va_start(x)
75 #endif
76
77 \f
78 /* {heap tuning parameters}
79 *
80 * These are parameters for controlling memory allocation. The heap
81 * is the area out of which scm_cons, and object headers are allocated.
82 *
83 * Each heap cell is 8 bytes on a 32 bit machine and 16 bytes on a
84 * 64 bit machine. The units of the _SIZE parameters are bytes.
85 * Cons pairs and object headers occupy one heap cell.
86 *
87 * SCM_INIT_HEAP_SIZE is the initial size of heap. If this much heap is
88 * allocated initially the heap will grow by half its current size
89 * each subsequent time more heap is needed.
90 *
91 * If SCM_INIT_HEAP_SIZE heap cannot be allocated initially, SCM_HEAP_SEG_SIZE
92 * will be used, and the heap will grow by SCM_HEAP_SEG_SIZE when more
93 * heap is needed. SCM_HEAP_SEG_SIZE must fit into type scm_sizet. This code
94 * is in scm_init_storage() and alloc_some_heap() in sys.c
95 *
96 * If SCM_INIT_HEAP_SIZE can be allocated initially, the heap will grow by
97 * SCM_EXPHEAP(scm_heap_size) when more heap is needed.
98 *
99 * SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
100 * is needed.
101 *
102 * INIT_MALLOC_LIMIT is the initial amount of malloc usage which will
103 * trigger a GC.
104 *
105 * SCM_MTRIGGER_HYSTERESIS is the amount of malloc storage that must be
106 * reclaimed by a GC triggered by must_malloc. If less than this is
107 * reclaimed, the trigger threshold is raised. [I don't know what a
108 * good value is. I arbitrarily chose 1/10 of the INIT_MALLOC_LIMIT to
109 * work around a oscillation that caused almost constant GC.]
110 */
111
112 #define SCM_INIT_HEAP_SIZE_1 (40000L * sizeof (scm_cell))
113 #define SCM_CLUSTER_SIZE_1 2000L
114 #define SCM_GC_TRIGGER_1 -50
115
116 #define SCM_INIT_HEAP_SIZE_2 (2500L * 2 * sizeof (scm_cell))
117 #define SCM_CLUSTER_SIZE_2 1000L
118 /* The following value may seem large, but note that if we get to GC at
119 * all, this means that we have a numerically intensive application
120 */
121 #define SCM_GC_TRIGGER_2 -50
122
123 #define SCM_MAX_SEGMENT_SIZE 2097000L /* a little less (adm) than 2 Mb */
124
125 #define SCM_MIN_HEAP_SEG_SIZE (2048L * sizeof (scm_cell))
126 #ifdef _QC
127 # define SCM_HEAP_SEG_SIZE 32768L
128 #else
129 # ifdef sequent
130 # define SCM_HEAP_SEG_SIZE (7000L * sizeof (scm_cell))
131 # else
132 # define SCM_HEAP_SEG_SIZE (16384L * sizeof (scm_cell))
133 # endif
134 #endif
135 /* Make heap grow with factor 1.5 */
136 #define SCM_EXPHEAP(scm_heap_size) (scm_heap_size / 2)
137 #define SCM_INIT_MALLOC_LIMIT 100000
138 #define SCM_MTRIGGER_HYSTERESIS (SCM_INIT_MALLOC_LIMIT/10)
139
140 /* CELL_UP and CELL_DN are used by scm_init_heap_seg to find scm_cell aligned inner
141 bounds for allocated storage */
142
143 #ifdef PROT386
144 /*in 386 protected mode we must only adjust the offset */
145 # define CELL_UP(p) MK_FP(FP_SEG(p), ~7&(FP_OFF(p)+7))
146 # define CELL_DN(p) MK_FP(FP_SEG(p), ~7&FP_OFF(p))
147 #else
148 # ifdef _UNICOS
149 # define CELL_UP(p) (SCM_CELLPTR)(~1L & ((long)(p)+1L))
150 # define CELL_DN(p) (SCM_CELLPTR)(~1L & (long)(p))
151 # else
152 # define CELL_UP(p) (SCM_CELLPTR)(~(sizeof(scm_cell)-1L) & ((long)(p)+sizeof(scm_cell)-1L))
153 # define CELL_DN(p) (SCM_CELLPTR)(~(sizeof(scm_cell)-1L) & (long)(p))
154 # endif /* UNICOS */
155 #endif /* PROT386 */
156
157
158 \f
159 /* scm_freelists
160 */
161
162 #ifdef GUILE_NEW_GC_SCHEME
163 SCM scm_freelist = SCM_EOL;
164 scm_freelist_t scm_master_freelist = {
165 SCM_EOL, 0, SCM_EOL, 0, SCM_CLUSTER_SIZE_1, 0, 0, 0, 1, 0, 0
166 };
167 SCM scm_freelist2 = SCM_EOL;
168 scm_freelist_t scm_master_freelist2 = {
169 SCM_EOL, 0, SCM_EOL, 0, SCM_CLUSTER_SIZE_2, 0, 0, 0, 2, 0, 0
170 };
171 #else
172 scm_freelist_t scm_freelist = { SCM_EOL, 1, 0, 0 };
173 scm_freelist_t scm_freelist2 = { SCM_EOL, 2, 0, 0 };
174 #endif
175
176 /* scm_mtrigger
177 * is the number of bytes of must_malloc allocation needed to trigger gc.
178 */
179 unsigned long scm_mtrigger;
180
181
182 /* scm_gc_heap_lock
183 * If set, don't expand the heap. Set only during gc, during which no allocation
184 * is supposed to take place anyway.
185 */
186 int scm_gc_heap_lock = 0;
187
188 /* GC Blocking
189 * Don't pause for collection if this is set -- just
190 * expand the heap.
191 */
192
193 int scm_block_gc = 1;
194
195 /* If fewer than MIN_GC_YIELD cells are recovered during a garbage
196 * collection (GC) more space is allocated for the heap.
197 */
198 #define MIN_GC_YIELD(freelist) (freelist->heap_size / 4)
199
200 /* During collection, this accumulates objects holding
201 * weak references.
202 */
203 SCM scm_weak_vectors;
204
205 /* GC Statistics Keeping
206 */
207 unsigned long scm_cells_allocated = 0;
208 long scm_mallocated = 0;
209 /* unsigned long scm_gc_cells_collected; */
210 unsigned long scm_gc_malloc_collected;
211 unsigned long scm_gc_ports_collected;
212 unsigned long scm_gc_rt;
213 unsigned long scm_gc_time_taken = 0;
214
215 SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
216 SCM_SYMBOL (sym_heap_size, "cell-heap-size");
217 SCM_SYMBOL (sym_mallocated, "bytes-malloced");
218 SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
219 SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
220 SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
221
222
223 struct scm_heap_seg_data
224 {
225 /* lower and upper bounds of the segment */
226 SCM_CELLPTR bounds[2];
227
228 /* address of the head-of-freelist pointer for this segment's cells.
229 All segments usually point to the same one, scm_freelist. */
230 scm_freelist_t *freelist;
231
232 /* number of SCM words per object in this segment */
233 int span;
234
235 /* If SEG_DATA->valid is non-zero, the conservative marking
236 functions will apply SEG_DATA->valid to the purported pointer and
237 SEG_DATA, and mark the object iff the function returns non-zero.
238 At the moment, I don't think anyone uses this. */
239 int (*valid) ();
240 };
241
242
243
244
245 static void scm_mark_weak_vector_spines (void);
246 static scm_sizet init_heap_seg (SCM_CELLPTR, scm_sizet, scm_freelist_t *);
247 static void alloc_some_heap (scm_freelist_t *);
248
249
250 \f
251 /* Debugging functions. */
252
253 #if defined (GUILE_DEBUG) || defined (GUILE_DEBUG_FREELIST)
254
255 /* Return the number of the heap segment containing CELL. */
256 static int
257 which_seg (SCM cell)
258 {
259 int i;
260
261 for (i = 0; i < scm_n_heap_segs; i++)
262 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], (SCM_CELLPTR) cell)
263 && SCM_PTR_GT (scm_heap_table[i].bounds[1], (SCM_CELLPTR) cell))
264 return i;
265 fprintf (stderr, "which_seg: can't find segment containing cell %lx\n",
266 SCM_UNPACK (cell));
267 abort ();
268 }
269
270
271 #ifdef GUILE_NEW_GC_SCHEME
272 static void
273 map_free_list (scm_freelist_t *master, SCM freelist)
274 {
275 int last_seg = -1, count = 0;
276 SCM f;
277
278 for (f = freelist; SCM_NIMP (f); f = SCM_CDR (f))
279 {
280 int this_seg = which_seg (f);
281
282 if (this_seg != last_seg)
283 {
284 if (last_seg != -1)
285 fprintf (stderr, " %5d %d-cells in segment %d\n",
286 count, master->span, last_seg);
287 last_seg = this_seg;
288 count = 0;
289 }
290 count++;
291 }
292 if (last_seg != -1)
293 fprintf (stderr, " %5d %d-cells in segment %d\n",
294 count, master->span, last_seg);
295 }
296 #else
297 static void
298 map_free_list (scm_freelist_t *freelist)
299 {
300 int last_seg = -1, count = 0;
301 SCM f;
302
303 for (f = freelist->cells; SCM_NIMP (f); f = SCM_CDR (f))
304 {
305 int this_seg = which_seg (f);
306
307 if (this_seg != last_seg)
308 {
309 if (last_seg != -1)
310 fprintf (stderr, " %5d %d-cells in segment %d\n",
311 count, freelist->span, last_seg);
312 last_seg = this_seg;
313 count = 0;
314 }
315 count++;
316 }
317 if (last_seg != -1)
318 fprintf (stderr, " %5d %d-cells in segment %d\n",
319 count, freelist->span, last_seg);
320 }
321 #endif
322
323 SCM_DEFINE (scm_map_free_list, "map-free-list", 0, 0, 0,
324 (),
325 "Print debugging information about the free-list.\n"
326 "`map-free-list' is only included in --enable-guile-debug builds of Guile.")
327 #define FUNC_NAME s_scm_map_free_list
328 {
329 int i;
330 fprintf (stderr, "%d segments total (%d:%d",
331 scm_n_heap_segs,
332 scm_heap_table[0].span,
333 scm_heap_table[0].bounds[1] - scm_heap_table[0].bounds[0]);
334 for (i = 1; i < scm_n_heap_segs; i++)
335 fprintf (stderr, ", %d:%d",
336 scm_heap_table[i].span,
337 scm_heap_table[i].bounds[1] - scm_heap_table[i].bounds[0]);
338 fprintf (stderr, ")\n");
339 #ifdef GUILE_NEW_GC_SCHEME
340 map_free_list (&scm_master_freelist, scm_freelist);
341 map_free_list (&scm_master_freelist2, scm_freelist2);
342 #else
343 map_free_list (&scm_freelist);
344 map_free_list (&scm_freelist2);
345 #endif
346 fflush (stderr);
347
348 return SCM_UNSPECIFIED;
349 }
350 #undef FUNC_NAME
351
352 #ifdef GUILE_NEW_GC_SCHEME
353 static int last_cluster;
354 static int last_size;
355
356 static int
357 free_list_length (char *title, int i, SCM freelist)
358 {
359 SCM ls;
360 int n = 0;
361 for (ls = freelist; SCM_NNULLP (ls); ls = SCM_CDR (ls))
362 if (SCM_UNPACK_CAR (ls) == scm_tc_free_cell)
363 ++n;
364 else
365 {
366 fprintf (stderr, "bad cell in %s at position %d\n", title, n);
367 abort ();
368 }
369 if (n != last_size)
370 {
371 if (i > 0)
372 {
373 if (last_cluster == i - 1)
374 fprintf (stderr, "\t%d\n", last_size);
375 else
376 fprintf (stderr, "-%d\t%d\n", i - 1, last_size);
377 }
378 if (i >= 0)
379 fprintf (stderr, "%s %d", title, i);
380 else
381 fprintf (stderr, "%s\t%d\n", title, n);
382 last_cluster = i;
383 last_size = n;
384 }
385 return n;
386 }
387
388 static void
389 free_list_lengths (char *title, scm_freelist_t *master, SCM freelist)
390 {
391 SCM clusters;
392 int i = 0, len, n = 0;
393 fprintf (stderr, "%s\n\n", title);
394 n += free_list_length ("free list", -1, freelist);
395 for (clusters = master->clusters;
396 SCM_NNULLP (clusters);
397 clusters = SCM_CDR (clusters))
398 {
399 len = free_list_length ("cluster", i++, SCM_CAR (clusters));
400 n += len;
401 }
402 if (last_cluster == i - 1)
403 fprintf (stderr, "\t%d\n", last_size);
404 else
405 fprintf (stderr, "-%d\t%d\n", i - 1, last_size);
406 fprintf (stderr, "\ntotal %d objects\n\n", n);
407 }
408
409 SCM_DEFINE (scm_free_list_length, "free-list-length", 0, 0, 0,
410 (),
411 "Print debugging information about the free-list.\n"
412 "`free-list-length' is only included in --enable-guile-debug builds of Guile.")
413 #define FUNC_NAME s_scm_free_list_length
414 {
415 free_list_lengths ("1-words", &scm_master_freelist, scm_freelist);
416 free_list_lengths ("2-words", &scm_master_freelist2, scm_freelist2);
417 return SCM_UNSPECIFIED;
418 }
419 #undef FUNC_NAME
420 #endif
421
422 #endif
423
424 #ifdef GUILE_DEBUG_FREELIST
425
426 /* Number of calls to SCM_NEWCELL since startup. */
427 static unsigned long scm_newcell_count;
428 static unsigned long scm_newcell2_count;
429
430 /* Search freelist for anything that isn't marked as a free cell.
431 Abort if we find something. */
432 #ifdef GUILE_NEW_GC_SCHEME
433 static void
434 scm_check_freelist (SCM freelist)
435 {
436 SCM f;
437 int i = 0;
438
439 for (f = freelist; SCM_NIMP (f); f = SCM_CDR (f), i++)
440 if (SCM_CAR (f) != (SCM) scm_tc_free_cell)
441 {
442 fprintf (stderr, "Bad cell in freelist on newcell %lu: %d'th elt\n",
443 scm_newcell_count, i);
444 fflush (stderr);
445 abort ();
446 }
447 }
448 #else
449 static void
450 scm_check_freelist (scm_freelist_t *freelist)
451 {
452 SCM f;
453 int i = 0;
454
455 for (f = freelist->cells; SCM_NIMP (f); f = SCM_CDR (f), i++)
456 if (SCM_CAR (f) != (SCM) scm_tc_free_cell)
457 {
458 fprintf (stderr, "Bad cell in freelist on newcell %lu: %d'th elt\n",
459 scm_newcell_count, i);
460 fflush (stderr);
461 abort ();
462 }
463 }
464 #endif
465
466 static int scm_debug_check_freelist = 0;
467
468 SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
469 (SCM flag),
470 "If FLAG is #t, check the freelist for consistency on each cell allocation.\n"
471 "This procedure only exists because the GUILE_DEBUG_FREELIST \n"
472 "compile-time flag was selected.\n")
473 #define FUNC_NAME s_scm_gc_set_debug_check_freelist_x
474 {
475 SCM_VALIDATE_BOOL_COPY (1, flag, scm_debug_check_freelist);
476 return SCM_UNSPECIFIED;
477 }
478 #undef FUNC_NAME
479
480
481 #ifdef GUILE_NEW_GC_SCHEME
482
483 SCM
484 scm_debug_newcell (void)
485 {
486 SCM new;
487
488 scm_newcell_count++;
489 if (scm_debug_check_freelist)
490 {
491 scm_check_freelist (scm_freelist);
492 scm_gc();
493 }
494
495 /* The rest of this is supposed to be identical to the SCM_NEWCELL
496 macro. */
497 if (SCM_IMP (scm_freelist))
498 new = scm_gc_for_newcell (&scm_master_freelist, &scm_freelist);
499 else
500 {
501 new = scm_freelist;
502 scm_freelist = SCM_CDR (scm_freelist);
503 SCM_SETCAR (new, scm_tc16_allocated);
504 }
505
506 return new;
507 }
508
509 SCM
510 scm_debug_newcell2 (void)
511 {
512 SCM new;
513
514 scm_newcell2_count++;
515 if (scm_debug_check_freelist)
516 {
517 scm_check_freelist (scm_freelist2);
518 scm_gc ();
519 }
520
521 /* The rest of this is supposed to be identical to the SCM_NEWCELL
522 macro. */
523 if (SCM_IMP (scm_freelist2))
524 new = scm_gc_for_newcell (&scm_master_freelist2, &scm_freelist2);
525 else
526 {
527 new = scm_freelist2;
528 scm_freelist2 = SCM_CDR (scm_freelist2);
529 SCM_SETCAR (new, scm_tc16_allocated);
530 }
531
532 return new;
533 }
534
535 #else /* GUILE_NEW_GC_SCHEME */
536
537 SCM
538 scm_debug_newcell (void)
539 {
540 SCM new;
541
542 scm_newcell_count++;
543 if (scm_debug_check_freelist)
544 {
545 scm_check_freelist (&scm_freelist);
546 scm_gc();
547 }
548
549 /* The rest of this is supposed to be identical to the SCM_NEWCELL
550 macro. */
551 if (SCM_IMP (scm_freelist.cells))
552 new = scm_gc_for_newcell (&scm_freelist);
553 else
554 {
555 new = scm_freelist.cells;
556 scm_freelist.cells = SCM_CDR (scm_freelist.cells);
557 SCM_SETCAR (new, scm_tc16_allocated);
558 ++scm_cells_allocated;
559 }
560
561 return new;
562 }
563
564 SCM
565 scm_debug_newcell2 (void)
566 {
567 SCM new;
568
569 scm_newcell2_count++;
570 if (scm_debug_check_freelist) {
571 scm_check_freelist (&scm_freelist2);
572 scm_gc();
573 }
574
575 /* The rest of this is supposed to be identical to the SCM_NEWCELL2
576 macro. */
577 if (SCM_IMP (scm_freelist2.cells))
578 new = scm_gc_for_newcell (&scm_freelist2);
579 else
580 {
581 new = scm_freelist2.cells;
582 scm_freelist2.cells = SCM_CDR (scm_freelist2.cells);
583 SCM_SETCAR (new, scm_tc16_allocated);
584 scm_cells_allocated += 2;
585 }
586
587 return new;
588 }
589
590 #endif /* GUILE_NEW_GC_SCHEME */
591 #endif /* GUILE_DEBUG_FREELIST */
592
593 \f
594
595 /* {Scheme Interface to GC}
596 */
597
598 SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
599 (),
600 "Returns an association list of statistics about Guile's current use of storage. ")
601 #define FUNC_NAME s_scm_gc_stats
602 {
603 int i;
604 int n;
605 SCM heap_segs;
606 long int local_scm_mtrigger;
607 long int local_scm_mallocated;
608 long int local_scm_heap_size;
609 long int local_scm_cells_allocated;
610 long int local_scm_gc_time_taken;
611 SCM answer;
612
613 SCM_DEFER_INTS;
614 scm_block_gc = 1;
615 retry:
616 heap_segs = SCM_EOL;
617 n = scm_n_heap_segs;
618 for (i = scm_n_heap_segs; i--; )
619 heap_segs = scm_cons (scm_cons (scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[1]),
620 scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[0])),
621 heap_segs);
622 if (scm_n_heap_segs != n)
623 goto retry;
624 scm_block_gc = 0;
625
626 /// ? ?? ?
627 local_scm_mtrigger = scm_mtrigger;
628 local_scm_mallocated = scm_mallocated;
629 #ifdef GUILE_NEW_GC_SCHEME
630 local_scm_heap_size = scm_master_freelist.heap_size; /*fixme*/
631 #else
632 local_scm_heap_size = scm_freelist.heap_size; /*fixme*/
633 #endif
634 local_scm_cells_allocated = scm_cells_allocated;
635 local_scm_gc_time_taken = scm_gc_time_taken;
636
637 answer = scm_listify (scm_cons (sym_gc_time_taken, scm_ulong2num (local_scm_gc_time_taken)),
638 scm_cons (sym_cells_allocated, scm_ulong2num (local_scm_cells_allocated)),
639 scm_cons (sym_heap_size, scm_ulong2num (local_scm_heap_size)),
640 scm_cons (sym_mallocated, scm_ulong2num (local_scm_mallocated)),
641 scm_cons (sym_mtrigger, scm_ulong2num (local_scm_mtrigger)),
642 scm_cons (sym_heap_segments, heap_segs),
643 SCM_UNDEFINED);
644 SCM_ALLOW_INTS;
645 return answer;
646 }
647 #undef FUNC_NAME
648
649
650 void
651 scm_gc_start (const char *what)
652 {
653 scm_gc_rt = SCM_INUM (scm_get_internal_run_time ());
654 /* scm_gc_cells_collected = 0; */
655 scm_gc_malloc_collected = 0;
656 scm_gc_ports_collected = 0;
657 }
658
659 void
660 scm_gc_end ()
661 {
662 scm_gc_rt = SCM_INUM (scm_get_internal_run_time ()) - scm_gc_rt;
663 scm_gc_time_taken += scm_gc_rt;
664 scm_system_async_mark (scm_gc_async);
665 }
666
667
668 SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
669 (SCM obj),
670 "Return an integer that for the lifetime of @var{obj} is uniquely\n"
671 "returned by this function for @var{obj}")
672 #define FUNC_NAME s_scm_object_address
673 {
674 return scm_ulong2num ((unsigned long) obj);
675 }
676 #undef FUNC_NAME
677
678
679 SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
680 (),
681 "Scans all of SCM objects and reclaims for further use those that are\n"
682 "no longer accessible.")
683 #define FUNC_NAME s_scm_gc
684 {
685 SCM_DEFER_INTS;
686 scm_igc ("call");
687 SCM_ALLOW_INTS;
688 return SCM_UNSPECIFIED;
689 }
690 #undef FUNC_NAME
691
692
693 \f
694 /* {C Interface For When GC is Triggered}
695 */
696
697 #ifdef GUILE_NEW_GC_SCHEME
698
699 /* When we get POSIX threads support, the master will be global and
700 * common while the freelist will be individual for each thread.
701 */
702
703 SCM
704 scm_gc_for_newcell (scm_freelist_t *master, SCM *freelist)
705 {
706 SCM cell;
707 ++scm_ints_disabled;
708 do
709 {
710 if (SCM_NULLP (master->clusters))
711 {
712 if (master->grow_heap_p)
713 {
714 master->grow_heap_p = 0;
715 alloc_some_heap (master);
716 }
717 else
718 scm_igc ("cells");
719 }
720 cell = SCM_CAR (master->clusters);
721 master->clusters = SCM_CDR (master->clusters);
722 }
723 while (SCM_NULLP (cell));
724 --scm_ints_disabled;
725 *freelist = SCM_CDR (cell);
726 SCM_SETCAR (cell, scm_tc16_allocated);
727 return cell;
728 }
729
730 #if 0
731 /* This is a support routine which can be used to reserve a cluster
732 * for some special use, such as debugging. It won't be useful until
733 * free cells are preserved between garbage collections.
734 */
735
736 void
737 scm_alloc_cluster (scm_freelist_t *master)
738 {
739 SCM freelist, cell;
740 cell = scm_gc_for_newcell (master, &freelist);
741 SCM_SETCDR (cell, freelist);
742 return cell;
743 }
744 #endif
745
746 #else /* GUILE_NEW_GC_SCHEME */
747
748 void
749 scm_gc_for_alloc (scm_freelist_t *freelist)
750 {
751 SCM_REDEFER_INTS;
752 scm_igc ("cells");
753 #ifdef GUILE_DEBUG_FREELIST
754 fprintf (stderr, "Collected: %d, min_yield: %d\n",
755 freelist->collected, MIN_GC_YIELD (freelist));
756 #endif
757 if ((freelist->collected < MIN_GC_YIELD (freelist))
758 || SCM_IMP (freelist->cells))
759 alloc_some_heap (freelist);
760 SCM_REALLOW_INTS;
761 }
762
763
764 SCM
765 scm_gc_for_newcell (scm_freelist_t *freelist)
766 {
767 SCM fl;
768 scm_gc_for_alloc (freelist);
769 fl = freelist->cells;
770 freelist->cells = SCM_CDR (fl);
771 SCM_SETCAR (fl, scm_tc16_allocated);
772 return fl;
773 }
774
775 #endif /* GUILE_NEW_GC_SCHEME */
776
777 void
778 scm_igc (const char *what)
779 {
780 int j;
781
782 #ifdef DEBUGINFO
783 fprintf (stderr,
784 SCM_NULLP (scm_freelist)
785 ? "*"
786 : (SCM_NULLP (scm_freelist2) ? "o" : "m"));
787 #endif
788 #ifdef USE_THREADS
789 /* During the critical section, only the current thread may run. */
790 SCM_THREAD_CRITICAL_SECTION_START;
791 #endif
792
793 /* fprintf (stderr, "gc: %s\n", what); */
794
795 scm_gc_start (what);
796
797 if (!scm_stack_base || scm_block_gc)
798 {
799 scm_gc_end ();
800 return;
801 }
802
803 if (scm_mallocated < 0)
804 /* The byte count of allocated objects has underflowed. This is
805 probably because you forgot to report the sizes of objects you
806 have allocated, by calling scm_done_malloc or some such. When
807 the GC freed them, it subtracted their size from
808 scm_mallocated, which underflowed. */
809 abort ();
810
811 if (scm_gc_heap_lock)
812 /* We've invoked the collector while a GC is already in progress.
813 That should never happen. */
814 abort ();
815
816 ++scm_gc_heap_lock;
817
818 scm_weak_vectors = SCM_EOL;
819
820 scm_guardian_gc_init ();
821
822 /* unprotect any struct types with no instances */
823 #if 0
824 {
825 SCM type_list;
826 SCM * pos;
827
828 pos = &scm_type_obj_list;
829 type_list = scm_type_obj_list;
830 while (type_list != SCM_EOL)
831 if (SCM_VELTS (SCM_CAR (type_list))[scm_struct_i_refcnt])
832 {
833 pos = SCM_CDRLOC (type_list);
834 type_list = SCM_CDR (type_list);
835 }
836 else
837 {
838 *pos = SCM_CDR (type_list);
839 type_list = SCM_CDR (type_list);
840 }
841 }
842 #endif
843
844 /* flush dead entries from the continuation stack */
845 {
846 int x;
847 int bound;
848 SCM * elts;
849 elts = SCM_VELTS (scm_continuation_stack);
850 bound = SCM_LENGTH (scm_continuation_stack);
851 x = SCM_INUM (scm_continuation_stack_ptr);
852 while (x < bound)
853 {
854 elts[x] = SCM_BOOL_F;
855 ++x;
856 }
857 }
858
859 #ifndef USE_THREADS
860
861 /* Protect from the C stack. This must be the first marking
862 * done because it provides information about what objects
863 * are "in-use" by the C code. "in-use" objects are those
864 * for which the values from SCM_LENGTH and SCM_CHARS must remain
865 * usable. This requirement is stricter than a liveness
866 * requirement -- in particular, it constrains the implementation
867 * of scm_vector_set_length_x.
868 */
869 SCM_FLUSH_REGISTER_WINDOWS;
870 /* This assumes that all registers are saved into the jmp_buf */
871 setjmp (scm_save_regs_gc_mark);
872 scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
873 ( (scm_sizet) (sizeof (SCM_STACKITEM) - 1 +
874 sizeof scm_save_regs_gc_mark)
875 / sizeof (SCM_STACKITEM)));
876
877 {
878 /* stack_len is long rather than scm_sizet in order to guarantee that
879 &stack_len is long aligned */
880 #ifdef SCM_STACK_GROWS_UP
881 #ifdef nosve
882 long stack_len = (SCM_STACKITEM *) (&stack_len) - scm_stack_base;
883 #else
884 long stack_len = scm_stack_size (scm_stack_base);
885 #endif
886 scm_mark_locations (scm_stack_base, (scm_sizet) stack_len);
887 #else
888 #ifdef nosve
889 long stack_len = scm_stack_base - (SCM_STACKITEM *) (&stack_len);
890 #else
891 long stack_len = scm_stack_size (scm_stack_base);
892 #endif
893 scm_mark_locations ((scm_stack_base - stack_len), (scm_sizet) stack_len);
894 #endif
895 }
896
897 #else /* USE_THREADS */
898
899 /* Mark every thread's stack and registers */
900 scm_threads_mark_stacks ();
901
902 #endif /* USE_THREADS */
903
904 /* FIXME: insert a phase to un-protect string-data preserved
905 * in scm_vector_set_length_x.
906 */
907
908 j = SCM_NUM_PROTECTS;
909 while (j--)
910 scm_gc_mark (scm_sys_protects[j]);
911
912 /* FIXME: we should have a means to register C functions to be run
913 * in different phases of GC
914 */
915 scm_mark_subr_table ();
916
917 #ifndef USE_THREADS
918 scm_gc_mark (scm_root->handle);
919 #endif
920
921 scm_mark_weak_vector_spines ();
922
923 scm_guardian_zombify ();
924
925 scm_gc_sweep ();
926
927 --scm_gc_heap_lock;
928 scm_gc_end ();
929
930 #ifdef USE_THREADS
931 SCM_THREAD_CRITICAL_SECTION_END;
932 #endif
933 }
934
935 \f
936 /* {Mark/Sweep}
937 */
938
939
940
941 /* Mark an object precisely.
942 */
943 void
944 scm_gc_mark (SCM p)
945 {
946 register long i;
947 register SCM ptr;
948
949 ptr = p;
950
951 gc_mark_loop:
952 if (SCM_IMP (ptr))
953 return;
954
955 gc_mark_nimp:
956 if (SCM_NCELLP (ptr))
957 scm_wta (ptr, "rogue pointer in heap", NULL);
958
959 switch (SCM_TYP7 (ptr))
960 {
961 case scm_tcs_cons_nimcar:
962 if (SCM_GCMARKP (ptr))
963 break;
964 SCM_SETGCMARK (ptr);
965 if (SCM_IMP (SCM_CDR (ptr))) /* SCM_IMP works even with a GC mark */
966 {
967 ptr = SCM_CAR (ptr);
968 goto gc_mark_nimp;
969 }
970 scm_gc_mark (SCM_CAR (ptr));
971 ptr = SCM_GCCDR (ptr);
972 goto gc_mark_nimp;
973 case scm_tcs_cons_imcar:
974 if (SCM_GCMARKP (ptr))
975 break;
976 SCM_SETGCMARK (ptr);
977 ptr = SCM_GCCDR (ptr);
978 goto gc_mark_loop;
979 case scm_tc7_pws:
980 if (SCM_GCMARKP (ptr))
981 break;
982 SCM_SETGCMARK (ptr);
983 scm_gc_mark (SCM_CELL_WORD (ptr, 2));
984 ptr = SCM_GCCDR (ptr);
985 goto gc_mark_loop;
986 case scm_tcs_cons_gloc:
987 if (SCM_GCMARKP (ptr))
988 break;
989 SCM_SETGCMARK (ptr);
990 {
991 SCM vcell;
992 vcell = SCM_CAR (ptr) - 1L;
993 switch (SCM_UNPACK (SCM_CDR (vcell)))
994 {
995 default:
996 scm_gc_mark (vcell);
997 ptr = SCM_GCCDR (ptr);
998 goto gc_mark_loop;
999 case 1: /* ! */
1000 case 0: /* ! */
1001 {
1002 SCM layout;
1003 SCM * vtable_data;
1004 int len;
1005 char * fields_desc;
1006 register SCM * mem;
1007 register int x;
1008
1009 vtable_data = (SCM *)vcell;
1010 layout = vtable_data[scm_vtable_index_layout];
1011 len = SCM_LENGTH (layout);
1012 fields_desc = SCM_CHARS (layout);
1013 /* We're using SCM_GCCDR here like STRUCT_DATA, except
1014 that it removes the mark */
1015 mem = (SCM *)SCM_GCCDR (ptr);
1016
1017 if (SCM_UNPACK (vtable_data[scm_struct_i_flags]) & SCM_STRUCTF_ENTITY)
1018 {
1019 scm_gc_mark (mem[scm_struct_i_procedure]);
1020 scm_gc_mark (mem[scm_struct_i_setter]);
1021 }
1022 if (len)
1023 {
1024 for (x = 0; x < len - 2; x += 2, ++mem)
1025 if (fields_desc[x] == 'p')
1026 scm_gc_mark (*mem);
1027 if (fields_desc[x] == 'p')
1028 {
1029 int j;
1030 if (SCM_LAYOUT_TAILP (fields_desc[x + 1]))
1031 for (j = (long int) *mem; x; --x)
1032 scm_gc_mark (*++mem);
1033 else
1034 scm_gc_mark (*mem);
1035 }
1036 }
1037 if (!SCM_CDR (vcell))
1038 {
1039 SCM_SETGCMARK (vcell);
1040 ptr = vtable_data[scm_vtable_index_vtable];
1041 goto gc_mark_loop;
1042 }
1043 }
1044 }
1045 }
1046 break;
1047 case scm_tcs_closures:
1048 if (SCM_GCMARKP (ptr))
1049 break;
1050 SCM_SETGCMARK (ptr);
1051 if (SCM_IMP (SCM_CDR (ptr)))
1052 {
1053 ptr = SCM_CLOSCAR (ptr);
1054 goto gc_mark_nimp;
1055 }
1056 scm_gc_mark (SCM_CLOSCAR (ptr));
1057 ptr = SCM_GCCDR (ptr);
1058 goto gc_mark_nimp;
1059 case scm_tc7_vector:
1060 case scm_tc7_lvector:
1061 #ifdef CCLO
1062 case scm_tc7_cclo:
1063 #endif
1064 if (SCM_GC8MARKP (ptr))
1065 break;
1066 SCM_SETGC8MARK (ptr);
1067 i = SCM_LENGTH (ptr);
1068 if (i == 0)
1069 break;
1070 while (--i > 0)
1071 if (SCM_NIMP (SCM_VELTS (ptr)[i]))
1072 scm_gc_mark (SCM_VELTS (ptr)[i]);
1073 ptr = SCM_VELTS (ptr)[0];
1074 goto gc_mark_loop;
1075 case scm_tc7_contin:
1076 if SCM_GC8MARKP
1077 (ptr) break;
1078 SCM_SETGC8MARK (ptr);
1079 if (SCM_VELTS (ptr))
1080 scm_mark_locations (SCM_VELTS_AS_STACKITEMS (ptr),
1081 (scm_sizet)
1082 (SCM_LENGTH (ptr) +
1083 (sizeof (SCM_STACKITEM) + -1 +
1084 sizeof (scm_contregs)) /
1085 sizeof (SCM_STACKITEM)));
1086 break;
1087 #ifdef HAVE_ARRAYS
1088 case scm_tc7_bvect:
1089 case scm_tc7_byvect:
1090 case scm_tc7_ivect:
1091 case scm_tc7_uvect:
1092 case scm_tc7_fvect:
1093 case scm_tc7_dvect:
1094 case scm_tc7_cvect:
1095 case scm_tc7_svect:
1096 #ifdef HAVE_LONG_LONGS
1097 case scm_tc7_llvect:
1098 #endif
1099 #endif
1100 case scm_tc7_string:
1101 SCM_SETGC8MARK (ptr);
1102 break;
1103
1104 case scm_tc7_substring:
1105 if (SCM_GC8MARKP(ptr))
1106 break;
1107 SCM_SETGC8MARK (ptr);
1108 ptr = SCM_CDR (ptr);
1109 goto gc_mark_loop;
1110
1111 case scm_tc7_wvect:
1112 if (SCM_GC8MARKP(ptr))
1113 break;
1114 SCM_WVECT_GC_CHAIN (ptr) = scm_weak_vectors;
1115 scm_weak_vectors = ptr;
1116 SCM_SETGC8MARK (ptr);
1117 if (SCM_IS_WHVEC_ANY (ptr))
1118 {
1119 int x;
1120 int len;
1121 int weak_keys;
1122 int weak_values;
1123
1124 len = SCM_LENGTH (ptr);
1125 weak_keys = SCM_IS_WHVEC (ptr) || SCM_IS_WHVEC_B (ptr);
1126 weak_values = SCM_IS_WHVEC_V (ptr) || SCM_IS_WHVEC_B (ptr);
1127
1128 for (x = 0; x < len; ++x)
1129 {
1130 SCM alist;
1131 alist = SCM_VELTS (ptr)[x];
1132
1133 /* mark everything on the alist except the keys or
1134 * values, according to weak_values and weak_keys. */
1135 while ( SCM_CONSP (alist)
1136 && !SCM_GCMARKP (alist)
1137 && SCM_CONSP (SCM_CAR (alist)))
1138 {
1139 SCM kvpair;
1140 SCM next_alist;
1141
1142 kvpair = SCM_CAR (alist);
1143 next_alist = SCM_CDR (alist);
1144 /*
1145 * Do not do this:
1146 * SCM_SETGCMARK (alist);
1147 * SCM_SETGCMARK (kvpair);
1148 *
1149 * It may be that either the key or value is protected by
1150 * an escaped reference to part of the spine of this alist.
1151 * If we mark the spine here, and only mark one or neither of the
1152 * key and value, they may never be properly marked.
1153 * This leads to a horrible situation in which an alist containing
1154 * freelist cells is exported.
1155 *
1156 * So only mark the spines of these arrays last of all marking.
1157 * If somebody confuses us by constructing a weak vector
1158 * with a circular alist then we are hosed, but at least we
1159 * won't prematurely drop table entries.
1160 */
1161 if (!weak_keys)
1162 scm_gc_mark (SCM_CAR (kvpair));
1163 if (!weak_values)
1164 scm_gc_mark (SCM_GCCDR (kvpair));
1165 alist = next_alist;
1166 }
1167 if (SCM_NIMP (alist))
1168 scm_gc_mark (alist);
1169 }
1170 }
1171 break;
1172
1173 case scm_tc7_msymbol:
1174 if (SCM_GC8MARKP(ptr))
1175 break;
1176 SCM_SETGC8MARK (ptr);
1177 scm_gc_mark (SCM_SYMBOL_FUNC (ptr));
1178 ptr = SCM_SYMBOL_PROPS (ptr);
1179 goto gc_mark_loop;
1180 case scm_tc7_ssymbol:
1181 if (SCM_GC8MARKP(ptr))
1182 break;
1183 SCM_SETGC8MARK (ptr);
1184 break;
1185 case scm_tcs_subrs:
1186 break;
1187 case scm_tc7_port:
1188 i = SCM_PTOBNUM (ptr);
1189 if (!(i < scm_numptob))
1190 goto def;
1191 if (SCM_GC8MARKP (ptr))
1192 break;
1193 SCM_SETGC8MARK (ptr);
1194 if (SCM_PTAB_ENTRY(ptr))
1195 scm_gc_mark (SCM_PTAB_ENTRY(ptr)->file_name);
1196 if (scm_ptobs[i].mark)
1197 {
1198 ptr = (scm_ptobs[i].mark) (ptr);
1199 goto gc_mark_loop;
1200 }
1201 else
1202 return;
1203 break;
1204 case scm_tc7_smob:
1205 if (SCM_GC8MARKP (ptr))
1206 break;
1207 SCM_SETGC8MARK (ptr);
1208 switch (SCM_GCTYP16 (ptr))
1209 { /* should be faster than going through scm_smobs */
1210 case scm_tc_free_cell:
1211 /* printf("found free_cell %X ", ptr); fflush(stdout); */
1212 case scm_tc16_allocated:
1213 case scm_tc16_big:
1214 case scm_tc16_real:
1215 case scm_tc16_complex:
1216 break;
1217 default:
1218 i = SCM_SMOBNUM (ptr);
1219 if (!(i < scm_numsmob))
1220 goto def;
1221 if (scm_smobs[i].mark)
1222 {
1223 ptr = (scm_smobs[i].mark) (ptr);
1224 goto gc_mark_loop;
1225 }
1226 else
1227 return;
1228 }
1229 break;
1230 default:
1231 def:scm_wta (ptr, "unknown type in ", "gc_mark");
1232 }
1233 }
1234
1235
1236 /* Mark a Region Conservatively
1237 */
1238
1239 void
1240 scm_mark_locations (SCM_STACKITEM x[], scm_sizet n)
1241 {
1242 register long m = n;
1243 register int i, j;
1244 register SCM_CELLPTR ptr;
1245
1246 while (0 <= --m)
1247 if (SCM_CELLP (*(SCM **) (& x[m])))
1248 {
1249 ptr = (SCM_CELLPTR) SCM2PTR ((*(SCM **) & x[m]));
1250 i = 0;
1251 j = scm_n_heap_segs - 1;
1252 if ( SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr)
1253 && SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
1254 {
1255 while (i <= j)
1256 {
1257 int seg_id;
1258 seg_id = -1;
1259 if ( (i == j)
1260 || SCM_PTR_GT (scm_heap_table[i].bounds[1], ptr))
1261 seg_id = i;
1262 else if (SCM_PTR_LE (scm_heap_table[j].bounds[0], ptr))
1263 seg_id = j;
1264 else
1265 {
1266 int k;
1267 k = (i + j) / 2;
1268 if (k == i)
1269 break;
1270 if (SCM_PTR_GT (scm_heap_table[k].bounds[1], ptr))
1271 {
1272 j = k;
1273 ++i;
1274 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr))
1275 continue;
1276 else
1277 break;
1278 }
1279 else if (SCM_PTR_LE (scm_heap_table[k].bounds[0], ptr))
1280 {
1281 i = k;
1282 --j;
1283 if (SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
1284 continue;
1285 else
1286 break;
1287 }
1288 }
1289 if ( !scm_heap_table[seg_id].valid
1290 || scm_heap_table[seg_id].valid (ptr,
1291 &scm_heap_table[seg_id]))
1292 scm_gc_mark (*(SCM *) & x[m]);
1293 break;
1294 }
1295
1296 }
1297 }
1298 }
1299
1300
1301 /* The following is a C predicate which determines if an SCM value can be
1302 regarded as a pointer to a cell on the heap. The code is duplicated
1303 from scm_mark_locations. */
1304
1305
1306 int
1307 scm_cellp (SCM value)
1308 {
1309 register int i, j;
1310 register SCM_CELLPTR ptr;
1311
1312 if SCM_CELLP (*(SCM **) (& value))
1313 {
1314 ptr = (SCM_CELLPTR) SCM2PTR ((*(SCM **) & value));
1315 i = 0;
1316 j = scm_n_heap_segs - 1;
1317 if ( SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr)
1318 && SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
1319 {
1320 while (i <= j)
1321 {
1322 int seg_id;
1323 seg_id = -1;
1324 if ( (i == j)
1325 || SCM_PTR_GT (scm_heap_table[i].bounds[1], ptr))
1326 seg_id = i;
1327 else if (SCM_PTR_LE (scm_heap_table[j].bounds[0], ptr))
1328 seg_id = j;
1329 else
1330 {
1331 int k;
1332 k = (i + j) / 2;
1333 if (k == i)
1334 break;
1335 if (SCM_PTR_GT (scm_heap_table[k].bounds[1], ptr))
1336 {
1337 j = k;
1338 ++i;
1339 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr))
1340 continue;
1341 else
1342 break;
1343 }
1344 else if (SCM_PTR_LE (scm_heap_table[k].bounds[0], ptr))
1345 {
1346 i = k;
1347 --j;
1348 if (SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
1349 continue;
1350 else
1351 break;
1352 }
1353 }
1354 if ( !scm_heap_table[seg_id].valid
1355 || scm_heap_table[seg_id].valid (ptr,
1356 &scm_heap_table[seg_id]))
1357 return 1;
1358 break;
1359 }
1360
1361 }
1362 }
1363 return 0;
1364 }
1365
1366
1367 static void
1368 scm_mark_weak_vector_spines ()
1369 {
1370 SCM w;
1371
1372 for (w = scm_weak_vectors; w != SCM_EOL; w = SCM_WVECT_GC_CHAIN (w))
1373 {
1374 if (SCM_IS_WHVEC_ANY (w))
1375 {
1376 SCM *ptr;
1377 SCM obj;
1378 int j;
1379 int n;
1380
1381 obj = w;
1382 ptr = SCM_VELTS (w);
1383 n = SCM_LENGTH (w);
1384 for (j = 0; j < n; ++j)
1385 {
1386 SCM alist;
1387
1388 alist = ptr[j];
1389 while ( SCM_CONSP (alist)
1390 && !SCM_GCMARKP (alist)
1391 && SCM_CONSP (SCM_CAR (alist)))
1392 {
1393 SCM_SETGCMARK (alist);
1394 SCM_SETGCMARK (SCM_CAR (alist));
1395 alist = SCM_GCCDR (alist);
1396 }
1397 }
1398 }
1399 }
1400 }
1401
1402
1403 #ifdef GUILE_NEW_GC_SCHEME
1404 static void
1405 gc_sweep_freelist_start (scm_freelist_t *freelist)
1406 {
1407 freelist->cells = SCM_EOL;
1408 freelist->left_to_collect = freelist->cluster_size;
1409 freelist->clusters = SCM_EOL;
1410 freelist->clustertail = &freelist->clusters;
1411 freelist->collected = 0;
1412 }
1413
1414 static void
1415 gc_sweep_freelist_finish (scm_freelist_t *freelist)
1416 {
1417 *freelist->clustertail = freelist->cells;
1418 if (SCM_NNULLP (freelist->cells))
1419 {
1420 SCM c = freelist->cells;
1421 SCM_SETCAR (c, SCM_CDR (c));
1422 SCM_SETCDR (c, SCM_EOL);
1423 freelist->collected +=
1424 freelist->span * (freelist->cluster_size - freelist->left_to_collect);
1425 }
1426
1427 freelist->grow_heap_p = (freelist->collected < freelist->gc_trigger);
1428 }
1429 #endif
1430
1431 void
1432 scm_gc_sweep ()
1433 {
1434 register SCM_CELLPTR ptr;
1435 #ifdef SCM_POINTERS_MUNGED
1436 register SCM scmptr;
1437 #else
1438 #undef scmptr
1439 #define scmptr (SCM)ptr
1440 #endif
1441 register SCM nfreelist;
1442 register scm_freelist_t *freelist;
1443 register long m;
1444 register int span;
1445 long i;
1446 scm_sizet seg_size;
1447
1448 m = 0;
1449
1450 #ifdef GUILE_NEW_GC_SCHEME
1451 gc_sweep_freelist_start (&scm_master_freelist);
1452 gc_sweep_freelist_start (&scm_master_freelist2);
1453 #else
1454 /* Reset all free list pointers. We'll reconstruct them completely
1455 while scanning. */
1456 for (i = 0; i < scm_n_heap_segs; i++)
1457 scm_heap_table[i].freelist->cells = SCM_EOL;
1458 #endif
1459
1460 for (i = 0; i < scm_n_heap_segs; i++)
1461 {
1462 #ifdef GUILE_NEW_GC_SCHEME
1463 register unsigned int left_to_collect;
1464 #else
1465 register scm_sizet n = 0;
1466 #endif
1467 register scm_sizet j;
1468
1469 /* Unmarked cells go onto the front of the freelist this heap
1470 segment points to. Rather than updating the real freelist
1471 pointer as we go along, we accumulate the new head in
1472 nfreelist. Then, if it turns out that the entire segment is
1473 free, we free (i.e., malloc's free) the whole segment, and
1474 simply don't assign nfreelist back into the real freelist. */
1475 freelist = scm_heap_table[i].freelist;
1476 nfreelist = freelist->cells;
1477 #ifdef GUILE_NEW_GC_SCHEME
1478 left_to_collect = freelist->left_to_collect;
1479 #endif
1480 span = scm_heap_table[i].span;
1481
1482 ptr = CELL_UP (scm_heap_table[i].bounds[0]);
1483 seg_size = CELL_DN (scm_heap_table[i].bounds[1]) - ptr;
1484 for (j = seg_size + span; j -= span; ptr += span)
1485 {
1486 #ifdef SCM_POINTERS_MUNGED
1487 scmptr = PTR2SCM (ptr);
1488 #endif
1489 switch SCM_TYP7 (scmptr)
1490 {
1491 case scm_tcs_cons_gloc:
1492 if (SCM_GCMARKP (scmptr))
1493 {
1494 if (SCM_CDR (SCM_CAR (scmptr) - 1) == (SCM)1)
1495 SCM_SETCDR (SCM_CAR (scmptr) - 1, (SCM) 0);
1496 goto cmrkcontinue;
1497 }
1498 {
1499 SCM vcell;
1500 vcell = SCM_CAR (scmptr) - 1L;
1501
1502 if ((SCM_CDR (vcell) == 0) || (SCM_UNPACK (SCM_CDR (vcell)) == 1))
1503 {
1504 scm_struct_free_t free
1505 = (scm_struct_free_t) ((SCM*) vcell)[scm_struct_i_free];
1506 m += free ((SCM *) vcell, (SCM *) SCM_GCCDR (scmptr));
1507 }
1508 }
1509 break;
1510 case scm_tcs_cons_imcar:
1511 case scm_tcs_cons_nimcar:
1512 case scm_tcs_closures:
1513 case scm_tc7_pws:
1514 if (SCM_GCMARKP (scmptr))
1515 goto cmrkcontinue;
1516 break;
1517 case scm_tc7_wvect:
1518 if (SCM_GC8MARKP (scmptr))
1519 {
1520 goto c8mrkcontinue;
1521 }
1522 else
1523 {
1524 m += (2 + SCM_LENGTH (scmptr)) * sizeof (SCM);
1525 scm_must_free ((char *)(SCM_VELTS (scmptr) - 2));
1526 break;
1527 }
1528
1529 case scm_tc7_vector:
1530 case scm_tc7_lvector:
1531 #ifdef CCLO
1532 case scm_tc7_cclo:
1533 #endif
1534 if (SCM_GC8MARKP (scmptr))
1535 goto c8mrkcontinue;
1536
1537 m += (SCM_LENGTH (scmptr) * sizeof (SCM));
1538 freechars:
1539 scm_must_free (SCM_CHARS (scmptr));
1540 /* SCM_SETCHARS(scmptr, 0);*/
1541 break;
1542 #ifdef HAVE_ARRAYS
1543 case scm_tc7_bvect:
1544 if SCM_GC8MARKP (scmptr)
1545 goto c8mrkcontinue;
1546 m += sizeof (long) * ((SCM_HUGE_LENGTH (scmptr) + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
1547 goto freechars;
1548 case scm_tc7_byvect:
1549 if SCM_GC8MARKP (scmptr)
1550 goto c8mrkcontinue;
1551 m += SCM_HUGE_LENGTH (scmptr) * sizeof (char);
1552 goto freechars;
1553 case scm_tc7_ivect:
1554 case scm_tc7_uvect:
1555 if SCM_GC8MARKP (scmptr)
1556 goto c8mrkcontinue;
1557 m += SCM_HUGE_LENGTH (scmptr) * sizeof (long);
1558 goto freechars;
1559 case scm_tc7_svect:
1560 if SCM_GC8MARKP (scmptr)
1561 goto c8mrkcontinue;
1562 m += SCM_HUGE_LENGTH (scmptr) * sizeof (short);
1563 goto freechars;
1564 #ifdef HAVE_LONG_LONGS
1565 case scm_tc7_llvect:
1566 if SCM_GC8MARKP (scmptr)
1567 goto c8mrkcontinue;
1568 m += SCM_HUGE_LENGTH (scmptr) * sizeof (long_long);
1569 goto freechars;
1570 #endif
1571 case scm_tc7_fvect:
1572 if SCM_GC8MARKP (scmptr)
1573 goto c8mrkcontinue;
1574 m += SCM_HUGE_LENGTH (scmptr) * sizeof (float);
1575 goto freechars;
1576 case scm_tc7_dvect:
1577 if SCM_GC8MARKP (scmptr)
1578 goto c8mrkcontinue;
1579 m += SCM_HUGE_LENGTH (scmptr) * sizeof (double);
1580 goto freechars;
1581 case scm_tc7_cvect:
1582 if SCM_GC8MARKP (scmptr)
1583 goto c8mrkcontinue;
1584 m += SCM_HUGE_LENGTH (scmptr) * 2 * sizeof (double);
1585 goto freechars;
1586 #endif
1587 case scm_tc7_substring:
1588 if (SCM_GC8MARKP (scmptr))
1589 goto c8mrkcontinue;
1590 break;
1591 case scm_tc7_string:
1592 if (SCM_GC8MARKP (scmptr))
1593 goto c8mrkcontinue;
1594 m += SCM_HUGE_LENGTH (scmptr) + 1;
1595 goto freechars;
1596 case scm_tc7_msymbol:
1597 if (SCM_GC8MARKP (scmptr))
1598 goto c8mrkcontinue;
1599 m += ( SCM_LENGTH (scmptr)
1600 + 1
1601 + sizeof (SCM) * ((SCM *)SCM_CHARS (scmptr) - SCM_SLOTS(scmptr)));
1602 scm_must_free ((char *)SCM_SLOTS (scmptr));
1603 break;
1604 case scm_tc7_contin:
1605 if SCM_GC8MARKP (scmptr)
1606 goto c8mrkcontinue;
1607 m += SCM_LENGTH (scmptr) * sizeof (SCM_STACKITEM) + sizeof (scm_contregs);
1608 if (SCM_VELTS (scmptr))
1609 goto freechars;
1610 case scm_tc7_ssymbol:
1611 if SCM_GC8MARKP(scmptr)
1612 goto c8mrkcontinue;
1613 break;
1614 case scm_tcs_subrs:
1615 continue;
1616 case scm_tc7_port:
1617 if SCM_GC8MARKP (scmptr)
1618 goto c8mrkcontinue;
1619 if SCM_OPENP (scmptr)
1620 {
1621 int k = SCM_PTOBNUM (scmptr);
1622 if (!(k < scm_numptob))
1623 goto sweeperr;
1624 /* Keep "revealed" ports alive. */
1625 if (scm_revealed_count (scmptr) > 0)
1626 continue;
1627 /* Yes, I really do mean scm_ptobs[k].free */
1628 /* rather than ftobs[k].close. .close */
1629 /* is for explicit CLOSE-PORT by user */
1630 m += (scm_ptobs[k].free) (scmptr);
1631 SCM_SETSTREAM (scmptr, 0);
1632 scm_remove_from_port_table (scmptr);
1633 scm_gc_ports_collected++;
1634 SCM_SETAND_CAR (scmptr, ~SCM_OPN);
1635 }
1636 break;
1637 case scm_tc7_smob:
1638 switch SCM_GCTYP16 (scmptr)
1639 {
1640 case scm_tc_free_cell:
1641 case scm_tc16_real:
1642 if SCM_GC8MARKP (scmptr)
1643 goto c8mrkcontinue;
1644 break;
1645 #ifdef SCM_BIGDIG
1646 case scm_tc16_big:
1647 if SCM_GC8MARKP (scmptr)
1648 goto c8mrkcontinue;
1649 m += (SCM_NUMDIGS (scmptr) * SCM_BITSPERDIG / SCM_CHAR_BIT);
1650 goto freechars;
1651 #endif /* def SCM_BIGDIG */
1652 case scm_tc16_complex:
1653 if SCM_GC8MARKP (scmptr)
1654 goto c8mrkcontinue;
1655 m += 2 * sizeof (double);
1656 goto freechars;
1657 default:
1658 if SCM_GC8MARKP (scmptr)
1659 goto c8mrkcontinue;
1660
1661 {
1662 int k;
1663 k = SCM_SMOBNUM (scmptr);
1664 if (!(k < scm_numsmob))
1665 goto sweeperr;
1666 m += (scm_smobs[k].free) ((SCM) scmptr);
1667 break;
1668 }
1669 }
1670 break;
1671 default:
1672 sweeperr:scm_wta (scmptr, "unknown type in ", "gc_sweep");
1673 }
1674 #if 0
1675 if (SCM_CAR (scmptr) == (SCM) scm_tc_free_cell)
1676 exit (2);
1677 #endif
1678 #ifndef GUILE_NEW_GC_SCHEME
1679 n += span;
1680 #else
1681 if (!--left_to_collect)
1682 {
1683 SCM_SETCAR (scmptr, nfreelist);
1684 *freelist->clustertail = scmptr;
1685 freelist->clustertail = SCM_CDRLOC (scmptr);
1686
1687 nfreelist = SCM_EOL;
1688 freelist->collected += span * freelist->cluster_size;
1689 left_to_collect = freelist->cluster_size;
1690 }
1691 else
1692 #endif
1693 {
1694 /* Stick the new cell on the front of nfreelist. It's
1695 critical that we mark this cell as freed; otherwise, the
1696 conservative collector might trace it as some other type
1697 of object. */
1698 SCM_SETCAR (scmptr, scm_tc_free_cell);
1699 SCM_SETCDR (scmptr, nfreelist);
1700 nfreelist = scmptr;
1701 }
1702
1703 continue;
1704 c8mrkcontinue:
1705 SCM_CLRGC8MARK (scmptr);
1706 continue;
1707 cmrkcontinue:
1708 SCM_CLRGCMARK (scmptr);
1709 }
1710 #ifdef GC_FREE_SEGMENTS
1711 if (n == seg_size)
1712 {
1713 register long j;
1714
1715 freelist->heap_size -= seg_size;
1716 free ((char *) scm_heap_table[i].bounds[0]);
1717 scm_heap_table[i].bounds[0] = 0;
1718 for (j = i + 1; j < scm_n_heap_segs; j++)
1719 scm_heap_table[j - 1] = scm_heap_table[j];
1720 scm_n_heap_segs -= 1;
1721 i--; /* We need to scan the segment just moved. */
1722 }
1723 else
1724 #endif /* ifdef GC_FREE_SEGMENTS */
1725 {
1726 /* Update the real freelist pointer to point to the head of
1727 the list of free cells we've built for this segment. */
1728 freelist->cells = nfreelist;
1729 #ifdef GUILE_NEW_GC_SCHEME
1730 freelist->left_to_collect = left_to_collect;
1731 #endif
1732 }
1733
1734 #ifndef GUILE_NEW_GC_SCHEME
1735 freelist->collected += n;
1736 scm_cells_allocated += freelist->heap_size - freelist->collected;
1737 #endif
1738
1739 #ifdef GUILE_DEBUG_FREELIST
1740 #ifdef GUILE_NEW_GC_SCHEME
1741 scm_check_freelist (freelist == &scm_master_freelist
1742 ? scm_freelist
1743 : scm_freelist2);
1744 #else
1745 scm_check_freelist (freelist);
1746 #endif
1747 scm_map_free_list ();
1748 #endif
1749 }
1750
1751 #ifdef GUILE_NEW_GC_SCHEME
1752 gc_sweep_freelist_finish (&scm_master_freelist);
1753 gc_sweep_freelist_finish (&scm_master_freelist2);
1754
1755 /* When we move to POSIX threads private freelists should probably
1756 be GC-protected instead. */
1757 scm_freelist = SCM_EOL;
1758 scm_freelist2 = SCM_EOL;
1759 #endif
1760
1761 /* Scan weak vectors. */
1762 {
1763 SCM *ptr, w;
1764 for (w = scm_weak_vectors; w != SCM_EOL; w = SCM_WVECT_GC_CHAIN (w))
1765 {
1766 if (!SCM_IS_WHVEC_ANY (w))
1767 {
1768 register long j, n;
1769
1770 ptr = SCM_VELTS (w);
1771 n = SCM_LENGTH (w);
1772 for (j = 0; j < n; ++j)
1773 if (SCM_FREEP (ptr[j]))
1774 ptr[j] = SCM_BOOL_F;
1775 }
1776 else /* if (SCM_IS_WHVEC_ANY (scm_weak_vectors[i])) */
1777 {
1778 SCM obj = w;
1779 register long n = SCM_LENGTH (w);
1780 register long j;
1781
1782 ptr = SCM_VELTS (w);
1783
1784 for (j = 0; j < n; ++j)
1785 {
1786 SCM * fixup;
1787 SCM alist;
1788 int weak_keys;
1789 int weak_values;
1790
1791 weak_keys = SCM_IS_WHVEC (obj) || SCM_IS_WHVEC_B (obj);
1792 weak_values = SCM_IS_WHVEC_V (obj) || SCM_IS_WHVEC_B (obj);
1793
1794 fixup = ptr + j;
1795 alist = *fixup;
1796
1797 while ( SCM_CONSP (alist)
1798 && SCM_CONSP (SCM_CAR (alist)))
1799 {
1800 SCM key;
1801 SCM value;
1802
1803 key = SCM_CAAR (alist);
1804 value = SCM_CDAR (alist);
1805 if ( (weak_keys && SCM_FREEP (key))
1806 || (weak_values && SCM_FREEP (value)))
1807 {
1808 *fixup = SCM_CDR (alist);
1809 }
1810 else
1811 fixup = SCM_CDRLOC (alist);
1812 alist = SCM_CDR (alist);
1813 }
1814 }
1815 }
1816 }
1817 }
1818 scm_mallocated -= m;
1819 scm_gc_malloc_collected = m;
1820 }
1821
1822
1823 \f
1824
1825 /* {Front end to malloc}
1826 *
1827 * scm_must_malloc, scm_must_realloc, scm_must_free, scm_done_malloc
1828 *
1829 * These functions provide services comperable to malloc, realloc, and
1830 * free. They are for allocating malloced parts of scheme objects.
1831 * The primary purpose of the front end is to impose calls to gc.
1832 */
1833
1834 /* scm_must_malloc
1835 * Return newly malloced storage or throw an error.
1836 *
1837 * The parameter WHAT is a string for error reporting.
1838 * If the threshold scm_mtrigger will be passed by this
1839 * allocation, or if the first call to malloc fails,
1840 * garbage collect -- on the presumption that some objects
1841 * using malloced storage may be collected.
1842 *
1843 * The limit scm_mtrigger may be raised by this allocation.
1844 */
1845 void *
1846 scm_must_malloc (scm_sizet size, const char *what)
1847 {
1848 void *ptr;
1849 unsigned long nm = scm_mallocated + size;
1850
1851 if (nm <= scm_mtrigger)
1852 {
1853 SCM_SYSCALL (ptr = malloc (size));
1854 if (NULL != ptr)
1855 {
1856 scm_mallocated = nm;
1857 return ptr;
1858 }
1859 }
1860
1861 scm_igc (what);
1862
1863 nm = scm_mallocated + size;
1864 SCM_SYSCALL (ptr = malloc (size));
1865 if (NULL != ptr)
1866 {
1867 scm_mallocated = nm;
1868 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
1869 if (nm > scm_mtrigger)
1870 scm_mtrigger = nm + nm / 2;
1871 else
1872 scm_mtrigger += scm_mtrigger / 2;
1873 }
1874 return ptr;
1875 }
1876
1877 scm_wta (SCM_MAKINUM (size), (char *) SCM_NALLOC, what);
1878 return 0; /* never reached */
1879 }
1880
1881
1882 /* scm_must_realloc
1883 * is similar to scm_must_malloc.
1884 */
1885 void *
1886 scm_must_realloc (void *where,
1887 scm_sizet old_size,
1888 scm_sizet size,
1889 const char *what)
1890 {
1891 void *ptr;
1892 scm_sizet nm = scm_mallocated + size - old_size;
1893
1894 if (nm <= scm_mtrigger)
1895 {
1896 SCM_SYSCALL (ptr = realloc (where, size));
1897 if (NULL != ptr)
1898 {
1899 scm_mallocated = nm;
1900 return ptr;
1901 }
1902 }
1903
1904 scm_igc (what);
1905
1906 nm = scm_mallocated + size - old_size;
1907 SCM_SYSCALL (ptr = realloc (where, size));
1908 if (NULL != ptr)
1909 {
1910 scm_mallocated = nm;
1911 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
1912 if (nm > scm_mtrigger)
1913 scm_mtrigger = nm + nm / 2;
1914 else
1915 scm_mtrigger += scm_mtrigger / 2;
1916 }
1917 return ptr;
1918 }
1919
1920 scm_wta (SCM_MAKINUM (size), (char *) SCM_NALLOC, what);
1921 return 0; /* never reached */
1922 }
1923
1924 void
1925 scm_must_free (void *obj)
1926 {
1927 if (obj)
1928 free (obj);
1929 else
1930 scm_wta (SCM_INUM0, "already free", "");
1931 }
1932
1933 /* Announce that there has been some malloc done that will be freed
1934 * during gc. A typical use is for a smob that uses some malloced
1935 * memory but can not get it from scm_must_malloc (for whatever
1936 * reason). When a new object of this smob is created you call
1937 * scm_done_malloc with the size of the object. When your smob free
1938 * function is called, be sure to include this size in the return
1939 * value. */
1940
1941 void
1942 scm_done_malloc (long size)
1943 {
1944 scm_mallocated += size;
1945
1946 if (scm_mallocated > scm_mtrigger)
1947 {
1948 scm_igc ("foreign mallocs");
1949 if (scm_mallocated > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS)
1950 {
1951 if (scm_mallocated > scm_mtrigger)
1952 scm_mtrigger = scm_mallocated + scm_mallocated / 2;
1953 else
1954 scm_mtrigger += scm_mtrigger / 2;
1955 }
1956 }
1957 }
1958
1959
1960 #ifdef GUILE_NEW_GC_SCHEME
1961 static void
1962 adjust_gc_trigger (scm_freelist_t *freelist)
1963 {
1964 /* Adjust GC trigger based on total heap size */
1965 if (freelist->gc_trigger_fraction)
1966 freelist->gc_trigger = ((scm_master_freelist.heap_size
1967 + scm_master_freelist2.heap_size)
1968 * freelist->gc_trigger_fraction
1969 / 100);
1970 }
1971 #endif
1972
1973
1974 \f
1975
1976 /* {Heap Segments}
1977 *
1978 * Each heap segment is an array of objects of a particular size.
1979 * Every segment has an associated (possibly shared) freelist.
1980 * A table of segment records is kept that records the upper and
1981 * lower extents of the segment; this is used during the conservative
1982 * phase of gc to identify probably gc roots (because they point
1983 * into valid segments at reasonable offsets). */
1984
1985 /* scm_expmem
1986 * is true if the first segment was smaller than INIT_HEAP_SEG.
1987 * If scm_expmem is set to one, subsequent segment allocations will
1988 * allocate segments of size SCM_EXPHEAP(scm_heap_size).
1989 */
1990 int scm_expmem = 0;
1991
1992 scm_sizet scm_max_segment_size;
1993
1994 /* scm_heap_org
1995 * is the lowest base address of any heap segment.
1996 */
1997 SCM_CELLPTR scm_heap_org;
1998
1999 struct scm_heap_seg_data * scm_heap_table = 0;
2000 int scm_n_heap_segs = 0;
2001
2002 /* init_heap_seg
2003 * initializes a new heap segment and return the number of objects it contains.
2004 *
2005 * The segment origin, segment size in bytes, and the span of objects
2006 * in cells are input parameters. The freelist is both input and output.
2007 *
2008 * This function presume that the scm_heap_table has already been expanded
2009 * to accomodate a new segment record.
2010 */
2011
2012
2013 static scm_sizet
2014 init_heap_seg (SCM_CELLPTR seg_org, scm_sizet size, scm_freelist_t *freelist)
2015 {
2016 register SCM_CELLPTR ptr;
2017 #ifdef SCM_POINTERS_MUNGED
2018 register SCM scmptr;
2019 #else
2020 #undef scmptr
2021 #define scmptr ptr
2022 #endif
2023 SCM_CELLPTR seg_end;
2024 int new_seg_index;
2025 int n_new_cells;
2026 int span = freelist->span;
2027
2028 if (seg_org == NULL)
2029 return 0;
2030
2031 ptr = seg_org;
2032
2033 size = (size / sizeof (scm_cell) / span) * span * sizeof (scm_cell);
2034
2035 /* Compute the ceiling on valid object pointers w/in this segment.
2036 */
2037 seg_end = CELL_DN ((char *) ptr + size);
2038
2039 /* Find the right place and insert the segment record.
2040 *
2041 */
2042 for (new_seg_index = 0;
2043 ( (new_seg_index < scm_n_heap_segs)
2044 && SCM_PTR_LE (scm_heap_table[new_seg_index].bounds[0], seg_org));
2045 new_seg_index++)
2046 ;
2047
2048 {
2049 int i;
2050 for (i = scm_n_heap_segs; i > new_seg_index; --i)
2051 scm_heap_table[i] = scm_heap_table[i - 1];
2052 }
2053
2054 ++scm_n_heap_segs;
2055
2056 scm_heap_table[new_seg_index].valid = 0;
2057 scm_heap_table[new_seg_index].span = span;
2058 scm_heap_table[new_seg_index].freelist = freelist;
2059 scm_heap_table[new_seg_index].bounds[0] = (SCM_CELLPTR)ptr;
2060 scm_heap_table[new_seg_index].bounds[1] = (SCM_CELLPTR)seg_end;
2061
2062
2063 /* Compute the least valid object pointer w/in this segment
2064 */
2065 ptr = CELL_UP (ptr);
2066
2067
2068 /*n_new_cells*/
2069 n_new_cells = seg_end - ptr;
2070
2071 #ifdef GUILE_NEW_GC_SCHEME
2072
2073 freelist->heap_size += n_new_cells;
2074
2075 /* Partition objects in this segment into clusters
2076 */
2077 {
2078 SCM clusters;
2079 SCM *clusterp = &clusters;
2080 int n_cluster_cells = span * freelist->cluster_size;
2081
2082 while (n_new_cells > span) /* at least one spine + one freecell */
2083 {
2084 /* Determine end of cluster
2085 */
2086 if (n_new_cells >= n_cluster_cells)
2087 {
2088 seg_end = ptr + n_cluster_cells;
2089 n_new_cells -= n_cluster_cells;
2090 }
2091 else
2092 {
2093 seg_end = ptr + n_new_cells;
2094 n_new_cells = 0;
2095 }
2096
2097 /* Allocate cluster spine
2098 */
2099 *clusterp = PTR2SCM (ptr);
2100 SCM_SETCAR (*clusterp, PTR2SCM (ptr + span));
2101 clusterp = SCM_CDRLOC (*clusterp);
2102 ptr += span;
2103
2104 while (ptr < seg_end)
2105 {
2106 #ifdef SCM_POINTERS_MUNGED
2107 scmptr = PTR2SCM (ptr);
2108 #endif
2109 SCM_SETCAR (scmptr, scm_tc_free_cell);
2110 SCM_SETCDR (scmptr, PTR2SCM (ptr + span));
2111 ptr += span;
2112 }
2113
2114 SCM_SETCDR (PTR2SCM (ptr - span), SCM_EOL);
2115 }
2116
2117 /* Patch up the last cluster pointer in the segment
2118 * to join it to the input freelist.
2119 */
2120 *clusterp = freelist->clusters;
2121 freelist->clusters = clusters;
2122 }
2123
2124 adjust_gc_trigger (&scm_master_freelist);
2125 adjust_gc_trigger (&scm_master_freelist2);
2126
2127 #else /* GUILE_NEW_GC_SCHEME */
2128
2129 /* Prepend objects in this segment to the freelist.
2130 */
2131 while (ptr < seg_end)
2132 {
2133 #ifdef SCM_POINTERS_MUNGED
2134 scmptr = PTR2SCM (ptr);
2135 #endif
2136 SCM_SETCAR (scmptr, (SCM) scm_tc_free_cell);
2137 SCM_SETCDR (scmptr, PTR2SCM (ptr + span));
2138 ptr += span;
2139 }
2140
2141 ptr -= span;
2142
2143 /* Patch up the last freelist pointer in the segment
2144 * to join it to the input freelist.
2145 */
2146 SCM_SETCDR (PTR2SCM (ptr), freelist->cells);
2147 freelist->cells = PTR2SCM (CELL_UP (seg_org));
2148
2149 freelist->heap_size += n_new_cells;
2150
2151 #endif /* GUILE_NEW_GC_SCHEME */
2152
2153 #ifdef DEBUGINFO
2154 fprintf (stderr, "H");
2155 #endif
2156 return size;
2157 #ifdef scmptr
2158 #undef scmptr
2159 #endif
2160 }
2161
2162
2163 static void
2164 alloc_some_heap (scm_freelist_t *freelist)
2165 {
2166 struct scm_heap_seg_data * tmptable;
2167 SCM_CELLPTR ptr;
2168 scm_sizet len;
2169
2170 /* Critical code sections (such as the garbage collector)
2171 * aren't supposed to add heap segments.
2172 */
2173 if (scm_gc_heap_lock)
2174 scm_wta (SCM_UNDEFINED, "need larger initial", "heap");
2175
2176 /* Expand the heap tables to have room for the new segment.
2177 * Do not yet increment scm_n_heap_segs -- that is done by init_heap_seg
2178 * only if the allocation of the segment itself succeeds.
2179 */
2180 len = (1 + scm_n_heap_segs) * sizeof (struct scm_heap_seg_data);
2181
2182 SCM_SYSCALL (tmptable = ((struct scm_heap_seg_data *)
2183 realloc ((char *)scm_heap_table, len)));
2184 if (!tmptable)
2185 scm_wta (SCM_UNDEFINED, "could not grow", "hplims");
2186 else
2187 scm_heap_table = tmptable;
2188
2189
2190 /* Pick a size for the new heap segment.
2191 * The rule for picking the size of a segment is explained in
2192 * gc.h
2193 */
2194 #ifdef GUILE_NEW_GC_SCHEME
2195 {
2196 /* Assure that the new segment is large enough for the new trigger */
2197 int slack = freelist->gc_trigger - freelist->collected;
2198 int min_cells = 100 * slack / (99 - freelist->gc_trigger_fraction);
2199 len = SCM_EXPHEAP (freelist->heap_size);
2200 #ifdef DEBUGINFO
2201 fprintf (stderr, "(%d < %d)", len, min_cells);
2202 #endif
2203 if (len < min_cells)
2204 len = min_cells + 1;
2205 len *= sizeof (scm_cell);
2206 }
2207
2208 if (len > scm_max_segment_size)
2209 len = scm_max_segment_size;
2210 #else
2211 if (scm_expmem)
2212 {
2213 len = (scm_sizet) SCM_EXPHEAP (freelist->heap_size * sizeof (scm_cell));
2214 if ((scm_sizet) SCM_EXPHEAP (freelist->heap_size * sizeof (scm_cell))
2215 != len)
2216 len = 0;
2217 }
2218 else
2219 len = SCM_HEAP_SEG_SIZE;
2220 #endif /* GUILE_NEW_GC_SCHEME */
2221
2222 {
2223 scm_sizet smallest;
2224
2225 smallest = (freelist->span * sizeof (scm_cell));
2226 if (len < smallest)
2227 len = (freelist->span * sizeof (scm_cell));
2228
2229 /* Allocate with decaying ambition. */
2230 while ((len >= SCM_MIN_HEAP_SEG_SIZE)
2231 && (len >= smallest))
2232 {
2233 SCM_SYSCALL (ptr = (SCM_CELLPTR) malloc (len));
2234 if (ptr)
2235 {
2236 init_heap_seg (ptr, len, freelist);
2237 return;
2238 }
2239 len /= 2;
2240 }
2241 }
2242
2243 scm_wta (SCM_UNDEFINED, "could not grow", "heap");
2244 }
2245
2246
2247
2248 SCM_DEFINE (scm_unhash_name, "unhash-name", 1, 0, 0,
2249 (SCM name),
2250 "")
2251 #define FUNC_NAME s_scm_unhash_name
2252 {
2253 int x;
2254 int bound;
2255 SCM_VALIDATE_SYMBOL (1,name);
2256 SCM_DEFER_INTS;
2257 bound = scm_n_heap_segs;
2258 for (x = 0; x < bound; ++x)
2259 {
2260 SCM_CELLPTR p;
2261 SCM_CELLPTR pbound;
2262 p = (SCM_CELLPTR)scm_heap_table[x].bounds[0];
2263 pbound = (SCM_CELLPTR)scm_heap_table[x].bounds[1];
2264 while (p < pbound)
2265 {
2266 SCM incar;
2267 incar = p->car;
2268 if (1 == (7 & (int)incar))
2269 {
2270 --incar;
2271 if ( ((name == SCM_BOOL_T) || (SCM_CAR (incar) == name))
2272 && (SCM_CDR (incar) != 0)
2273 && (SCM_UNPACK (SCM_CDR (incar)) != 1))
2274 {
2275 p->car = name;
2276 }
2277 }
2278 ++p;
2279 }
2280 }
2281 SCM_ALLOW_INTS;
2282 return name;
2283 }
2284 #undef FUNC_NAME
2285
2286
2287 \f
2288 /* {GC Protection Helper Functions}
2289 */
2290
2291
2292 void
2293 scm_remember (SCM *ptr)
2294 { /* empty */ }
2295
2296
2297 /*
2298 These crazy functions prevent garbage collection
2299 of arguments after the first argument by
2300 ensuring they remain live throughout the
2301 function because they are used in the last
2302 line of the code block.
2303 It'd be better to have a nice compiler hint to
2304 aid the conservative stack-scanning GC. --03/09/00 gjb */
2305 SCM
2306 scm_return_first (SCM elt, ...)
2307 {
2308 return elt;
2309 }
2310
2311 int
2312 scm_return_first_int (int i, ...)
2313 {
2314 return i;
2315 }
2316
2317
2318 SCM
2319 scm_permanent_object (SCM obj)
2320 {
2321 SCM_REDEFER_INTS;
2322 scm_permobjs = scm_cons (obj, scm_permobjs);
2323 SCM_REALLOW_INTS;
2324 return obj;
2325 }
2326
2327
2328 /* Protect OBJ from the garbage collector. OBJ will not be freed,
2329 even if all other references are dropped, until someone applies
2330 scm_unprotect_object to it. This function returns OBJ.
2331
2332 Calls to scm_protect_object nest. For every object OBJ, there is a
2333 counter which scm_protect_object(OBJ) increments and
2334 scm_unprotect_object(OBJ) decrements, if it is greater than zero. If
2335 an object's counter is greater than zero, the garbage collector
2336 will not free it.
2337
2338 Of course, that's not how it's implemented. scm_protect_object and
2339 scm_unprotect_object just maintain a list of references to things.
2340 Since the GC knows about this list, all objects it mentions stay
2341 alive. scm_protect_object adds its argument to the list;
2342 scm_unprotect_object removes the first occurrence of its argument
2343 to the list. */
2344 SCM
2345 scm_protect_object (SCM obj)
2346 {
2347 scm_protects = scm_cons (obj, scm_protects);
2348
2349 return obj;
2350 }
2351
2352
2353 /* Remove any protection for OBJ established by a prior call to
2354 scm_protect_object. This function returns OBJ.
2355
2356 See scm_protect_object for more information. */
2357 SCM
2358 scm_unprotect_object (SCM obj)
2359 {
2360 SCM *tail_ptr = &scm_protects;
2361
2362 while (SCM_CONSP (*tail_ptr))
2363 if (SCM_CAR (*tail_ptr) == obj)
2364 {
2365 *tail_ptr = SCM_CDR (*tail_ptr);
2366 break;
2367 }
2368 else
2369 tail_ptr = SCM_CDRLOC (*tail_ptr);
2370
2371 return obj;
2372 }
2373
2374 int terminating;
2375
2376 /* called on process termination. */
2377 #ifdef HAVE_ATEXIT
2378 static void
2379 cleanup (void)
2380 #else
2381 #ifdef HAVE_ON_EXIT
2382 extern int on_exit (void (*procp) (), int arg);
2383
2384 static void
2385 cleanup (int status, void *arg)
2386 #else
2387 #error Dont know how to setup a cleanup handler on your system.
2388 #endif
2389 #endif
2390 {
2391 terminating = 1;
2392 scm_flush_all_ports ();
2393 }
2394
2395 \f
2396 static int
2397 make_initial_segment (scm_sizet init_heap_size, scm_freelist_t *freelist)
2398 {
2399 if (!init_heap_seg ((SCM_CELLPTR) malloc (init_heap_size),
2400 init_heap_size,
2401 freelist))
2402 {
2403 init_heap_size = SCM_HEAP_SEG_SIZE;
2404 if (!init_heap_seg ((SCM_CELLPTR) malloc (init_heap_size),
2405 init_heap_size,
2406 freelist))
2407 return 1;
2408 }
2409 else
2410 scm_expmem = 1;
2411
2412 freelist->grow_heap_p = (freelist->heap_size < freelist->gc_trigger);
2413
2414 return 0;
2415 }
2416
2417 \f
2418 #ifdef GUILE_NEW_GC_SCHEME
2419 static void
2420 init_freelist (scm_freelist_t *freelist,
2421 int span,
2422 int cluster_size,
2423 int gc_trigger)
2424 {
2425 freelist->clusters = SCM_EOL;
2426 freelist->cluster_size = cluster_size + 1;
2427 if (gc_trigger < 0)
2428 freelist->gc_trigger_fraction = - gc_trigger;
2429 else
2430 {
2431 freelist->gc_trigger = gc_trigger;
2432 freelist->gc_trigger_fraction = 0;
2433 }
2434 freelist->span = span;
2435 freelist->collected = 0;
2436 freelist->heap_size = 0;
2437 }
2438
2439 int
2440 scm_init_storage (scm_sizet init_heap_size_1, int gc_trigger_1,
2441 scm_sizet init_heap_size_2, int gc_trigger_2,
2442 scm_sizet max_segment_size)
2443 #else
2444 int
2445 scm_init_storage (scm_sizet init_heap_size, scm_sizet init_heap2_size)
2446 #endif
2447 {
2448 scm_sizet j;
2449
2450 if (!init_heap_size_1)
2451 init_heap_size_1 = SCM_INIT_HEAP_SIZE_1;
2452 if (!init_heap_size_2)
2453 init_heap_size_2 = SCM_INIT_HEAP_SIZE_2;
2454
2455 j = SCM_NUM_PROTECTS;
2456 while (j)
2457 scm_sys_protects[--j] = SCM_BOOL_F;
2458 scm_block_gc = 1;
2459
2460 #ifdef GUILE_NEW_GC_SCHEME
2461 scm_freelist = SCM_EOL;
2462 scm_freelist2 = SCM_EOL;
2463 init_freelist (&scm_master_freelist,
2464 1, SCM_CLUSTER_SIZE_1,
2465 gc_trigger_1 ? gc_trigger_1 : SCM_GC_TRIGGER_1);
2466 init_freelist (&scm_master_freelist2,
2467 2, SCM_CLUSTER_SIZE_2,
2468 gc_trigger_2 ? gc_trigger_2 : SCM_GC_TRIGGER_2);
2469 scm_max_segment_size
2470 = max_segment_size ? max_segment_size : SCM_MAX_SEGMENT_SIZE;
2471 #else
2472 scm_freelist.cells = SCM_EOL;
2473 scm_freelist.span = 1;
2474 scm_freelist.collected = 0;
2475 scm_freelist.heap_size = 0;
2476
2477 scm_freelist2.cells = SCM_EOL;
2478 scm_freelist2.span = 2;
2479 scm_freelist2.collected = 0;
2480 scm_freelist2.heap_size = 0;
2481 #endif
2482
2483 scm_expmem = 0;
2484
2485 j = SCM_HEAP_SEG_SIZE;
2486 scm_mtrigger = SCM_INIT_MALLOC_LIMIT;
2487 scm_heap_table = ((struct scm_heap_seg_data *)
2488 scm_must_malloc (sizeof (struct scm_heap_seg_data) * 2, "hplims"));
2489
2490 #ifdef GUILE_NEW_GC_SCHEME
2491 if (make_initial_segment (init_heap_size_1, &scm_master_freelist) ||
2492 make_initial_segment (init_heap_size_2, &scm_master_freelist2))
2493 return 1;
2494 #else
2495 if (make_initial_segment (init_heap_size_1, &scm_freelist) ||
2496 make_initial_segment (init_heap_size_2, &scm_freelist2))
2497 return 1;
2498 #endif
2499
2500 scm_heap_org = CELL_UP (scm_heap_table[0].bounds[0]);
2501
2502 /* scm_hplims[0] can change. do not remove scm_heap_org */
2503 scm_weak_vectors = SCM_EOL;
2504
2505 /* Initialise the list of ports. */
2506 scm_port_table = (scm_port **)
2507 malloc (sizeof (scm_port *) * scm_port_table_room);
2508 if (!scm_port_table)
2509 return 1;
2510
2511 #ifdef HAVE_ATEXIT
2512 atexit (cleanup);
2513 #else
2514 #ifdef HAVE_ON_EXIT
2515 on_exit (cleanup, 0);
2516 #endif
2517 #endif
2518
2519 scm_undefineds = scm_cons (SCM_UNDEFINED, SCM_EOL);
2520 SCM_SETCDR (scm_undefineds, scm_undefineds);
2521
2522 scm_listofnull = scm_cons (SCM_EOL, SCM_EOL);
2523 scm_nullstr = scm_makstr (0L, 0);
2524 scm_nullvect = scm_make_vector (SCM_INUM0, SCM_UNDEFINED);
2525 scm_symhash = scm_make_vector ((SCM) SCM_MAKINUM (scm_symhash_dim), SCM_EOL);
2526 scm_weak_symhash = scm_make_weak_key_hash_table ((SCM) SCM_MAKINUM (scm_symhash_dim));
2527 scm_symhash_vars = scm_make_vector ((SCM) SCM_MAKINUM (scm_symhash_dim), SCM_EOL);
2528 scm_stand_in_procs = SCM_EOL;
2529 scm_permobjs = SCM_EOL;
2530 scm_protects = SCM_EOL;
2531 scm_asyncs = SCM_EOL;
2532 scm_sysintern ("most-positive-fixnum", (SCM) SCM_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
2533 scm_sysintern ("most-negative-fixnum", (SCM) SCM_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
2534 #ifdef SCM_BIGDIG
2535 scm_sysintern ("bignum-radix", SCM_MAKINUM (SCM_BIGRAD));
2536 #endif
2537 return 0;
2538 }
2539 \f
2540
2541 void
2542 scm_init_gc ()
2543 {
2544 #include "gc.x"
2545 }