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