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 |
|
---|