#ifndef SCM_GC_H
#define SCM_GC_H
-/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2002, 2003, 2004 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
typedef struct scm_t_cell
{
- scm_t_bits word_0;
- scm_t_bits word_1;
+ SCM word_0;
+ SCM word_1;
} scm_t_cell;
/*
A card is a small `page' of memory; it will be the unit for lazy
sweeping, generations, etc. The first cell of a card contains a
- pointer to the mark bitvector, so that we can find the bitvector efficiently: we
- knock off some lowerorder bits.
+ pointer to the mark bitvector, so that we can find the bitvector
+ efficiently: we knock off some lowerorder bits.
- The size on a 32 bit machine is 256 cells = 2kb. The card
+ The size on a 32 bit machine is 256 cells = 2kb. The card [XXX]
*/
-/* Cray machines have pointers that are incremented once for each word,
- * rather than each byte, the 3 most significant bits encode the byte
- * within the word. The following macros deal with this by storing the
- * native Cray pointers like the ones that looks like scm expects. This
- * is done for any pointers that might appear in the car of a scm_t_cell,
+/* Cray machines have pointers that are incremented once for each
+ * word, rather than each byte, the 3 most significant bits encode the
+ * byte within the word. The following macros deal with this by
+ * storing the native Cray pointers like the ones that looks like scm
+ * expects. This is done for any pointers that point to a cell,
* pointers to scm_vector elts, functions, &c are not munged.
*/
#ifdef _UNICOS
#define SCM_GC_CARD_BVEC(card) ((scm_t_c_bvec_long *) ((card)->word_0))
#define SCM_GC_SET_CARD_BVEC(card, bvec) \
- ((card)->word_0 = (scm_t_bits) (bvec))
-
-
+ ((card)->word_0 = (SCM) (bvec))
#define SCM_GC_GET_CARD_FLAGS(card) ((long) ((card)->word_1))
#define SCM_GC_SET_CARD_FLAGS(card, flags) \
- ((card)->word_1 = (scm_t_bits) (flags))
-#define SCM_GC_CLEAR_CARD_FLAGS(card) (SCM_GC_SET_CARD_FLAGS (card, 0L))
+ ((card)->word_1 = (SCM) (flags))
-#define SCM_GC_GET_CARD_FLAG(card, shift) (SCM_GC_GET_CARD_FLAGS (card) & (1L << (shift)))
+#define SCM_GC_GET_CARD_FLAG(card, shift) \
+ (SCM_GC_GET_CARD_FLAGS (card) & (1L << (shift)))
#define SCM_GC_SET_CARD_FLAG(card, shift) \
- (SCM_GC_SET_CARD_FLAGS (card, SCM_GC_GET_CARD_FLAGS(card) | (1L << (shift))))
+ (SCM_GC_SET_CARD_FLAGS (card, SCM_GC_GET_CARD_FLAGS(card) | (1L << (shift))))
#define SCM_GC_CLEAR_CARD_FLAG(card, shift) \
- (SCM_GC_SET_CARD_FLAGS (card, SCM_GC_GET_CARD_FLAGS(card) & ~(1L << (shift))))
+ (SCM_GC_SET_CARD_FLAGS (card, SCM_GC_GET_CARD_FLAGS(card) & ~(1L << (shift))))
/*
Remove card flags. They hamper lazy initialization, and aren't used
/* card addressing. for efficiency, cards are *always* aligned to
SCM_GC_CARD_SIZE. */
-#define SCM_GC_CARD_SIZE_MASK (SCM_GC_CARD_N_CELLS * sizeof (scm_t_cell) - 1)
+#define SCM_GC_CARD_SIZE_MASK (SCM_GC_SIZEOF_CARD-1)
#define SCM_GC_CARD_ADDR_MASK (~SCM_GC_CARD_SIZE_MASK)
#define SCM_GC_CELL_CARD(x) ((scm_t_cell *) ((long) (x) & SCM_GC_CARD_ADDR_MASK))
* in debug mode. In particular these macros will even work for free cells,
* which should never be encountered by user code. */
-#define SCM_GC_CELL_WORD(x, n) \
- (((const scm_t_bits *) SCM2PTR (x)) [n])
-#define SCM_GC_CELL_OBJECT(x, n) \
- (SCM_PACK (((const scm_t_bits *) SCM2PTR (x)) [n]))
-#define SCM_GC_SET_CELL_WORD(x, n, v) \
- (((scm_t_bits *) SCM2PTR (x)) [n] = (scm_t_bits) (v))
-#define SCM_GC_SET_CELL_OBJECT(x, n, v) \
- (((scm_t_bits *) SCM2PTR (x)) [n] = SCM_UNPACK (v))
-#define SCM_GC_CELL_TYPE(x) SCM_GC_CELL_WORD (x, 0)
+#define SCM_GC_CELL_OBJECT(x, n) (((SCM *)SCM2PTR (x)) [n])
+#define SCM_GC_CELL_WORD(x, n) (SCM_UNPACK (SCM_GC_CELL_OBJECT ((x), (n))))
+
+#define SCM_GC_SET_CELL_OBJECT(x, n, v) ((((SCM *)SCM2PTR (x)) [n]) = (v))
+#define SCM_GC_SET_CELL_WORD(x, n, v) \
+ (SCM_GC_SET_CELL_OBJECT ((x), (n), SCM_PACK (v)))
+
+#define SCM_GC_CELL_TYPE(x) (SCM_GC_CELL_OBJECT ((x), 0))
/* Except for the garbage collector, no part of guile should ever run over a
#define SCM_CELL_WORD(x, n) \
SCM_VALIDATE_CELL ((x), SCM_GC_CELL_WORD ((x), (n)))
-#define SCM_CELL_WORD_0(x) SCM_CELL_WORD (x, 0)
-#define SCM_CELL_WORD_1(x) SCM_CELL_WORD (x, 1)
-#define SCM_CELL_WORD_2(x) SCM_CELL_WORD (x, 2)
-#define SCM_CELL_WORD_3(x) SCM_CELL_WORD (x, 3)
+#define SCM_CELL_WORD_0(x) SCM_CELL_WORD ((x), 0)
+#define SCM_CELL_WORD_1(x) SCM_CELL_WORD ((x), 1)
+#define SCM_CELL_WORD_2(x) SCM_CELL_WORD ((x), 2)
+#define SCM_CELL_WORD_3(x) SCM_CELL_WORD ((x), 3)
#define SCM_CELL_OBJECT(x, n) \
SCM_VALIDATE_CELL ((x), SCM_GC_CELL_OBJECT ((x), (n)))
-#define SCM_CELL_OBJECT_0(x) SCM_CELL_OBJECT (x, 0)
-#define SCM_CELL_OBJECT_1(x) SCM_CELL_OBJECT (x, 1)
-#define SCM_CELL_OBJECT_2(x) SCM_CELL_OBJECT (x, 2)
-#define SCM_CELL_OBJECT_3(x) SCM_CELL_OBJECT (x, 3)
+#define SCM_CELL_OBJECT_0(x) SCM_CELL_OBJECT ((x), 0)
+#define SCM_CELL_OBJECT_1(x) SCM_CELL_OBJECT ((x), 1)
+#define SCM_CELL_OBJECT_2(x) SCM_CELL_OBJECT ((x), 2)
+#define SCM_CELL_OBJECT_3(x) SCM_CELL_OBJECT ((x), 3)
#define SCM_SET_CELL_WORD(x, n, v) \
SCM_VALIDATE_CELL ((x), SCM_GC_SET_CELL_WORD ((x), (n), (v)))
-#define SCM_SET_CELL_WORD_0(x, v) SCM_SET_CELL_WORD (x, 0, v)
-#define SCM_SET_CELL_WORD_1(x, v) SCM_SET_CELL_WORD (x, 1, v)
-#define SCM_SET_CELL_WORD_2(x, v) SCM_SET_CELL_WORD (x, 2, v)
-#define SCM_SET_CELL_WORD_3(x, v) SCM_SET_CELL_WORD (x, 3, v)
+#define SCM_SET_CELL_WORD_0(x, v) SCM_SET_CELL_WORD ((x), 0, (v))
+#define SCM_SET_CELL_WORD_1(x, v) SCM_SET_CELL_WORD ((x), 1, (v))
+#define SCM_SET_CELL_WORD_2(x, v) SCM_SET_CELL_WORD ((x), 2, (v))
+#define SCM_SET_CELL_WORD_3(x, v) SCM_SET_CELL_WORD ((x), 3, (v))
#define SCM_SET_CELL_OBJECT(x, n, v) \
SCM_VALIDATE_CELL ((x), SCM_GC_SET_CELL_OBJECT ((x), (n), (v)))
-#define SCM_SET_CELL_OBJECT_0(x, v) SCM_SET_CELL_OBJECT (x, 0, v)
-#define SCM_SET_CELL_OBJECT_1(x, v) SCM_SET_CELL_OBJECT (x, 1, v)
-#define SCM_SET_CELL_OBJECT_2(x, v) SCM_SET_CELL_OBJECT (x, 2, v)
-#define SCM_SET_CELL_OBJECT_3(x, v) SCM_SET_CELL_OBJECT (x, 3, v)
+#define SCM_SET_CELL_OBJECT_0(x, v) SCM_SET_CELL_OBJECT ((x), 0, (v))
+#define SCM_SET_CELL_OBJECT_1(x, v) SCM_SET_CELL_OBJECT ((x), 1, (v))
+#define SCM_SET_CELL_OBJECT_2(x, v) SCM_SET_CELL_OBJECT ((x), 2, (v))
+#define SCM_SET_CELL_OBJECT_3(x, v) SCM_SET_CELL_OBJECT ((x), 3, (v))
#define SCM_CELL_TYPE(x) SCM_CELL_WORD_0 (x)
-#define SCM_SET_CELL_TYPE(x, t) SCM_SET_CELL_WORD_0 (x, t)
+#define SCM_SET_CELL_TYPE(x, t) SCM_SET_CELL_WORD_0 ((x), (t))
/* Freelists consist of linked cells where the type entry holds the value
* scm_tc_free_cell and the second entry holds a pointer to the next cell of
(SCM_GC_SET_CELL_OBJECT ((x), 1, (v)))
-#define SCM_CELL_WORD_LOC(x, n) ((scm_t_bits *) & SCM_CELL_WORD (x, n))
-#define SCM_CARLOC(x) ((SCM *) SCM_CELL_WORD_LOC ((x), 0))
-#define SCM_CDRLOC(x) ((SCM *) SCM_CELL_WORD_LOC ((x), 1))
+#define SCM_CELL_OBJECT_LOC(x, n) (SCM_VALIDATE_CELL((x), &SCM_GC_CELL_OBJECT ((x), (n))))
+#define SCM_CARLOC(x) (SCM_CELL_OBJECT_LOC ((x), 0))
+#define SCM_CDRLOC(x) (SCM_CELL_OBJECT_LOC ((x), 1))
void scm_i_expensive_validation_check (SCM cell);
#endif
+SCM_API scm_t_mutex scm_i_gc_admin_mutex;
+
SCM_API int scm_block_gc;
SCM_API int scm_gc_heap_lock;
SCM_API unsigned int scm_gc_running_p;
SCM_API unsigned long scm_gc_cells_swept;
SCM_API unsigned long scm_gc_cells_collected;
-SCM_API unsigned long scm_gc_cells_collected;
SCM_API unsigned long scm_gc_malloc_collected;
SCM_API unsigned long scm_gc_ports_collected;
SCM_API unsigned long scm_cells_allocated;
SCM_API SCM scm_object_address (SCM obj);
SCM_API SCM scm_gc_stats (void);
+SCM_API SCM scm_gc_live_object_stats (void);
+SCM_API SCM scm_gc_tag_name (SCM tag);
SCM_API SCM scm_gc (void);
SCM_API void scm_gc_for_alloc (struct scm_t_cell_type_statistics *freelist);
SCM_API SCM scm_gc_for_newcell (struct scm_t_cell_type_statistics *master, SCM *freelist);
SCM_API void scm_remember_upto_here_1 (SCM obj);
SCM_API void scm_remember_upto_here_2 (SCM obj1, SCM obj2);
SCM_API void scm_remember_upto_here (SCM obj1, ...);
+
+/* In GCC we can force a reference to an SCM by making it an input to an
+ empty asm. This avoids the code size and slowdown of an actual function
+ call. Unfortunately there doesn't seem to be any way to do the varargs
+ scm_remember_upto_here like this.
+
+ __volatile__ ensures nothing will be moved across the asm, and it won't
+ be optimized away (or only if proved unreachable). Constraint "g" can be
+ used on all processors and allows any memory or general register (or
+ immediate) operand. The actual asm syntax doesn't matter, we don't want
+ to use it, just ensure the operand is still alive. See "Extended Asm" in
+ the GCC manual for more. */
+
+#ifdef __GNUC__
+#define scm_remember_upto_here_1(x) \
+ do { \
+ __asm__ __volatile__ ("" : : "g" (x)); \
+ } while (0)
+#define scm_remember_upto_here_2(x, y) \
+ do { \
+ scm_remember_upto_here_1 (x); \
+ scm_remember_upto_here_1 (y); \
+ } while (0)
+#endif
+
SCM_API SCM scm_return_first (SCM elt, ...);
SCM_API int scm_return_first_int (int x, ...);
SCM_API SCM scm_permanent_object (SCM obj);