*** empty log message ***
[bpt/guile.git] / libguile / gc.c
CommitLineData
22a52da1 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
a00c95d9 2 *
0f2d19dd
JB
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.
a00c95d9 7 *
0f2d19dd
JB
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.
a00c95d9 12 *
0f2d19dd
JB
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
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
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.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
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
37ddcaf6
MD
45/* #define DEBUGINFO */
46
56495472
ML
47/* SECTION: This code is compiled once.
48 */
49
50#ifndef MARK_DEPENDENCIES
51
0f2d19dd
JB
52\f
53#include <stdio.h>
e6e2e95a 54#include <errno.h>
783e7774 55#include <string.h>
e6e2e95a 56
a0599745 57#include "libguile/_scm.h"
0a7a7445 58#include "libguile/eval.h"
a0599745
MD
59#include "libguile/stime.h"
60#include "libguile/stackchk.h"
61#include "libguile/struct.h"
a0599745
MD
62#include "libguile/smob.h"
63#include "libguile/unif.h"
64#include "libguile/async.h"
65#include "libguile/ports.h"
66#include "libguile/root.h"
67#include "libguile/strings.h"
68#include "libguile/vectors.h"
801cb5e7 69#include "libguile/weaks.h"
686765af 70#include "libguile/hashtab.h"
ecf470a2 71#include "libguile/tags.h"
a0599745
MD
72
73#include "libguile/validate.h"
1be6b49c 74#include "libguile/deprecation.h"
a0599745 75#include "libguile/gc.h"
fce59c93 76
bc9d9bb2 77#ifdef GUILE_DEBUG_MALLOC
a0599745 78#include "libguile/debug-malloc.h"
bc9d9bb2
MD
79#endif
80
0f2d19dd 81#ifdef HAVE_MALLOC_H
95b88819 82#include <malloc.h>
0f2d19dd
JB
83#endif
84
85#ifdef HAVE_UNISTD_H
95b88819 86#include <unistd.h>
0f2d19dd
JB
87#endif
88
1cc91f1b
JB
89#ifdef __STDC__
90#include <stdarg.h>
91#define var_start(x, y) va_start(x, y)
92#else
93#include <varargs.h>
94#define var_start(x, y) va_start(x)
95#endif
96
0f2d19dd 97\f
406c7d90
DH
98
99unsigned int scm_gc_running_p = 0;
100
101\f
102
103#if (SCM_DEBUG_CELL_ACCESSES == 1)
104
92c2555f 105scm_t_bits scm_tc16_allocated;
61045190
DH
106
107/* Set this to != 0 if every cell that is accessed shall be checked:
108 */
109unsigned int scm_debug_cell_accesses_p = 1;
406c7d90 110
e81d98ec
DH
111/* Set this to 0 if no additional gc's shall be performed, otherwise set it to
112 * the number of cell accesses after which a gc shall be called.
113 */
114static unsigned int debug_cells_gc_interval = 0;
115
406c7d90 116
592996c9
DH
117/* If an allocated cell is detected during garbage collection, this means that
118 * some code has just obtained the object but was preempted before the
119 * initialization of the object was completed. This meanst that some entries
120 * of the allocated cell may already contain SCM objects. Therefore,
121 * allocated cells are scanned conservatively. */
122static SCM
123allocated_mark (SCM allocated)
124{
125 scm_gc_mark_cell_conservatively (allocated);
126 return SCM_BOOL_F;
127}
128
129
406c7d90
DH
130/* Assert that the given object is a valid reference to a valid cell. This
131 * test involves to determine whether the object is a cell pointer, whether
132 * this pointer actually points into a heap segment and whether the cell
e81d98ec
DH
133 * pointed to is not a free cell. Further, additional garbage collections may
134 * get executed after a user defined number of cell accesses. This helps to
135 * find places in the C code where references are dropped for extremely short
136 * periods.
406c7d90
DH
137 */
138void
139scm_assert_cell_valid (SCM cell)
140{
61045190
DH
141 static unsigned int already_running = 0;
142
143 if (scm_debug_cell_accesses_p && !already_running)
406c7d90 144 {
61045190 145 already_running = 1; /* set to avoid recursion */
406c7d90 146
9d47a1e6 147 if (!scm_cellp (cell))
406c7d90 148 {
1be6b49c
ML
149 fprintf (stderr, "scm_assert_cell_valid: Not a cell object: %lux\n",
150 (unsigned long) SCM_UNPACK (cell));
406c7d90
DH
151 abort ();
152 }
153 else if (!scm_gc_running_p)
154 {
155 /* Dirk::FIXME:: During garbage collection there occur references to
156 free cells. This is allright during conservative marking, but
157 should not happen otherwise (I think). The case of free cells
158 accessed during conservative marking is handled in function
159 scm_mark_locations. However, there still occur accesses to free
160 cells during gc. I don't understand why this happens. If it is
161 a bug and gets fixed, the following test should also work while
162 gc is running.
163 */
164 if (SCM_FREE_CELL_P (cell))
165 {
1be6b49c
ML
166 fprintf (stderr, "scm_assert_cell_valid: Accessing free cell: %lux\n",
167 (unsigned long) SCM_UNPACK (cell));
406c7d90
DH
168 abort ();
169 }
e81d98ec
DH
170
171 /* If desired, perform additional garbage collections after a user
172 * defined number of cell accesses.
173 */
174 if (debug_cells_gc_interval)
175 {
176 static unsigned int counter = 0;
177
178 if (counter != 0)
179 {
180 --counter;
181 }
182 else
183 {
184 counter = debug_cells_gc_interval;
185 scm_igc ("scm_assert_cell_valid");
186 }
187 }
406c7d90 188 }
61045190 189 already_running = 0; /* re-enable */
406c7d90
DH
190 }
191}
192
193
194SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
195 (SCM flag),
1e6808ea 196 "If @var{flag} is @code{#f}, cell access checking is disabled.\n"
e81d98ec
DH
197 "If @var{flag} is @code{#t}, cell access checking is enabled,\n"
198 "but no additional calls to garbage collection are issued.\n"
199 "If @var{flag} is a number, cell access checking is enabled,\n"
200 "with an additional garbage collection after the given\n"
201 "number of cell accesses.\n"
1e6808ea
MG
202 "This procedure only exists when the compile-time flag\n"
203 "@code{SCM_DEBUG_CELL_ACCESSES} was set to 1.")
406c7d90
DH
204#define FUNC_NAME s_scm_set_debug_cell_accesses_x
205{
206 if (SCM_FALSEP (flag)) {
207 scm_debug_cell_accesses_p = 0;
208 } else if (SCM_EQ_P (flag, SCM_BOOL_T)) {
e81d98ec
DH
209 debug_cells_gc_interval = 0;
210 scm_debug_cell_accesses_p = 1;
211 } else if (SCM_INUMP (flag)) {
212 long int f = SCM_INUM (flag);
213 if (f <= 0) SCM_OUT_OF_RANGE (1, flag);
214 debug_cells_gc_interval = f;
406c7d90
DH
215 scm_debug_cell_accesses_p = 1;
216 } else {
217 SCM_WRONG_TYPE_ARG (1, flag);
218 }
219 return SCM_UNSPECIFIED;
220}
221#undef FUNC_NAME
222
223#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
224
225\f
226
0f2d19dd 227/* {heap tuning parameters}
a00c95d9 228 *
0f2d19dd
JB
229 * These are parameters for controlling memory allocation. The heap
230 * is the area out of which scm_cons, and object headers are allocated.
231 *
232 * Each heap cell is 8 bytes on a 32 bit machine and 16 bytes on a
233 * 64 bit machine. The units of the _SIZE parameters are bytes.
234 * Cons pairs and object headers occupy one heap cell.
235 *
236 * SCM_INIT_HEAP_SIZE is the initial size of heap. If this much heap is
237 * allocated initially the heap will grow by half its current size
238 * each subsequent time more heap is needed.
239 *
240 * If SCM_INIT_HEAP_SIZE heap cannot be allocated initially, SCM_HEAP_SEG_SIZE
241 * will be used, and the heap will grow by SCM_HEAP_SEG_SIZE when more
1be6b49c 242 * heap is needed. SCM_HEAP_SEG_SIZE must fit into type size_t. This code
0f2d19dd 243 * is in scm_init_storage() and alloc_some_heap() in sys.c
a00c95d9 244 *
0f2d19dd
JB
245 * If SCM_INIT_HEAP_SIZE can be allocated initially, the heap will grow by
246 * SCM_EXPHEAP(scm_heap_size) when more heap is needed.
247 *
248 * SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
249 * is needed.
250 *
251 * INIT_MALLOC_LIMIT is the initial amount of malloc usage which will
a00c95d9 252 * trigger a GC.
6064dcc6
MV
253 *
254 * SCM_MTRIGGER_HYSTERESIS is the amount of malloc storage that must be
255 * reclaimed by a GC triggered by must_malloc. If less than this is
256 * reclaimed, the trigger threshold is raised. [I don't know what a
257 * good value is. I arbitrarily chose 1/10 of the INIT_MALLOC_LIMIT to
a00c95d9 258 * work around a oscillation that caused almost constant GC.]
0f2d19dd
JB
259 */
260
8fef55a8
MD
261/*
262 * Heap size 45000 and 40% min yield gives quick startup and no extra
263 * heap allocation. Having higher values on min yield may lead to
264 * large heaps, especially if code behaviour is varying its
265 * maximum consumption between different freelists.
266 */
d6884e63
ML
267
268#define SCM_DATA_CELLS2CARDS(n) (((n) + SCM_GC_CARD_N_DATA_CELLS - 1) / SCM_GC_CARD_N_DATA_CELLS)
269#define SCM_CARDS_PER_CLUSTER SCM_DATA_CELLS2CARDS (2000L)
270#define SCM_CLUSTER_SIZE_1 (SCM_CARDS_PER_CLUSTER * SCM_GC_CARD_N_DATA_CELLS)
1be6b49c 271size_t scm_default_init_heap_size_1 = (((SCM_DATA_CELLS2CARDS (45000L) + SCM_CARDS_PER_CLUSTER - 1)
d6884e63 272 / SCM_CARDS_PER_CLUSTER) * SCM_GC_CARD_SIZE);
aeacfc8f 273int scm_default_min_yield_1 = 40;
4c48ba06 274
d6884e63 275#define SCM_CLUSTER_SIZE_2 (SCM_CARDS_PER_CLUSTER * (SCM_GC_CARD_N_DATA_CELLS / 2))
1be6b49c 276size_t scm_default_init_heap_size_2 = (((SCM_DATA_CELLS2CARDS (2500L * 2) + SCM_CARDS_PER_CLUSTER - 1)
d6884e63 277 / SCM_CARDS_PER_CLUSTER) * SCM_GC_CARD_SIZE);
4c48ba06
MD
278/* The following value may seem large, but note that if we get to GC at
279 * all, this means that we have a numerically intensive application
280 */
aeacfc8f 281int scm_default_min_yield_2 = 40;
4c48ba06 282
1be6b49c 283size_t scm_default_max_segment_size = 2097000L;/* a little less (adm) than 2 Mb */
4c48ba06 284
d6884e63 285#define SCM_MIN_HEAP_SEG_SIZE (8 * SCM_GC_CARD_SIZE)
0f2d19dd
JB
286#ifdef _QC
287# define SCM_HEAP_SEG_SIZE 32768L
288#else
289# ifdef sequent
4c48ba06 290# define SCM_HEAP_SEG_SIZE (7000L * sizeof (scm_cell))
0f2d19dd 291# else
4c48ba06 292# define SCM_HEAP_SEG_SIZE (16384L * sizeof (scm_cell))
0f2d19dd
JB
293# endif
294#endif
4c48ba06 295/* Make heap grow with factor 1.5 */
4a4c9785 296#define SCM_EXPHEAP(scm_heap_size) (scm_heap_size / 2)
0f2d19dd 297#define SCM_INIT_MALLOC_LIMIT 100000
6064dcc6 298#define SCM_MTRIGGER_HYSTERESIS (SCM_INIT_MALLOC_LIMIT/10)
0f2d19dd 299
d6884e63
ML
300/* CELL_UP and CELL_DN are used by scm_init_heap_seg to find (scm_cell * span)
301 aligned inner bounds for allocated storage */
0f2d19dd
JB
302
303#ifdef PROT386
304/*in 386 protected mode we must only adjust the offset */
a00c95d9
ML
305# define CELL_UP(p, span) MK_FP(FP_SEG(p), ~(8*(span)-1)&(FP_OFF(p)+8*(span)-1))
306# define CELL_DN(p, span) MK_FP(FP_SEG(p), ~(8*(span)-1)&FP_OFF(p))
0f2d19dd
JB
307#else
308# ifdef _UNICOS
c014a02e
ML
309# define CELL_UP(p, span) (SCM_CELLPTR)(~(span) & ((long)(p)+(span)))
310# define CELL_DN(p, span) (SCM_CELLPTR)(~(span) & (long)(p))
0f2d19dd 311# else
c014a02e
ML
312# define CELL_UP(p, span) (SCM_CELLPTR)(~(sizeof(scm_cell)*(span)-1L) & ((long)(p)+sizeof(scm_cell)*(span)-1L))
313# define CELL_DN(p, span) (SCM_CELLPTR)(~(sizeof(scm_cell)*(span)-1L) & (long)(p))
0f2d19dd
JB
314# endif /* UNICOS */
315#endif /* PROT386 */
316
ecf470a2
ML
317#define DOUBLECELL_ALIGNED_P(x) (((2 * sizeof (scm_cell) - 1) & SCM_UNPACK (x)) == 0)
318
d6884e63
ML
319#define ALIGNMENT_SLACK(freelist) (SCM_GC_CARD_SIZE - 1)
320#define CLUSTER_SIZE_IN_BYTES(freelist) \
321 (((freelist)->cluster_size / (SCM_GC_CARD_N_DATA_CELLS / (freelist)->span)) * SCM_GC_CARD_SIZE)
0f2d19dd
JB
322
323\f
945fec60 324/* scm_freelists
0f2d19dd 325 */
945fec60 326
92c2555f 327typedef struct scm_t_freelist {
a00c95d9
ML
328 /* collected cells */
329 SCM cells;
a00c95d9
ML
330 /* number of cells left to collect before cluster is full */
331 unsigned int left_to_collect;
b37fe1c5
MD
332 /* number of clusters which have been allocated */
333 unsigned int clusters_allocated;
8fef55a8
MD
334 /* a list of freelists, each of size cluster_size,
335 * except the last one which may be shorter
336 */
a00c95d9
ML
337 SCM clusters;
338 SCM *clustertail;
b37fe1c5 339 /* this is the number of objects in each cluster, including the spine cell */
1be6b49c 340 unsigned int cluster_size;
8fef55a8 341 /* indicates that we should grow heap instead of GC:ing
a00c95d9
ML
342 */
343 int grow_heap_p;
8fef55a8 344 /* minimum yield on this list in order not to grow the heap
a00c95d9 345 */
8fef55a8
MD
346 long min_yield;
347 /* defines min_yield as percent of total heap size
a00c95d9 348 */
8fef55a8 349 int min_yield_fraction;
a00c95d9
ML
350 /* number of cells per object on this list */
351 int span;
352 /* number of collected cells during last GC */
c014a02e 353 unsigned long collected;
1811ebce 354 /* number of collected cells during penultimate GC */
c014a02e 355 unsigned long collected_1;
a00c95d9
ML
356 /* total number of cells in heap segments
357 * belonging to this list.
358 */
c014a02e 359 unsigned long heap_size;
92c2555f 360} scm_t_freelist;
a00c95d9 361
4a4c9785 362SCM scm_freelist = SCM_EOL;
92c2555f 363scm_t_freelist scm_master_freelist = {
729dbac3 364 SCM_EOL, 0, 0, SCM_EOL, 0, SCM_CLUSTER_SIZE_1, 0, 0, 0, 1, 0, 0, 0
4a4c9785
MD
365};
366SCM scm_freelist2 = SCM_EOL;
92c2555f 367scm_t_freelist scm_master_freelist2 = {
729dbac3 368 SCM_EOL, 0, 0, SCM_EOL, 0, SCM_CLUSTER_SIZE_2, 0, 0, 0, 2, 0, 0, 0
4a4c9785 369};
0f2d19dd
JB
370
371/* scm_mtrigger
372 * is the number of bytes of must_malloc allocation needed to trigger gc.
373 */
c014a02e 374unsigned long scm_mtrigger;
0f2d19dd 375
0f2d19dd
JB
376/* scm_gc_heap_lock
377 * If set, don't expand the heap. Set only during gc, during which no allocation
378 * is supposed to take place anyway.
379 */
380int scm_gc_heap_lock = 0;
381
382/* GC Blocking
383 * Don't pause for collection if this is set -- just
384 * expand the heap.
385 */
0f2d19dd
JB
386int scm_block_gc = 1;
387
0f2d19dd
JB
388/* During collection, this accumulates objects holding
389 * weak references.
390 */
ab4bef85 391SCM scm_weak_vectors;
0f2d19dd 392
7445e0e8
MD
393/* During collection, this accumulates structures which are to be freed.
394 */
395SCM scm_structs_to_free;
396
0f2d19dd
JB
397/* GC Statistics Keeping
398 */
c014a02e
ML
399unsigned long scm_cells_allocated = 0;
400unsigned long scm_mallocated = 0;
401unsigned long scm_gc_cells_collected;
402unsigned long scm_gc_yield;
403static unsigned long scm_gc_yield_1 = 0; /* previous GC yield */
404unsigned long scm_gc_malloc_collected;
405unsigned long scm_gc_ports_collected;
0f2d19dd 406unsigned long scm_gc_time_taken = 0;
c014a02e
ML
407static unsigned long t_before_gc;
408static unsigned long t_before_sweep;
c9b0d4b0
ML
409unsigned long scm_gc_mark_time_taken = 0;
410unsigned long scm_gc_sweep_time_taken = 0;
c014a02e
ML
411unsigned long scm_gc_times = 0;
412unsigned long scm_gc_cells_swept = 0;
c9b0d4b0
ML
413double scm_gc_cells_marked_acc = 0.;
414double scm_gc_cells_swept_acc = 0.;
0f2d19dd
JB
415
416SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
417SCM_SYMBOL (sym_heap_size, "cell-heap-size");
418SCM_SYMBOL (sym_mallocated, "bytes-malloced");
419SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
420SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
421SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
c9b0d4b0
ML
422SCM_SYMBOL (sym_gc_mark_time_taken, "gc-mark-time-taken");
423SCM_SYMBOL (sym_gc_sweep_time_taken, "gc-sweep-time-taken");
424SCM_SYMBOL (sym_times, "gc-times");
425SCM_SYMBOL (sym_cells_marked, "cells-marked");
426SCM_SYMBOL (sym_cells_swept, "cells-swept");
0f2d19dd 427
92c2555f 428typedef struct scm_t_heap_seg_data
0f2d19dd 429{
cf2d30f6
JB
430 /* lower and upper bounds of the segment */
431 SCM_CELLPTR bounds[2];
432
433 /* address of the head-of-freelist pointer for this segment's cells.
434 All segments usually point to the same one, scm_freelist. */
92c2555f 435 scm_t_freelist *freelist;
cf2d30f6 436
fe517a7d 437 /* number of cells per object in this segment */
945fec60 438 int span;
92c2555f 439} scm_t_heap_seg_data;
0f2d19dd
JB
440
441
442
92c2555f 443static size_t init_heap_seg (SCM_CELLPTR, size_t, scm_t_freelist *);
b6efc951
DH
444
445typedef enum { return_on_error, abort_on_error } policy_on_error;
92c2555f 446static void alloc_some_heap (scm_t_freelist *, policy_on_error);
0f2d19dd
JB
447
448
d6884e63
ML
449#define SCM_HEAP_SIZE \
450 (scm_master_freelist.heap_size + scm_master_freelist2.heap_size)
451#define SCM_MAX(A, B) ((A) > (B) ? (A) : (B))
452
453#define BVEC_GROW_SIZE 256
454#define BVEC_GROW_SIZE_IN_LIMBS (SCM_GC_CARD_BVEC_SIZE_IN_LIMBS * BVEC_GROW_SIZE)
92c2555f 455#define BVEC_GROW_SIZE_IN_BYTES (BVEC_GROW_SIZE_IN_LIMBS * sizeof (scm_t_c_bvec_limb))
d6884e63
ML
456
457/* mark space allocation */
458
92c2555f 459typedef struct scm_t_mark_space
d6884e63 460{
92c2555f
MV
461 scm_t_c_bvec_limb *bvec_space;
462 struct scm_t_mark_space *next;
463} scm_t_mark_space;
d6884e63 464
92c2555f
MV
465static scm_t_mark_space *current_mark_space;
466static scm_t_mark_space **mark_space_ptr;
1be6b49c 467static ptrdiff_t current_mark_space_offset;
92c2555f 468static scm_t_mark_space *mark_space_head;
d6884e63 469
92c2555f 470static scm_t_c_bvec_limb *
d6884e63 471get_bvec ()
db4b4ca6 472#define FUNC_NAME "get_bvec"
d6884e63 473{
92c2555f 474 scm_t_c_bvec_limb *res;
d6884e63
ML
475
476 if (!current_mark_space)
477 {
92c2555f 478 SCM_SYSCALL (current_mark_space = (scm_t_mark_space *) malloc (sizeof (scm_t_mark_space)));
d6884e63 479 if (!current_mark_space)
db4b4ca6 480 SCM_MISC_ERROR ("could not grow heap", SCM_EOL);
d6884e63
ML
481
482 current_mark_space->bvec_space = NULL;
483 current_mark_space->next = NULL;
484
485 *mark_space_ptr = current_mark_space;
486 mark_space_ptr = &(current_mark_space->next);
487
488 return get_bvec ();
489 }
490
491 if (!(current_mark_space->bvec_space))
492 {
493 SCM_SYSCALL (current_mark_space->bvec_space =
92c2555f 494 (scm_t_c_bvec_limb *) calloc (BVEC_GROW_SIZE_IN_BYTES, 1));
d6884e63 495 if (!(current_mark_space->bvec_space))
db4b4ca6 496 SCM_MISC_ERROR ("could not grow heap", SCM_EOL);
d6884e63
ML
497
498 current_mark_space_offset = 0;
499
500 return get_bvec ();
501 }
502
503 if (current_mark_space_offset == BVEC_GROW_SIZE_IN_LIMBS)
504 {
505 current_mark_space = NULL;
506
507 return get_bvec ();
508 }
509
510 res = current_mark_space->bvec_space + current_mark_space_offset;
511 current_mark_space_offset += SCM_GC_CARD_BVEC_SIZE_IN_LIMBS;
512
513 return res;
514}
db4b4ca6
DH
515#undef FUNC_NAME
516
d6884e63
ML
517
518static void
519clear_mark_space ()
520{
92c2555f 521 scm_t_mark_space *ms;
d6884e63
ML
522
523 for (ms = mark_space_head; ms; ms = ms->next)
524 memset (ms->bvec_space, 0, BVEC_GROW_SIZE_IN_BYTES);
525}
526
527
0f2d19dd 528\f
cf2d30f6
JB
529/* Debugging functions. */
530
bb2c57fa 531#if defined (GUILE_DEBUG) || defined (GUILE_DEBUG_FREELIST)
cf2d30f6 532
8ded62a3 533static void
92c2555f 534map_free_list (scm_t_freelist *master, SCM freelist)
8ded62a3 535{
c014a02e 536 long last_seg = -1, count = 0;
8ded62a3 537 SCM f;
a00c95d9 538
3f5d82cd 539 for (f = freelist; !SCM_NULLP (f); f = SCM_FREE_CELL_CDR (f))
8ded62a3 540 {
592996c9 541 long int this_seg = heap_segment (f);
8ded62a3 542
592996c9
DH
543 if (this_seg == -1)
544 {
545 fprintf (stderr,
546 "map_free_list: can't find segment containing cell %lux\n",
547 (unsigned long int) SCM_UNPACK (cell));
548 abort ();
549 }
550 else if (this_seg != last_seg)
8ded62a3
MD
551 {
552 if (last_seg != -1)
1be6b49c
ML
553 fprintf (stderr, " %5ld %d-cells in segment %ld\n",
554 (long) count, master->span, (long) last_seg);
8ded62a3
MD
555 last_seg = this_seg;
556 count = 0;
557 }
558 count++;
559 }
560 if (last_seg != -1)
1be6b49c
ML
561 fprintf (stderr, " %5ld %d-cells in segment %ld\n",
562 (long) count, master->span, (long) last_seg);
8ded62a3 563}
cf2d30f6 564
a00c95d9 565SCM_DEFINE (scm_map_free_list, "map-free-list", 0, 0, 0,
acb0a19c 566 (),
5352393c
MG
567 "Print debugging information about the free-list.\n"
568 "@code{map-free-list} is only included in\n"
569 "@code{--enable-guile-debug} builds of Guile.")
acb0a19c
MD
570#define FUNC_NAME s_scm_map_free_list
571{
592996c9
DH
572 size_t i;
573
1be6b49c
ML
574 fprintf (stderr, "%ld segments total (%d:%ld",
575 (long) scm_n_heap_segs,
4c48ba06 576 scm_heap_table[0].span,
1be6b49c 577 (long) (scm_heap_table[0].bounds[1] - scm_heap_table[0].bounds[0]));
592996c9
DH
578
579 for (i = 1; i != scm_n_heap_segs; i++)
1be6b49c 580 fprintf (stderr, ", %d:%ld",
4c48ba06 581 scm_heap_table[i].span,
1be6b49c 582 (long) (scm_heap_table[i].bounds[1] - scm_heap_table[i].bounds[0]));
4c48ba06 583 fprintf (stderr, ")\n");
8ded62a3
MD
584 map_free_list (&scm_master_freelist, scm_freelist);
585 map_free_list (&scm_master_freelist2, scm_freelist2);
cf2d30f6
JB
586 fflush (stderr);
587
588 return SCM_UNSPECIFIED;
589}
1bbd0b84 590#undef FUNC_NAME
cf2d30f6 591
c014a02e
ML
592static long last_cluster;
593static long last_size;
4c48ba06 594
c014a02e
ML
595static long
596free_list_length (char *title, long i, SCM freelist)
5384bc5b
MD
597{
598 SCM ls;
c014a02e 599 long n = 0;
3f5d82cd
DH
600 for (ls = freelist; !SCM_NULLP (ls); ls = SCM_FREE_CELL_CDR (ls))
601 if (SCM_FREE_CELL_P (ls))
5384bc5b
MD
602 ++n;
603 else
604 {
1be6b49c 605 fprintf (stderr, "bad cell in %s at position %ld\n", title, (long) n);
5384bc5b
MD
606 abort ();
607 }
4c48ba06
MD
608 if (n != last_size)
609 {
610 if (i > 0)
611 {
612 if (last_cluster == i - 1)
1be6b49c 613 fprintf (stderr, "\t%ld\n", (long) last_size);
4c48ba06 614 else
1be6b49c 615 fprintf (stderr, "-%ld\t%ld\n", (long) (i - 1), (long) last_size);
4c48ba06
MD
616 }
617 if (i >= 0)
1be6b49c 618 fprintf (stderr, "%s %ld", title, (long) i);
4c48ba06 619 else
1be6b49c 620 fprintf (stderr, "%s\t%ld\n", title, (long) n);
4c48ba06
MD
621 last_cluster = i;
622 last_size = n;
623 }
5384bc5b
MD
624 return n;
625}
626
627static void
92c2555f 628free_list_lengths (char *title, scm_t_freelist *master, SCM freelist)
5384bc5b
MD
629{
630 SCM clusters;
c014a02e 631 long i = 0, len, n = 0;
5384bc5b
MD
632 fprintf (stderr, "%s\n\n", title);
633 n += free_list_length ("free list", -1, freelist);
634 for (clusters = master->clusters;
635 SCM_NNULLP (clusters);
636 clusters = SCM_CDR (clusters))
4c48ba06
MD
637 {
638 len = free_list_length ("cluster", i++, SCM_CAR (clusters));
639 n += len;
640 }
641 if (last_cluster == i - 1)
1be6b49c 642 fprintf (stderr, "\t%ld\n", (long) last_size);
4c48ba06 643 else
1be6b49c
ML
644 fprintf (stderr, "-%ld\t%ld\n", (long) (i - 1), (long) last_size);
645 fprintf (stderr, "\ntotal %ld objects\n\n", (long) n);
5384bc5b
MD
646}
647
a00c95d9 648SCM_DEFINE (scm_free_list_length, "free-list-length", 0, 0, 0,
5384bc5b 649 (),
5352393c
MG
650 "Print debugging information about the free-list.\n"
651 "@code{free-list-length} is only included in\n"
652 "@code{--enable-guile-debug} builds of Guile.")
5384bc5b
MD
653#define FUNC_NAME s_scm_free_list_length
654{
b37fe1c5
MD
655 free_list_lengths ("1-cells", &scm_master_freelist, scm_freelist);
656 free_list_lengths ("2-cells", &scm_master_freelist2, scm_freelist2);
12e5fb3b 657 return SCM_UNSPECIFIED;
5384bc5b
MD
658}
659#undef FUNC_NAME
660
bb2c57fa
MD
661#endif
662
663#ifdef GUILE_DEBUG_FREELIST
cf2d30f6 664
d3dd80ab
MG
665/* Non-zero if freelist debugging is in effect. Set this via
666 `gc-set-debug-check-freelist!'. */
667static int scm_debug_check_freelist = 0;
668
cf2d30f6 669/* Number of calls to SCM_NEWCELL since startup. */
c014a02e
ML
670static unsigned long scm_newcell_count;
671static unsigned long scm_newcell2_count;
cf2d30f6
JB
672
673/* Search freelist for anything that isn't marked as a free cell.
674 Abort if we find something. */
8ded62a3
MD
675static void
676scm_check_freelist (SCM freelist)
677{
678 SCM f;
c014a02e 679 long i = 0;
8ded62a3 680
3f5d82cd
DH
681 for (f = freelist; !SCM_NULLP (f); f = SCM_FREE_CELL_CDR (f), i++)
682 if (!SCM_FREE_CELL_P (f))
8ded62a3 683 {
1be6b49c
ML
684 fprintf (stderr, "Bad cell in freelist on newcell %lu: %lu'th elt\n",
685 (long) scm_newcell_count, (long) i);
8ded62a3
MD
686 abort ();
687 }
688}
cf2d30f6 689
a00c95d9 690SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
1bbd0b84 691 (SCM flag),
1e6808ea
MG
692 "If @var{flag} is @code{#t}, check the freelist for consistency\n"
693 "on each cell allocation. This procedure only exists when the\n"
694 "@code{GUILE_DEBUG_FREELIST} compile-time flag was selected.")
1bbd0b84 695#define FUNC_NAME s_scm_gc_set_debug_check_freelist_x
25748c78 696{
d6884e63
ML
697 /* [cmm] I did a double-take when I read this code the first time.
698 well, FWIW. */
945fec60 699 SCM_VALIDATE_BOOL_COPY (1, flag, scm_debug_check_freelist);
25748c78
GB
700 return SCM_UNSPECIFIED;
701}
1bbd0b84 702#undef FUNC_NAME
25748c78
GB
703
704
4a4c9785
MD
705SCM
706scm_debug_newcell (void)
707{
708 SCM new;
709
710 scm_newcell_count++;
711 if (scm_debug_check_freelist)
712 {
8ded62a3 713 scm_check_freelist (scm_freelist);
4a4c9785
MD
714 scm_gc();
715 }
716
717 /* The rest of this is supposed to be identical to the SCM_NEWCELL
718 macro. */
3f5d82cd 719 if (SCM_NULLP (scm_freelist))
7c33806a
DH
720 {
721 new = scm_gc_for_newcell (&scm_master_freelist, &scm_freelist);
722 SCM_GC_SET_ALLOCATED (new);
723 }
4a4c9785
MD
724 else
725 {
726 new = scm_freelist;
3f5d82cd 727 scm_freelist = SCM_FREE_CELL_CDR (scm_freelist);
7c33806a 728 SCM_GC_SET_ALLOCATED (new);
4a4c9785
MD
729 }
730
731 return new;
732}
733
734SCM
735scm_debug_newcell2 (void)
736{
737 SCM new;
738
739 scm_newcell2_count++;
740 if (scm_debug_check_freelist)
741 {
8ded62a3 742 scm_check_freelist (scm_freelist2);
4a4c9785
MD
743 scm_gc ();
744 }
745
746 /* The rest of this is supposed to be identical to the SCM_NEWCELL
747 macro. */
3f5d82cd 748 if (SCM_NULLP (scm_freelist2))
7c33806a
DH
749 {
750 new = scm_gc_for_newcell (&scm_master_freelist2, &scm_freelist2);
751 SCM_GC_SET_ALLOCATED (new);
752 }
4a4c9785
MD
753 else
754 {
755 new = scm_freelist2;
3f5d82cd 756 scm_freelist2 = SCM_FREE_CELL_CDR (scm_freelist2);
7c33806a 757 SCM_GC_SET_ALLOCATED (new);
4a4c9785
MD
758 }
759
760 return new;
761}
762
fca7547b 763#endif /* GUILE_DEBUG_FREELIST */
cf2d30f6
JB
764
765\f
0f2d19dd 766
c014a02e 767static unsigned long
92c2555f 768master_cells_allocated (scm_t_freelist *master)
b37fe1c5 769{
d6884e63 770 /* the '- 1' below is to ignore the cluster spine cells. */
c014a02e 771 long objects = master->clusters_allocated * (master->cluster_size - 1);
b37fe1c5
MD
772 if (SCM_NULLP (master->clusters))
773 objects -= master->left_to_collect;
774 return master->span * objects;
775}
776
c014a02e 777static unsigned long
b37fe1c5
MD
778freelist_length (SCM freelist)
779{
c014a02e 780 long n;
3f5d82cd 781 for (n = 0; !SCM_NULLP (freelist); freelist = SCM_FREE_CELL_CDR (freelist))
b37fe1c5
MD
782 ++n;
783 return n;
784}
785
c014a02e 786static unsigned long
b37fe1c5
MD
787compute_cells_allocated ()
788{
789 return (scm_cells_allocated
790 + master_cells_allocated (&scm_master_freelist)
791 + master_cells_allocated (&scm_master_freelist2)
792 - scm_master_freelist.span * freelist_length (scm_freelist)
793 - scm_master_freelist2.span * freelist_length (scm_freelist2));
794}
b37fe1c5 795
0f2d19dd
JB
796/* {Scheme Interface to GC}
797 */
798
a00c95d9 799SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
1bbd0b84 800 (),
1e6808ea
MG
801 "Return an association list of statistics about Guile's current\n"
802 "use of storage.")
1bbd0b84 803#define FUNC_NAME s_scm_gc_stats
0f2d19dd 804{
c014a02e
ML
805 long i;
806 long n;
0f2d19dd 807 SCM heap_segs;
c014a02e
ML
808 unsigned long int local_scm_mtrigger;
809 unsigned long int local_scm_mallocated;
810 unsigned long int local_scm_heap_size;
811 unsigned long int local_scm_cells_allocated;
812 unsigned long int local_scm_gc_time_taken;
813 unsigned long int local_scm_gc_times;
814 unsigned long int local_scm_gc_mark_time_taken;
815 unsigned long int local_scm_gc_sweep_time_taken;
c9b0d4b0
ML
816 double local_scm_gc_cells_swept;
817 double local_scm_gc_cells_marked;
0f2d19dd
JB
818 SCM answer;
819
820 SCM_DEFER_INTS;
939794ce
DH
821
822 ++scm_block_gc;
823
0f2d19dd
JB
824 retry:
825 heap_segs = SCM_EOL;
826 n = scm_n_heap_segs;
827 for (i = scm_n_heap_segs; i--; )
c014a02e
ML
828 heap_segs = scm_cons (scm_cons (scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[1]),
829 scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[0])),
0f2d19dd
JB
830 heap_segs);
831 if (scm_n_heap_segs != n)
832 goto retry;
939794ce
DH
833
834 --scm_block_gc;
0f2d19dd 835
7febb4a2
MD
836 /* Below, we cons to produce the resulting list. We want a snapshot of
837 * the heap situation before consing.
838 */
0f2d19dd
JB
839 local_scm_mtrigger = scm_mtrigger;
840 local_scm_mallocated = scm_mallocated;
b37fe1c5 841 local_scm_heap_size = SCM_HEAP_SIZE;
b37fe1c5 842 local_scm_cells_allocated = compute_cells_allocated ();
0f2d19dd 843 local_scm_gc_time_taken = scm_gc_time_taken;
c9b0d4b0
ML
844 local_scm_gc_mark_time_taken = scm_gc_mark_time_taken;
845 local_scm_gc_sweep_time_taken = scm_gc_sweep_time_taken;
846 local_scm_gc_times = scm_gc_times;
847 local_scm_gc_cells_swept = scm_gc_cells_swept_acc;
848 local_scm_gc_cells_marked = scm_gc_cells_marked_acc;
0f2d19dd 849
1afff620
KN
850 answer = scm_list_n (scm_cons (sym_gc_time_taken, scm_ulong2num (local_scm_gc_time_taken)),
851 scm_cons (sym_cells_allocated, scm_ulong2num (local_scm_cells_allocated)),
852 scm_cons (sym_heap_size, scm_ulong2num (local_scm_heap_size)),
853 scm_cons (sym_mallocated, scm_ulong2num (local_scm_mallocated)),
854 scm_cons (sym_mtrigger, scm_ulong2num (local_scm_mtrigger)),
855 scm_cons (sym_times, scm_ulong2num (local_scm_gc_times)),
856 scm_cons (sym_gc_mark_time_taken, scm_ulong2num (local_scm_gc_mark_time_taken)),
857 scm_cons (sym_gc_sweep_time_taken, scm_ulong2num (local_scm_gc_sweep_time_taken)),
858 scm_cons (sym_cells_marked, scm_i_dbl2big (local_scm_gc_cells_marked)),
859 scm_cons (sym_cells_swept, scm_i_dbl2big (local_scm_gc_cells_swept)),
860 scm_cons (sym_heap_segments, heap_segs),
861 SCM_UNDEFINED);
0f2d19dd
JB
862 SCM_ALLOW_INTS;
863 return answer;
864}
1bbd0b84 865#undef FUNC_NAME
0f2d19dd
JB
866
867
c9b0d4b0 868static void
e81d98ec 869gc_start_stats (const char *what SCM_UNUSED)
0f2d19dd 870{
c9b0d4b0
ML
871 t_before_gc = scm_c_get_internal_run_time ();
872 scm_gc_cells_swept = 0;
b37fe1c5 873 scm_gc_cells_collected = 0;
37ddcaf6 874 scm_gc_yield_1 = scm_gc_yield;
8b0d194f
MD
875 scm_gc_yield = (scm_cells_allocated
876 + master_cells_allocated (&scm_master_freelist)
877 + master_cells_allocated (&scm_master_freelist2));
0f2d19dd
JB
878 scm_gc_malloc_collected = 0;
879 scm_gc_ports_collected = 0;
880}
881
939794ce 882
c9b0d4b0
ML
883static void
884gc_end_stats ()
0f2d19dd 885{
c9b0d4b0
ML
886 unsigned long t = scm_c_get_internal_run_time ();
887 scm_gc_time_taken += (t - t_before_gc);
888 scm_gc_sweep_time_taken += (t - t_before_sweep);
889 ++scm_gc_times;
890
891 scm_gc_cells_marked_acc += scm_gc_cells_swept - scm_gc_cells_collected;
892 scm_gc_cells_swept_acc += scm_gc_cells_swept;
0f2d19dd
JB
893}
894
895
a00c95d9 896SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
1bbd0b84 897 (SCM obj),
b380b885
MD
898 "Return an integer that for the lifetime of @var{obj} is uniquely\n"
899 "returned by this function for @var{obj}")
1bbd0b84 900#define FUNC_NAME s_scm_object_address
0f2d19dd 901{
c014a02e 902 return scm_ulong2num ((unsigned long) SCM_UNPACK (obj));
0f2d19dd 903}
1bbd0b84 904#undef FUNC_NAME
0f2d19dd
JB
905
906
a00c95d9 907SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
1bbd0b84 908 (),
b380b885
MD
909 "Scans all of SCM objects and reclaims for further use those that are\n"
910 "no longer accessible.")
1bbd0b84 911#define FUNC_NAME s_scm_gc
0f2d19dd
JB
912{
913 SCM_DEFER_INTS;
914 scm_igc ("call");
915 SCM_ALLOW_INTS;
916 return SCM_UNSPECIFIED;
917}
1bbd0b84 918#undef FUNC_NAME
0f2d19dd
JB
919
920
921\f
922/* {C Interface For When GC is Triggered}
923 */
924
b37fe1c5 925static void
92c2555f 926adjust_min_yield (scm_t_freelist *freelist)
b37fe1c5 927{
8fef55a8 928 /* min yield is adjusted upwards so that next predicted total yield
bda1446c 929 * (allocated cells actually freed by GC) becomes
8fef55a8
MD
930 * `min_yield_fraction' of total heap size. Note, however, that
931 * the absolute value of min_yield will correspond to `collected'
bda1446c 932 * on one master (the one which currently is triggering GC).
b37fe1c5 933 *
bda1446c
MD
934 * The reason why we look at total yield instead of cells collected
935 * on one list is that we want to take other freelists into account.
936 * On this freelist, we know that (local) yield = collected cells,
937 * but that's probably not the case on the other lists.
b37fe1c5
MD
938 *
939 * (We might consider computing a better prediction, for example
940 * by computing an average over multiple GC:s.)
941 */
8fef55a8 942 if (freelist->min_yield_fraction)
b37fe1c5 943 {
37ddcaf6 944 /* Pick largest of last two yields. */
1be6b49c 945 long delta = ((SCM_HEAP_SIZE * freelist->min_yield_fraction / 100)
8fef55a8 946 - (long) SCM_MAX (scm_gc_yield_1, scm_gc_yield));
b37fe1c5 947#ifdef DEBUGINFO
1be6b49c
ML
948 fprintf (stderr, " after GC = %lu, delta = %ld\n",
949 (long) scm_cells_allocated,
950 (long) delta);
b37fe1c5
MD
951#endif
952 if (delta > 0)
8fef55a8 953 freelist->min_yield += delta;
b37fe1c5
MD
954 }
955}
956
b6efc951 957
4a4c9785 958/* When we get POSIX threads support, the master will be global and
4c48ba06
MD
959 * common while the freelist will be individual for each thread.
960 */
4a4c9785
MD
961
962SCM
92c2555f 963scm_gc_for_newcell (scm_t_freelist *master, SCM *freelist)
4a4c9785
MD
964{
965 SCM cell;
966 ++scm_ints_disabled;
4c48ba06
MD
967 do
968 {
c7387918 969 if (SCM_NULLP (master->clusters))
4c48ba06 970 {
150c200b 971 if (master->grow_heap_p || scm_block_gc)
4c48ba06 972 {
b6efc951
DH
973 /* In order to reduce gc frequency, try to allocate a new heap
974 * segment first, even if gc might find some free cells. If we
975 * can't obtain a new heap segment, we will try gc later.
976 */
4c48ba06 977 master->grow_heap_p = 0;
b6efc951 978 alloc_some_heap (master, return_on_error);
4c48ba06 979 }
b6efc951 980 if (SCM_NULLP (master->clusters))
b37fe1c5 981 {
b6efc951
DH
982 /* The heap was not grown, either because it wasn't scheduled to
983 * grow, or because there was not enough memory available. In
984 * both cases we have to try gc to get some free cells.
985 */
37ddcaf6 986#ifdef DEBUGINFO
1be6b49c
ML
987 fprintf (stderr, "allocated = %lu, ",
988 (long) (scm_cells_allocated
37ddcaf6 989 + master_cells_allocated (&scm_master_freelist)
c014a02e 990 + master_cells_allocated (&scm_master_freelist2)));
37ddcaf6 991#endif
b37fe1c5 992 scm_igc ("cells");
8fef55a8 993 adjust_min_yield (master);
c7387918
DH
994 if (SCM_NULLP (master->clusters))
995 {
b6efc951
DH
996 /* gc could not free any cells. Now, we _must_ allocate a
997 * new heap segment, because there is no other possibility
998 * to provide a new cell for the caller.
999 */
1000 alloc_some_heap (master, abort_on_error);
c7387918 1001 }
b37fe1c5 1002 }
4c48ba06
MD
1003 }
1004 cell = SCM_CAR (master->clusters);
1005 master->clusters = SCM_CDR (master->clusters);
b37fe1c5 1006 ++master->clusters_allocated;
4c48ba06
MD
1007 }
1008 while (SCM_NULLP (cell));
d6884e63
ML
1009
1010#ifdef GUILE_DEBUG_FREELIST
1011 scm_check_freelist (cell);
1012#endif
1013
4a4c9785 1014 --scm_ints_disabled;
3f5d82cd 1015 *freelist = SCM_FREE_CELL_CDR (cell);
4a4c9785
MD
1016 return cell;
1017}
1018
b6efc951 1019
4c48ba06
MD
1020#if 0
1021/* This is a support routine which can be used to reserve a cluster
1022 * for some special use, such as debugging. It won't be useful until
1023 * free cells are preserved between garbage collections.
1024 */
1025
1026void
92c2555f 1027scm_alloc_cluster (scm_t_freelist *master)
4c48ba06
MD
1028{
1029 SCM freelist, cell;
1030 cell = scm_gc_for_newcell (master, &freelist);
1031 SCM_SETCDR (cell, freelist);
1032 return cell;
1033}
1034#endif
1035
801cb5e7 1036
92c2555f
MV
1037scm_t_c_hook scm_before_gc_c_hook;
1038scm_t_c_hook scm_before_mark_c_hook;
1039scm_t_c_hook scm_before_sweep_c_hook;
1040scm_t_c_hook scm_after_sweep_c_hook;
1041scm_t_c_hook scm_after_gc_c_hook;
801cb5e7 1042
b6efc951 1043
0f2d19dd 1044void
1bbd0b84 1045scm_igc (const char *what)
0f2d19dd 1046{
c014a02e 1047 long j;
0f2d19dd 1048
406c7d90 1049 ++scm_gc_running_p;
801cb5e7 1050 scm_c_hook_run (&scm_before_gc_c_hook, 0);
4c48ba06
MD
1051#ifdef DEBUGINFO
1052 fprintf (stderr,
1053 SCM_NULLP (scm_freelist)
1054 ? "*"
1055 : (SCM_NULLP (scm_freelist2) ? "o" : "m"));
1056#endif
42db06f0 1057 /* During the critical section, only the current thread may run. */
216eedfc 1058 SCM_CRITICAL_SECTION_START;
42db06f0 1059
e242dfd2 1060 /* fprintf (stderr, "gc: %s\n", what); */
c68296f8 1061
ab4bef85
JB
1062 if (!scm_stack_base || scm_block_gc)
1063 {
406c7d90 1064 --scm_gc_running_p;
ab4bef85
JB
1065 return;
1066 }
1067
c9b0d4b0
ML
1068 gc_start_stats (what);
1069
ab4bef85
JB
1070 if (scm_gc_heap_lock)
1071 /* We've invoked the collector while a GC is already in progress.
1072 That should never happen. */
1073 abort ();
0f2d19dd
JB
1074
1075 ++scm_gc_heap_lock;
ab4bef85 1076
0f2d19dd
JB
1077 /* flush dead entries from the continuation stack */
1078 {
c014a02e
ML
1079 long x;
1080 long bound;
0f2d19dd
JB
1081 SCM * elts;
1082 elts = SCM_VELTS (scm_continuation_stack);
b5c2579a 1083 bound = SCM_VECTOR_LENGTH (scm_continuation_stack);
0f2d19dd
JB
1084 x = SCM_INUM (scm_continuation_stack_ptr);
1085 while (x < bound)
1086 {
1087 elts[x] = SCM_BOOL_F;
1088 ++x;
1089 }
1090 }
1091
801cb5e7
MD
1092 scm_c_hook_run (&scm_before_mark_c_hook, 0);
1093
d6884e63
ML
1094 clear_mark_space ();
1095
42db06f0 1096#ifndef USE_THREADS
a00c95d9 1097
1b9be268 1098 /* Mark objects on the C stack. */
0f2d19dd
JB
1099 SCM_FLUSH_REGISTER_WINDOWS;
1100 /* This assumes that all registers are saved into the jmp_buf */
1101 setjmp (scm_save_regs_gc_mark);
1102 scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
1be6b49c 1103 ( (size_t) (sizeof (SCM_STACKITEM) - 1 +
ce4a361d
JB
1104 sizeof scm_save_regs_gc_mark)
1105 / sizeof (SCM_STACKITEM)));
0f2d19dd
JB
1106
1107 {
6b1b030e 1108 unsigned long stack_len = scm_stack_size (scm_stack_base);
0f2d19dd 1109#ifdef SCM_STACK_GROWS_UP
6ba93e5e 1110 scm_mark_locations (scm_stack_base, stack_len);
0f2d19dd 1111#else
6ba93e5e 1112 scm_mark_locations (scm_stack_base - stack_len, stack_len);
0f2d19dd
JB
1113#endif
1114 }
1115
42db06f0
MD
1116#else /* USE_THREADS */
1117
1118 /* Mark every thread's stack and registers */
945fec60 1119 scm_threads_mark_stacks ();
42db06f0
MD
1120
1121#endif /* USE_THREADS */
0f2d19dd 1122
0f2d19dd
JB
1123 j = SCM_NUM_PROTECTS;
1124 while (j--)
1125 scm_gc_mark (scm_sys_protects[j]);
1126
6b1b030e
ML
1127 /* mark the registered roots */
1128 {
592996c9 1129 size_t i;
6b1b030e
ML
1130 for (i = 0; i < SCM_VECTOR_LENGTH (scm_gc_registered_roots); ++i) {
1131 SCM l = SCM_VELTS (scm_gc_registered_roots)[i];
592996c9 1132 for (; !SCM_NULLP (l); l = SCM_CDR (l)) {
6b1b030e
ML
1133 SCM *p = (SCM *) (scm_num2long (SCM_CAAR (l), 0, NULL));
1134 scm_gc_mark (*p);
1135 }
1136 }
1137 }
1138
9de33deb
MD
1139 /* FIXME: we should have a means to register C functions to be run
1140 * in different phases of GC
a00c95d9 1141 */
9de33deb 1142 scm_mark_subr_table ();
a00c95d9 1143
42db06f0
MD
1144#ifndef USE_THREADS
1145 scm_gc_mark (scm_root->handle);
1146#endif
a00c95d9 1147
c9b0d4b0
ML
1148 t_before_sweep = scm_c_get_internal_run_time ();
1149 scm_gc_mark_time_taken += (t_before_sweep - t_before_gc);
1150
801cb5e7 1151 scm_c_hook_run (&scm_before_sweep_c_hook, 0);
0493cd89 1152
0f2d19dd
JB
1153 scm_gc_sweep ();
1154
801cb5e7
MD
1155 scm_c_hook_run (&scm_after_sweep_c_hook, 0);
1156
0f2d19dd 1157 --scm_gc_heap_lock;
c9b0d4b0 1158 gc_end_stats ();
42db06f0 1159
216eedfc 1160 SCM_CRITICAL_SECTION_END;
801cb5e7 1161 scm_c_hook_run (&scm_after_gc_c_hook, 0);
406c7d90 1162 --scm_gc_running_p;
0f2d19dd
JB
1163}
1164
1165\f
939794ce 1166
a00c95d9 1167/* {Mark/Sweep}
0f2d19dd
JB
1168 */
1169
56495472
ML
1170#define MARK scm_gc_mark
1171#define FNAME "scm_gc_mark"
0f2d19dd 1172
56495472 1173#endif /*!MARK_DEPENDENCIES*/
0f2d19dd
JB
1174
1175/* Mark an object precisely.
1176 */
a00c95d9 1177void
56495472
ML
1178MARK (SCM p)
1179#define FUNC_NAME FNAME
0f2d19dd 1180{
c014a02e 1181 register long i;
0f2d19dd 1182 register SCM ptr;
92c2555f 1183 scm_t_bits cell_type;
0f2d19dd 1184
56495472
ML
1185#ifndef MARK_DEPENDENCIES
1186# define RECURSE scm_gc_mark
1187#else
1188 /* go through the usual marking, but not for self-cycles. */
1189# define RECURSE(x) do { if ((x) != p) scm_gc_mark (x); } while (0)
1190#endif
0f2d19dd
JB
1191 ptr = p;
1192
56495472
ML
1193#ifdef MARK_DEPENDENCIES
1194 goto gc_mark_loop_first_time;
1195#endif
1196
86d31dfe
MV
1197/* A simple hack for debugging. Chose the second branch to get a
1198 meaningful backtrace for crashes inside the GC.
1199*/
1200#if 1
1201#define goto_gc_mark_loop goto gc_mark_loop
1202#define goto_gc_mark_nimp goto gc_mark_nimp
1203#else
1204#define goto_gc_mark_loop RECURSE(ptr); return
1205#define goto_gc_mark_nimp RECURSE(ptr); return
1206#endif
1207
0f2d19dd
JB
1208gc_mark_loop:
1209 if (SCM_IMP (ptr))
1210 return;
1211
1212gc_mark_nimp:
56495472
ML
1213
1214#ifdef MARK_DEPENDENCIES
0209177b 1215 if (SCM_EQ_P (ptr, p))
56495472
ML
1216 return;
1217
1218 scm_gc_mark (ptr);
0209177b 1219 return;
56495472
ML
1220
1221gc_mark_loop_first_time:
1222#endif
9a6976cd 1223
61045190 1224#if (SCM_DEBUG_CELL_ACCESSES == 1) || (defined (GUILE_DEBUG_FREELIST))
9a6976cd 1225 /* We are in debug mode. Check the ptr exhaustively. */
61045190 1226 if (!scm_cellp (ptr))
db4b4ca6 1227 SCM_MISC_ERROR ("rogue pointer in heap", SCM_EOL);
9a6976cd
DH
1228#else
1229 /* In non-debug mode, do at least some cheap testing. */
1230 if (!SCM_CELLP (ptr))
1231 SCM_MISC_ERROR ("rogue pointer in heap", SCM_EOL);
d6884e63
ML
1232#endif
1233
56495472
ML
1234#ifndef MARK_DEPENDENCIES
1235
d6884e63
ML
1236 if (SCM_GCMARKP (ptr))
1237 return;
56495472 1238
d6884e63
ML
1239 SCM_SETGCMARK (ptr);
1240
56495472
ML
1241#endif
1242
61045190
DH
1243 cell_type = SCM_GC_CELL_TYPE (ptr);
1244 switch (SCM_ITAG7 (cell_type))
0f2d19dd
JB
1245 {
1246 case scm_tcs_cons_nimcar:
d6884e63 1247 if (SCM_IMP (SCM_CDR (ptr)))
0f2d19dd
JB
1248 {
1249 ptr = SCM_CAR (ptr);
86d31dfe 1250 goto_gc_mark_nimp;
0f2d19dd 1251 }
56495472 1252 RECURSE (SCM_CAR (ptr));
d6884e63 1253 ptr = SCM_CDR (ptr);
86d31dfe 1254 goto_gc_mark_nimp;
0f2d19dd 1255 case scm_tcs_cons_imcar:
d6884e63 1256 ptr = SCM_CDR (ptr);
86d31dfe 1257 goto_gc_mark_loop;
e641afaf 1258 case scm_tc7_pws:
22a52da1
DH
1259 RECURSE (SCM_SETTER (ptr));
1260 ptr = SCM_PROCEDURE (ptr);
86d31dfe 1261 goto_gc_mark_loop;
0f2d19dd 1262 case scm_tcs_cons_gloc:
0f2d19dd 1263 {
86d31dfe
MV
1264 /* Dirk:FIXME:: The following code is super ugly: ptr may be a
1265 * struct or a gloc. If it is a gloc, the cell word #0 of ptr
1266 * is the address of a scm_tc16_variable smob. If it is a
1267 * struct, the cell word #0 of ptr is a pointer to a struct
1268 * vtable data region. (The fact that these are accessed in
1269 * the same way restricts the possibilites to change the data
1270 * layout of structs or heap cells.) To discriminate between
1271 * the two, it is guaranteed that the scm_vtable_index_vcell
1272 * element of the prospective vtable is always zero. For a
1273 * gloc, this location has the CDR of the variable smob, which
1274 * is guaranteed to be non-zero.
c8045e8d 1275 */
92c2555f
MV
1276 scm_t_bits word0 = SCM_CELL_WORD_0 (ptr) - scm_tc3_cons_gloc;
1277 scm_t_bits * vtable_data = (scm_t_bits *) word0; /* access as struct */
7445e0e8 1278 if (vtable_data [scm_vtable_index_vcell] != 0)
0f2d19dd 1279 {
d6884e63
ML
1280 /* ptr is a gloc */
1281 SCM gloc_car = SCM_PACK (word0);
56495472 1282 RECURSE (gloc_car);
d6884e63
ML
1283 ptr = SCM_CDR (ptr);
1284 goto gc_mark_loop;
1285 }
1286 else
1287 {
1288 /* ptr is a struct */
1289 SCM layout = SCM_PACK (vtable_data [scm_vtable_index_layout]);
c014a02e 1290 long len = SCM_SYMBOL_LENGTH (layout);
06ee04b2 1291 char * fields_desc = SCM_SYMBOL_CHARS (layout);
92c2555f 1292 scm_t_bits * struct_data = (scm_t_bits *) SCM_STRUCT_DATA (ptr);
7bb8eac7 1293
d6884e63
ML
1294 if (vtable_data[scm_struct_i_flags] & SCM_STRUCTF_ENTITY)
1295 {
56495472
ML
1296 RECURSE (SCM_PACK (struct_data[scm_struct_i_procedure]));
1297 RECURSE (SCM_PACK (struct_data[scm_struct_i_setter]));
d6884e63
ML
1298 }
1299 if (len)
1300 {
c014a02e 1301 long x;
7bb8eac7 1302
d6884e63
ML
1303 for (x = 0; x < len - 2; x += 2, ++struct_data)
1304 if (fields_desc[x] == 'p')
56495472 1305 RECURSE (SCM_PACK (*struct_data));
d6884e63
ML
1306 if (fields_desc[x] == 'p')
1307 {
1308 if (SCM_LAYOUT_TAILP (fields_desc[x + 1]))
56495472
ML
1309 for (x = *struct_data++; x; --x, ++struct_data)
1310 RECURSE (SCM_PACK (*struct_data));
d6884e63 1311 else
56495472 1312 RECURSE (SCM_PACK (*struct_data));
d6884e63
ML
1313 }
1314 }
1315 /* mark vtable */
1316 ptr = SCM_PACK (vtable_data [scm_vtable_index_vtable]);
86d31dfe 1317 goto_gc_mark_loop;
0f2d19dd
JB
1318 }
1319 }
1320 break;
1321 case scm_tcs_closures:
22a52da1 1322 if (SCM_IMP (SCM_ENV (ptr)))
0f2d19dd
JB
1323 {
1324 ptr = SCM_CLOSCAR (ptr);
86d31dfe 1325 goto_gc_mark_nimp;
0f2d19dd 1326 }
56495472 1327 RECURSE (SCM_CLOSCAR (ptr));
22a52da1 1328 ptr = SCM_ENV (ptr);
86d31dfe 1329 goto_gc_mark_nimp;
0f2d19dd 1330 case scm_tc7_vector:
b5c2579a
DH
1331 i = SCM_VECTOR_LENGTH (ptr);
1332 if (i == 0)
1333 break;
1334 while (--i > 0)
1335 if (SCM_NIMP (SCM_VELTS (ptr)[i]))
56495472 1336 RECURSE (SCM_VELTS (ptr)[i]);
b5c2579a 1337 ptr = SCM_VELTS (ptr)[0];
86d31dfe 1338 goto_gc_mark_loop;
0f2d19dd
JB
1339#ifdef CCLO
1340 case scm_tc7_cclo:
362306b9 1341 {
1be6b49c
ML
1342 size_t i = SCM_CCLO_LENGTH (ptr);
1343 size_t j;
362306b9
DH
1344 for (j = 1; j != i; ++j)
1345 {
1346 SCM obj = SCM_CCLO_REF (ptr, j);
1347 if (!SCM_IMP (obj))
56495472 1348 RECURSE (obj);
362306b9
DH
1349 }
1350 ptr = SCM_CCLO_REF (ptr, 0);
86d31dfe 1351 goto_gc_mark_loop;
362306b9 1352 }
b5c2579a 1353#endif
afe5177e 1354#ifdef HAVE_ARRAYS
0f2d19dd
JB
1355 case scm_tc7_bvect:
1356 case scm_tc7_byvect:
1357 case scm_tc7_ivect:
1358 case scm_tc7_uvect:
1359 case scm_tc7_fvect:
1360 case scm_tc7_dvect:
1361 case scm_tc7_cvect:
1362 case scm_tc7_svect:
5c11cc9d 1363#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1364 case scm_tc7_llvect:
1365#endif
afe5177e 1366#endif
0f2d19dd 1367 case scm_tc7_string:
0f2d19dd
JB
1368 break;
1369
1370 case scm_tc7_substring:
0f2d19dd 1371 ptr = SCM_CDR (ptr);
86d31dfe 1372 goto_gc_mark_loop;
0f2d19dd
JB
1373
1374 case scm_tc7_wvect:
592996c9 1375 SCM_SET_WVECT_GC_CHAIN (ptr, scm_weak_vectors);
ab4bef85 1376 scm_weak_vectors = ptr;
0f2d19dd
JB
1377 if (SCM_IS_WHVEC_ANY (ptr))
1378 {
c014a02e
ML
1379 long x;
1380 long len;
0f2d19dd
JB
1381 int weak_keys;
1382 int weak_values;
1383
b5c2579a 1384 len = SCM_VECTOR_LENGTH (ptr);
0f2d19dd
JB
1385 weak_keys = SCM_IS_WHVEC (ptr) || SCM_IS_WHVEC_B (ptr);
1386 weak_values = SCM_IS_WHVEC_V (ptr) || SCM_IS_WHVEC_B (ptr);
a00c95d9 1387
0f2d19dd
JB
1388 for (x = 0; x < len; ++x)
1389 {
1390 SCM alist;
1391 alist = SCM_VELTS (ptr)[x];
46408039
JB
1392
1393 /* mark everything on the alist except the keys or
1394 * values, according to weak_values and weak_keys. */
0b5f3f34 1395 while ( SCM_CONSP (alist)
0f2d19dd 1396 && !SCM_GCMARKP (alist)
0f2d19dd
JB
1397 && SCM_CONSP (SCM_CAR (alist)))
1398 {
1399 SCM kvpair;
1400 SCM next_alist;
1401
1402 kvpair = SCM_CAR (alist);
1403 next_alist = SCM_CDR (alist);
a00c95d9 1404 /*
0f2d19dd
JB
1405 * Do not do this:
1406 * SCM_SETGCMARK (alist);
1407 * SCM_SETGCMARK (kvpair);
1408 *
1409 * It may be that either the key or value is protected by
1410 * an escaped reference to part of the spine of this alist.
1411 * If we mark the spine here, and only mark one or neither of the
1412 * key and value, they may never be properly marked.
1413 * This leads to a horrible situation in which an alist containing
1414 * freelist cells is exported.
1415 *
1416 * So only mark the spines of these arrays last of all marking.
1417 * If somebody confuses us by constructing a weak vector
1418 * with a circular alist then we are hosed, but at least we
1419 * won't prematurely drop table entries.
1420 */
1421 if (!weak_keys)
56495472 1422 RECURSE (SCM_CAR (kvpair));
0f2d19dd 1423 if (!weak_values)
56495472 1424 RECURSE (SCM_CDR (kvpair));
0f2d19dd
JB
1425 alist = next_alist;
1426 }
1427 if (SCM_NIMP (alist))
56495472 1428 RECURSE (alist);
0f2d19dd
JB
1429 }
1430 }
1431 break;
1432
28b06554
DH
1433 case scm_tc7_symbol:
1434 ptr = SCM_PROP_SLOTS (ptr);
86d31dfe 1435 goto_gc_mark_loop;
0f2d19dd 1436 case scm_tcs_subrs:
9de33deb 1437 break;
0f2d19dd
JB
1438 case scm_tc7_port:
1439 i = SCM_PTOBNUM (ptr);
7a7f7c53 1440#if (SCM_DEBUG_CELL_ACCESSES == 1) || (defined (GUILE_DEBUG_FREELIST))
0f2d19dd 1441 if (!(i < scm_numptob))
7a7f7c53
DH
1442 SCM_MISC_ERROR ("undefined port type", SCM_EOL);
1443#endif
ebf7394e 1444 if (SCM_PTAB_ENTRY(ptr))
56495472 1445 RECURSE (SCM_FILENAME (ptr));
dc53f026
JB
1446 if (scm_ptobs[i].mark)
1447 {
1448 ptr = (scm_ptobs[i].mark) (ptr);
86d31dfe 1449 goto_gc_mark_loop;
dc53f026
JB
1450 }
1451 else
1452 return;
0f2d19dd
JB
1453 break;
1454 case scm_tc7_smob:
d6884e63 1455 switch (SCM_TYP16 (ptr))
0f2d19dd
JB
1456 { /* should be faster than going through scm_smobs */
1457 case scm_tc_free_cell:
592996c9
DH
1458 /* We have detected a free cell. This can happen if non-object data
1459 * on the C stack points into guile's heap and is scanned during
1460 * conservative marking. */
1461#if (SCM_DEBUG_CELL_ACCESSES == 0)
1462 /* If cell debugging is disabled, there is a second situation in
1463 * which a free cell can be encountered, namely if with preemptive
1464 * threading one thread has just obtained a fresh cell and was
1465 * preempted before the cell initialization was completed. In this
1466 * case, some entries of the cell may already contain objects.
1467 * Thus, if cell debugging is disabled, free cells are scanned
1468 * conservatively. */
1469 scm_gc_mark_cell_conservatively (ptr);
1470#else /* SCM_DEBUG_CELL_ACCESSES == 1 */
1471 /* With cell debugging enabled, a freshly obtained but not fully
1472 * initialized cell is guaranteed to be of type scm_tc16_allocated.
1473 * Thus, no conservative scanning for free cells is necessary, but
1474 * instead cells of type scm_tc16_allocated have to be scanned
1475 * conservatively. This is done in the mark function of the
1476 * scm_tc16_allocated smob type. */
1477#endif
1478 break;
acb0a19c
MD
1479 case scm_tc16_big:
1480 case scm_tc16_real:
1481 case scm_tc16_complex:
0f2d19dd
JB
1482 break;
1483 default:
1484 i = SCM_SMOBNUM (ptr);
7a7f7c53 1485#if (SCM_DEBUG_CELL_ACCESSES == 1) || (defined (GUILE_DEBUG_FREELIST))
0f2d19dd 1486 if (!(i < scm_numsmob))
7a7f7c53
DH
1487 SCM_MISC_ERROR ("undefined smob type", SCM_EOL);
1488#endif
dc53f026
JB
1489 if (scm_smobs[i].mark)
1490 {
1491 ptr = (scm_smobs[i].mark) (ptr);
86d31dfe 1492 goto_gc_mark_loop;
dc53f026
JB
1493 }
1494 else
1495 return;
0f2d19dd
JB
1496 }
1497 break;
1498 default:
acf4331f 1499 SCM_MISC_ERROR ("unknown type", SCM_EOL);
0f2d19dd 1500 }
0209177b 1501#undef RECURSE
0f2d19dd 1502}
acf4331f 1503#undef FUNC_NAME
0f2d19dd 1504
56495472
ML
1505#ifndef MARK_DEPENDENCIES
1506
1507#undef MARK
56495472
ML
1508#undef FNAME
1509
1510/* And here we define `scm_gc_mark_dependencies', by including this
1511 * same file in itself.
1512 */
1513#define MARK scm_gc_mark_dependencies
1514#define FNAME "scm_gc_mark_dependencies"
1515#define MARK_DEPENDENCIES
1516#include "gc.c"
1517#undef MARK_DEPENDENCIES
1518#undef MARK
56495472
ML
1519#undef FNAME
1520
0f2d19dd 1521
592996c9
DH
1522/* Determine whether the given value does actually represent a cell in some
1523 * heap segment. If this is the case, the number of the heap segment is
1524 * returned. Otherwise, -1 is returned. Binary search is used in order to
1525 * determine the heap segment that contains the cell.*/
1526/* FIXME: To be used within scm_gc_mark_cell_conservatively,
1527 * scm_mark_locations and scm_cellp this function should be an inline
1528 * function. */
1529static long int
1530heap_segment (SCM obj)
0f2d19dd 1531{
592996c9
DH
1532 if (!SCM_CELLP (obj))
1533 return -1;
1534 else
c4da09e2 1535 {
592996c9
DH
1536 SCM_CELLPTR ptr = SCM2PTR (obj);
1537 unsigned long int i = 0;
1538 unsigned long int j = scm_n_heap_segs - 1;
1539
1540 if (SCM_PTR_LT (ptr, scm_heap_table[i].bounds[0]))
1541 return -1;
1542 else if (SCM_PTR_LE (scm_heap_table[j].bounds[1], ptr))
1543 return -1;
1544 else
c4da09e2 1545 {
592996c9 1546 while (i < j)
c4da09e2 1547 {
592996c9 1548 if (SCM_PTR_LT (ptr, scm_heap_table[i].bounds[1]))
c4da09e2 1549 {
592996c9
DH
1550 break;
1551 }
1552 else if (SCM_PTR_LE (scm_heap_table[j].bounds[0], ptr))
1553 {
1554 i = j;
1555 break;
1556 }
1557 else
1558 {
1559 unsigned long int k = (i + j) / 2;
1560
1561 if (k == i)
1562 return -1;
1563 else if (SCM_PTR_LT (ptr, scm_heap_table[k].bounds[1]))
c4da09e2 1564 {
592996c9
DH
1565 j = k;
1566 ++i;
1567 if (SCM_PTR_LT (ptr, scm_heap_table[i].bounds[0]))
1568 return -1;
1569 }
1570 else if (SCM_PTR_LE (scm_heap_table[k].bounds[0], ptr))
1571 {
1572 i = k;
1573 --j;
1574 if (SCM_PTR_LE (scm_heap_table[j].bounds[1], ptr))
1575 return -1;
c4da09e2 1576 }
c4da09e2
DH
1577 }
1578 }
592996c9
DH
1579
1580 if (!DOUBLECELL_ALIGNED_P (obj) && scm_heap_table[i].span == 2)
1581 return -1;
1582 else if (SCM_GC_IN_CARD_HEADERP (ptr))
1583 return -1;
1584 else
1585 return i;
c4da09e2
DH
1586 }
1587 }
0f2d19dd
JB
1588}
1589
1590
592996c9
DH
1591/* Mark the entries of a cell conservatively. The given cell is known to be
1592 * on the heap. Still we have to determine its heap segment in order to
1593 * figure out whether it is a single or a double cell. Then, each of the cell
1594 * elements itself is checked and potentially marked. */
1595void
1596scm_gc_mark_cell_conservatively (SCM cell)
2e11a577 1597{
592996c9
DH
1598 unsigned long int cell_segment = heap_segment (cell);
1599 unsigned int span = scm_heap_table[cell_segment].span;
1600 unsigned int i;
1a548472 1601
592996c9
DH
1602 for (i = 1; i != span * 2; ++i)
1603 {
1604 SCM obj = SCM_CELL_OBJECT (cell, i);
1605 long int obj_segment = heap_segment (obj);
1606 if (obj_segment >= 0)
1607 scm_gc_mark (obj);
1608 }
1609}
61045190 1610
592996c9
DH
1611
1612/* Mark a region conservatively */
1613void
1614scm_mark_locations (SCM_STACKITEM x[], unsigned long n)
1615{
1616 unsigned long m;
1617
1618 for (m = 0; m < n; ++m)
1619 {
1620 SCM obj = * (SCM *) &x[m];
1621 long int segment = heap_segment (obj);
1622 if (segment >= 0)
1623 scm_gc_mark (obj);
1a548472 1624 }
592996c9 1625}
2e11a577 1626
592996c9
DH
1627
1628/* The function scm_cellp determines whether an SCM value can be regarded as a
1629 * pointer to a cell on the heap.
1630 */
1631int
1632scm_cellp (SCM value)
1633{
1634 long int segment = heap_segment (value);
1635 return (segment >= 0);
2e11a577
MD
1636}
1637
1638
4c48ba06 1639static void
92c2555f 1640gc_sweep_freelist_start (scm_t_freelist *freelist)
4c48ba06
MD
1641{
1642 freelist->cells = SCM_EOL;
1643 freelist->left_to_collect = freelist->cluster_size;
b37fe1c5 1644 freelist->clusters_allocated = 0;
4c48ba06
MD
1645 freelist->clusters = SCM_EOL;
1646 freelist->clustertail = &freelist->clusters;
1811ebce 1647 freelist->collected_1 = freelist->collected;
4c48ba06
MD
1648 freelist->collected = 0;
1649}
1650
1651static void
92c2555f 1652gc_sweep_freelist_finish (scm_t_freelist *freelist)
4c48ba06 1653{
c014a02e 1654 long collected;
4c48ba06 1655 *freelist->clustertail = freelist->cells;
3f5d82cd 1656 if (!SCM_NULLP (freelist->cells))
4c48ba06
MD
1657 {
1658 SCM c = freelist->cells;
22a52da1
DH
1659 SCM_SET_CELL_WORD_0 (c, SCM_FREE_CELL_CDR (c));
1660 SCM_SET_CELL_WORD_1 (c, SCM_EOL);
4c48ba06
MD
1661 freelist->collected +=
1662 freelist->span * (freelist->cluster_size - freelist->left_to_collect);
1663 }
b37fe1c5 1664 scm_gc_cells_collected += freelist->collected;
a00c95d9 1665
8fef55a8 1666 /* Although freelist->min_yield is used to test freelist->collected
7dbff8b1 1667 * (which is the local GC yield for freelist), it is adjusted so
8fef55a8 1668 * that *total* yield is freelist->min_yield_fraction of total heap
7dbff8b1
MD
1669 * size. This means that a too low yield is compensated by more
1670 * heap on the list which is currently doing most work, which is
1671 * just what we want.
1672 */
1811ebce 1673 collected = SCM_MAX (freelist->collected_1, freelist->collected);
8fef55a8 1674 freelist->grow_heap_p = (collected < freelist->min_yield);
4c48ba06 1675}
0f2d19dd 1676
d6884e63
ML
1677#define NEXT_DATA_CELL(ptr, span) \
1678 do { \
1679 scm_cell *nxt__ = CELL_UP ((char *) (ptr) + 1, (span)); \
1680 (ptr) = (SCM_GC_IN_CARD_HEADERP (nxt__) ? \
1681 CELL_UP (SCM_GC_CELL_CARD (nxt__) + SCM_GC_CARD_N_HEADER_CELLS, span) \
1682 : nxt__); \
1683 } while (0)
1684
a00c95d9 1685void
0f2d19dd 1686scm_gc_sweep ()
acf4331f 1687#define FUNC_NAME "scm_gc_sweep"
0f2d19dd
JB
1688{
1689 register SCM_CELLPTR ptr;
0f2d19dd 1690 register SCM nfreelist;
92c2555f 1691 register scm_t_freelist *freelist;
c014a02e 1692 register unsigned long m;
0f2d19dd 1693 register int span;
592996c9 1694 size_t i;
1be6b49c 1695 size_t seg_size;
0f2d19dd 1696
0f2d19dd 1697 m = 0;
0f2d19dd 1698
4c48ba06
MD
1699 gc_sweep_freelist_start (&scm_master_freelist);
1700 gc_sweep_freelist_start (&scm_master_freelist2);
a00c95d9 1701
cf2d30f6 1702 for (i = 0; i < scm_n_heap_segs; i++)
0f2d19dd 1703 {
c014a02e 1704 register long left_to_collect;
1be6b49c 1705 register size_t j;
15e9d186 1706
cf2d30f6
JB
1707 /* Unmarked cells go onto the front of the freelist this heap
1708 segment points to. Rather than updating the real freelist
1709 pointer as we go along, we accumulate the new head in
1710 nfreelist. Then, if it turns out that the entire segment is
1711 free, we free (i.e., malloc's free) the whole segment, and
1712 simply don't assign nfreelist back into the real freelist. */
4c48ba06
MD
1713 freelist = scm_heap_table[i].freelist;
1714 nfreelist = freelist->cells;
4c48ba06 1715 left_to_collect = freelist->left_to_collect;
945fec60 1716 span = scm_heap_table[i].span;
cf2d30f6 1717
a00c95d9
ML
1718 ptr = CELL_UP (scm_heap_table[i].bounds[0], span);
1719 seg_size = CELL_DN (scm_heap_table[i].bounds[1], span) - ptr;
c9b0d4b0 1720
d6884e63
ML
1721 /* use only data cells in seg_size */
1722 seg_size = (seg_size / SCM_GC_CARD_N_CELLS) * (SCM_GC_CARD_N_DATA_CELLS / span) * span;
1723
c9b0d4b0
ML
1724 scm_gc_cells_swept += seg_size;
1725
0f2d19dd
JB
1726 for (j = seg_size + span; j -= span; ptr += span)
1727 {
d6884e63 1728 SCM scmptr;
96f6f4ae 1729
d6884e63 1730 if (SCM_GC_IN_CARD_HEADERP (ptr))
0f2d19dd 1731 {
d6884e63
ML
1732 SCM_CELLPTR nxt;
1733
1734 /* cheat here */
1735 nxt = ptr;
1736 NEXT_DATA_CELL (nxt, span);
1737 j += span;
1738
1739 ptr = nxt - span;
1740 continue;
1741 }
1742
1743 scmptr = PTR2SCM (ptr);
1744
1745 if (SCM_GCMARKP (scmptr))
1746 continue;
7bb8eac7 1747
d6884e63
ML
1748 switch SCM_TYP7 (scmptr)
1749 {
0f2d19dd 1750 case scm_tcs_cons_gloc:
0f2d19dd 1751 {
c8045e8d
DH
1752 /* Dirk:FIXME:: Again, super ugly code: scmptr may be a
1753 * struct or a gloc. See the corresponding comment in
1754 * scm_gc_mark.
1755 */
92c2555f 1756 scm_t_bits word0 = (SCM_CELL_WORD_0 (scmptr)
7445e0e8
MD
1757 - scm_tc3_cons_gloc);
1758 /* access as struct */
92c2555f 1759 scm_t_bits * vtable_data = (scm_t_bits *) word0;
d6884e63 1760 if (vtable_data[scm_vtable_index_vcell] == 0)
0f2d19dd 1761 {
7445e0e8
MD
1762 /* Structs need to be freed in a special order.
1763 * This is handled by GC C hooks in struct.c.
1764 */
1765 SCM_SET_STRUCT_GC_CHAIN (scmptr, scm_structs_to_free);
1766 scm_structs_to_free = scmptr;
7bb8eac7 1767 continue;
c8045e8d 1768 }
7445e0e8 1769 /* fall through so that scmptr gets collected */
0f2d19dd
JB
1770 }
1771 break;
1772 case scm_tcs_cons_imcar:
1773 case scm_tcs_cons_nimcar:
1774 case scm_tcs_closures:
e641afaf 1775 case scm_tc7_pws:
0f2d19dd
JB
1776 break;
1777 case scm_tc7_wvect:
0f2d19dd 1778 case scm_tc7_vector:
1b9be268 1779 {
c014a02e 1780 unsigned long int length = SCM_VECTOR_LENGTH (scmptr);
1b9be268
DH
1781 if (length > 0)
1782 {
92c2555f 1783 m += length * sizeof (scm_t_bits);
1b9be268
DH
1784 scm_must_free (SCM_VECTOR_BASE (scmptr));
1785 }
1786 break;
1787 }
0f2d19dd
JB
1788#ifdef CCLO
1789 case scm_tc7_cclo:
b5c2579a 1790 m += (SCM_CCLO_LENGTH (scmptr) * sizeof (SCM));
06ee04b2 1791 scm_must_free (SCM_CCLO_BASE (scmptr));
0f2d19dd 1792 break;
06ee04b2 1793#endif
afe5177e 1794#ifdef HAVE_ARRAYS
0f2d19dd 1795 case scm_tc7_bvect:
93778877 1796 {
c014a02e 1797 unsigned long int length = SCM_BITVECTOR_LENGTH (scmptr);
93778877
DH
1798 if (length > 0)
1799 {
c014a02e 1800 m += sizeof (long) * ((length + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
93778877
DH
1801 scm_must_free (SCM_BITVECTOR_BASE (scmptr));
1802 }
1803 }
06ee04b2 1804 break;
0f2d19dd 1805 case scm_tc7_byvect:
0f2d19dd
JB
1806 case scm_tc7_ivect:
1807 case scm_tc7_uvect:
0f2d19dd 1808 case scm_tc7_svect:
5c11cc9d 1809#ifdef HAVE_LONG_LONGS
0f2d19dd 1810 case scm_tc7_llvect:
0f2d19dd
JB
1811#endif
1812 case scm_tc7_fvect:
0f2d19dd 1813 case scm_tc7_dvect:
0f2d19dd 1814 case scm_tc7_cvect:
d1ca2c64 1815 m += SCM_UVECTOR_LENGTH (scmptr) * scm_uniform_element_size (scmptr);
06ee04b2
DH
1816 scm_must_free (SCM_UVECTOR_BASE (scmptr));
1817 break;
afe5177e 1818#endif
0f2d19dd 1819 case scm_tc7_substring:
0f2d19dd
JB
1820 break;
1821 case scm_tc7_string:
b5c2579a 1822 m += SCM_STRING_LENGTH (scmptr) + 1;
f151f912
DH
1823 scm_must_free (SCM_STRING_CHARS (scmptr));
1824 break;
28b06554 1825 case scm_tc7_symbol:
b5c2579a 1826 m += SCM_SYMBOL_LENGTH (scmptr) + 1;
f151f912 1827 scm_must_free (SCM_SYMBOL_CHARS (scmptr));
0f2d19dd 1828 break;
0f2d19dd 1829 case scm_tcs_subrs:
d6884e63 1830 /* the various "subrs" (primitives) are never freed */
0f2d19dd
JB
1831 continue;
1832 case scm_tc7_port:
0f2d19dd
JB
1833 if SCM_OPENP (scmptr)
1834 {
1835 int k = SCM_PTOBNUM (scmptr);
7a7f7c53 1836#if (SCM_DEBUG_CELL_ACCESSES == 1) || (defined (GUILE_DEBUG_FREELIST))
0f2d19dd 1837 if (!(k < scm_numptob))
7a7f7c53
DH
1838 SCM_MISC_ERROR ("undefined port type", SCM_EOL);
1839#endif
0f2d19dd 1840 /* Keep "revealed" ports alive. */
945fec60 1841 if (scm_revealed_count (scmptr) > 0)
0f2d19dd
JB
1842 continue;
1843 /* Yes, I really do mean scm_ptobs[k].free */
1844 /* rather than ftobs[k].close. .close */
1845 /* is for explicit CLOSE-PORT by user */
84af0382 1846 m += (scm_ptobs[k].free) (scmptr);
0f2d19dd
JB
1847 SCM_SETSTREAM (scmptr, 0);
1848 scm_remove_from_port_table (scmptr);
1849 scm_gc_ports_collected++;
22a52da1 1850 SCM_CLR_PORT_OPEN_FLAG (scmptr);
0f2d19dd
JB
1851 }
1852 break;
1853 case scm_tc7_smob:
d6884e63 1854 switch SCM_TYP16 (scmptr)
0f2d19dd
JB
1855 {
1856 case scm_tc_free_cell:
acb0a19c 1857 case scm_tc16_real:
0f2d19dd
JB
1858 break;
1859#ifdef SCM_BIGDIG
acb0a19c 1860 case scm_tc16_big:
0f2d19dd 1861 m += (SCM_NUMDIGS (scmptr) * SCM_BITSPERDIG / SCM_CHAR_BIT);
06ee04b2
DH
1862 scm_must_free (SCM_BDIGITS (scmptr));
1863 break;
0f2d19dd 1864#endif /* def SCM_BIGDIG */
acb0a19c 1865 case scm_tc16_complex:
92c2555f 1866 m += sizeof (scm_t_complex);
405aaef9 1867 scm_must_free (SCM_COMPLEX_MEM (scmptr));
06ee04b2 1868 break;
0f2d19dd 1869 default:
0f2d19dd
JB
1870 {
1871 int k;
1872 k = SCM_SMOBNUM (scmptr);
7a7f7c53 1873#if (SCM_DEBUG_CELL_ACCESSES == 1) || (defined (GUILE_DEBUG_FREELIST))
0f2d19dd 1874 if (!(k < scm_numsmob))
7a7f7c53
DH
1875 SCM_MISC_ERROR ("undefined smob type", SCM_EOL);
1876#endif
1877 if (scm_smobs[k].free)
1878 m += (scm_smobs[k].free) (scmptr);
0f2d19dd
JB
1879 break;
1880 }
1881 }
1882 break;
1883 default:
acf4331f 1884 SCM_MISC_ERROR ("unknown type", SCM_EOL);
0f2d19dd 1885 }
7bb8eac7 1886
4c48ba06 1887 if (!--left_to_collect)
4a4c9785 1888 {
22a52da1 1889 SCM_SET_CELL_WORD_0 (scmptr, nfreelist);
4c48ba06
MD
1890 *freelist->clustertail = scmptr;
1891 freelist->clustertail = SCM_CDRLOC (scmptr);
a00c95d9 1892
4a4c9785 1893 nfreelist = SCM_EOL;
4c48ba06
MD
1894 freelist->collected += span * freelist->cluster_size;
1895 left_to_collect = freelist->cluster_size;
4a4c9785
MD
1896 }
1897 else
4a4c9785
MD
1898 {
1899 /* Stick the new cell on the front of nfreelist. It's
1900 critical that we mark this cell as freed; otherwise, the
1901 conservative collector might trace it as some other type
1902 of object. */
54778cd3 1903 SCM_SET_CELL_TYPE (scmptr, scm_tc_free_cell);
3f5d82cd 1904 SCM_SET_FREE_CELL_CDR (scmptr, nfreelist);
4a4c9785
MD
1905 nfreelist = scmptr;
1906 }
0f2d19dd 1907 }
d6884e63 1908
0f2d19dd
JB
1909#ifdef GC_FREE_SEGMENTS
1910 if (n == seg_size)
1911 {
c014a02e 1912 register long j;
15e9d186 1913
4c48ba06 1914 freelist->heap_size -= seg_size;
cf2d30f6
JB
1915 free ((char *) scm_heap_table[i].bounds[0]);
1916 scm_heap_table[i].bounds[0] = 0;
1917 for (j = i + 1; j < scm_n_heap_segs; j++)
0f2d19dd
JB
1918 scm_heap_table[j - 1] = scm_heap_table[j];
1919 scm_n_heap_segs -= 1;
cf2d30f6 1920 i--; /* We need to scan the segment just moved. */
0f2d19dd
JB
1921 }
1922 else
1923#endif /* ifdef GC_FREE_SEGMENTS */
4a4c9785
MD
1924 {
1925 /* Update the real freelist pointer to point to the head of
1926 the list of free cells we've built for this segment. */
4c48ba06 1927 freelist->cells = nfreelist;
4c48ba06 1928 freelist->left_to_collect = left_to_collect;
4a4c9785
MD
1929 }
1930
fca7547b 1931#ifdef GUILE_DEBUG_FREELIST
cf2d30f6
JB
1932 scm_map_free_list ();
1933#endif
4a4c9785 1934 }
a00c95d9 1935
4c48ba06
MD
1936 gc_sweep_freelist_finish (&scm_master_freelist);
1937 gc_sweep_freelist_finish (&scm_master_freelist2);
a00c95d9 1938
8ded62a3
MD
1939 /* When we move to POSIX threads private freelists should probably
1940 be GC-protected instead. */
1941 scm_freelist = SCM_EOL;
1942 scm_freelist2 = SCM_EOL;
a00c95d9 1943
b37fe1c5 1944 scm_cells_allocated = (SCM_HEAP_SIZE - scm_gc_cells_collected);
8b0d194f 1945 scm_gc_yield -= scm_cells_allocated;
1be6b49c
ML
1946
1947 if (scm_mallocated < m)
1948 /* The byte count of allocated objects has underflowed. This is
1949 probably because you forgot to report the sizes of objects you
1950 have allocated, by calling scm_done_malloc or some such. When
1951 the GC freed them, it subtracted their size from
1952 scm_mallocated, which underflowed. */
1953 abort ();
1954
0f2d19dd
JB
1955 scm_mallocated -= m;
1956 scm_gc_malloc_collected = m;
1957}
acf4331f 1958#undef FUNC_NAME
0f2d19dd
JB
1959
1960
1961\f
0f2d19dd
JB
1962/* {Front end to malloc}
1963 *
9d47a1e6
ML
1964 * scm_must_malloc, scm_must_realloc, scm_must_free, scm_done_malloc,
1965 * scm_done_free
0f2d19dd 1966 *
c6c79933
GH
1967 * These functions provide services comparable to malloc, realloc, and
1968 * free. They should be used when allocating memory that will be under
1969 * control of the garbage collector, i.e., if the memory may be freed
1970 * during garbage collection.
1971 */
bc9d9bb2 1972
0f2d19dd
JB
1973/* scm_must_malloc
1974 * Return newly malloced storage or throw an error.
1975 *
1976 * The parameter WHAT is a string for error reporting.
a00c95d9 1977 * If the threshold scm_mtrigger will be passed by this
0f2d19dd
JB
1978 * allocation, or if the first call to malloc fails,
1979 * garbage collect -- on the presumption that some objects
1980 * using malloced storage may be collected.
1981 *
1982 * The limit scm_mtrigger may be raised by this allocation.
1983 */
07806695 1984void *
1be6b49c 1985scm_must_malloc (size_t size, const char *what)
0f2d19dd 1986{
07806695 1987 void *ptr;
c014a02e 1988 unsigned long nm = scm_mallocated + size;
1be6b49c
ML
1989
1990 if (nm < size)
1991 /* The byte count of allocated objects has overflowed. This is
1992 probably because you forgot to report the correct size of freed
1993 memory in some of your smob free methods. */
1994 abort ();
e4ef2330
MD
1995
1996 if (nm <= scm_mtrigger)
0f2d19dd 1997 {
07806695 1998 SCM_SYSCALL (ptr = malloc (size));
0f2d19dd
JB
1999 if (NULL != ptr)
2000 {
2001 scm_mallocated = nm;
bc9d9bb2
MD
2002#ifdef GUILE_DEBUG_MALLOC
2003 scm_malloc_register (ptr, what);
2004#endif
0f2d19dd
JB
2005 return ptr;
2006 }
2007 }
6064dcc6 2008
0f2d19dd 2009 scm_igc (what);
e4ef2330 2010
0f2d19dd 2011 nm = scm_mallocated + size;
1be6b49c
ML
2012
2013 if (nm < size)
2014 /* The byte count of allocated objects has overflowed. This is
2015 probably because you forgot to report the correct size of freed
2016 memory in some of your smob free methods. */
2017 abort ();
2018
07806695 2019 SCM_SYSCALL (ptr = malloc (size));
0f2d19dd
JB
2020 if (NULL != ptr)
2021 {
2022 scm_mallocated = nm;
6064dcc6
MV
2023 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
2024 if (nm > scm_mtrigger)
2025 scm_mtrigger = nm + nm / 2;
2026 else
2027 scm_mtrigger += scm_mtrigger / 2;
2028 }
bc9d9bb2
MD
2029#ifdef GUILE_DEBUG_MALLOC
2030 scm_malloc_register (ptr, what);
2031#endif
2032
0f2d19dd
JB
2033 return ptr;
2034 }
e4ef2330 2035
acf4331f 2036 scm_memory_error (what);
0f2d19dd
JB
2037}
2038
2039
2040/* scm_must_realloc
2041 * is similar to scm_must_malloc.
2042 */
07806695
JB
2043void *
2044scm_must_realloc (void *where,
1be6b49c
ML
2045 size_t old_size,
2046 size_t size,
3eeba8d4 2047 const char *what)
0f2d19dd 2048{
07806695 2049 void *ptr;
c014a02e 2050 unsigned long nm;
1be6b49c
ML
2051
2052 if (size <= old_size)
2053 return where;
2054
2055 nm = scm_mallocated + size - old_size;
2056
2057 if (nm < (size - old_size))
2058 /* The byte count of allocated objects has overflowed. This is
2059 probably because you forgot to report the correct size of freed
2060 memory in some of your smob free methods. */
2061 abort ();
e4ef2330
MD
2062
2063 if (nm <= scm_mtrigger)
0f2d19dd 2064 {
07806695 2065 SCM_SYSCALL (ptr = realloc (where, size));
0f2d19dd
JB
2066 if (NULL != ptr)
2067 {
2068 scm_mallocated = nm;
bc9d9bb2
MD
2069#ifdef GUILE_DEBUG_MALLOC
2070 scm_malloc_reregister (where, ptr, what);
2071#endif
0f2d19dd
JB
2072 return ptr;
2073 }
2074 }
e4ef2330 2075
0f2d19dd 2076 scm_igc (what);
e4ef2330
MD
2077
2078 nm = scm_mallocated + size - old_size;
1be6b49c
ML
2079
2080 if (nm < (size - old_size))
2081 /* The byte count of allocated objects has overflowed. This is
2082 probably because you forgot to report the correct size of freed
2083 memory in some of your smob free methods. */
2084 abort ();
2085
07806695 2086 SCM_SYSCALL (ptr = realloc (where, size));
0f2d19dd
JB
2087 if (NULL != ptr)
2088 {
2089 scm_mallocated = nm;
6064dcc6
MV
2090 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
2091 if (nm > scm_mtrigger)
2092 scm_mtrigger = nm + nm / 2;
2093 else
2094 scm_mtrigger += scm_mtrigger / 2;
2095 }
bc9d9bb2
MD
2096#ifdef GUILE_DEBUG_MALLOC
2097 scm_malloc_reregister (where, ptr, what);
2098#endif
0f2d19dd
JB
2099 return ptr;
2100 }
e4ef2330 2101
acf4331f 2102 scm_memory_error (what);
0f2d19dd
JB
2103}
2104
e4a7824f 2105char *
1be6b49c 2106scm_must_strndup (const char *str, size_t length)
e4a7824f
MV
2107{
2108 char * dst = scm_must_malloc (length + 1, "scm_must_strndup");
2109 memcpy (dst, str, length);
2110 dst[length] = 0;
2111 return dst;
2112}
2113
2114char *
2115scm_must_strdup (const char *str)
2116{
2117 return scm_must_strndup (str, strlen (str));
2118}
acf4331f 2119
a00c95d9 2120void
07806695 2121scm_must_free (void *obj)
acf4331f 2122#define FUNC_NAME "scm_must_free"
0f2d19dd 2123{
bc9d9bb2
MD
2124#ifdef GUILE_DEBUG_MALLOC
2125 scm_malloc_unregister (obj);
2126#endif
0f2d19dd
JB
2127 if (obj)
2128 free (obj);
2129 else
acf4331f 2130 SCM_MISC_ERROR ("freeing NULL pointer", SCM_EOL);
0f2d19dd 2131}
acf4331f
DH
2132#undef FUNC_NAME
2133
0f2d19dd 2134
c68296f8
MV
2135/* Announce that there has been some malloc done that will be freed
2136 * during gc. A typical use is for a smob that uses some malloced
2137 * memory but can not get it from scm_must_malloc (for whatever
2138 * reason). When a new object of this smob is created you call
2139 * scm_done_malloc with the size of the object. When your smob free
2140 * function is called, be sure to include this size in the return
9d47a1e6
ML
2141 * value.
2142 *
2143 * If you can't actually free the memory in the smob free function,
2144 * for whatever reason (like reference counting), you still can (and
2145 * should) report the amount of memory freed when you actually free it.
2146 * Do it by calling scm_done_malloc with the _negated_ size. Clever,
2147 * eh? Or even better, call scm_done_free. */
0f2d19dd 2148
c68296f8 2149void
c014a02e 2150scm_done_malloc (long size)
c68296f8 2151{
1be6b49c
ML
2152 if (size < 0) {
2153 if (scm_mallocated < size)
2154 /* The byte count of allocated objects has underflowed. This is
2155 probably because you forgot to report the sizes of objects you
2156 have allocated, by calling scm_done_malloc or some such. When
2157 the GC freed them, it subtracted their size from
2158 scm_mallocated, which underflowed. */
2159 abort ();
2160 } else {
c014a02e 2161 unsigned long nm = scm_mallocated + size;
1be6b49c
ML
2162 if (nm < size)
2163 /* The byte count of allocated objects has overflowed. This is
2164 probably because you forgot to report the correct size of freed
2165 memory in some of your smob free methods. */
2166 abort ();
2167 }
2168
c68296f8
MV
2169 scm_mallocated += size;
2170
2171 if (scm_mallocated > scm_mtrigger)
2172 {
2173 scm_igc ("foreign mallocs");
2174 if (scm_mallocated > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS)
2175 {
2176 if (scm_mallocated > scm_mtrigger)
2177 scm_mtrigger = scm_mallocated + scm_mallocated / 2;
2178 else
2179 scm_mtrigger += scm_mtrigger / 2;
2180 }
2181 }
2182}
2183
9d47a1e6 2184void
c014a02e 2185scm_done_free (long size)
9d47a1e6 2186{
1be6b49c
ML
2187 if (size >= 0) {
2188 if (scm_mallocated < size)
2189 /* The byte count of allocated objects has underflowed. This is
2190 probably because you forgot to report the sizes of objects you
2191 have allocated, by calling scm_done_malloc or some such. When
2192 the GC freed them, it subtracted their size from
2193 scm_mallocated, which underflowed. */
2194 abort ();
2195 } else {
c014a02e 2196 unsigned long nm = scm_mallocated + size;
1be6b49c
ML
2197 if (nm < size)
2198 /* The byte count of allocated objects has overflowed. This is
2199 probably because you forgot to report the correct size of freed
2200 memory in some of your smob free methods. */
2201 abort ();
2202 }
2203
9d47a1e6
ML
2204 scm_mallocated -= size;
2205}
2206
c68296f8
MV
2207
2208\f
0f2d19dd
JB
2209/* {Heap Segments}
2210 *
2211 * Each heap segment is an array of objects of a particular size.
2212 * Every segment has an associated (possibly shared) freelist.
2213 * A table of segment records is kept that records the upper and
2214 * lower extents of the segment; this is used during the conservative
2215 * phase of gc to identify probably gc roots (because they point
c68296f8 2216 * into valid segments at reasonable offsets). */
0f2d19dd
JB
2217
2218/* scm_expmem
2219 * is true if the first segment was smaller than INIT_HEAP_SEG.
2220 * If scm_expmem is set to one, subsequent segment allocations will
2221 * allocate segments of size SCM_EXPHEAP(scm_heap_size).
2222 */
2223int scm_expmem = 0;
2224
1be6b49c 2225size_t scm_max_segment_size;
4c48ba06 2226
0f2d19dd
JB
2227/* scm_heap_org
2228 * is the lowest base address of any heap segment.
2229 */
2230SCM_CELLPTR scm_heap_org;
2231
92c2555f 2232scm_t_heap_seg_data * scm_heap_table = 0;
1be6b49c
ML
2233static size_t heap_segment_table_size = 0;
2234size_t scm_n_heap_segs = 0;
0f2d19dd 2235
0f2d19dd 2236/* init_heap_seg
d6884e63 2237 * initializes a new heap segment and returns the number of objects it contains.
0f2d19dd 2238 *
d6884e63
ML
2239 * The segment origin and segment size in bytes are input parameters.
2240 * The freelist is both input and output.
0f2d19dd 2241 *
d6884e63
ML
2242 * This function presumes that the scm_heap_table has already been expanded
2243 * to accomodate a new segment record and that the markbit space was reserved
2244 * for all the cards in this segment.
0f2d19dd
JB
2245 */
2246
d6884e63
ML
2247#define INIT_CARD(card, span) \
2248 do { \
322ec19d 2249 SCM_GC_SET_CARD_BVEC (card, get_bvec ()); \
d6884e63
ML
2250 if ((span) == 2) \
2251 SCM_GC_SET_CARD_DOUBLECELL (card); \
2252 } while (0)
0f2d19dd 2253
1be6b49c 2254static size_t
92c2555f 2255init_heap_seg (SCM_CELLPTR seg_org, size_t size, scm_t_freelist *freelist)
0f2d19dd
JB
2256{
2257 register SCM_CELLPTR ptr;
0f2d19dd 2258 SCM_CELLPTR seg_end;
592996c9 2259 size_t new_seg_index;
1be6b49c 2260 ptrdiff_t n_new_cells;
4c48ba06 2261 int span = freelist->span;
a00c95d9 2262
0f2d19dd
JB
2263 if (seg_org == NULL)
2264 return 0;
2265
d6884e63
ML
2266 /* Align the begin ptr up.
2267 */
2268 ptr = SCM_GC_CARD_UP (seg_org);
acb0a19c 2269
a00c95d9 2270 /* Compute the ceiling on valid object pointers w/in this segment.
0f2d19dd 2271 */
d6884e63 2272 seg_end = SCM_GC_CARD_DOWN ((char *)seg_org + size);
0f2d19dd 2273
a00c95d9 2274 /* Find the right place and insert the segment record.
0f2d19dd 2275 */
592996c9
DH
2276 new_seg_index = 0;
2277 while (new_seg_index < scm_n_heap_segs
2278 && SCM_PTR_LE (scm_heap_table[new_seg_index].bounds[0], seg_org))
2279 new_seg_index++;
0f2d19dd
JB
2280
2281 {
2282 int i;
2283 for (i = scm_n_heap_segs; i > new_seg_index; --i)
2284 scm_heap_table[i] = scm_heap_table[i - 1];
2285 }
a00c95d9 2286
0f2d19dd
JB
2287 ++scm_n_heap_segs;
2288
945fec60 2289 scm_heap_table[new_seg_index].span = span;
4c48ba06 2290 scm_heap_table[new_seg_index].freelist = freelist;
195e6201
DH
2291 scm_heap_table[new_seg_index].bounds[0] = ptr;
2292 scm_heap_table[new_seg_index].bounds[1] = seg_end;
0f2d19dd 2293
acb0a19c
MD
2294 /*n_new_cells*/
2295 n_new_cells = seg_end - ptr;
0f2d19dd 2296
4c48ba06 2297 freelist->heap_size += n_new_cells;
4a4c9785 2298
a00c95d9 2299 /* Partition objects in this segment into clusters */
4a4c9785
MD
2300 {
2301 SCM clusters;
2302 SCM *clusterp = &clusters;
4a4c9785 2303
d6884e63
ML
2304 NEXT_DATA_CELL (ptr, span);
2305 while (ptr < seg_end)
4a4c9785 2306 {
d6884e63
ML
2307 scm_cell *nxt = ptr;
2308 scm_cell *prv = NULL;
2309 scm_cell *last_card = NULL;
2310 int n_data_cells = (SCM_GC_CARD_N_DATA_CELLS / span) * SCM_CARDS_PER_CLUSTER - 1;
2311 NEXT_DATA_CELL(nxt, span);
4a4c9785 2312
4c48ba06
MD
2313 /* Allocate cluster spine
2314 */
4a4c9785 2315 *clusterp = PTR2SCM (ptr);
d6884e63 2316 SCM_SETCAR (*clusterp, PTR2SCM (nxt));
4a4c9785 2317 clusterp = SCM_CDRLOC (*clusterp);
d6884e63 2318 ptr = nxt;
a00c95d9 2319
d6884e63 2320 while (n_data_cells--)
4a4c9785 2321 {
d6884e63 2322 scm_cell *card = SCM_GC_CELL_CARD (ptr);
96f6f4ae 2323 SCM scmptr = PTR2SCM (ptr);
d6884e63
ML
2324 nxt = ptr;
2325 NEXT_DATA_CELL (nxt, span);
2326 prv = ptr;
2327
2328 if (card != last_card)
2329 {
2330 INIT_CARD (card, span);
2331 last_card = card;
2332 }
96f6f4ae 2333
54778cd3 2334 SCM_SET_CELL_TYPE (scmptr, scm_tc_free_cell);
22a52da1 2335 SCM_SET_FREE_CELL_CDR (scmptr, PTR2SCM (nxt));
d6884e63
ML
2336
2337 ptr = nxt;
4a4c9785 2338 }
4c48ba06 2339
d6884e63 2340 SCM_SET_FREE_CELL_CDR (PTR2SCM (prv), SCM_EOL);
4a4c9785 2341 }
a00c95d9 2342
d6884e63
ML
2343 /* sanity check */
2344 {
2345 scm_cell *ref = seg_end;
2346 NEXT_DATA_CELL (ref, span);
2347 if (ref != ptr)
2348 /* [cmm] looks like the segment size doesn't divide cleanly by
2349 cluster size. bad cmm! */
2350 abort();
2351 }
2352
4a4c9785
MD
2353 /* Patch up the last cluster pointer in the segment
2354 * to join it to the input freelist.
2355 */
4c48ba06
MD
2356 *clusterp = freelist->clusters;
2357 freelist->clusters = clusters;
4a4c9785
MD
2358 }
2359
4c48ba06
MD
2360#ifdef DEBUGINFO
2361 fprintf (stderr, "H");
2362#endif
0f2d19dd 2363 return size;
0f2d19dd
JB
2364}
2365
1be6b49c 2366static size_t
92c2555f 2367round_to_cluster_size (scm_t_freelist *freelist, size_t len)
a00c95d9 2368{
1be6b49c 2369 size_t cluster_size_in_bytes = CLUSTER_SIZE_IN_BYTES (freelist);
a00c95d9
ML
2370
2371 return
2372 (len + cluster_size_in_bytes - 1) / cluster_size_in_bytes * cluster_size_in_bytes
2373 + ALIGNMENT_SLACK (freelist);
2374}
2375
a00c95d9 2376static void
92c2555f 2377alloc_some_heap (scm_t_freelist *freelist, policy_on_error error_policy)
acf4331f 2378#define FUNC_NAME "alloc_some_heap"
0f2d19dd 2379{
0f2d19dd 2380 SCM_CELLPTR ptr;
1be6b49c 2381 size_t len;
a00c95d9 2382
9d47a1e6 2383 if (scm_gc_heap_lock)
b6efc951
DH
2384 {
2385 /* Critical code sections (such as the garbage collector) aren't
2386 * supposed to add heap segments.
2387 */
2388 fprintf (stderr, "alloc_some_heap: Can not extend locked heap.\n");
2389 abort ();
2390 }
0f2d19dd 2391
9d47a1e6 2392 if (scm_n_heap_segs == heap_segment_table_size)
b6efc951
DH
2393 {
2394 /* We have to expand the heap segment table to have room for the new
2395 * segment. Do not yet increment scm_n_heap_segs -- that is done by
2396 * init_heap_seg only if the allocation of the segment itself succeeds.
2397 */
1be6b49c 2398 size_t new_table_size = scm_n_heap_segs + 1;
92c2555f
MV
2399 size_t size = new_table_size * sizeof (scm_t_heap_seg_data);
2400 scm_t_heap_seg_data *new_heap_table;
b6efc951 2401
92c2555f 2402 SCM_SYSCALL (new_heap_table = ((scm_t_heap_seg_data *)
b6efc951
DH
2403 realloc ((char *)scm_heap_table, size)));
2404 if (!new_heap_table)
2405 {
2406 if (error_policy == abort_on_error)
2407 {
2408 fprintf (stderr, "alloc_some_heap: Could not grow heap segment table.\n");
2409 abort ();
2410 }
2411 else
2412 {
2413 return;
2414 }
2415 }
2416 else
2417 {
2418 scm_heap_table = new_heap_table;
2419 heap_segment_table_size = new_table_size;
2420 }
2421 }
0f2d19dd 2422
0f2d19dd 2423 /* Pick a size for the new heap segment.
a00c95d9 2424 * The rule for picking the size of a segment is explained in
0f2d19dd
JB
2425 * gc.h
2426 */
4c48ba06 2427 {
1811ebce
MD
2428 /* Assure that the new segment is predicted to be large enough.
2429 *
2430 * New yield should at least equal GC fraction of new heap size, i.e.
2431 *
2432 * y + dh > f * (h + dh)
2433 *
2434 * y : yield
8fef55a8 2435 * f : min yield fraction
1811ebce
MD
2436 * h : heap size
2437 * dh : size of new heap segment
2438 *
2439 * This gives dh > (f * h - y) / (1 - f)
bda1446c 2440 */
8fef55a8 2441 int f = freelist->min_yield_fraction;
c014a02e 2442 unsigned long h = SCM_HEAP_SIZE;
1be6b49c 2443 size_t min_cells = (f * h - 100 * (long) scm_gc_yield) / (99 - f);
4c48ba06
MD
2444 len = SCM_EXPHEAP (freelist->heap_size);
2445#ifdef DEBUGINFO
1be6b49c 2446 fprintf (stderr, "(%ld < %ld)", (long) len, (long) min_cells);
4c48ba06
MD
2447#endif
2448 if (len < min_cells)
1811ebce 2449 len = min_cells + freelist->cluster_size;
4c48ba06 2450 len *= sizeof (scm_cell);
1811ebce
MD
2451 /* force new sampling */
2452 freelist->collected = LONG_MAX;
4c48ba06 2453 }
a00c95d9 2454
4c48ba06
MD
2455 if (len > scm_max_segment_size)
2456 len = scm_max_segment_size;
0f2d19dd
JB
2457
2458 {
1be6b49c 2459 size_t smallest;
0f2d19dd 2460
a00c95d9 2461 smallest = CLUSTER_SIZE_IN_BYTES (freelist);
a00c95d9 2462
0f2d19dd 2463 if (len < smallest)
a00c95d9 2464 len = smallest;
0f2d19dd
JB
2465
2466 /* Allocate with decaying ambition. */
2467 while ((len >= SCM_MIN_HEAP_SEG_SIZE)
2468 && (len >= smallest))
2469 {
1be6b49c 2470 size_t rounded_len = round_to_cluster_size (freelist, len);
a00c95d9 2471 SCM_SYSCALL (ptr = (SCM_CELLPTR) malloc (rounded_len));
0f2d19dd
JB
2472 if (ptr)
2473 {
a00c95d9 2474 init_heap_seg (ptr, rounded_len, freelist);
0f2d19dd
JB
2475 return;
2476 }
2477 len /= 2;
2478 }
2479 }
2480
b6efc951
DH
2481 if (error_policy == abort_on_error)
2482 {
2483 fprintf (stderr, "alloc_some_heap: Could not grow heap.\n");
2484 abort ();
2485 }
0f2d19dd 2486}
acf4331f 2487#undef FUNC_NAME
0f2d19dd 2488
0f2d19dd
JB
2489\f
2490/* {GC Protection Helper Functions}
2491 */
2492
2493
5d2b97cd
DH
2494/*
2495 * If within a function you need to protect one or more scheme objects from
2496 * garbage collection, pass them as parameters to one of the
2497 * scm_remember_upto_here* functions below. These functions don't do
2498 * anything, but since the compiler does not know that they are actually
2499 * no-ops, it will generate code that calls these functions with the given
2500 * parameters. Therefore, you can be sure that the compiler will keep those
2501 * scheme values alive (on the stack or in a register) up to the point where
2502 * scm_remember_upto_here* is called. In other words, place the call to
592996c9 2503 * scm_remember_upto_here* _behind_ the last code in your function, that
5d2b97cd
DH
2504 * depends on the scheme object to exist.
2505 *
2506 * Example: We want to make sure, that the string object str does not get
2507 * garbage collected during the execution of 'some_function', because
2508 * otherwise the characters belonging to str would be freed and
2509 * 'some_function' might access freed memory. To make sure that the compiler
2510 * keeps str alive on the stack or in a register such that it is visible to
2511 * the conservative gc we add the call to scm_remember_upto_here_1 _after_ the
2512 * call to 'some_function'. Note that this would not be necessary if str was
2513 * used anyway after the call to 'some_function'.
2514 * char *chars = SCM_STRING_CHARS (str);
2515 * some_function (chars);
2516 * scm_remember_upto_here_1 (str); // str will be alive up to this point.
2517 */
2518
2519void
e81d98ec 2520scm_remember_upto_here_1 (SCM obj SCM_UNUSED)
5d2b97cd
DH
2521{
2522 /* Empty. Protects a single object from garbage collection. */
2523}
2524
2525void
e81d98ec 2526scm_remember_upto_here_2 (SCM obj1 SCM_UNUSED, SCM obj2 SCM_UNUSED)
5d2b97cd
DH
2527{
2528 /* Empty. Protects two objects from garbage collection. */
2529}
2530
2531void
e81d98ec 2532scm_remember_upto_here (SCM obj SCM_UNUSED, ...)
5d2b97cd
DH
2533{
2534 /* Empty. Protects any number of objects from garbage collection. */
2535}
2536
2537
2538#if (SCM_DEBUG_DEPRECATED == 0)
2539
0f2d19dd 2540void
6e8d25a6 2541scm_remember (SCM *ptr)
b24b5e13 2542{
1be6b49c
ML
2543 scm_c_issue_deprecation_warning ("`scm_remember' is deprecated. "
2544 "Use the `scm_remember_upto_here*' family of functions instead.");
b24b5e13 2545}
0f2d19dd 2546
6b1b030e
ML
2547SCM
2548scm_protect_object (SCM obj)
2549{
2550 scm_c_issue_deprecation_warning ("`scm_protect_object' is deprecated. "
2551 "Use `scm_gc_protect_object' instead.");
2552 return scm_gc_protect_object (obj);
2553}
2554
2555SCM
2556scm_unprotect_object (SCM obj)
2557{
2558 scm_c_issue_deprecation_warning ("`scm_unprotect_object' is deprecated. "
2559 "Use `scm_gc_unprotect_object' instead.");
2560 return scm_gc_unprotect_object (obj);
2561}
2562
5d2b97cd 2563#endif /* SCM_DEBUG_DEPRECATED == 0 */
1cc91f1b 2564
c209c88e 2565/*
41b0806d
GB
2566 These crazy functions prevent garbage collection
2567 of arguments after the first argument by
2568 ensuring they remain live throughout the
2569 function because they are used in the last
2570 line of the code block.
2571 It'd be better to have a nice compiler hint to
2572 aid the conservative stack-scanning GC. --03/09/00 gjb */
0f2d19dd
JB
2573SCM
2574scm_return_first (SCM elt, ...)
0f2d19dd
JB
2575{
2576 return elt;
2577}
2578
41b0806d
GB
2579int
2580scm_return_first_int (int i, ...)
2581{
2582 return i;
2583}
2584
0f2d19dd 2585
0f2d19dd 2586SCM
6e8d25a6 2587scm_permanent_object (SCM obj)
0f2d19dd
JB
2588{
2589 SCM_REDEFER_INTS;
2590 scm_permobjs = scm_cons (obj, scm_permobjs);
2591 SCM_REALLOW_INTS;
2592 return obj;
2593}
2594
2595
7bd4fbe2
MD
2596/* Protect OBJ from the garbage collector. OBJ will not be freed, even if all
2597 other references are dropped, until the object is unprotected by calling
6b1b030e 2598 scm_gc_unprotect_object (OBJ). Calls to scm_gc_protect/unprotect_object nest,
7bd4fbe2
MD
2599 i. e. it is possible to protect the same object several times, but it is
2600 necessary to unprotect the object the same number of times to actually get
2601 the object unprotected. It is an error to unprotect an object more often
2602 than it has been protected before. The function scm_protect_object returns
2603 OBJ.
2604*/
2605
2606/* Implementation note: For every object X, there is a counter which
6b1b030e 2607 scm_gc_protect_object(X) increments and scm_gc_unprotect_object(X) decrements.
7bd4fbe2 2608*/
686765af 2609
ef290276 2610SCM
6b1b030e 2611scm_gc_protect_object (SCM obj)
ef290276 2612{
686765af 2613 SCM handle;
9d47a1e6 2614
686765af 2615 /* This critical section barrier will be replaced by a mutex. */
2dd6a83a 2616 SCM_REDEFER_INTS;
9d47a1e6 2617
0f0f0899 2618 handle = scm_hashq_create_handle_x (scm_protects, obj, SCM_MAKINUM (0));
1be6b49c 2619 SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), SCM_MAKINUM (1)));
9d47a1e6 2620
2dd6a83a 2621 SCM_REALLOW_INTS;
9d47a1e6 2622
ef290276
JB
2623 return obj;
2624}
2625
2626
2627/* Remove any protection for OBJ established by a prior call to
dab7f566 2628 scm_protect_object. This function returns OBJ.
ef290276 2629
dab7f566 2630 See scm_protect_object for more information. */
ef290276 2631SCM
6b1b030e 2632scm_gc_unprotect_object (SCM obj)
ef290276 2633{
686765af 2634 SCM handle;
9d47a1e6 2635
686765af 2636 /* This critical section barrier will be replaced by a mutex. */
2dd6a83a 2637 SCM_REDEFER_INTS;
9d47a1e6 2638
686765af 2639 handle = scm_hashq_get_handle (scm_protects, obj);
9d47a1e6 2640
22a52da1 2641 if (SCM_FALSEP (handle))
686765af 2642 {
0f0f0899
MD
2643 fprintf (stderr, "scm_unprotect_object called on unprotected object\n");
2644 abort ();
686765af 2645 }
6a199940
DH
2646 else
2647 {
1be6b49c
ML
2648 SCM count = scm_difference (SCM_CDR (handle), SCM_MAKINUM (1));
2649 if (SCM_EQ_P (count, SCM_MAKINUM (0)))
6a199940
DH
2650 scm_hashq_remove_x (scm_protects, obj);
2651 else
1be6b49c 2652 SCM_SETCDR (handle, count);
6a199940 2653 }
686765af 2654
2dd6a83a 2655 SCM_REALLOW_INTS;
ef290276
JB
2656
2657 return obj;
2658}
2659
6b1b030e
ML
2660void
2661scm_gc_register_root (SCM *p)
2662{
2663 SCM handle;
2664 SCM key = scm_long2num ((long) p);
2665
2666 /* This critical section barrier will be replaced by a mutex. */
2667 SCM_REDEFER_INTS;
2668
2669 handle = scm_hashv_create_handle_x (scm_gc_registered_roots, key, SCM_MAKINUM (0));
2670 SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), SCM_MAKINUM (1)));
2671
2672 SCM_REALLOW_INTS;
2673}
2674
2675void
2676scm_gc_unregister_root (SCM *p)
2677{
2678 SCM handle;
2679 SCM key = scm_long2num ((long) p);
2680
2681 /* This critical section barrier will be replaced by a mutex. */
2682 SCM_REDEFER_INTS;
2683
2684 handle = scm_hashv_get_handle (scm_gc_registered_roots, key);
2685
2686 if (SCM_FALSEP (handle))
2687 {
2688 fprintf (stderr, "scm_gc_unregister_root called on unregistered root\n");
2689 abort ();
2690 }
2691 else
2692 {
2693 SCM count = scm_difference (SCM_CDR (handle), SCM_MAKINUM (1));
2694 if (SCM_EQ_P (count, SCM_MAKINUM (0)))
2695 scm_hashv_remove_x (scm_gc_registered_roots, key);
2696 else
2697 SCM_SETCDR (handle, count);
2698 }
2699
2700 SCM_REALLOW_INTS;
2701}
2702
2703void
2704scm_gc_register_roots (SCM *b, unsigned long n)
2705{
2706 SCM *p = b;
2707 for (; p < b + n; ++p)
2708 scm_gc_register_root (p);
2709}
2710
2711void
2712scm_gc_unregister_roots (SCM *b, unsigned long n)
2713{
2714 SCM *p = b;
2715 for (; p < b + n; ++p)
2716 scm_gc_unregister_root (p);
2717}
2718
c45acc34
JB
2719int terminating;
2720
2721/* called on process termination. */
e52ceaac
MD
2722#ifdef HAVE_ATEXIT
2723static void
2724cleanup (void)
2725#else
2726#ifdef HAVE_ON_EXIT
51157deb
MD
2727extern int on_exit (void (*procp) (), int arg);
2728
e52ceaac
MD
2729static void
2730cleanup (int status, void *arg)
2731#else
2732#error Dont know how to setup a cleanup handler on your system.
2733#endif
2734#endif
c45acc34
JB
2735{
2736 terminating = 1;
2737 scm_flush_all_ports ();
2738}
ef290276 2739
0f2d19dd 2740\f
acb0a19c 2741static int
92c2555f 2742make_initial_segment (size_t init_heap_size, scm_t_freelist *freelist)
acb0a19c 2743{
1be6b49c 2744 size_t rounded_size = round_to_cluster_size (freelist, init_heap_size);
d6884e63 2745
a00c95d9
ML
2746 if (!init_heap_seg ((SCM_CELLPTR) malloc (rounded_size),
2747 rounded_size,
4c48ba06 2748 freelist))
acb0a19c 2749 {
a00c95d9
ML
2750 rounded_size = round_to_cluster_size (freelist, SCM_HEAP_SEG_SIZE);
2751 if (!init_heap_seg ((SCM_CELLPTR) malloc (rounded_size),
2752 rounded_size,
4c48ba06 2753 freelist))
acb0a19c
MD
2754 return 1;
2755 }
2756 else
2757 scm_expmem = 1;
2758
8fef55a8
MD
2759 if (freelist->min_yield_fraction)
2760 freelist->min_yield = (freelist->heap_size * freelist->min_yield_fraction
b37fe1c5 2761 / 100);
8fef55a8 2762 freelist->grow_heap_p = (freelist->heap_size < freelist->min_yield);
a00c95d9 2763
acb0a19c
MD
2764 return 0;
2765}
2766
2767\f
4c48ba06 2768static void
92c2555f 2769init_freelist (scm_t_freelist *freelist,
4c48ba06 2770 int span,
c014a02e 2771 long cluster_size,
8fef55a8 2772 int min_yield)
4c48ba06
MD
2773{
2774 freelist->clusters = SCM_EOL;
2775 freelist->cluster_size = cluster_size + 1;
b37fe1c5
MD
2776 freelist->left_to_collect = 0;
2777 freelist->clusters_allocated = 0;
8fef55a8
MD
2778 freelist->min_yield = 0;
2779 freelist->min_yield_fraction = min_yield;
4c48ba06
MD
2780 freelist->span = span;
2781 freelist->collected = 0;
1811ebce 2782 freelist->collected_1 = 0;
4c48ba06
MD
2783 freelist->heap_size = 0;
2784}
2785
85db4a2c
DH
2786
2787/* Get an integer from an environment variable. */
2788static int
2789scm_i_getenv_int (const char *var, int def)
2790{
2791 char *end, *val = getenv (var);
2792 long res;
2793 if (!val)
2794 return def;
2795 res = strtol (val, &end, 10);
2796 if (end == val)
2797 return def;
2798 return res;
2799}
2800
2801
4a4c9785 2802int
85db4a2c 2803scm_init_storage ()
0f2d19dd 2804{
1be6b49c
ML
2805 unsigned long gc_trigger_1;
2806 unsigned long gc_trigger_2;
2807 size_t init_heap_size_1;
2808 size_t init_heap_size_2;
2809 size_t j;
0f2d19dd 2810
7c33806a
DH
2811#if (SCM_DEBUG_CELL_ACCESSES == 1)
2812 scm_tc16_allocated = scm_make_smob_type ("allocated cell", 0);
592996c9 2813 scm_set_smob_mark (scm_tc16_allocated, allocated_mark);
7c33806a
DH
2814#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
2815
0f2d19dd
JB
2816 j = SCM_NUM_PROTECTS;
2817 while (j)
2818 scm_sys_protects[--j] = SCM_BOOL_F;
2819 scm_block_gc = 1;
4a4c9785 2820
4a4c9785 2821 scm_freelist = SCM_EOL;
4c48ba06 2822 scm_freelist2 = SCM_EOL;
85db4a2c
DH
2823 gc_trigger_1 = scm_i_getenv_int ("GUILE_MIN_YIELD_1", scm_default_min_yield_1);
2824 init_freelist (&scm_master_freelist, 1, SCM_CLUSTER_SIZE_1, gc_trigger_1);
2825 gc_trigger_2 = scm_i_getenv_int ("GUILE_MIN_YIELD_2", scm_default_min_yield_2);
2826 init_freelist (&scm_master_freelist2, 2, SCM_CLUSTER_SIZE_2, gc_trigger_2);
2827 scm_max_segment_size = scm_i_getenv_int ("GUILE_MAX_SEGMENT_SIZE", scm_default_max_segment_size);
4a4c9785 2828
0f2d19dd
JB
2829 scm_expmem = 0;
2830
2831 j = SCM_HEAP_SEG_SIZE;
2832 scm_mtrigger = SCM_INIT_MALLOC_LIMIT;
92c2555f
MV
2833 scm_heap_table = ((scm_t_heap_seg_data *)
2834 scm_must_malloc (sizeof (scm_t_heap_seg_data) * 2, "hplims"));
b6efc951 2835 heap_segment_table_size = 2;
acb0a19c 2836
d6884e63
ML
2837 mark_space_ptr = &mark_space_head;
2838
85db4a2c
DH
2839 init_heap_size_1 = scm_i_getenv_int ("GUILE_INIT_SEGMENT_SIZE_1", scm_default_init_heap_size_1);
2840 init_heap_size_2 = scm_i_getenv_int ("GUILE_INIT_SEGMENT_SIZE_2", scm_default_init_heap_size_2);
4c48ba06
MD
2841 if (make_initial_segment (init_heap_size_1, &scm_master_freelist) ||
2842 make_initial_segment (init_heap_size_2, &scm_master_freelist2))
4a4c9785 2843 return 1;
acb0a19c 2844
801cb5e7 2845 /* scm_hplims[0] can change. do not remove scm_heap_org */
a00c95d9 2846 scm_heap_org = CELL_UP (scm_heap_table[0].bounds[0], 1);
acb0a19c 2847
801cb5e7
MD
2848 scm_c_hook_init (&scm_before_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
2849 scm_c_hook_init (&scm_before_mark_c_hook, 0, SCM_C_HOOK_NORMAL);
2850 scm_c_hook_init (&scm_before_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
2851 scm_c_hook_init (&scm_after_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
2852 scm_c_hook_init (&scm_after_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
0f2d19dd
JB
2853
2854 /* Initialise the list of ports. */
92c2555f
MV
2855 scm_t_portable = (scm_t_port **)
2856 malloc (sizeof (scm_t_port *) * scm_t_portable_room);
2857 if (!scm_t_portable)
0f2d19dd
JB
2858 return 1;
2859
a18bcd0e 2860#ifdef HAVE_ATEXIT
c45acc34 2861 atexit (cleanup);
e52ceaac
MD
2862#else
2863#ifdef HAVE_ON_EXIT
2864 on_exit (cleanup, 0);
2865#endif
a18bcd0e 2866#endif
0f2d19dd 2867
8960e0a0 2868 scm_stand_in_procs = SCM_EOL;
0f2d19dd 2869 scm_permobjs = SCM_EOL;
00ffa0e7 2870 scm_protects = scm_c_make_hash_table (31);
6b1b030e 2871 scm_gc_registered_roots = scm_c_make_hash_table (31);
d6884e63 2872
0f2d19dd
JB
2873 return 0;
2874}
939794ce 2875
0f2d19dd
JB
2876\f
2877
939794ce
DH
2878SCM scm_after_gc_hook;
2879
939794ce
DH
2880static SCM gc_async;
2881
939794ce
DH
2882/* The function gc_async_thunk causes the execution of the after-gc-hook. It
2883 * is run after the gc, as soon as the asynchronous events are handled by the
2884 * evaluator.
2885 */
2886static SCM
2887gc_async_thunk (void)
2888{
2889 scm_c_run_hook (scm_after_gc_hook, SCM_EOL);
939794ce
DH
2890 return SCM_UNSPECIFIED;
2891}
2892
2893
2894/* The function mark_gc_async is run by the scm_after_gc_c_hook at the end of
2895 * the garbage collection. The only purpose of this function is to mark the
2896 * gc_async (which will eventually lead to the execution of the
2897 * gc_async_thunk).
2898 */
2899static void *
e81d98ec
DH
2900mark_gc_async (void * hook_data SCM_UNUSED,
2901 void *func_data SCM_UNUSED,
2902 void *data SCM_UNUSED)
2903{
2904 /* If cell access debugging is enabled, the user may choose to perform
2905 * additional garbage collections after an arbitrary number of cell
2906 * accesses. We don't want the scheme level after-gc-hook to be performed
2907 * for each of these garbage collections for the following reason: The
2908 * execution of the after-gc-hook causes cell accesses itself. Thus, if the
2909 * after-gc-hook was performed with every gc, and if the gc was performed
2910 * after a very small number of cell accesses, then the number of cell
2911 * accesses during the execution of the after-gc-hook will suffice to cause
2912 * the execution of the next gc. Then, guile would keep executing the
2913 * after-gc-hook over and over again, and would never come to do other
2914 * things.
2915 *
2916 * To overcome this problem, if cell access debugging with additional
2917 * garbage collections is enabled, the after-gc-hook is never run by the
2918 * garbage collecter. When running guile with cell access debugging and the
2919 * execution of the after-gc-hook is desired, then it is necessary to run
2920 * the hook explicitly from the user code. This has the effect, that from
2921 * the scheme level point of view it seems that garbage collection is
2922 * performed with a much lower frequency than it actually is. Obviously,
2923 * this will not work for code that depends on a fixed one to one
2924 * relationship between the execution counts of the C level garbage
2925 * collection hooks and the execution count of the scheme level
2926 * after-gc-hook.
2927 */
2928#if (SCM_DEBUG_CELL_ACCESSES == 1)
2929 if (debug_cells_gc_interval == 0)
2930 scm_system_async_mark (gc_async);
2931#else
939794ce 2932 scm_system_async_mark (gc_async);
e81d98ec
DH
2933#endif
2934
939794ce
DH
2935 return NULL;
2936}
2937
2938
0f2d19dd
JB
2939void
2940scm_init_gc ()
0f2d19dd 2941{
939794ce
DH
2942 SCM after_gc_thunk;
2943
fde50407
ML
2944 scm_after_gc_hook = scm_permanent_object (scm_make_hook (SCM_INUM0));
2945 scm_c_define ("after-gc-hook", scm_after_gc_hook);
939794ce 2946
9a441ddb
MV
2947 after_gc_thunk = scm_c_make_subr ("%gc-thunk", scm_tc7_subr_0,
2948 gc_async_thunk);
23670993 2949 gc_async = scm_system_async (after_gc_thunk); /* protected via scm_asyncs */
939794ce
DH
2950
2951 scm_c_hook_add (&scm_after_gc_c_hook, mark_gc_async, NULL, 0);
2952
8dc9439f 2953#ifndef SCM_MAGIC_SNARFER
a0599745 2954#include "libguile/gc.x"
8dc9439f 2955#endif
0f2d19dd 2956}
89e00824 2957
56495472
ML
2958#endif /*MARK_DEPENDENCIES*/
2959
89e00824
ML
2960/*
2961 Local Variables:
2962 c-file-style: "gnu"
2963 End:
2964*/