]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(size) | |
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 2 (words) cleared objects inside hblk h. | |
28 | * Set the last link to | |
29 | * be ofl. Return a pointer tpo the first free list entry. | |
30 | */ | |
31 | ptr_t GC_build_fl_clear2(struct hblk *h, ptr_t ofl) | |
32 | { | |
33 | word * p = (word *)(h -> hb_body); | |
34 | word * lim = (word *)(h + 1); | |
35 | ||
36 | p[0] = (word)ofl; | |
37 | p[1] = 0; | |
38 | p[2] = (word)p; | |
39 | p[3] = 0; | |
40 | p += 4; | |
41 | for (; p < lim; p += 4) { | |
42 | p[0] = (word)(p-2); | |
43 | p[1] = 0; | |
44 | p[2] = (word)p; | |
45 | p[3] = 0; | |
46 | }; | |
47 | return((ptr_t)(p-2)); | |
48 | } | |
49 | ||
50 | /* The same for size 4 cleared objects */ | |
51 | ptr_t GC_build_fl_clear4(struct hblk *h, ptr_t ofl) | |
52 | { | |
53 | word * p = (word *)(h -> hb_body); | |
54 | word * lim = (word *)(h + 1); | |
55 | ||
56 | p[0] = (word)ofl; | |
57 | p[1] = 0; | |
58 | p[2] = 0; | |
59 | p[3] = 0; | |
60 | p += 4; | |
61 | for (; p < lim; p += 4) { | |
62 | PREFETCH_FOR_WRITE((ptr_t)(p+64)); | |
63 | p[0] = (word)(p-4); | |
64 | p[1] = 0; | |
65 | CLEAR_DOUBLE(p+2); | |
66 | }; | |
67 | return((ptr_t)(p-4)); | |
68 | } | |
69 | ||
70 | /* The same for size 2 uncleared objects */ | |
71 | ptr_t GC_build_fl2(struct hblk *h, ptr_t ofl) | |
72 | { | |
73 | word * p = (word *)(h -> hb_body); | |
74 | word * lim = (word *)(h + 1); | |
75 | ||
76 | p[0] = (word)ofl; | |
77 | p[2] = (word)p; | |
78 | p += 4; | |
79 | for (; p < lim; p += 4) { | |
80 | p[0] = (word)(p-2); | |
81 | p[2] = (word)p; | |
82 | }; | |
83 | return((ptr_t)(p-2)); | |
84 | } | |
85 | ||
86 | /* The same for size 4 uncleared objects */ | |
87 | ptr_t GC_build_fl4(struct hblk *h, ptr_t ofl) | |
88 | { | |
89 | word * p = (word *)(h -> hb_body); | |
90 | word * lim = (word *)(h + 1); | |
91 | ||
92 | p[0] = (word)ofl; | |
93 | p[4] = (word)p; | |
94 | p += 8; | |
95 | for (; p < lim; p += 8) { | |
96 | PREFETCH_FOR_WRITE((ptr_t)(p+64)); | |
97 | p[0] = (word)(p-4); | |
98 | p[4] = (word)p; | |
99 | }; | |
100 | return((ptr_t)(p-4)); | |
101 | } | |
102 | ||
103 | #endif /* !SMALL_CONFIG */ | |
104 | ||
105 | ||
106 | /* Build a free list for objects of size sz inside heap block h. */ | |
107 | /* Clear objects inside h if clear is set. Add list to the end of */ | |
108 | /* the free list we build. Return the new free list. */ | |
109 | /* This could be called without the main GC lock, if we ensure that */ | |
110 | /* there is no concurrent collection which might reclaim objects that */ | |
111 | /* we have not yet allocated. */ | |
112 | ptr_t GC_build_fl(struct hblk *h, size_t sz, GC_bool clear, ptr_t list) | |
113 | { | |
114 | word *p, *prev; | |
115 | word *last_object; /* points to last object in new hblk */ | |
116 | ||
117 | /* Do a few prefetches here, just because its cheap. */ | |
118 | /* If we were more serious about it, these should go inside */ | |
119 | /* the loops. But write prefetches usually don't seem to */ | |
120 | /* matter much. */ | |
121 | PREFETCH_FOR_WRITE((ptr_t)h); | |
122 | PREFETCH_FOR_WRITE((ptr_t)h + 128); | |
123 | PREFETCH_FOR_WRITE((ptr_t)h + 256); | |
124 | PREFETCH_FOR_WRITE((ptr_t)h + 378); | |
125 | /* Handle small objects sizes more efficiently. For larger objects */ | |
126 | /* the difference is less significant. */ | |
127 | # ifndef SMALL_CONFIG | |
128 | switch (sz) { | |
129 | case 2: if (clear) { | |
130 | return GC_build_fl_clear2(h, list); | |
131 | } else { | |
132 | return GC_build_fl2(h, list); | |
133 | } | |
134 | case 4: if (clear) { | |
135 | return GC_build_fl_clear4(h, list); | |
136 | } else { | |
137 | return GC_build_fl4(h, list); | |
138 | } | |
139 | default: | |
140 | break; | |
141 | } | |
142 | # endif /* !SMALL_CONFIG */ | |
143 | ||
144 | /* Clear the page if necessary. */ | |
145 | if (clear) BZERO(h, HBLKSIZE); | |
146 | ||
147 | /* Add objects to free list */ | |
148 | p = (word *)(h -> hb_body) + sz; /* second object in *h */ | |
149 | prev = (word *)(h -> hb_body); /* One object behind p */ | |
150 | last_object = (word *)((char *)h + HBLKSIZE); | |
151 | last_object -= sz; | |
152 | /* Last place for last object to start */ | |
153 | ||
154 | /* make a list of all objects in *h with head as last object */ | |
155 | while (p <= last_object) { | |
156 | /* current object's link points to last object */ | |
157 | obj_link(p) = (ptr_t)prev; | |
158 | prev = p; | |
159 | p += sz; | |
160 | } | |
161 | p -= sz; /* p now points to last object */ | |
162 | ||
163 | /* | |
164 | * put p (which is now head of list of objects in *h) as first | |
165 | * pointer in the appropriate free list for this size. | |
166 | */ | |
167 | obj_link(h -> hb_body) = list; | |
168 | return ((ptr_t)p); | |
169 | } | |
170 | ||
171 | ||
172 | /* | |
173 | * Allocate a new heapblock for small objects of size gran granules. | |
174 | * Add all of the heapblock's objects to the free list for objects | |
175 | * of that size. | |
176 | * Set all mark bits if objects are uncollectable. | |
177 | * Will fail to do anything if we are out of memory. | |
178 | */ | |
179 | void GC_new_hblk(size_t gran, int kind) | |
180 | { | |
181 | struct hblk *h; /* the new heap block */ | |
182 | GC_bool clear = GC_obj_kinds[kind].ok_init; | |
183 | ||
184 | /* Ignore gcc "no effect" warning on the following: */ | |
185 | GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE); | |
186 | ||
187 | if (GC_debugging_started) clear = TRUE; | |
188 | ||
189 | /* Allocate a new heap block */ | |
190 | h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0); | |
191 | if (h == 0) return; | |
192 | ||
193 | /* Mark all objects if appropriate. */ | |
194 | if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h)); | |
195 | ||
196 | /* Build the free list */ | |
197 | GC_obj_kinds[kind].ok_freelist[gran] = | |
198 | GC_build_fl(h, GRANULES_TO_WORDS(gran), clear, | |
199 | GC_obj_kinds[kind].ok_freelist[gran]); | |
200 | } | |
201 |