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