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