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  */
GC_build_fl_clear2(struct hblk * h,ptr_t ofl)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 */
GC_build_fl_clear4(struct hblk * h,ptr_t ofl)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 */
GC_build_fl2(struct hblk * h,ptr_t ofl)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 */
GC_build_fl4(struct hblk * h,ptr_t ofl)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.						*/
GC_build_fl(struct hblk * h,size_t sz,GC_bool clear,ptr_t list)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  */
GC_new_hblk(size_t gran,int kind)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 
202