Line data Source code
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. */
30 332 : STATIC ptr_t GC_build_fl_clear2(struct hblk *h, ptr_t ofl)
31 : {
32 332 : word * p = (word *)(h -> hb_body);
33 332 : word * lim = (word *)(h + 1);
34 :
35 332 : p[0] = (word)ofl;
36 332 : p[1] = 0;
37 332 : p[2] = (word)p;
38 332 : p[3] = 0;
39 332 : p += 4;
40 42496 : for (; p < lim; p += 4) {
41 42164 : p[0] = (word)(p-2);
42 42164 : p[1] = 0;
43 42164 : p[2] = (word)p;
44 42164 : p[3] = 0;
45 : };
46 332 : return((ptr_t)(p-2));
47 : }
48 :
49 : /* The same for size 4 cleared objects. */
50 913 : STATIC ptr_t GC_build_fl_clear4(struct hblk *h, ptr_t ofl)
51 : {
52 913 : word * p = (word *)(h -> hb_body);
53 913 : word * lim = (word *)(h + 1);
54 :
55 913 : p[0] = (word)ofl;
56 913 : p[1] = 0;
57 913 : p[2] = 0;
58 913 : p[3] = 0;
59 913 : p += 4;
60 116864 : for (; p < lim; p += 4) {
61 115951 : PREFETCH_FOR_WRITE((ptr_t)(p+64));
62 115951 : p[0] = (word)(p-4);
63 115951 : p[1] = 0;
64 115951 : CLEAR_DOUBLE(p+2);
65 : };
66 913 : return((ptr_t)(p-4));
67 : }
68 :
69 : /* The same for size 2 uncleared objects. */
70 242 : STATIC ptr_t GC_build_fl2(struct hblk *h, ptr_t ofl)
71 : {
72 242 : word * p = (word *)(h -> hb_body);
73 242 : word * lim = (word *)(h + 1);
74 :
75 242 : p[0] = (word)ofl;
76 242 : p[2] = (word)p;
77 242 : p += 4;
78 30976 : for (; p < lim; p += 4) {
79 30734 : p[0] = (word)(p-2);
80 30734 : p[2] = (word)p;
81 : };
82 242 : return((ptr_t)(p-2));
83 : }
84 :
85 : /* The same for size 4 uncleared objects. */
86 2819 : STATIC ptr_t GC_build_fl4(struct hblk *h, ptr_t ofl)
87 : {
88 2819 : word * p = (word *)(h -> hb_body);
89 2819 : word * lim = (word *)(h + 1);
90 :
91 2819 : p[0] = (word)ofl;
92 2819 : p[4] = (word)p;
93 2819 : p += 8;
94 180416 : for (; p < lim; p += 8) {
95 177597 : PREFETCH_FOR_WRITE((ptr_t)(p+64));
96 177597 : p[0] = (word)(p-4);
97 177597 : p[4] = (word)p;
98 : };
99 2819 : 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. */
109 50091 : 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 50091 : PREFETCH_FOR_WRITE((ptr_t)h);
120 50091 : PREFETCH_FOR_WRITE((ptr_t)h + 128);
121 50091 : PREFETCH_FOR_WRITE((ptr_t)h + 256);
122 50091 : 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 50091 : switch (sz) {
127 574 : case 2: if (clear) {
128 332 : return GC_build_fl_clear2(h, list);
129 : } else {
130 242 : return GC_build_fl2(h, list);
131 : }
132 3732 : case 4: if (clear) {
133 913 : return GC_build_fl_clear4(h, list);
134 : } else {
135 2819 : return GC_build_fl4(h, list);
136 : }
137 : default:
138 : break;
139 : }
140 : # endif /* !SMALL_CONFIG */
141 :
142 : /* Clear the page if necessary. */
143 45785 : if (clear) BZERO(h, HBLKSIZE);
144 :
145 : /* Add objects to free list */
146 45785 : p = (word *)(h -> hb_body) + sz; /* second object in *h */
147 45785 : prev = (word *)(h -> hb_body); /* One object behind p */
148 45785 : last_object = (word *)((char *)h + HBLKSIZE);
149 45785 : 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 1561774 : while (p <= last_object) {
154 : /* current object's link points to last object */
155 1470204 : obj_link(p) = (ptr_t)prev;
156 1470204 : prev = p;
157 1470204 : p += sz;
158 : }
159 45785 : p -= sz; /* p now points to last object */
160 :
161 : /* Put p (which is now head of list of objects in *h) as first */
162 : /* pointer in the appropriate free list for this size. */
163 45785 : *(ptr_t *)h = list;
164 45785 : return ((ptr_t)p);
165 : }
166 :
167 : /*
168 : * Allocate a new heapblock for small objects of size gran granules.
169 : * Add all of the heapblock's objects to the free list for objects
170 : * of that size.
171 : * Set all mark bits if objects are uncollectable.
172 : * Will fail to do anything if we are out of memory.
173 : */
174 16613 : GC_INNER void GC_new_hblk(size_t gran, int kind)
175 : {
176 : struct hblk *h; /* the new heap block */
177 16613 : GC_bool clear = GC_obj_kinds[kind].ok_init;
178 :
179 : GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE);
180 :
181 16613 : if (GC_debugging_started) clear = TRUE;
182 :
183 : /* Allocate a new heap block */
184 16613 : h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0);
185 16613 : if (h == 0) return;
186 :
187 : /* Mark all objects if appropriate. */
188 16548 : if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
189 :
190 : /* Build the free list */
191 33096 : GC_obj_kinds[kind].ok_freelist[gran] =
192 16548 : GC_build_fl(h, GRANULES_TO_WORDS(gran), clear,
193 16548 : GC_obj_kinds[kind].ok_freelist[gran]);
194 : }
|