*.[ch]: Replace GUILE_PROC w/ SCM_DEFINE.
[bpt/guile.git] / libguile / gc.c
CommitLineData
ab4bef85 1/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
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
0f2d19dd
JB
45\f
46#include <stdio.h>
47#include "_scm.h"
20e6290e
JB
48#include "stime.h"
49#include "stackchk.h"
50#include "struct.h"
51#include "genio.h"
52#include "weaks.h"
0493cd89 53#include "guardians.h"
20e6290e
JB
54#include "smob.h"
55#include "unif.h"
56#include "async.h"
0f2d19dd 57
1bbd0b84 58#include "scm_validate.h"
fce59c93
JB
59#include "gc.h"
60
0f2d19dd 61#ifdef HAVE_MALLOC_H
95b88819 62#include <malloc.h>
0f2d19dd
JB
63#endif
64
65#ifdef HAVE_UNISTD_H
95b88819 66#include <unistd.h>
0f2d19dd
JB
67#endif
68
1cc91f1b
JB
69#ifdef __STDC__
70#include <stdarg.h>
71#define var_start(x, y) va_start(x, y)
72#else
73#include <varargs.h>
74#define var_start(x, y) va_start(x)
75#endif
76
0f2d19dd
JB
77\f
78/* {heap tuning parameters}
79 *
80 * These are parameters for controlling memory allocation. The heap
81 * is the area out of which scm_cons, and object headers are allocated.
82 *
83 * Each heap cell is 8 bytes on a 32 bit machine and 16 bytes on a
84 * 64 bit machine. The units of the _SIZE parameters are bytes.
85 * Cons pairs and object headers occupy one heap cell.
86 *
87 * SCM_INIT_HEAP_SIZE is the initial size of heap. If this much heap is
88 * allocated initially the heap will grow by half its current size
89 * each subsequent time more heap is needed.
90 *
91 * If SCM_INIT_HEAP_SIZE heap cannot be allocated initially, SCM_HEAP_SEG_SIZE
92 * will be used, and the heap will grow by SCM_HEAP_SEG_SIZE when more
93 * heap is needed. SCM_HEAP_SEG_SIZE must fit into type scm_sizet. This code
94 * is in scm_init_storage() and alloc_some_heap() in sys.c
95 *
96 * If SCM_INIT_HEAP_SIZE can be allocated initially, the heap will grow by
97 * SCM_EXPHEAP(scm_heap_size) when more heap is needed.
98 *
99 * SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
100 * is needed.
101 *
102 * INIT_MALLOC_LIMIT is the initial amount of malloc usage which will
103 * trigger a GC.
6064dcc6
MV
104 *
105 * SCM_MTRIGGER_HYSTERESIS is the amount of malloc storage that must be
106 * reclaimed by a GC triggered by must_malloc. If less than this is
107 * reclaimed, the trigger threshold is raised. [I don't know what a
108 * good value is. I arbitrarily chose 1/10 of the INIT_MALLOC_LIMIT to
109 * work around a oscillation that caused almost constant GC.]
0f2d19dd
JB
110 */
111
112#define SCM_INIT_HEAP_SIZE (32768L*sizeof(scm_cell))
113#define SCM_MIN_HEAP_SEG_SIZE (2048L*sizeof(scm_cell))
114#ifdef _QC
115# define SCM_HEAP_SEG_SIZE 32768L
116#else
117# ifdef sequent
118# define SCM_HEAP_SEG_SIZE (7000L*sizeof(scm_cell))
119# else
120# define SCM_HEAP_SEG_SIZE (16384L*sizeof(scm_cell))
121# endif
122#endif
123#define SCM_EXPHEAP(scm_heap_size) (scm_heap_size*2)
124#define SCM_INIT_MALLOC_LIMIT 100000
6064dcc6 125#define SCM_MTRIGGER_HYSTERESIS (SCM_INIT_MALLOC_LIMIT/10)
0f2d19dd
JB
126
127/* CELL_UP and CELL_DN are used by scm_init_heap_seg to find scm_cell aligned inner
128 bounds for allocated storage */
129
130#ifdef PROT386
131/*in 386 protected mode we must only adjust the offset */
132# define CELL_UP(p) MK_FP(FP_SEG(p), ~7&(FP_OFF(p)+7))
133# define CELL_DN(p) MK_FP(FP_SEG(p), ~7&FP_OFF(p))
134#else
135# ifdef _UNICOS
136# define CELL_UP(p) (SCM_CELLPTR)(~1L & ((long)(p)+1L))
137# define CELL_DN(p) (SCM_CELLPTR)(~1L & (long)(p))
138# else
139# define CELL_UP(p) (SCM_CELLPTR)(~(sizeof(scm_cell)-1L) & ((long)(p)+sizeof(scm_cell)-1L))
140# define CELL_DN(p) (SCM_CELLPTR)(~(sizeof(scm_cell)-1L) & (long)(p))
141# endif /* UNICOS */
142#endif /* PROT386 */
143
144
145\f
146/* scm_freelist
147 * is the head of freelist of cons pairs.
148 */
149SCM scm_freelist = SCM_EOL;
150
151/* scm_mtrigger
152 * is the number of bytes of must_malloc allocation needed to trigger gc.
153 */
15e9d186 154unsigned long scm_mtrigger;
0f2d19dd
JB
155
156
157/* scm_gc_heap_lock
158 * If set, don't expand the heap. Set only during gc, during which no allocation
159 * is supposed to take place anyway.
160 */
161int scm_gc_heap_lock = 0;
162
163/* GC Blocking
164 * Don't pause for collection if this is set -- just
165 * expand the heap.
166 */
167
168int scm_block_gc = 1;
169
170/* If fewer than MIN_GC_YIELD cells are recovered during a garbage
171 * collection (GC) more space is allocated for the heap.
172 */
173#define MIN_GC_YIELD (scm_heap_size/4)
174
175/* During collection, this accumulates objects holding
176 * weak references.
177 */
ab4bef85 178SCM scm_weak_vectors;
0f2d19dd
JB
179
180/* GC Statistics Keeping
181 */
182unsigned long scm_cells_allocated = 0;
a5c314c8 183long scm_mallocated = 0;
0f2d19dd
JB
184unsigned long scm_gc_cells_collected;
185unsigned long scm_gc_malloc_collected;
186unsigned long scm_gc_ports_collected;
187unsigned long scm_gc_rt;
188unsigned long scm_gc_time_taken = 0;
189
190SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
191SCM_SYMBOL (sym_heap_size, "cell-heap-size");
192SCM_SYMBOL (sym_mallocated, "bytes-malloced");
193SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
194SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
195SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
196
197
198struct scm_heap_seg_data
199{
cf2d30f6
JB
200 /* lower and upper bounds of the segment */
201 SCM_CELLPTR bounds[2];
202
203 /* address of the head-of-freelist pointer for this segment's cells.
204 All segments usually point to the same one, scm_freelist. */
205 SCM *freelistp;
206
207 /* number of SCM words per object in this segment */
208 int ncells;
209
210 /* If SEG_DATA->valid is non-zero, the conservative marking
211 functions will apply SEG_DATA->valid to the purported pointer and
212 SEG_DATA, and mark the object iff the function returns non-zero.
213 At the moment, I don't think anyone uses this. */
0f2d19dd
JB
214 int (*valid) ();
215};
216
217
218
219
1bbd0b84
GB
220static void scm_mark_weak_vector_spines(void);
221static scm_sizet init_heap_seg(SCM_CELLPTR, scm_sizet, int, SCM *);
222static void alloc_some_heap(int, SCM *);
0f2d19dd
JB
223
224
225\f
cf2d30f6
JB
226/* Debugging functions. */
227
fca7547b 228#ifdef GUILE_DEBUG_FREELIST
cf2d30f6
JB
229
230/* Return the number of the heap segment containing CELL. */
231static int
232which_seg (SCM cell)
233{
234 int i;
235
236 for (i = 0; i < scm_n_heap_segs; i++)
237 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], (SCM_CELLPTR) cell)
238 && SCM_PTR_GT (scm_heap_table[i].bounds[1], (SCM_CELLPTR) cell))
239 return i;
240 fprintf (stderr, "which_seg: can't find segment containing cell %lx\n",
241 cell);
242 abort ();
243}
244
245
a1ec6916 246SCM_DEFINE (scm_map_free_list, "map-free-list", 0, 0, 0,
1bbd0b84
GB
247 (),
248"")
249#define FUNC_NAME s_scm_map_free_list
cf2d30f6
JB
250{
251 int last_seg = -1, count = 0;
252 SCM f;
253
254 fprintf (stderr, "%d segments total\n", scm_n_heap_segs);
255 for (f = scm_freelist; SCM_NIMP (f); f = SCM_CDR (f))
256 {
257 int this_seg = which_seg (f);
258
259 if (this_seg != last_seg)
260 {
261 if (last_seg != -1)
262 fprintf (stderr, " %5d cells in segment %d\n", count, last_seg);
263 last_seg = this_seg;
264 count = 0;
265 }
266 count++;
267 }
268 if (last_seg != -1)
269 fprintf (stderr, " %5d cells in segment %d\n", count, last_seg);
270
271 fflush (stderr);
272
273 return SCM_UNSPECIFIED;
274}
1bbd0b84 275#undef FUNC_NAME
cf2d30f6
JB
276
277
278/* Number of calls to SCM_NEWCELL since startup. */
279static unsigned long scm_newcell_count;
280
281/* Search freelist for anything that isn't marked as a free cell.
282 Abort if we find something. */
283static void
284scm_check_freelist ()
285{
286 SCM f;
287 int i = 0;
288
289 for (f = scm_freelist; SCM_NIMP (f); f = SCM_CDR (f), i++)
290 if (SCM_CAR (f) != (SCM) scm_tc_free_cell)
291 {
292 fprintf (stderr, "Bad cell in freelist on newcell %lu: %d'th elt\n",
293 scm_newcell_count, i);
294 fflush (stderr);
295 abort ();
296 }
297}
298
299static int scm_debug_check_freelist = 0;
25748c78 300
a1ec6916 301SCM_DEFINE (scm_gc_set_debug_check_freelist_x, "gc-set-debug-check-freelist!", 1, 0, 0,
1bbd0b84
GB
302 (SCM flag),
303"")
304#define FUNC_NAME s_scm_gc_set_debug_check_freelist_x
25748c78 305{
1bbd0b84 306 SCM_VALIDATE_BOOL_COPY(1,flag,scm_debug_check_freelist);
25748c78
GB
307 return SCM_UNSPECIFIED;
308}
1bbd0b84 309#undef FUNC_NAME
25748c78
GB
310
311
f2333166
JB
312SCM
313scm_debug_newcell (void)
cf2d30f6 314{
f2333166
JB
315 SCM new;
316
cf2d30f6 317 scm_newcell_count++;
25748c78 318 if (scm_debug_check_freelist) {
cf2d30f6 319 scm_check_freelist ();
25748c78
GB
320 scm_gc();
321 }
cf2d30f6
JB
322
323 /* The rest of this is supposed to be identical to the SCM_NEWCELL
324 macro. */
325 if (SCM_IMP (scm_freelist))
f2333166 326 new = scm_gc_for_newcell ();
cf2d30f6
JB
327 else
328 {
f2333166 329 new = scm_freelist;
cf2d30f6 330 scm_freelist = SCM_CDR (scm_freelist);
d9de3881 331 SCM_SETCAR (new, scm_tc16_allocated);
cf2d30f6
JB
332 ++scm_cells_allocated;
333 }
f2333166
JB
334
335 return new;
cf2d30f6
JB
336}
337
fca7547b 338#endif /* GUILE_DEBUG_FREELIST */
cf2d30f6
JB
339
340\f
0f2d19dd
JB
341
342/* {Scheme Interface to GC}
343 */
344
a1ec6916 345SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
1bbd0b84 346 (),
4079f87e 347"Returns an association list of statistics about Guile's current use of storage. ")
1bbd0b84 348#define FUNC_NAME s_scm_gc_stats
0f2d19dd
JB
349{
350 int i;
351 int n;
352 SCM heap_segs;
353 SCM local_scm_mtrigger;
354 SCM local_scm_mallocated;
355 SCM local_scm_heap_size;
356 SCM local_scm_cells_allocated;
357 SCM local_scm_gc_time_taken;
358 SCM answer;
359
360 SCM_DEFER_INTS;
361 scm_block_gc = 1;
362 retry:
363 heap_segs = SCM_EOL;
364 n = scm_n_heap_segs;
365 for (i = scm_n_heap_segs; i--; )
366 heap_segs = scm_cons (scm_cons (scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[1]),
367 scm_ulong2num ((unsigned long)scm_heap_table[i].bounds[0])),
368 heap_segs);
369 if (scm_n_heap_segs != n)
370 goto retry;
371 scm_block_gc = 0;
372
373 local_scm_mtrigger = scm_mtrigger;
374 local_scm_mallocated = scm_mallocated;
375 local_scm_heap_size = scm_heap_size;
376 local_scm_cells_allocated = scm_cells_allocated;
377 local_scm_gc_time_taken = scm_gc_time_taken;
378
379 answer = scm_listify (scm_cons (sym_gc_time_taken, scm_ulong2num (local_scm_gc_time_taken)),
380 scm_cons (sym_cells_allocated, scm_ulong2num (local_scm_cells_allocated)),
381 scm_cons (sym_heap_size, scm_ulong2num (local_scm_heap_size)),
382 scm_cons (sym_mallocated, scm_ulong2num (local_scm_mallocated)),
383 scm_cons (sym_mtrigger, scm_ulong2num (local_scm_mtrigger)),
384 scm_cons (sym_heap_segments, heap_segs),
385 SCM_UNDEFINED);
386 SCM_ALLOW_INTS;
387 return answer;
388}
1bbd0b84 389#undef FUNC_NAME
0f2d19dd
JB
390
391
0f2d19dd 392void
6e8d25a6 393scm_gc_start (const char *what)
0f2d19dd
JB
394{
395 scm_gc_rt = SCM_INUM (scm_get_internal_run_time ());
396 scm_gc_cells_collected = 0;
397 scm_gc_malloc_collected = 0;
398 scm_gc_ports_collected = 0;
399}
400
0f2d19dd
JB
401void
402scm_gc_end ()
0f2d19dd
JB
403{
404 scm_gc_rt = SCM_INUM (scm_get_internal_run_time ()) - scm_gc_rt;
405 scm_gc_time_taken = scm_gc_time_taken + scm_gc_rt;
9ea54cc6 406 scm_system_async_mark (scm_gc_async);
0f2d19dd
JB
407}
408
409
a1ec6916 410SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
1bbd0b84 411 (SCM obj),
4079f87e
GB
412"Return an integer that for the lifetime of @var{obj} is uniquely
413returned by this function for @var{obj}")
1bbd0b84 414#define FUNC_NAME s_scm_object_address
0f2d19dd
JB
415{
416 return scm_ulong2num ((unsigned long)obj);
417}
1bbd0b84 418#undef FUNC_NAME
0f2d19dd
JB
419
420
a1ec6916 421SCM_DEFINE(scm_gc, "gc", 0, 0, 0,
1bbd0b84 422 (),
4079f87e
GB
423"Scans all of SCM objects and reclaims for further use those that are
424no longer accessible.")
1bbd0b84 425#define FUNC_NAME s_scm_gc
0f2d19dd
JB
426{
427 SCM_DEFER_INTS;
428 scm_igc ("call");
429 SCM_ALLOW_INTS;
430 return SCM_UNSPECIFIED;
431}
1bbd0b84 432#undef FUNC_NAME
0f2d19dd
JB
433
434
435\f
436/* {C Interface For When GC is Triggered}
437 */
438
0f2d19dd 439void
1bbd0b84 440scm_gc_for_alloc (int ncells, SCM *freelistp)
0f2d19dd
JB
441{
442 SCM_REDEFER_INTS;
443 scm_igc ("cells");
444 if ((scm_gc_cells_collected < MIN_GC_YIELD) || SCM_IMP (*freelistp))
445 {
446 alloc_some_heap (ncells, freelistp);
447 }
448 SCM_REALLOW_INTS;
449}
450
451
0f2d19dd
JB
452SCM
453scm_gc_for_newcell ()
0f2d19dd
JB
454{
455 SCM fl;
456 scm_gc_for_alloc (1, &scm_freelist);
457 fl = scm_freelist;
458 scm_freelist = SCM_CDR (fl);
1bbd0b84 459 SCM_SETCAR(fl, scm_tc16_allocated);
0f2d19dd
JB
460 return fl;
461}
462
0f2d19dd 463void
1bbd0b84 464scm_igc (const char *what)
0f2d19dd
JB
465{
466 int j;
467
42db06f0
MD
468#ifdef USE_THREADS
469 /* During the critical section, only the current thread may run. */
470 SCM_THREAD_CRITICAL_SECTION_START;
471#endif
472
e242dfd2 473 /* fprintf (stderr, "gc: %s\n", what); */
c68296f8 474
ab4bef85
JB
475 scm_gc_start (what);
476
477 if (!scm_stack_base || scm_block_gc)
478 {
479 scm_gc_end ();
480 return;
481 }
482
a5c314c8
JB
483 if (scm_mallocated < 0)
484 /* The byte count of allocated objects has underflowed. This is
485 probably because you forgot to report the sizes of objects you
486 have allocated, by calling scm_done_malloc or some such. When
487 the GC freed them, it subtracted their size from
488 scm_mallocated, which underflowed. */
489 abort ();
c45acc34 490
ab4bef85
JB
491 if (scm_gc_heap_lock)
492 /* We've invoked the collector while a GC is already in progress.
493 That should never happen. */
494 abort ();
0f2d19dd
JB
495
496 ++scm_gc_heap_lock;
ab4bef85
JB
497
498 scm_weak_vectors = SCM_EOL;
0f2d19dd 499
0493cd89
MD
500 scm_guardian_gc_init ();
501
0f2d19dd
JB
502 /* unprotect any struct types with no instances */
503#if 0
504 {
505 SCM type_list;
506 SCM * pos;
507
508 pos = &scm_type_obj_list;
509 type_list = scm_type_obj_list;
510 while (type_list != SCM_EOL)
511 if (SCM_VELTS (SCM_CAR (type_list))[scm_struct_i_refcnt])
512 {
24e68a57 513 pos = SCM_CDRLOC (type_list);
0f2d19dd
JB
514 type_list = SCM_CDR (type_list);
515 }
516 else
517 {
518 *pos = SCM_CDR (type_list);
519 type_list = SCM_CDR (type_list);
520 }
521 }
522#endif
523
524 /* flush dead entries from the continuation stack */
525 {
526 int x;
527 int bound;
528 SCM * elts;
529 elts = SCM_VELTS (scm_continuation_stack);
530 bound = SCM_LENGTH (scm_continuation_stack);
531 x = SCM_INUM (scm_continuation_stack_ptr);
532 while (x < bound)
533 {
534 elts[x] = SCM_BOOL_F;
535 ++x;
536 }
537 }
538
42db06f0
MD
539#ifndef USE_THREADS
540
0f2d19dd
JB
541 /* Protect from the C stack. This must be the first marking
542 * done because it provides information about what objects
543 * are "in-use" by the C code. "in-use" objects are those
544 * for which the values from SCM_LENGTH and SCM_CHARS must remain
545 * usable. This requirement is stricter than a liveness
546 * requirement -- in particular, it constrains the implementation
547 * of scm_vector_set_length_x.
548 */
549 SCM_FLUSH_REGISTER_WINDOWS;
550 /* This assumes that all registers are saved into the jmp_buf */
551 setjmp (scm_save_regs_gc_mark);
552 scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
ce4a361d
JB
553 ( (scm_sizet) (sizeof (SCM_STACKITEM) - 1 +
554 sizeof scm_save_regs_gc_mark)
555 / sizeof (SCM_STACKITEM)));
0f2d19dd
JB
556
557 {
558 /* stack_len is long rather than scm_sizet in order to guarantee that
559 &stack_len is long aligned */
560#ifdef SCM_STACK_GROWS_UP
561#ifdef nosve
562 long stack_len = (SCM_STACKITEM *) (&stack_len) - scm_stack_base;
563#else
564 long stack_len = scm_stack_size (scm_stack_base);
565#endif
566 scm_mark_locations (scm_stack_base, (scm_sizet) stack_len);
567#else
568#ifdef nosve
569 long stack_len = scm_stack_base - (SCM_STACKITEM *) (&stack_len);
570#else
571 long stack_len = scm_stack_size (scm_stack_base);
572#endif
573 scm_mark_locations ((scm_stack_base - stack_len), (scm_sizet) stack_len);
574#endif
575 }
576
42db06f0
MD
577#else /* USE_THREADS */
578
579 /* Mark every thread's stack and registers */
580 scm_threads_mark_stacks();
581
582#endif /* USE_THREADS */
0f2d19dd
JB
583
584 /* FIXME: insert a phase to un-protect string-data preserved
585 * in scm_vector_set_length_x.
586 */
587
588 j = SCM_NUM_PROTECTS;
589 while (j--)
590 scm_gc_mark (scm_sys_protects[j]);
591
9de33deb
MD
592 /* FIXME: we should have a means to register C functions to be run
593 * in different phases of GC
594 */
595 scm_mark_subr_table ();
596
42db06f0
MD
597#ifndef USE_THREADS
598 scm_gc_mark (scm_root->handle);
599#endif
0f2d19dd
JB
600
601 scm_mark_weak_vector_spines ();
602
0493cd89
MD
603 scm_guardian_zombify ();
604
0f2d19dd
JB
605 scm_gc_sweep ();
606
607 --scm_gc_heap_lock;
608 scm_gc_end ();
42db06f0
MD
609
610#ifdef USE_THREADS
611 SCM_THREAD_CRITICAL_SECTION_END;
612#endif
0f2d19dd
JB
613}
614
615\f
616/* {Mark/Sweep}
617 */
618
619
620
621/* Mark an object precisely.
622 */
0f2d19dd 623void
1bbd0b84 624scm_gc_mark (SCM p)
0f2d19dd
JB
625{
626 register long i;
627 register SCM ptr;
628
629 ptr = p;
630
631gc_mark_loop:
632 if (SCM_IMP (ptr))
633 return;
634
635gc_mark_nimp:
636 if (SCM_NCELLP (ptr))
f8392303 637 scm_wta (ptr, "rogue pointer in heap", NULL);
0f2d19dd
JB
638
639 switch (SCM_TYP7 (ptr))
640 {
641 case scm_tcs_cons_nimcar:
642 if (SCM_GCMARKP (ptr))
643 break;
644 SCM_SETGCMARK (ptr);
645 if (SCM_IMP (SCM_CDR (ptr))) /* SCM_IMP works even with a GC mark */
646 {
647 ptr = SCM_CAR (ptr);
648 goto gc_mark_nimp;
649 }
650 scm_gc_mark (SCM_CAR (ptr));
651 ptr = SCM_GCCDR (ptr);
652 goto gc_mark_nimp;
653 case scm_tcs_cons_imcar:
e641afaf 654 case scm_tc7_pws:
0f2d19dd
JB
655 if (SCM_GCMARKP (ptr))
656 break;
657 SCM_SETGCMARK (ptr);
658 ptr = SCM_GCCDR (ptr);
659 goto gc_mark_loop;
660 case scm_tcs_cons_gloc:
661 if (SCM_GCMARKP (ptr))
662 break;
663 SCM_SETGCMARK (ptr);
664 {
665 SCM vcell;
666 vcell = SCM_CAR (ptr) - 1L;
667 switch (SCM_CDR (vcell))
668 {
669 default:
670 scm_gc_mark (vcell);
671 ptr = SCM_GCCDR (ptr);
672 goto gc_mark_loop;
673 case 1: /* ! */
674 case 0: /* ! */
675 {
676 SCM layout;
677 SCM * vtable_data;
678 int len;
679 char * fields_desc;
ad75306c
MD
680 register SCM * mem;
681 register int x;
0f2d19dd
JB
682
683 vtable_data = (SCM *)vcell;
4bfdf158 684 layout = vtable_data[scm_vtable_index_layout];
0f2d19dd
JB
685 len = SCM_LENGTH (layout);
686 fields_desc = SCM_CHARS (layout);
14d1400f
JB
687 /* We're using SCM_GCCDR here like STRUCT_DATA, except
688 that it removes the mark */
689 mem = (SCM *)SCM_GCCDR (ptr);
0f2d19dd 690
aa0761ec
MD
691 if (vtable_data[scm_struct_i_flags] & SCM_STRUCTF_ENTITY)
692 {
73e10adf 693 scm_gc_mark (mem[scm_struct_i_procedure]);
e641afaf 694 scm_gc_mark (mem[scm_struct_i_setter]);
aa0761ec 695 }
ad75306c
MD
696 if (len)
697 {
698 for (x = 0; x < len - 2; x += 2, ++mem)
699 if (fields_desc[x] == 'p')
700 scm_gc_mark (*mem);
701 if (fields_desc[x] == 'p')
702 {
703 if (SCM_LAYOUT_TAILP (fields_desc[x + 1]))
704 for (x = *mem; x; --x)
705 scm_gc_mark (*++mem);
706 else
707 scm_gc_mark (*mem);
708 }
709 }
0f2d19dd
JB
710 if (!SCM_CDR (vcell))
711 {
712 SCM_SETGCMARK (vcell);
4bfdf158 713 ptr = vtable_data[scm_vtable_index_vtable];
0f2d19dd
JB
714 goto gc_mark_loop;
715 }
716 }
717 }
718 }
719 break;
720 case scm_tcs_closures:
721 if (SCM_GCMARKP (ptr))
722 break;
723 SCM_SETGCMARK (ptr);
724 if (SCM_IMP (SCM_CDR (ptr)))
725 {
726 ptr = SCM_CLOSCAR (ptr);
727 goto gc_mark_nimp;
728 }
729 scm_gc_mark (SCM_CLOSCAR (ptr));
730 ptr = SCM_GCCDR (ptr);
731 goto gc_mark_nimp;
732 case scm_tc7_vector:
733 case scm_tc7_lvector:
734#ifdef CCLO
735 case scm_tc7_cclo:
736#endif
737 if (SCM_GC8MARKP (ptr))
738 break;
739 SCM_SETGC8MARK (ptr);
740 i = SCM_LENGTH (ptr);
741 if (i == 0)
742 break;
743 while (--i > 0)
744 if (SCM_NIMP (SCM_VELTS (ptr)[i]))
745 scm_gc_mark (SCM_VELTS (ptr)[i]);
746 ptr = SCM_VELTS (ptr)[0];
747 goto gc_mark_loop;
748 case scm_tc7_contin:
749 if SCM_GC8MARKP
750 (ptr) break;
751 SCM_SETGC8MARK (ptr);
c68296f8
MV
752 if (SCM_VELTS (ptr))
753 scm_mark_locations (SCM_VELTS (ptr),
754 (scm_sizet)
755 (SCM_LENGTH (ptr) +
756 (sizeof (SCM_STACKITEM) + -1 +
757 sizeof (scm_contregs)) /
758 sizeof (SCM_STACKITEM)));
0f2d19dd 759 break;
afe5177e 760#ifdef HAVE_ARRAYS
0f2d19dd
JB
761 case scm_tc7_bvect:
762 case scm_tc7_byvect:
763 case scm_tc7_ivect:
764 case scm_tc7_uvect:
765 case scm_tc7_fvect:
766 case scm_tc7_dvect:
767 case scm_tc7_cvect:
768 case scm_tc7_svect:
5c11cc9d 769#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
770 case scm_tc7_llvect:
771#endif
afe5177e 772#endif
0f2d19dd 773 case scm_tc7_string:
0f2d19dd
JB
774 SCM_SETGC8MARK (ptr);
775 break;
776
777 case scm_tc7_substring:
0f2d19dd
JB
778 if (SCM_GC8MARKP(ptr))
779 break;
780 SCM_SETGC8MARK (ptr);
781 ptr = SCM_CDR (ptr);
782 goto gc_mark_loop;
783
784 case scm_tc7_wvect:
785 if (SCM_GC8MARKP(ptr))
786 break;
ab4bef85
JB
787 SCM_WVECT_GC_CHAIN (ptr) = scm_weak_vectors;
788 scm_weak_vectors = ptr;
0f2d19dd
JB
789 SCM_SETGC8MARK (ptr);
790 if (SCM_IS_WHVEC_ANY (ptr))
791 {
792 int x;
793 int len;
794 int weak_keys;
795 int weak_values;
796
797 len = SCM_LENGTH (ptr);
798 weak_keys = SCM_IS_WHVEC (ptr) || SCM_IS_WHVEC_B (ptr);
799 weak_values = SCM_IS_WHVEC_V (ptr) || SCM_IS_WHVEC_B (ptr);
800
801 for (x = 0; x < len; ++x)
802 {
803 SCM alist;
804 alist = SCM_VELTS (ptr)[x];
46408039
JB
805
806 /* mark everything on the alist except the keys or
807 * values, according to weak_values and weak_keys. */
0b5f3f34 808 while ( SCM_CONSP (alist)
0f2d19dd 809 && !SCM_GCMARKP (alist)
0f2d19dd
JB
810 && SCM_CONSP (SCM_CAR (alist)))
811 {
812 SCM kvpair;
813 SCM next_alist;
814
815 kvpair = SCM_CAR (alist);
816 next_alist = SCM_CDR (alist);
817 /*
818 * Do not do this:
819 * SCM_SETGCMARK (alist);
820 * SCM_SETGCMARK (kvpair);
821 *
822 * It may be that either the key or value is protected by
823 * an escaped reference to part of the spine of this alist.
824 * If we mark the spine here, and only mark one or neither of the
825 * key and value, they may never be properly marked.
826 * This leads to a horrible situation in which an alist containing
827 * freelist cells is exported.
828 *
829 * So only mark the spines of these arrays last of all marking.
830 * If somebody confuses us by constructing a weak vector
831 * with a circular alist then we are hosed, but at least we
832 * won't prematurely drop table entries.
833 */
834 if (!weak_keys)
835 scm_gc_mark (SCM_CAR (kvpair));
836 if (!weak_values)
837 scm_gc_mark (SCM_GCCDR (kvpair));
838 alist = next_alist;
839 }
840 if (SCM_NIMP (alist))
841 scm_gc_mark (alist);
842 }
843 }
844 break;
845
846 case scm_tc7_msymbol:
847 if (SCM_GC8MARKP(ptr))
848 break;
849 SCM_SETGC8MARK (ptr);
850 scm_gc_mark (SCM_SYMBOL_FUNC (ptr));
851 ptr = SCM_SYMBOL_PROPS (ptr);
852 goto gc_mark_loop;
853 case scm_tc7_ssymbol:
854 if (SCM_GC8MARKP(ptr))
855 break;
856 SCM_SETGC8MARK (ptr);
857 break;
858 case scm_tcs_subrs:
9de33deb 859 break;
0f2d19dd
JB
860 case scm_tc7_port:
861 i = SCM_PTOBNUM (ptr);
862 if (!(i < scm_numptob))
863 goto def;
864 if (SCM_GC8MARKP (ptr))
865 break;
dc53f026 866 SCM_SETGC8MARK (ptr);
ebf7394e
GH
867 if (SCM_PTAB_ENTRY(ptr))
868 scm_gc_mark (SCM_PTAB_ENTRY(ptr)->file_name);
dc53f026
JB
869 if (scm_ptobs[i].mark)
870 {
871 ptr = (scm_ptobs[i].mark) (ptr);
872 goto gc_mark_loop;
873 }
874 else
875 return;
0f2d19dd
JB
876 break;
877 case scm_tc7_smob:
878 if (SCM_GC8MARKP (ptr))
879 break;
dc53f026
JB
880 SCM_SETGC8MARK (ptr);
881 switch SCM_GCTYP16 (ptr)
0f2d19dd
JB
882 { /* should be faster than going through scm_smobs */
883 case scm_tc_free_cell:
884 /* printf("found free_cell %X ", ptr); fflush(stdout); */
1bbd0b84
GB
885 break;
886 case scm_tc16_allocated:
887 SCM_SETGC8MARK (ptr);
0f2d19dd
JB
888 break;
889 case scm_tcs_bignums:
890 case scm_tc16_flo:
0f2d19dd
JB
891 break;
892 default:
893 i = SCM_SMOBNUM (ptr);
894 if (!(i < scm_numsmob))
895 goto def;
dc53f026
JB
896 if (scm_smobs[i].mark)
897 {
898 ptr = (scm_smobs[i].mark) (ptr);
899 goto gc_mark_loop;
900 }
901 else
902 return;
0f2d19dd
JB
903 }
904 break;
905 default:
906 def:scm_wta (ptr, "unknown type in ", "gc_mark");
907 }
908}
909
910
911/* Mark a Region Conservatively
912 */
913
0f2d19dd 914void
6e8d25a6 915scm_mark_locations (SCM_STACKITEM x[], scm_sizet n)
0f2d19dd
JB
916{
917 register long m = n;
918 register int i, j;
919 register SCM_CELLPTR ptr;
920
921 while (0 <= --m)
922 if SCM_CELLP (*(SCM **) & x[m])
923 {
924 ptr = (SCM_CELLPTR) SCM2PTR ((*(SCM **) & x[m]));
925 i = 0;
926 j = scm_n_heap_segs - 1;
927 if ( SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr)
928 && SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
929 {
930 while (i <= j)
931 {
932 int seg_id;
933 seg_id = -1;
934 if ( (i == j)
935 || SCM_PTR_GT (scm_heap_table[i].bounds[1], ptr))
936 seg_id = i;
937 else if (SCM_PTR_LE (scm_heap_table[j].bounds[0], ptr))
938 seg_id = j;
939 else
940 {
941 int k;
942 k = (i + j) / 2;
943 if (k == i)
944 break;
945 if (SCM_PTR_GT (scm_heap_table[k].bounds[1], ptr))
946 {
947 j = k;
948 ++i;
949 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr))
950 continue;
951 else
952 break;
953 }
954 else if (SCM_PTR_LE (scm_heap_table[k].bounds[0], ptr))
955 {
956 i = k;
957 --j;
958 if (SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
959 continue;
960 else
961 break;
962 }
963 }
964 if ( !scm_heap_table[seg_id].valid
965 || scm_heap_table[seg_id].valid (ptr,
966 &scm_heap_table[seg_id]))
967 scm_gc_mark (*(SCM *) & x[m]);
968 break;
969 }
970
971 }
972 }
973}
974
975
2e11a577
MD
976/* The following is a C predicate which determines if an SCM value can be
977 regarded as a pointer to a cell on the heap. The code is duplicated
978 from scm_mark_locations. */
979
1cc91f1b 980
2e11a577 981int
6e8d25a6 982scm_cellp (SCM value)
2e11a577
MD
983{
984 register int i, j;
985 register SCM_CELLPTR ptr;
986
987 if SCM_CELLP (*(SCM **) & value)
988 {
989 ptr = (SCM_CELLPTR) SCM2PTR ((*(SCM **) & value));
990 i = 0;
991 j = scm_n_heap_segs - 1;
992 if ( SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr)
993 && SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
994 {
995 while (i <= j)
996 {
997 int seg_id;
998 seg_id = -1;
999 if ( (i == j)
1000 || SCM_PTR_GT (scm_heap_table[i].bounds[1], ptr))
1001 seg_id = i;
1002 else if (SCM_PTR_LE (scm_heap_table[j].bounds[0], ptr))
1003 seg_id = j;
1004 else
1005 {
1006 int k;
1007 k = (i + j) / 2;
1008 if (k == i)
1009 break;
1010 if (SCM_PTR_GT (scm_heap_table[k].bounds[1], ptr))
1011 {
1012 j = k;
1013 ++i;
1014 if (SCM_PTR_LE (scm_heap_table[i].bounds[0], ptr))
1015 continue;
1016 else
1017 break;
1018 }
1019 else if (SCM_PTR_LE (scm_heap_table[k].bounds[0], ptr))
1020 {
1021 i = k;
1022 --j;
1023 if (SCM_PTR_GT (scm_heap_table[j].bounds[1], ptr))
1024 continue;
1025 else
1026 break;
1027 }
1028 }
1029 if ( !scm_heap_table[seg_id].valid
1030 || scm_heap_table[seg_id].valid (ptr,
1031 &scm_heap_table[seg_id]))
1032 return 1;
1033 break;
1034 }
1035
1036 }
1037 }
1038 return 0;
1039}
1040
1041
3b2b8760 1042static void
0f2d19dd 1043scm_mark_weak_vector_spines ()
0f2d19dd 1044{
ab4bef85 1045 SCM w;
0f2d19dd 1046
ab4bef85 1047 for (w = scm_weak_vectors; w != SCM_EOL; w = SCM_WVECT_GC_CHAIN (w))
0f2d19dd 1048 {
ab4bef85 1049 if (SCM_IS_WHVEC_ANY (w))
0f2d19dd
JB
1050 {
1051 SCM *ptr;
1052 SCM obj;
1053 int j;
1054 int n;
1055
ab4bef85
JB
1056 obj = w;
1057 ptr = SCM_VELTS (w);
1058 n = SCM_LENGTH (w);
0f2d19dd
JB
1059 for (j = 0; j < n; ++j)
1060 {
1061 SCM alist;
1062
1063 alist = ptr[j];
0b5f3f34 1064 while ( SCM_CONSP (alist)
0f2d19dd 1065 && !SCM_GCMARKP (alist)
0f2d19dd
JB
1066 && SCM_CONSP (SCM_CAR (alist)))
1067 {
1068 SCM_SETGCMARK (alist);
1069 SCM_SETGCMARK (SCM_CAR (alist));
1070 alist = SCM_GCCDR (alist);
1071 }
1072 }
1073 }
1074 }
1075}
1076
1077
1078
0f2d19dd
JB
1079void
1080scm_gc_sweep ()
0f2d19dd
JB
1081{
1082 register SCM_CELLPTR ptr;
1083#ifdef SCM_POINTERS_MUNGED
1084 register SCM scmptr;
1085#else
1086#undef scmptr
1087#define scmptr (SCM)ptr
1088#endif
1089 register SCM nfreelist;
1090 register SCM *hp_freelist;
0f2d19dd 1091 register long m;
0f2d19dd 1092 register int span;
15e9d186 1093 long i;
0f2d19dd
JB
1094 scm_sizet seg_size;
1095
0f2d19dd 1096 m = 0;
0f2d19dd 1097
cf2d30f6
JB
1098 /* Reset all free list pointers. We'll reconstruct them completely
1099 while scanning. */
1100 for (i = 0; i < scm_n_heap_segs; i++)
1101 *scm_heap_table[i].freelistp = SCM_EOL;
1102
1103 for (i = 0; i < scm_n_heap_segs; i++)
0f2d19dd 1104 {
15e9d186
JB
1105 register scm_sizet n = 0;
1106 register scm_sizet j;
1107
cf2d30f6
JB
1108 /* Unmarked cells go onto the front of the freelist this heap
1109 segment points to. Rather than updating the real freelist
1110 pointer as we go along, we accumulate the new head in
1111 nfreelist. Then, if it turns out that the entire segment is
1112 free, we free (i.e., malloc's free) the whole segment, and
1113 simply don't assign nfreelist back into the real freelist. */
0f2d19dd 1114 hp_freelist = scm_heap_table[i].freelistp;
cf2d30f6
JB
1115 nfreelist = *hp_freelist;
1116
0f2d19dd
JB
1117 span = scm_heap_table[i].ncells;
1118 ptr = CELL_UP (scm_heap_table[i].bounds[0]);
1119 seg_size = CELL_DN (scm_heap_table[i].bounds[1]) - ptr;
0f2d19dd
JB
1120 for (j = seg_size + span; j -= span; ptr += span)
1121 {
1122#ifdef SCM_POINTERS_MUNGED
1123 scmptr = PTR2SCM (ptr);
1124#endif
1125 switch SCM_TYP7 (scmptr)
1126 {
1127 case scm_tcs_cons_gloc:
1128 if (SCM_GCMARKP (scmptr))
1129 {
1130 if (SCM_CDR (SCM_CAR (scmptr) - 1) == (SCM)1)
24e68a57 1131 SCM_SETCDR (SCM_CAR (scmptr) - 1, (SCM) 0);
0f2d19dd
JB
1132 goto cmrkcontinue;
1133 }
1134 {
1135 SCM vcell;
1136 vcell = SCM_CAR (scmptr) - 1L;
1137
1138 if ((SCM_CDR (vcell) == 0) || (SCM_CDR (vcell) == 1))
1139 {
f0cb1733
MD
1140 scm_struct_free_t free
1141 = (scm_struct_free_t) ((SCM*) vcell)[scm_struct_i_free];
1142 m += free ((SCM *) vcell, (SCM *) SCM_GCCDR (scmptr));
0f2d19dd
JB
1143 }
1144 }
1145 break;
1146 case scm_tcs_cons_imcar:
1147 case scm_tcs_cons_nimcar:
1148 case scm_tcs_closures:
e641afaf 1149 case scm_tc7_pws:
0f2d19dd
JB
1150 if (SCM_GCMARKP (scmptr))
1151 goto cmrkcontinue;
1152 break;
1153 case scm_tc7_wvect:
1154 if (SCM_GC8MARKP (scmptr))
1155 {
1156 goto c8mrkcontinue;
1157 }
1158 else
1159 {
ab4bef85
JB
1160 m += (2 + SCM_LENGTH (scmptr)) * sizeof (SCM);
1161 scm_must_free ((char *)(SCM_VELTS (scmptr) - 2));
0f2d19dd
JB
1162 break;
1163 }
1164
1165 case scm_tc7_vector:
1166 case scm_tc7_lvector:
1167#ifdef CCLO
1168 case scm_tc7_cclo:
1169#endif
1170 if (SCM_GC8MARKP (scmptr))
1171 goto c8mrkcontinue;
1172
1173 m += (SCM_LENGTH (scmptr) * sizeof (SCM));
1174 freechars:
1175 scm_must_free (SCM_CHARS (scmptr));
1176 /* SCM_SETCHARS(scmptr, 0);*/
1177 break;
afe5177e 1178#ifdef HAVE_ARRAYS
0f2d19dd
JB
1179 case scm_tc7_bvect:
1180 if SCM_GC8MARKP (scmptr)
1181 goto c8mrkcontinue;
1182 m += sizeof (long) * ((SCM_HUGE_LENGTH (scmptr) + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
1183 goto freechars;
1184 case scm_tc7_byvect:
1185 if SCM_GC8MARKP (scmptr)
1186 goto c8mrkcontinue;
1187 m += SCM_HUGE_LENGTH (scmptr) * sizeof (char);
1188 goto freechars;
1189 case scm_tc7_ivect:
1190 case scm_tc7_uvect:
1191 if SCM_GC8MARKP (scmptr)
1192 goto c8mrkcontinue;
1193 m += SCM_HUGE_LENGTH (scmptr) * sizeof (long);
1194 goto freechars;
1195 case scm_tc7_svect:
1196 if SCM_GC8MARKP (scmptr)
1197 goto c8mrkcontinue;
1198 m += SCM_HUGE_LENGTH (scmptr) * sizeof (short);
1199 goto freechars;
5c11cc9d 1200#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1201 case scm_tc7_llvect:
1202 if SCM_GC8MARKP (scmptr)
1203 goto c8mrkcontinue;
1204 m += SCM_HUGE_LENGTH (scmptr) * sizeof (long_long);
1205 goto freechars;
1206#endif
1207 case scm_tc7_fvect:
1208 if SCM_GC8MARKP (scmptr)
1209 goto c8mrkcontinue;
1210 m += SCM_HUGE_LENGTH (scmptr) * sizeof (float);
1211 goto freechars;
1212 case scm_tc7_dvect:
1213 if SCM_GC8MARKP (scmptr)
1214 goto c8mrkcontinue;
1215 m += SCM_HUGE_LENGTH (scmptr) * sizeof (double);
1216 goto freechars;
1217 case scm_tc7_cvect:
1218 if SCM_GC8MARKP (scmptr)
1219 goto c8mrkcontinue;
1220 m += SCM_HUGE_LENGTH (scmptr) * 2 * sizeof (double);
1221 goto freechars;
afe5177e 1222#endif
0f2d19dd 1223 case scm_tc7_substring:
0f2d19dd
JB
1224 if (SCM_GC8MARKP (scmptr))
1225 goto c8mrkcontinue;
1226 break;
1227 case scm_tc7_string:
0f2d19dd
JB
1228 if (SCM_GC8MARKP (scmptr))
1229 goto c8mrkcontinue;
1230 m += SCM_HUGE_LENGTH (scmptr) + 1;
1231 goto freechars;
1232 case scm_tc7_msymbol:
1233 if (SCM_GC8MARKP (scmptr))
1234 goto c8mrkcontinue;
1235 m += ( SCM_LENGTH (scmptr)
1236 + 1
1237 + sizeof (SCM) * ((SCM *)SCM_CHARS (scmptr) - SCM_SLOTS(scmptr)));
1238 scm_must_free ((char *)SCM_SLOTS (scmptr));
1239 break;
1240 case scm_tc7_contin:
1241 if SCM_GC8MARKP (scmptr)
1242 goto c8mrkcontinue;
0db18cf4 1243 m += SCM_LENGTH (scmptr) * sizeof (SCM_STACKITEM) + sizeof (scm_contregs);
c68296f8
MV
1244 if (SCM_VELTS (scmptr))
1245 goto freechars;
0f2d19dd
JB
1246 case scm_tc7_ssymbol:
1247 if SCM_GC8MARKP(scmptr)
1248 goto c8mrkcontinue;
1249 break;
1250 case scm_tcs_subrs:
1251 continue;
1252 case scm_tc7_port:
1253 if SCM_GC8MARKP (scmptr)
1254 goto c8mrkcontinue;
1255 if SCM_OPENP (scmptr)
1256 {
1257 int k = SCM_PTOBNUM (scmptr);
1258 if (!(k < scm_numptob))
1259 goto sweeperr;
1260 /* Keep "revealed" ports alive. */
1261 if (scm_revealed_count(scmptr) > 0)
1262 continue;
1263 /* Yes, I really do mean scm_ptobs[k].free */
1264 /* rather than ftobs[k].close. .close */
1265 /* is for explicit CLOSE-PORT by user */
84af0382 1266 m += (scm_ptobs[k].free) (scmptr);
0f2d19dd
JB
1267 SCM_SETSTREAM (scmptr, 0);
1268 scm_remove_from_port_table (scmptr);
1269 scm_gc_ports_collected++;
24e68a57 1270 SCM_SETAND_CAR (scmptr, ~SCM_OPN);
0f2d19dd
JB
1271 }
1272 break;
1273 case scm_tc7_smob:
1274 switch SCM_GCTYP16 (scmptr)
1275 {
1276 case scm_tc_free_cell:
1277 if SCM_GC8MARKP (scmptr)
1278 goto c8mrkcontinue;
1279 break;
1280#ifdef SCM_BIGDIG
1281 case scm_tcs_bignums:
1282 if SCM_GC8MARKP (scmptr)
1283 goto c8mrkcontinue;
1284 m += (SCM_NUMDIGS (scmptr) * SCM_BITSPERDIG / SCM_CHAR_BIT);
1285 goto freechars;
1286#endif /* def SCM_BIGDIG */
1287 case scm_tc16_flo:
1288 if SCM_GC8MARKP (scmptr)
1289 goto c8mrkcontinue;
1290 switch ((int) (SCM_CAR (scmptr) >> 16))
1291 {
1292 case (SCM_IMAG_PART | SCM_REAL_PART) >> 16:
1293 m += sizeof (double);
1294 case SCM_REAL_PART >> 16:
1295 case SCM_IMAG_PART >> 16:
1296 m += sizeof (double);
1297 goto freechars;
1298 case 0:
1299 break;
1300 default:
1301 goto sweeperr;
1302 }
1303 break;
1304 default:
1305 if SCM_GC8MARKP (scmptr)
1306 goto c8mrkcontinue;
1307
1308 {
1309 int k;
1310 k = SCM_SMOBNUM (scmptr);
1311 if (!(k < scm_numsmob))
1312 goto sweeperr;
1313 m += (scm_smobs[k].free) ((SCM) scmptr);
1314 break;
1315 }
1316 }
1317 break;
1318 default:
1319 sweeperr:scm_wta (scmptr, "unknown type in ", "gc_sweep");
1320 }
1321 n += span;
1322#if 0
1323 if (SCM_CAR (scmptr) == (SCM) scm_tc_free_cell)
1324 exit (2);
1325#endif
e7c5fb37
JB
1326 /* Stick the new cell on the front of nfreelist. It's
1327 critical that we mark this cell as freed; otherwise, the
1328 conservative collector might trace it as some other type
1329 of object. */
24e68a57
MD
1330 SCM_SETCAR (scmptr, (SCM) scm_tc_free_cell);
1331 SCM_SETCDR (scmptr, nfreelist);
0f2d19dd 1332 nfreelist = scmptr;
cf2d30f6 1333
0f2d19dd
JB
1334 continue;
1335 c8mrkcontinue:
1336 SCM_CLRGC8MARK (scmptr);
1337 continue;
1338 cmrkcontinue:
1339 SCM_CLRGCMARK (scmptr);
1340 }
1341#ifdef GC_FREE_SEGMENTS
1342 if (n == seg_size)
1343 {
15e9d186
JB
1344 register long j;
1345
0f2d19dd 1346 scm_heap_size -= seg_size;
cf2d30f6
JB
1347 free ((char *) scm_heap_table[i].bounds[0]);
1348 scm_heap_table[i].bounds[0] = 0;
1349 for (j = i + 1; j < scm_n_heap_segs; j++)
0f2d19dd
JB
1350 scm_heap_table[j - 1] = scm_heap_table[j];
1351 scm_n_heap_segs -= 1;
cf2d30f6 1352 i--; /* We need to scan the segment just moved. */
0f2d19dd
JB
1353 }
1354 else
1355#endif /* ifdef GC_FREE_SEGMENTS */
cf2d30f6
JB
1356 /* Update the real freelist pointer to point to the head of
1357 the list of free cells we've built for this segment. */
0f2d19dd
JB
1358 *hp_freelist = nfreelist;
1359
fca7547b 1360#ifdef GUILE_DEBUG_FREELIST
cf2d30f6
JB
1361 scm_check_freelist ();
1362 scm_map_free_list ();
1363#endif
1364
0f2d19dd 1365 scm_gc_cells_collected += n;
0f2d19dd
JB
1366 }
1367 /* Scan weak vectors. */
1368 {
ab4bef85
JB
1369 SCM *ptr, w;
1370 for (w = scm_weak_vectors; w != SCM_EOL; w = SCM_WVECT_GC_CHAIN (w))
0f2d19dd 1371 {
ab4bef85 1372 if (!SCM_IS_WHVEC_ANY (w))
0f2d19dd 1373 {
15e9d186
JB
1374 register long j, n;
1375
ab4bef85
JB
1376 ptr = SCM_VELTS (w);
1377 n = SCM_LENGTH (w);
0f2d19dd 1378 for (j = 0; j < n; ++j)
0c95b57d 1379 if (SCM_FREEP (ptr[j]))
0f2d19dd
JB
1380 ptr[j] = SCM_BOOL_F;
1381 }
1382 else /* if (SCM_IS_WHVEC_ANY (scm_weak_vectors[i])) */
1383 {
ab4bef85
JB
1384 SCM obj = w;
1385 register long n = SCM_LENGTH (w);
15e9d186
JB
1386 register long j;
1387
ab4bef85 1388 ptr = SCM_VELTS (w);
15e9d186 1389
0f2d19dd
JB
1390 for (j = 0; j < n; ++j)
1391 {
1392 SCM * fixup;
1393 SCM alist;
1394 int weak_keys;
1395 int weak_values;
1396
1397 weak_keys = SCM_IS_WHVEC (obj) || SCM_IS_WHVEC_B (obj);
1398 weak_values = SCM_IS_WHVEC_V (obj) || SCM_IS_WHVEC_B (obj);
1399
1400 fixup = ptr + j;
1401 alist = *fixup;
1402
0b5f3f34 1403 while ( SCM_CONSP (alist)
0f2d19dd
JB
1404 && SCM_CONSP (SCM_CAR (alist)))
1405 {
1406 SCM key;
1407 SCM value;
1408
1409 key = SCM_CAAR (alist);
1410 value = SCM_CDAR (alist);
0c95b57d
GB
1411 if ( (weak_keys && SCM_FREEP (key))
1412 || (weak_values && SCM_FREEP (value)))
0f2d19dd
JB
1413 {
1414 *fixup = SCM_CDR (alist);
1415 }
1416 else
24e68a57 1417 fixup = SCM_CDRLOC (alist);
0f2d19dd
JB
1418 alist = SCM_CDR (alist);
1419 }
1420 }
1421 }
1422 }
1423 }
1424 scm_cells_allocated = (scm_heap_size - scm_gc_cells_collected);
1425 scm_mallocated -= m;
1426 scm_gc_malloc_collected = m;
1427}
1428
1429
1430\f
1431
1432/* {Front end to malloc}
1433 *
c68296f8 1434 * scm_must_malloc, scm_must_realloc, scm_must_free, scm_done_malloc
0f2d19dd
JB
1435 *
1436 * These functions provide services comperable to malloc, realloc, and
1437 * free. They are for allocating malloced parts of scheme objects.
1438 * The primary purpose of the front end is to impose calls to gc.
1439 */
1440
1441/* scm_must_malloc
1442 * Return newly malloced storage or throw an error.
1443 *
1444 * The parameter WHAT is a string for error reporting.
1445 * If the threshold scm_mtrigger will be passed by this
1446 * allocation, or if the first call to malloc fails,
1447 * garbage collect -- on the presumption that some objects
1448 * using malloced storage may be collected.
1449 *
1450 * The limit scm_mtrigger may be raised by this allocation.
1451 */
07806695 1452void *
e4ef2330 1453scm_must_malloc (scm_sizet size, const char *what)
0f2d19dd 1454{
07806695 1455 void *ptr;
15e9d186 1456 unsigned long nm = scm_mallocated + size;
e4ef2330
MD
1457
1458 if (nm <= scm_mtrigger)
0f2d19dd 1459 {
07806695 1460 SCM_SYSCALL (ptr = malloc (size));
0f2d19dd
JB
1461 if (NULL != ptr)
1462 {
1463 scm_mallocated = nm;
1464 return ptr;
1465 }
1466 }
6064dcc6 1467
0f2d19dd 1468 scm_igc (what);
e4ef2330 1469
0f2d19dd 1470 nm = scm_mallocated + size;
07806695 1471 SCM_SYSCALL (ptr = malloc (size));
0f2d19dd
JB
1472 if (NULL != ptr)
1473 {
1474 scm_mallocated = nm;
6064dcc6
MV
1475 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
1476 if (nm > scm_mtrigger)
1477 scm_mtrigger = nm + nm / 2;
1478 else
1479 scm_mtrigger += scm_mtrigger / 2;
1480 }
0f2d19dd
JB
1481 return ptr;
1482 }
e4ef2330
MD
1483
1484 scm_wta (SCM_MAKINUM (size), (char *) SCM_NALLOC, what);
1485 return 0; /* never reached */
0f2d19dd
JB
1486}
1487
1488
1489/* scm_must_realloc
1490 * is similar to scm_must_malloc.
1491 */
07806695
JB
1492void *
1493scm_must_realloc (void *where,
e4ef2330
MD
1494 scm_sizet old_size,
1495 scm_sizet size,
3eeba8d4 1496 const char *what)
0f2d19dd 1497{
07806695 1498 void *ptr;
e4ef2330
MD
1499 scm_sizet nm = scm_mallocated + size - old_size;
1500
1501 if (nm <= scm_mtrigger)
0f2d19dd 1502 {
07806695 1503 SCM_SYSCALL (ptr = realloc (where, size));
0f2d19dd
JB
1504 if (NULL != ptr)
1505 {
1506 scm_mallocated = nm;
1507 return ptr;
1508 }
1509 }
e4ef2330 1510
0f2d19dd 1511 scm_igc (what);
e4ef2330
MD
1512
1513 nm = scm_mallocated + size - old_size;
07806695 1514 SCM_SYSCALL (ptr = realloc (where, size));
0f2d19dd
JB
1515 if (NULL != ptr)
1516 {
1517 scm_mallocated = nm;
6064dcc6
MV
1518 if (nm > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS) {
1519 if (nm > scm_mtrigger)
1520 scm_mtrigger = nm + nm / 2;
1521 else
1522 scm_mtrigger += scm_mtrigger / 2;
1523 }
0f2d19dd
JB
1524 return ptr;
1525 }
e4ef2330
MD
1526
1527 scm_wta (SCM_MAKINUM (size), (char *) SCM_NALLOC, what);
1528 return 0; /* never reached */
0f2d19dd
JB
1529}
1530
0f2d19dd 1531void
07806695 1532scm_must_free (void *obj)
0f2d19dd
JB
1533{
1534 if (obj)
1535 free (obj);
1536 else
1537 scm_wta (SCM_INUM0, "already free", "");
1538}
0f2d19dd 1539
c68296f8
MV
1540/* Announce that there has been some malloc done that will be freed
1541 * during gc. A typical use is for a smob that uses some malloced
1542 * memory but can not get it from scm_must_malloc (for whatever
1543 * reason). When a new object of this smob is created you call
1544 * scm_done_malloc with the size of the object. When your smob free
1545 * function is called, be sure to include this size in the return
1546 * value. */
0f2d19dd 1547
c68296f8 1548void
6e8d25a6 1549scm_done_malloc (long size)
c68296f8
MV
1550{
1551 scm_mallocated += size;
1552
1553 if (scm_mallocated > scm_mtrigger)
1554 {
1555 scm_igc ("foreign mallocs");
1556 if (scm_mallocated > scm_mtrigger - SCM_MTRIGGER_HYSTERESIS)
1557 {
1558 if (scm_mallocated > scm_mtrigger)
1559 scm_mtrigger = scm_mallocated + scm_mallocated / 2;
1560 else
1561 scm_mtrigger += scm_mtrigger / 2;
1562 }
1563 }
1564}
1565
1566
1567\f
0f2d19dd
JB
1568
1569/* {Heap Segments}
1570 *
1571 * Each heap segment is an array of objects of a particular size.
1572 * Every segment has an associated (possibly shared) freelist.
1573 * A table of segment records is kept that records the upper and
1574 * lower extents of the segment; this is used during the conservative
1575 * phase of gc to identify probably gc roots (because they point
c68296f8 1576 * into valid segments at reasonable offsets). */
0f2d19dd
JB
1577
1578/* scm_expmem
1579 * is true if the first segment was smaller than INIT_HEAP_SEG.
1580 * If scm_expmem is set to one, subsequent segment allocations will
1581 * allocate segments of size SCM_EXPHEAP(scm_heap_size).
1582 */
1583int scm_expmem = 0;
1584
1585/* scm_heap_org
1586 * is the lowest base address of any heap segment.
1587 */
1588SCM_CELLPTR scm_heap_org;
1589
1590struct scm_heap_seg_data * scm_heap_table = 0;
1591int scm_n_heap_segs = 0;
1592
1593/* scm_heap_size
1594 * is the total number of cells in heap segments.
1595 */
15e9d186 1596unsigned long scm_heap_size = 0;
0f2d19dd
JB
1597
1598/* init_heap_seg
1599 * initializes a new heap segment and return the number of objects it contains.
1600 *
1601 * The segment origin, segment size in bytes, and the span of objects
1602 * in cells are input parameters. The freelist is both input and output.
1603 *
1604 * This function presume that the scm_heap_table has already been expanded
1605 * to accomodate a new segment record.
1606 */
1607
1608
0f2d19dd 1609static scm_sizet
6e8d25a6 1610init_heap_seg (SCM_CELLPTR seg_org, scm_sizet size, int ncells, SCM *freelistp)
0f2d19dd
JB
1611{
1612 register SCM_CELLPTR ptr;
1613#ifdef SCM_POINTERS_MUNGED
1614 register SCM scmptr;
1615#else
1616#undef scmptr
1617#define scmptr ptr
1618#endif
1619 SCM_CELLPTR seg_end;
15e9d186
JB
1620 int new_seg_index;
1621 int n_new_objects;
0f2d19dd
JB
1622
1623 if (seg_org == NULL)
1624 return 0;
1625
1626 ptr = seg_org;
1627
1628 /* Compute the ceiling on valid object pointers w/in this segment.
1629 */
1630 seg_end = CELL_DN ((char *) ptr + size);
1631
1632 /* Find the right place and insert the segment record.
1633 *
1634 */
1635 for (new_seg_index = 0;
1636 ( (new_seg_index < scm_n_heap_segs)
1637 && SCM_PTR_LE (scm_heap_table[new_seg_index].bounds[0], seg_org));
1638 new_seg_index++)
1639 ;
1640
1641 {
1642 int i;
1643 for (i = scm_n_heap_segs; i > new_seg_index; --i)
1644 scm_heap_table[i] = scm_heap_table[i - 1];
1645 }
1646
1647 ++scm_n_heap_segs;
1648
1649 scm_heap_table[new_seg_index].valid = 0;
1650 scm_heap_table[new_seg_index].ncells = ncells;
1651 scm_heap_table[new_seg_index].freelistp = freelistp;
1652 scm_heap_table[new_seg_index].bounds[0] = (SCM_CELLPTR)ptr;
1653 scm_heap_table[new_seg_index].bounds[1] = (SCM_CELLPTR)seg_end;
1654
1655
1656 /* Compute the least valid object pointer w/in this segment
1657 */
1658 ptr = CELL_UP (ptr);
1659
1660
1661 n_new_objects = seg_end - ptr;
1662
1663 /* Prepend objects in this segment to the freelist.
1664 */
1665 while (ptr < seg_end)
1666 {
1667#ifdef SCM_POINTERS_MUNGED
1668 scmptr = PTR2SCM (ptr);
1669#endif
24e68a57
MD
1670 SCM_SETCAR (scmptr, (SCM) scm_tc_free_cell);
1671 SCM_SETCDR (scmptr, PTR2SCM (ptr + ncells));
0f2d19dd
JB
1672 ptr += ncells;
1673 }
1674
1675 ptr -= ncells;
1676
1677 /* Patch up the last freelist pointer in the segment
1678 * to join it to the input freelist.
1679 */
24e68a57 1680 SCM_SETCDR (PTR2SCM (ptr), *freelistp);
0f2d19dd
JB
1681 *freelistp = PTR2SCM (CELL_UP (seg_org));
1682
1683 scm_heap_size += (ncells * n_new_objects);
1684 return size;
1685#ifdef scmptr
1686#undef scmptr
1687#endif
1688}
1689
1690
0f2d19dd 1691static void
6e8d25a6 1692alloc_some_heap (int ncells, SCM *freelistp)
0f2d19dd
JB
1693{
1694 struct scm_heap_seg_data * tmptable;
1695 SCM_CELLPTR ptr;
1696 scm_sizet len;
1697
1698 /* Critical code sections (such as the garbage collector)
1699 * aren't supposed to add heap segments.
1700 */
1701 if (scm_gc_heap_lock)
1702 scm_wta (SCM_UNDEFINED, "need larger initial", "heap");
1703
1704 /* Expand the heap tables to have room for the new segment.
1705 * Do not yet increment scm_n_heap_segs -- that is done by init_heap_seg
1706 * only if the allocation of the segment itself succeeds.
1707 */
1708 len = (1 + scm_n_heap_segs) * sizeof (struct scm_heap_seg_data);
1709
1710 SCM_SYSCALL (tmptable = ((struct scm_heap_seg_data *)
1711 realloc ((char *)scm_heap_table, len)));
1712 if (!tmptable)
1713 scm_wta (SCM_UNDEFINED, "could not grow", "hplims");
1714 else
1715 scm_heap_table = tmptable;
1716
1717
1718 /* Pick a size for the new heap segment.
1719 * The rule for picking the size of a segment is explained in
1720 * gc.h
1721 */
1722 if (scm_expmem)
1723 {
1724 len = (scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell));
1725 if ((scm_sizet) (SCM_EXPHEAP (scm_heap_size) * sizeof (scm_cell)) != len)
1726 len = 0;
1727 }
1728 else
1729 len = SCM_HEAP_SEG_SIZE;
1730
1731 {
1732 scm_sizet smallest;
1733
1734 smallest = (ncells * sizeof (scm_cell));
1735 if (len < smallest)
1736 len = (ncells * sizeof (scm_cell));
1737
1738 /* Allocate with decaying ambition. */
1739 while ((len >= SCM_MIN_HEAP_SEG_SIZE)
1740 && (len >= smallest))
1741 {
1742 SCM_SYSCALL (ptr = (SCM_CELLPTR) malloc (len));
1743 if (ptr)
1744 {
1745 init_heap_seg (ptr, len, ncells, freelistp);
1746 return;
1747 }
1748 len /= 2;
1749 }
1750 }
1751
1752 scm_wta (SCM_UNDEFINED, "could not grow", "heap");
1753}
1754
1755
1756
a1ec6916 1757SCM_DEFINE (scm_unhash_name, "unhash-name", 1, 0, 0,
1bbd0b84
GB
1758 (SCM name),
1759"")
1760#define FUNC_NAME s_scm_unhash_name
0f2d19dd
JB
1761{
1762 int x;
1763 int bound;
1bbd0b84 1764 SCM_VALIDATE_SYMBOL(1,name);
0f2d19dd
JB
1765 SCM_DEFER_INTS;
1766 bound = scm_n_heap_segs;
1767 for (x = 0; x < bound; ++x)
1768 {
1769 SCM_CELLPTR p;
1770 SCM_CELLPTR pbound;
1771 p = (SCM_CELLPTR)scm_heap_table[x].bounds[0];
1772 pbound = (SCM_CELLPTR)scm_heap_table[x].bounds[1];
1773 while (p < pbound)
1774 {
1775 SCM incar;
1776 incar = p->car;
1777 if (1 == (7 & (int)incar))
1778 {
1779 --incar;
1780 if ( ((name == SCM_BOOL_T) || (SCM_CAR (incar) == name))
1781 && (SCM_CDR (incar) != 0)
1782 && (SCM_CDR (incar) != 1))
1783 {
1784 p->car = name;
1785 }
1786 }
1787 ++p;
1788 }
1789 }
1790 SCM_ALLOW_INTS;
1791 return name;
1792}
1bbd0b84 1793#undef FUNC_NAME
0f2d19dd
JB
1794
1795
1796\f
1797/* {GC Protection Helper Functions}
1798 */
1799
1800
0f2d19dd 1801void
6e8d25a6
GB
1802scm_remember (SCM *ptr)
1803{ /* empty */ }
0f2d19dd 1804
1cc91f1b 1805
0f2d19dd
JB
1806SCM
1807scm_return_first (SCM elt, ...)
0f2d19dd
JB
1808{
1809 return elt;
1810}
1811
1812
0f2d19dd 1813SCM
6e8d25a6 1814scm_permanent_object (SCM obj)
0f2d19dd
JB
1815{
1816 SCM_REDEFER_INTS;
1817 scm_permobjs = scm_cons (obj, scm_permobjs);
1818 SCM_REALLOW_INTS;
1819 return obj;
1820}
1821
1822
ef290276
JB
1823/* Protect OBJ from the garbage collector. OBJ will not be freed,
1824 even if all other references are dropped, until someone applies
1825 scm_unprotect_object to it. This function returns OBJ.
1826
dab7f566
JB
1827 Calls to scm_protect_object nest. For every object O, there is a
1828 counter which scm_protect_object(O) increments and
1829 scm_unprotect_object(O) decrements, if it is greater than zero. If
1830 an object's counter is greater than zero, the garbage collector
1831 will not free it.
1832
1833 Of course, that's not how it's implemented. scm_protect_object and
1834 scm_unprotect_object just maintain a list of references to things.
1835 Since the GC knows about this list, all objects it mentions stay
1836 alive. scm_protect_object adds its argument to the list;
1837 scm_unprotect_object removes the first occurrence of its argument
1838 to the list. */
ef290276 1839SCM
6e8d25a6 1840scm_protect_object (SCM obj)
ef290276 1841{
ef290276
JB
1842 scm_protects = scm_cons (obj, scm_protects);
1843
1844 return obj;
1845}
1846
1847
1848/* Remove any protection for OBJ established by a prior call to
dab7f566 1849 scm_protect_object. This function returns OBJ.
ef290276 1850
dab7f566 1851 See scm_protect_object for more information. */
ef290276 1852SCM
6e8d25a6 1853scm_unprotect_object (SCM obj)
ef290276 1854{
dab7f566
JB
1855 SCM *tail_ptr = &scm_protects;
1856
0c95b57d 1857 while (SCM_CONSP (*tail_ptr))
dab7f566
JB
1858 if (SCM_CAR (*tail_ptr) == obj)
1859 {
1860 *tail_ptr = SCM_CDR (*tail_ptr);
1861 break;
1862 }
1863 else
1864 tail_ptr = SCM_CDRLOC (*tail_ptr);
ef290276
JB
1865
1866 return obj;
1867}
1868
c45acc34
JB
1869int terminating;
1870
1871/* called on process termination. */
e52ceaac
MD
1872#ifdef HAVE_ATEXIT
1873static void
1874cleanup (void)
1875#else
1876#ifdef HAVE_ON_EXIT
51157deb
MD
1877extern int on_exit (void (*procp) (), int arg);
1878
e52ceaac
MD
1879static void
1880cleanup (int status, void *arg)
1881#else
1882#error Dont know how to setup a cleanup handler on your system.
1883#endif
1884#endif
c45acc34
JB
1885{
1886 terminating = 1;
1887 scm_flush_all_ports ();
1888}
ef290276 1889
0f2d19dd 1890\f
0f2d19dd 1891int
15e9d186 1892scm_init_storage (scm_sizet init_heap_size)
0f2d19dd
JB
1893{
1894 scm_sizet j;
1895
1896 j = SCM_NUM_PROTECTS;
1897 while (j)
1898 scm_sys_protects[--j] = SCM_BOOL_F;
1899 scm_block_gc = 1;
1900 scm_freelist = SCM_EOL;
1901 scm_expmem = 0;
1902
1903 j = SCM_HEAP_SEG_SIZE;
1904 scm_mtrigger = SCM_INIT_MALLOC_LIMIT;
1905 scm_heap_table = ((struct scm_heap_seg_data *)
1906 scm_must_malloc (sizeof (struct scm_heap_seg_data), "hplims"));
1907 if (0L == init_heap_size)
1908 init_heap_size = SCM_INIT_HEAP_SIZE;
1909 j = init_heap_size;
1910 if ((init_heap_size != j)
1911 || !init_heap_seg ((SCM_CELLPTR) malloc (j), j, 1, &scm_freelist))
1912 {
1913 j = SCM_HEAP_SEG_SIZE;
1914 if (!init_heap_seg ((SCM_CELLPTR) malloc (j), j, 1, &scm_freelist))
1915 return 1;
1916 }
1917 else
1918 scm_expmem = 1;
1919 scm_heap_org = CELL_UP (scm_heap_table[0].bounds[0]);
1920 /* scm_hplims[0] can change. do not remove scm_heap_org */
ab4bef85 1921 scm_weak_vectors = SCM_EOL;
0f2d19dd
JB
1922
1923 /* Initialise the list of ports. */
840ae05d
JB
1924 scm_port_table = (scm_port **)
1925 malloc (sizeof (scm_port *) * scm_port_table_room);
0f2d19dd
JB
1926 if (!scm_port_table)
1927 return 1;
1928
a18bcd0e 1929#ifdef HAVE_ATEXIT
c45acc34 1930 atexit (cleanup);
e52ceaac
MD
1931#else
1932#ifdef HAVE_ON_EXIT
1933 on_exit (cleanup, 0);
1934#endif
a18bcd0e 1935#endif
0f2d19dd
JB
1936
1937 scm_undefineds = scm_cons (SCM_UNDEFINED, SCM_EOL);
24e68a57 1938 SCM_SETCDR (scm_undefineds, scm_undefineds);
0f2d19dd
JB
1939
1940 scm_listofnull = scm_cons (SCM_EOL, SCM_EOL);
1941 scm_nullstr = scm_makstr (0L, 0);
a8741caa
MD
1942 scm_nullvect = scm_make_vector (SCM_INUM0, SCM_UNDEFINED);
1943 scm_symhash = scm_make_vector ((SCM) SCM_MAKINUM (scm_symhash_dim), SCM_EOL);
4037ac5f 1944 scm_weak_symhash = scm_make_weak_key_hash_table ((SCM) SCM_MAKINUM (scm_symhash_dim));
a8741caa 1945 scm_symhash_vars = scm_make_vector ((SCM) SCM_MAKINUM (scm_symhash_dim), SCM_EOL);
8960e0a0 1946 scm_stand_in_procs = SCM_EOL;
0f2d19dd 1947 scm_permobjs = SCM_EOL;
ef290276 1948 scm_protects = SCM_EOL;
3b2b8760 1949 scm_asyncs = SCM_EOL;
0f2d19dd
JB
1950 scm_sysintern ("most-positive-fixnum", (SCM) SCM_MAKINUM (SCM_MOST_POSITIVE_FIXNUM));
1951 scm_sysintern ("most-negative-fixnum", (SCM) SCM_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM));
1952#ifdef SCM_BIGDIG
1953 scm_sysintern ("bignum-radix", SCM_MAKINUM (SCM_BIGRAD));
1954#endif
1955 return 0;
1956}
1957\f
1958
0f2d19dd
JB
1959void
1960scm_init_gc ()
0f2d19dd
JB
1961{
1962#include "gc.x"
1963}