make the fallback path look less like line noise
[bpt/guile.git] / libguile / gc-segment-table.c
CommitLineData
dbb605f5 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2006, 2008 Free Software Foundation, Inc.
82ae1b8e
HWN
2 *
3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
82ae1b8e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
82ae1b8e
HWN
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
82ae1b8e
HWN
17 */
18
dbb605f5
LC
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
82ae1b8e
HWN
23#include <assert.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "libguile/_scm.h"
28#include "libguile/pairs.h"
29#include "libguile/gc.h"
30#include "libguile/private-gc.h"
31
32
33/*
34 Heap segment table.
35
36 The table is sorted by the address of the data itself. This makes
37 for easy lookups. This is not portable: according to ANSI C,
38 pointers can only be compared within the same object (i.e. the same
39 block of malloced memory.). For machines with weird architectures,
40 this should be revised.
41
42 (Apparently, for this reason 1.6 and earlier had macros for pointer
43 comparison. )
44
45 perhaps it is worthwhile to remove the 2nd level of indirection in
46 the table, but this certainly makes for cleaner code.
47*/
48scm_t_heap_segment **scm_i_heap_segment_table;
49size_t scm_i_heap_segment_table_size;
50static scm_t_cell *lowest_cell;
51static scm_t_cell *highest_cell;
52
53
54/*
55 RETURN: index of inserted segment.
56 */
57int
58scm_i_insert_segment (scm_t_heap_segment *seg)
59{
60 size_t size = (scm_i_heap_segment_table_size + 1) * sizeof (scm_t_heap_segment *);
1f584400 61 SCM_SYSCALL (scm_i_heap_segment_table
82ae1b8e
HWN
62 = ((scm_t_heap_segment **)
63 realloc ((char *)scm_i_heap_segment_table, size)));
64
65 /*
66 We can't alloc 4 more bytes. This is hopeless.
67 */
68 if (!scm_i_heap_segment_table)
69 {
70 fprintf (stderr, "scm_i_get_new_heap_segment: Could not grow heap segment table.\n");
71 abort ();
72 }
73
74 if (!lowest_cell)
75 {
76 lowest_cell = seg->bounds[0];
77 highest_cell = seg->bounds[1];
78 }
79 else
80 {
81 lowest_cell = SCM_MIN (lowest_cell, seg->bounds[0]);
82 highest_cell = SCM_MAX (highest_cell, seg->bounds[1]);
83 }
84
85
86 {
87 int i = 0;
88 int j = 0;
89
90 while (i < scm_i_heap_segment_table_size
91 && scm_i_heap_segment_table[i]->bounds[0] <= seg->bounds[0])
92 i++;
93
94 /*
95 We insert a new entry; if that happens to be before the
96 "current" segment of a freelist, we must move the freelist index
97 as well.
98 */
99 if (scm_i_master_freelist.heap_segment_idx >= i)
100 scm_i_master_freelist.heap_segment_idx ++;
101 if (scm_i_master_freelist2.heap_segment_idx >= i)
102 scm_i_master_freelist2.heap_segment_idx ++;
103
104 for (j = scm_i_heap_segment_table_size; j > i; --j)
105 scm_i_heap_segment_table[j] = scm_i_heap_segment_table[j - 1];
106
107 scm_i_heap_segment_table[i] = seg;
108 scm_i_heap_segment_table_size ++;
109
110 return i;
111 }
112}
113
114
115/*
116 Determine whether the given value does actually represent a cell in
117 some heap segment. If this is the case, the number of the heap
118 segment is returned. Otherwise, -1 is returned. Binary search is
119 used to determine the heap segment that contains the cell.
120
121 I think this function is too long to be inlined. --hwn
122*/
40945e5e 123
82ae1b8e
HWN
124int
125scm_i_find_heap_segment_containing_object (SCM obj)
126{
127 if (!CELL_P (obj))
128 return -1;
129
40945e5e 130 scm_i_find_heap_calls ++;
82ae1b8e
HWN
131 if ((scm_t_cell *) obj < lowest_cell || (scm_t_cell *) obj >= highest_cell)
132 return -1;
133
134 {
135 scm_t_cell *ptr = SCM2PTR (obj);
136 unsigned int i = 0;
137 unsigned int j = scm_i_heap_segment_table_size - 1;
138
139 if (ptr < scm_i_heap_segment_table[i]->bounds[0])
140 return -1;
141 else if (scm_i_heap_segment_table[j]->bounds[1] <= ptr)
142 return -1;
143 else
144 {
145 while (i < j)
146 {
147 if (ptr < scm_i_heap_segment_table[i]->bounds[1])
148 {
149 break;
150 }
151 else if (scm_i_heap_segment_table[j]->bounds[0] <= ptr)
152 {
153 i = j;
154 break;
155 }
156 else
157 {
158 unsigned long int k = (i + j) / 2;
159
160 if (k == i)
161 return -1;
162 else if (ptr < scm_i_heap_segment_table[k]->bounds[1])
163 {
164 j = k;
165 ++i;
166 if (ptr < scm_i_heap_segment_table[i]->bounds[0])
167 return -1;
168 }
169 else if (scm_i_heap_segment_table[k]->bounds[0] <= ptr)
170 {
171 i = k;
172 --j;
173 if (scm_i_heap_segment_table[j]->bounds[1] <= ptr)
174 return -1;
175 }
176 }
177 }
178
179 if (!SCM_DOUBLECELL_ALIGNED_P (obj) && scm_i_heap_segment_table[i]->span == 2)
180 return -1;
181 else if (SCM_GC_IN_CARD_HEADERP (ptr))
182 return -1;
183 else
184 return i;
185 }
186 }
187}
188
189
190int
191scm_i_marked_count (void)
192{
193 int i = 0;
194 int c = 0;
195 for (; i < scm_i_heap_segment_table_size; i++)
196 {
197 c += scm_i_heap_segment_marked_count (scm_i_heap_segment_table[i]);
198 }
199 return c;
200}
201
202
203SCM
204scm_i_sweep_some_segments (scm_t_cell_type_statistics *freelist,
205 scm_t_sweep_statistics *sweep_stats)
206{
207 int i = freelist->heap_segment_idx;
208 SCM collected = SCM_EOL;
209
210 if (i == -1) /* huh? --hwn */
211 i++;
212
213 for (;
214 i < scm_i_heap_segment_table_size; i++)
215 {
216 if (scm_i_heap_segment_table[i]->freelist != freelist)
217 continue;
218
219 collected = scm_i_sweep_some_cards (scm_i_heap_segment_table[i],
220 sweep_stats,
221 DEFAULT_SWEEP_AMOUNT);
222
223 if (collected != SCM_EOL) /* Don't increment i */
224 break;
225 }
226
227 freelist->heap_segment_idx = i;
228
229 return collected;
230}
231
232void
233scm_i_reset_segments (void)
234{
235 int i = 0;
236 for (; i < scm_i_heap_segment_table_size; i++)
237 {
238 scm_t_heap_segment *seg = scm_i_heap_segment_table[i];
239 seg->next_free_card = seg->bounds[0];
240 }
241}
242
243
244
245
246/*
247 Return a hashtab with counts of live objects, with tags as keys.
248 */
249SCM
250scm_i_all_segments_statistics (SCM tab)
251{
252 int i = 0;
253 for (; i < scm_i_heap_segment_table_size; i++)
254 {
255 scm_t_heap_segment *seg = scm_i_heap_segment_table[i];
256 scm_i_heap_segment_statistics (seg, tab);
257 }
258
259 return tab;
260}
261
262
263unsigned long*
1f584400 264scm_i_segment_table_info (int* size)
82ae1b8e
HWN
265{
266 *size = scm_i_heap_segment_table_size;
267 unsigned long *bounds = malloc (sizeof (unsigned long) * *size * 2);
268 int i;
269 if (!bounds)
1f584400 270 abort ();
82ae1b8e
HWN
271 for (i = *size; i-- > 0; )
272 {
273 bounds[2*i] = (unsigned long)scm_i_heap_segment_table[i]->bounds[0];
274 bounds[2*i+1] = (unsigned long)scm_i_heap_segment_table[i]->bounds[1];
275 }
276 return bounds;
277}
278
279
280void
281scm_i_sweep_all_segments (char const *reason,
282 scm_t_sweep_statistics *sweep_stats)
283{
284 unsigned i= 0;
285 for (i = 0; i < scm_i_heap_segment_table_size; i++)
286 {
287 scm_i_sweep_segment (scm_i_heap_segment_table[i], sweep_stats);
288 }
289}
290
291
292void
293scm_i_clear_mark_space (void)
294{
295 int i = 0;
296 for (; i < scm_i_heap_segment_table_size; i++)
297 {
298 scm_i_clear_segment_mark_space (scm_i_heap_segment_table[i]);
299 }
300}