1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
/*
* private-gc.h - private declarations for garbage collection.
*
* Copyright (C) 2002, 03, 04, 05, 06, 07, 08, 09 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PRIVATE_GC
#define PRIVATE_GC
#include "_scm.h"
/* {heap tuning parameters}
*
* These are parameters for controlling memory allocation. The heap
* is the area out of which scm_cons, and object headers are allocated.
*
* Each heap cell is 8 bytes on a 32 bit machine and 16 bytes on a
* 64 bit machine. The units of the _SIZE parameters are bytes.
* Cons pairs and object headers occupy one heap cell.
*
* SCM_MIN_HEAP_SEG_SIZE is minimum size of heap to accept when more heap
* is needed.
*/
/*
* Heap size 45000 and 40% min yield gives quick startup and no extra
* heap allocation. Having higher values on min yield may lead to
* large heaps, especially if code behaviour is varying its
* maximum consumption between different freelists.
*/
/*
These values used to be global C variables. However, they're also
available through the environment, and having a double interface is
confusing. Now they're #defines --hwn.
*/
#define SCM_DEFAULT_INIT_HEAP_SIZE_1 256*1024
#define SCM_DEFAULT_MIN_YIELD_1 40
#define SCM_DEFAULT_INIT_HEAP_SIZE_2 32*1024
/*
How many cells to collect during one sweep call. This is the pool
size of each thread.
*/
#define DEFAULT_SWEEP_AMOUNT 512
/* The following value may seem large, but note that if we get to GC at
* all, this means that we have a numerically intensive application
*/
#define SCM_DEFAULT_MIN_YIELD_2 40
#define SCM_DEFAULT_MAX_SEGMENT_SIZE (20*1024*1024L)
#define SCM_MIN_HEAP_SEG_SIZE (8 * SCM_GC_SIZEOF_CARD)
#define SCM_HEAP_SEG_SIZE (16384L * sizeof (scm_t_cell))
#define SCM_DOUBLECELL_ALIGNED_P(x) (((2 * sizeof (scm_t_cell) - 1) & SCM_UNPACK (x)) == 0)
#define SCM_GC_CARD_BVEC_SIZE_IN_LONGS \
((SCM_GC_CARD_N_CELLS + SCM_C_BVEC_LONG_BITS - 1) / SCM_C_BVEC_LONG_BITS)
#define SCM_GC_IN_CARD_HEADERP(x) \
(scm_t_cell *) (x) < SCM_GC_CELL_CARD (x) + SCM_GC_CARD_N_HEADER_CELLS
int scm_getenv_int (const char *var, int def);
typedef enum { return_on_error, abort_on_error } policy_on_error;
/* gc-freelist */
/*
FREELIST:
A struct holding GC statistics on a particular type of cells.
Counts in cells are mainly for heap statistics, and for
double-cells, they are still measured in single-cell units.
*/
typedef struct scm_t_cell_type_statistics {
/*
heap segment where the last cell was allocated
*/
int heap_segment_idx;
/* defines min_yield as fraction of total heap size
*/
float min_yield_fraction;
/* number of cells per object on this list */
int span;
/* number of collected cells during last GC. */
unsigned long collected;
unsigned long swept;
/*
Total number of cells in heap segments belonging to this list.
*/
unsigned long heap_total_cells;
} scm_t_cell_type_statistics;
/* Sweep statistics. */
typedef struct scm_sweep_statistics
{
/* Number of cells "swept", i.e., visited during the sweep operation. */
unsigned swept;
/* Number of cells collected during the sweep operation. This number must
always be lower than or equal to SWEPT. */
unsigned collected;
} scm_t_sweep_statistics;
SCM_INTERNAL scm_t_sweep_statistics scm_i_gc_sweep_stats;
extern scm_t_cell_type_statistics scm_i_master_freelist;
extern scm_t_cell_type_statistics scm_i_master_freelist2;
SCM_INTERNAL
void scm_i_adjust_min_yield (scm_t_cell_type_statistics *freelist,
scm_t_sweep_statistics sweep_stats,
scm_t_sweep_statistics sweep_stats_1);
SCM_INTERNAL
void scm_i_gc_sweep_freelist_reset (scm_t_cell_type_statistics *freelist);
SCM_INTERNAL float
scm_i_gc_heap_size_delta (scm_t_cell_type_statistics * freelist);
#define SCM_MAX(A, B) ((A) > (B) ? (A) : (B))
#define SCM_MIN(A, B) ((A) < (B) ? (A) : (B))
/* CELL_P checks a random word whether it has the right form for a
pointer to a cell. Use scm_i_find_heap_segment_containing_object
to find out whether it actually points to a real cell.
The right form for a cell pointer is this: the low three bits must
be scm_tc3_cons, and when the scm_tc3_cons tag is stripped, the
resulting pointer must be correctly aligned.
scm_i_initialize_heap_segment_data guarantees that the test below
works.
*/
#define CELL_P(x) ((SCM_UNPACK(x) & (sizeof(scm_t_cell)-1)) == scm_tc3_cons)
/*
gc-mark
*/
/* Non-zero while in the mark phase. */
SCM_INTERNAL int scm_i_marking;
SCM_INTERNAL void scm_mark_all (void);
/*
gc-segment:
*/
/*
Cells are stored in a heap-segment: it is a contiguous chunk of
memory, that associated with one freelist.
*/
typedef struct scm_t_heap_segment
{
/*
{lower, upper} bounds of the segment
The upper bound is also the start of the mark space.
*/
scm_t_cell *bounds[2];
/*
If we ever decide to give it back, we could do it with this ptr.
Note that giving back memory is not very useful; as long we don't
touch a chunk of memory, the virtual memory system will keep it
swapped out. We could simply forget about a block.
(not that we do that, but anyway.)
*/
void *malloced;
scm_t_cell *next_free_card;
/* address of the head-of-freelist pointer for this segment's cells.
All segments usually point to the same one, scm_i_freelist. */
scm_t_cell_type_statistics *freelist;
/* number of cells per object in this segment */
int span;
/*
Is this the first time that the cells are accessed?
*/
int first_time;
} scm_t_heap_segment;
/*
A table of segment records is kept that records the upper and
lower extents of the segment; this is used during the conservative
phase of gc to identify probably gc roots (because they point
into valid segments at reasonable offsets).
*/
extern scm_t_heap_segment ** scm_i_heap_segment_table;
extern size_t scm_i_heap_segment_table_size;
SCM_INTERNAL int scm_i_init_card_freelist (scm_t_cell * card, SCM *free_list,
scm_t_heap_segment*);
SCM_INTERNAL int scm_i_sweep_card (scm_t_cell *card, SCM *free_list,
scm_t_heap_segment *);
SCM_INTERNAL int scm_i_card_marked_count (scm_t_cell *card, int span);
SCM_INTERNAL void scm_i_card_statistics (scm_t_cell *p, SCM hashtab,
scm_t_heap_segment *seg);
SCM_INTERNAL char const *scm_i_tag_name (scm_t_bits tag); /* MOVEME */
SCM_INTERNAL int scm_i_initialize_heap_segment_data (scm_t_heap_segment *seg,
size_t requested);
SCM_INTERNAL int scm_i_segment_cells_per_card (scm_t_heap_segment *seg);
SCM_INTERNAL int scm_i_segment_card_number (scm_t_heap_segment *seg,
scm_t_cell *card);
SCM_INTERNAL int scm_i_segment_card_count (scm_t_heap_segment *seg);
SCM_INTERNAL int scm_i_segment_cell_count (scm_t_heap_segment *seg);
SCM_INTERNAL int scm_i_heap_segment_marked_count (scm_t_heap_segment *seg);
SCM_INTERNAL void scm_i_clear_segment_mark_space (scm_t_heap_segment *seg);
SCM_INTERNAL scm_t_heap_segment *
scm_i_make_empty_heap_segment (scm_t_cell_type_statistics*);
SCM_INTERNAL SCM scm_i_sweep_for_freelist (scm_t_cell_type_statistics *seg);
SCM_INTERNAL SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg,
scm_t_sweep_statistics *sweep_stats,
int threshold);
SCM_INTERNAL void scm_i_sweep_segment (scm_t_heap_segment *seg,
scm_t_sweep_statistics *sweep_stats);
SCM_INTERNAL void scm_i_heap_segment_statistics (scm_t_heap_segment *seg,
SCM tab);
SCM_INTERNAL int scm_i_insert_segment (scm_t_heap_segment *seg);
SCM_INTERNAL int scm_i_find_heap_segment_containing_object (SCM obj);
SCM_INTERNAL int scm_i_get_new_heap_segment (scm_t_cell_type_statistics *freelist,
size_t length,
policy_on_error);
SCM_INTERNAL int scm_i_marked_count (void);
SCM_INTERNAL void scm_i_clear_mark_space (void);
SCM_INTERNAL void scm_i_sweep_segments (void);
SCM_INTERNAL SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
scm_t_sweep_statistics *sweep_stats);
SCM_INTERNAL void scm_i_reset_segments (void);
SCM_INTERNAL void scm_i_sweep_all_segments (char const *reason,
scm_t_sweep_statistics *sweep_stats);
SCM_INTERNAL SCM scm_i_all_segments_statistics (SCM hashtab);
SCM_INTERNAL unsigned long *scm_i_segment_table_info(int *size);
SCM_INTERNAL long int scm_i_deprecated_memory_return;
SCM_INTERNAL long int scm_i_find_heap_calls;
SCM_INTERNAL long int scm_i_last_marked_cell_count;
/*
global init funcs.
*/
void scm_gc_init_malloc (void);
void scm_gc_init_freelist (void);
void scm_gc_init_segments (void);
void scm_gc_init_mark (void);
#endif
|