51488
|
1 /*
|
|
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
|
|
3 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
|
|
4 * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
|
|
5 *
|
|
6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
7 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
8 *
|
|
9 * Permission is hereby granted to use or copy this program
|
|
10 * for any purpose, provided the above notices are retained on all copies.
|
|
11 * Permission to modify the code and to distribute modified code is granted,
|
|
12 * provided the above notices are retained, and a notice that the code was
|
|
13 * modified is included with the above copyright notice.
|
|
14 *
|
|
15 * This file contains the functions:
|
|
16 * ptr_t GC_build_flXXX(h, old_fl)
|
|
17 * void GC_new_hblk(n)
|
|
18 */
|
|
19 /* Boehm, May 19, 1994 2:09 pm PDT */
|
|
20
|
|
21
|
|
22 # include <stdio.h>
|
|
23 # include "private/gc_priv.h"
|
|
24
|
|
25 #ifndef SMALL_CONFIG
|
|
26 /*
|
|
27 * Build a free list for size 1 objects inside hblk h. Set the last link to
|
|
28 * be ofl. Return a pointer tpo the first free list entry.
|
|
29 */
|
|
30 ptr_t GC_build_fl1(h, ofl)
|
|
31 struct hblk *h;
|
|
32 ptr_t ofl;
|
|
33 {
|
|
34 register word * p = h -> hb_body;
|
|
35 register word * lim = (word *)(h + 1);
|
|
36
|
|
37 p[0] = (word)ofl;
|
|
38 p[1] = (word)(p);
|
|
39 p[2] = (word)(p+1);
|
|
40 p[3] = (word)(p+2);
|
|
41 p += 4;
|
|
42 for (; p < lim; p += 4) {
|
|
43 p[0] = (word)(p-1);
|
|
44 p[1] = (word)(p);
|
|
45 p[2] = (word)(p+1);
|
|
46 p[3] = (word)(p+2);
|
|
47 };
|
|
48 return((ptr_t)(p-1));
|
|
49 }
|
|
50
|
|
51 /* The same for size 2 cleared objects */
|
|
52 ptr_t GC_build_fl_clear2(h, ofl)
|
|
53 struct hblk *h;
|
|
54 ptr_t ofl;
|
|
55 {
|
|
56 register word * p = h -> hb_body;
|
|
57 register word * lim = (word *)(h + 1);
|
|
58
|
|
59 p[0] = (word)ofl;
|
|
60 p[1] = 0;
|
|
61 p[2] = (word)p;
|
|
62 p[3] = 0;
|
|
63 p += 4;
|
|
64 for (; p < lim; p += 4) {
|
|
65 p[0] = (word)(p-2);
|
|
66 p[1] = 0;
|
|
67 p[2] = (word)p;
|
|
68 p[3] = 0;
|
|
69 };
|
|
70 return((ptr_t)(p-2));
|
|
71 }
|
|
72
|
|
73 /* The same for size 3 cleared objects */
|
|
74 ptr_t GC_build_fl_clear3(h, ofl)
|
|
75 struct hblk *h;
|
|
76 ptr_t ofl;
|
|
77 {
|
|
78 register word * p = h -> hb_body;
|
|
79 register word * lim = (word *)(h + 1) - 2;
|
|
80
|
|
81 p[0] = (word)ofl;
|
|
82 p[1] = 0;
|
|
83 p[2] = 0;
|
|
84 p += 3;
|
|
85 for (; p < lim; p += 3) {
|
|
86 p[0] = (word)(p-3);
|
|
87 p[1] = 0;
|
|
88 p[2] = 0;
|
|
89 };
|
|
90 return((ptr_t)(p-3));
|
|
91 }
|
|
92
|
|
93 /* The same for size 4 cleared objects */
|
|
94 ptr_t GC_build_fl_clear4(h, ofl)
|
|
95 struct hblk *h;
|
|
96 ptr_t ofl;
|
|
97 {
|
|
98 register word * p = h -> hb_body;
|
|
99 register word * lim = (word *)(h + 1);
|
|
100
|
|
101 p[0] = (word)ofl;
|
|
102 p[1] = 0;
|
|
103 p[2] = 0;
|
|
104 p[3] = 0;
|
|
105 p += 4;
|
|
106 for (; p < lim; p += 4) {
|
|
107 PREFETCH_FOR_WRITE(p+64);
|
|
108 p[0] = (word)(p-4);
|
|
109 p[1] = 0;
|
|
110 CLEAR_DOUBLE(p+2);
|
|
111 };
|
|
112 return((ptr_t)(p-4));
|
|
113 }
|
|
114
|
|
115 /* The same for size 2 uncleared objects */
|
|
116 ptr_t GC_build_fl2(h, ofl)
|
|
117 struct hblk *h;
|
|
118 ptr_t ofl;
|
|
119 {
|
|
120 register word * p = h -> hb_body;
|
|
121 register word * lim = (word *)(h + 1);
|
|
122
|
|
123 p[0] = (word)ofl;
|
|
124 p[2] = (word)p;
|
|
125 p += 4;
|
|
126 for (; p < lim; p += 4) {
|
|
127 p[0] = (word)(p-2);
|
|
128 p[2] = (word)p;
|
|
129 };
|
|
130 return((ptr_t)(p-2));
|
|
131 }
|
|
132
|
|
133 /* The same for size 4 uncleared objects */
|
|
134 ptr_t GC_build_fl4(h, ofl)
|
|
135 struct hblk *h;
|
|
136 ptr_t ofl;
|
|
137 {
|
|
138 register word * p = h -> hb_body;
|
|
139 register word * lim = (word *)(h + 1);
|
|
140
|
|
141 p[0] = (word)ofl;
|
|
142 p[4] = (word)p;
|
|
143 p += 8;
|
|
144 for (; p < lim; p += 8) {
|
|
145 PREFETCH_FOR_WRITE(p+64);
|
|
146 p[0] = (word)(p-4);
|
|
147 p[4] = (word)p;
|
|
148 };
|
|
149 return((ptr_t)(p-4));
|
|
150 }
|
|
151
|
|
152 #endif /* !SMALL_CONFIG */
|
|
153
|
|
154
|
|
155 /* Build a free list for objects of size sz inside heap block h. */
|
|
156 /* Clear objects inside h if clear is set. Add list to the end of */
|
|
157 /* the free list we build. Return the new free list. */
|
|
158 /* This could be called without the main GC lock, if we ensure that */
|
|
159 /* there is no concurrent collection which might reclaim objects that */
|
|
160 /* we have not yet allocated. */
|
|
161 ptr_t GC_build_fl(h, sz, clear, list)
|
|
162 struct hblk *h;
|
|
163 word sz;
|
|
164 GC_bool clear;
|
|
165 ptr_t list;
|
|
166 {
|
|
167 word *p, *prev;
|
|
168 word *last_object; /* points to last object in new hblk */
|
|
169
|
|
170 /* Do a few prefetches here, just because its cheap. */
|
|
171 /* If we were more serious about it, these should go inside */
|
|
172 /* the loops. But write prefetches usually don't seem to */
|
|
173 /* matter much. */
|
|
174 PREFETCH_FOR_WRITE((char *)h);
|
|
175 PREFETCH_FOR_WRITE((char *)h + 128);
|
|
176 PREFETCH_FOR_WRITE((char *)h + 256);
|
|
177 PREFETCH_FOR_WRITE((char *)h + 378);
|
|
178 /* Handle small objects sizes more efficiently. For larger objects */
|
|
179 /* the difference is less significant. */
|
|
180 # ifndef SMALL_CONFIG
|
|
181 switch (sz) {
|
|
182 case 1: return GC_build_fl1(h, list);
|
|
183 case 2: if (clear) {
|
|
184 return GC_build_fl_clear2(h, list);
|
|
185 } else {
|
|
186 return GC_build_fl2(h, list);
|
|
187 }
|
|
188 case 3: if (clear) {
|
|
189 return GC_build_fl_clear3(h, list);
|
|
190 } else {
|
|
191 /* It's messy to do better than the default here. */
|
|
192 break;
|
|
193 }
|
|
194 case 4: if (clear) {
|
|
195 return GC_build_fl_clear4(h, list);
|
|
196 } else {
|
|
197 return GC_build_fl4(h, list);
|
|
198 }
|
|
199 default:
|
|
200 break;
|
|
201 }
|
|
202 # endif /* !SMALL_CONFIG */
|
|
203
|
|
204 /* Clear the page if necessary. */
|
|
205 if (clear) BZERO(h, HBLKSIZE);
|
|
206
|
|
207 /* Add objects to free list */
|
|
208 p = &(h -> hb_body[sz]); /* second object in *h */
|
|
209 prev = &(h -> hb_body[0]); /* One object behind p */
|
|
210 last_object = (word *)((char *)h + HBLKSIZE);
|
|
211 last_object -= sz;
|
|
212 /* Last place for last object to start */
|
|
213
|
|
214 /* make a list of all objects in *h with head as last object */
|
|
215 while (p <= last_object) {
|
|
216 /* current object's link points to last object */
|
|
217 obj_link(p) = (ptr_t)prev;
|
|
218 prev = p;
|
|
219 p += sz;
|
|
220 }
|
|
221 p -= sz; /* p now points to last object */
|
|
222
|
|
223 /*
|
|
224 * put p (which is now head of list of objects in *h) as first
|
|
225 * pointer in the appropriate free list for this size.
|
|
226 */
|
|
227 obj_link(h -> hb_body) = list;
|
|
228 return ((ptr_t)p);
|
|
229 }
|
|
230
|
|
231 /*
|
|
232 * Allocate a new heapblock for small objects of size n.
|
|
233 * Add all of the heapblock's objects to the free list for objects
|
|
234 * of that size.
|
|
235 * Set all mark bits if objects are uncollectable.
|
|
236 * Will fail to do anything if we are out of memory.
|
|
237 */
|
|
238 void GC_new_hblk(sz, kind)
|
|
239 register word sz;
|
|
240 int kind;
|
|
241 {
|
|
242 register struct hblk *h; /* the new heap block */
|
|
243 register GC_bool clear = GC_obj_kinds[kind].ok_init;
|
|
244
|
|
245 # ifdef PRINTSTATS
|
|
246 if ((sizeof (struct hblk)) > HBLKSIZE) {
|
|
247 ABORT("HBLK SZ inconsistency");
|
|
248 }
|
|
249 # endif
|
|
250 if (GC_debugging_started) clear = TRUE;
|
|
251
|
|
252 /* Allocate a new heap block */
|
|
253 h = GC_allochblk(sz, kind, 0);
|
|
254 if (h == 0) return;
|
|
255
|
|
256 /* Mark all objects if appropriate. */
|
|
257 if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
|
|
258
|
|
259 /* Build the free list */
|
|
260 GC_obj_kinds[kind].ok_freelist[sz] =
|
|
261 GC_build_fl(h, sz, clear, GC_obj_kinds[kind].ok_freelist[sz]);
|
|
262 }
|
|
263
|