51488
|
1 /*
|
|
2 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
|
|
3 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
|
|
4 *
|
|
5 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
6 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
7 *
|
|
8 * Permission is hereby granted to use or copy this program
|
|
9 * for any purpose, provided the above notices are retained on all copies.
|
|
10 * Permission to modify the code and to distribute modified code is granted,
|
|
11 * provided the above notices are retained, and a notice that the code was
|
|
12 * modified is included with the above copyright notice.
|
|
13 *
|
|
14 */
|
|
15 /* Boehm, July 31, 1995 5:02 pm PDT */
|
|
16
|
|
17 #ifdef GC_GCJ_SUPPORT
|
|
18
|
|
19 /*
|
|
20 * This is an allocator interface tuned for gcj (the GNU static
|
|
21 * java compiler).
|
|
22 *
|
|
23 * Each allocated object has a pointer in its first word to a vtable,
|
|
24 * which for our purposes is simply a structure describing the type of
|
|
25 * the object.
|
|
26 * This descriptor structure contains a GC marking descriptor at offset
|
|
27 * MARK_DESCR_OFFSET.
|
|
28 *
|
|
29 * It is hoped that this interface may also be useful for other systems,
|
|
30 * possibly with some tuning of the constants. But the immediate goal
|
|
31 * is to get better gcj performance.
|
|
32 *
|
|
33 * We assume:
|
|
34 * 1) We have an ANSI conforming C compiler.
|
|
35 * 2) Counting on explicit initialization of this interface is OK.
|
|
36 * 3) FASTLOCK is not a significant win.
|
|
37 */
|
|
38
|
|
39 #include "private/gc_pmark.h"
|
|
40 #include "gc_gcj.h"
|
|
41 #include "private/dbg_mlc.h"
|
|
42
|
|
43 GC_bool GC_gcj_malloc_initialized = FALSE;
|
|
44
|
|
45 int GC_gcj_kind; /* Object kind for objects with descriptors */
|
|
46 /* in "vtable". */
|
|
47 int GC_gcj_debug_kind; /* The kind of objects that is always marked */
|
|
48 /* with a mark proc call. */
|
|
49
|
|
50 ptr_t * GC_gcjobjfreelist;
|
|
51 ptr_t * GC_gcjdebugobjfreelist;
|
|
52
|
|
53 /* Caller does not hold allocation lock. */
|
|
54 void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
|
|
55 {
|
|
56 register int i;
|
|
57 GC_bool ignore_gcj_info;
|
|
58 DCL_LOCK_STATE;
|
|
59
|
|
60 GC_init(); /* In case it's not already done. */
|
|
61 DISABLE_SIGNALS();
|
|
62 LOCK();
|
|
63 if (GC_gcj_malloc_initialized) {
|
|
64 UNLOCK();
|
|
65 ENABLE_SIGNALS();
|
|
66 return;
|
|
67 }
|
|
68 GC_gcj_malloc_initialized = TRUE;
|
|
69 ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
|
|
70 # ifdef CONDPRINT
|
|
71 if (GC_print_stats && ignore_gcj_info) {
|
|
72 GC_printf0("Gcj-style type information is disabled!\n");
|
|
73 }
|
|
74 # endif
|
|
75 GC_mark_procs[mp_index] = (GC_mark_proc)mp;
|
|
76 if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
|
|
77 /* Set up object kind gcj-style indirect descriptor. */
|
|
78 GC_gcjobjfreelist = (ptr_t *)
|
|
79 GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
|
|
80 if (GC_gcjobjfreelist == 0) ABORT("Couldn't allocate GC_gcjobjfreelist");
|
|
81 BZERO(GC_gcjobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
|
|
82 GC_gcj_kind = GC_n_kinds++;
|
|
83 GC_obj_kinds[GC_gcj_kind].ok_freelist = GC_gcjobjfreelist;
|
|
84 GC_obj_kinds[GC_gcj_kind].ok_reclaim_list = 0;
|
|
85 if (ignore_gcj_info) {
|
|
86 /* Use a simple length-based descriptor, thus forcing a fully */
|
|
87 /* conservative scan. */
|
|
88 GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
|
|
89 GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
|
|
90 } else {
|
|
91 GC_obj_kinds[GC_gcj_kind].ok_descriptor =
|
|
92 (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
|
|
93 | GC_DS_PER_OBJECT);
|
|
94 GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = FALSE;
|
|
95 }
|
|
96 GC_obj_kinds[GC_gcj_kind].ok_init = TRUE;
|
|
97 /* Set up object kind for objects that require mark proc call. */
|
|
98 GC_gcjdebugobjfreelist = (ptr_t *)
|
|
99 GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
|
|
100 if (GC_gcjdebugobjfreelist == 0)
|
|
101 ABORT("Couldn't allocate GC_gcjdebugobjfreelist");
|
|
102 BZERO(GC_gcjdebugobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t));
|
|
103 GC_gcj_debug_kind = GC_n_kinds++;
|
|
104 GC_obj_kinds[GC_gcj_debug_kind].ok_freelist = GC_gcjdebugobjfreelist;
|
|
105 GC_obj_kinds[GC_gcj_debug_kind].ok_reclaim_list = 0;
|
|
106 if (ignore_gcj_info) {
|
|
107 GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
|
|
108 GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
|
|
109 } else {
|
|
110 GC_obj_kinds[GC_gcj_debug_kind].ok_descriptor =
|
|
111 GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */);
|
|
112 GC_obj_kinds[GC_gcj_debug_kind].ok_relocate_descr = FALSE;
|
|
113 }
|
|
114 GC_obj_kinds[GC_gcj_debug_kind].ok_init = TRUE;
|
|
115 UNLOCK();
|
|
116 ENABLE_SIGNALS();
|
|
117 }
|
|
118
|
|
119 ptr_t GC_clear_stack();
|
|
120
|
|
121 #define GENERAL_MALLOC(lb,k) \
|
|
122 (GC_PTR)GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
|
|
123
|
|
124 #define GENERAL_MALLOC_IOP(lb,k) \
|
|
125 (GC_PTR)GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
|
|
126
|
|
127 /* Allocate an object, clear it, and store the pointer to the */
|
|
128 /* type structure (vtable in gcj). */
|
|
129 /* This adds a byte at the end of the object if GC_malloc would.*/
|
|
130 void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
|
|
131 {
|
|
132 register ptr_t op;
|
|
133 register ptr_t * opp;
|
|
134 register word lw;
|
|
135 DCL_LOCK_STATE;
|
|
136
|
|
137 if( EXPECT(SMALL_OBJ(lb), 1) ) {
|
|
138 # ifdef MERGE_SIZES
|
|
139 lw = GC_size_map[lb];
|
|
140 # else
|
|
141 lw = ALIGNED_WORDS(lb);
|
|
142 # endif
|
|
143 opp = &(GC_gcjobjfreelist[lw]);
|
|
144 LOCK();
|
|
145 op = *opp;
|
|
146 if( EXPECT(op == 0, 0)) {
|
|
147 op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
|
|
148 if (0 == op) {
|
|
149 UNLOCK();
|
|
150 return(GC_oom_fn(lb));
|
|
151 }
|
|
152 # ifdef MERGE_SIZES
|
|
153 lw = GC_size_map[lb]; /* May have been uninitialized. */
|
|
154 # endif
|
|
155 } else {
|
|
156 *opp = obj_link(op);
|
|
157 GC_words_allocd += lw;
|
|
158 }
|
|
159 *(void **)op = ptr_to_struct_containing_descr;
|
|
160 GC_ASSERT(((void **)op)[1] == 0);
|
|
161 UNLOCK();
|
|
162 } else {
|
|
163 LOCK();
|
|
164 op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
|
|
165 if (0 == op) {
|
|
166 UNLOCK();
|
|
167 return(GC_oom_fn(lb));
|
|
168 }
|
|
169 *(void **)op = ptr_to_struct_containing_descr;
|
|
170 UNLOCK();
|
|
171 }
|
|
172 return((GC_PTR) op);
|
|
173 }
|
|
174
|
|
175 /* Similar to GC_gcj_malloc, but add debug info. This is allocated */
|
|
176 /* with GC_gcj_debug_kind. */
|
|
177 GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
|
|
178 GC_EXTRA_PARAMS)
|
|
179 {
|
|
180 GC_PTR result;
|
|
181
|
|
182 /* We clone the code from GC_debug_gcj_malloc, so that we */
|
|
183 /* dont end up with extra frames on the stack, which could */
|
|
184 /* confuse the backtrace. */
|
|
185 LOCK();
|
|
186 result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
|
|
187 if (result == 0) {
|
|
188 UNLOCK();
|
|
189 GC_err_printf2("GC_debug_gcj_malloc(%ld, 0x%lx) returning NIL (",
|
|
190 (unsigned long) lb,
|
|
191 (unsigned long) ptr_to_struct_containing_descr);
|
|
192 GC_err_puts(s);
|
|
193 GC_err_printf1(":%ld)\n", (unsigned long)i);
|
|
194 return(GC_oom_fn(lb));
|
|
195 }
|
|
196 *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
|
|
197 UNLOCK();
|
|
198 if (!GC_debugging_started) {
|
|
199 GC_start_debugging();
|
|
200 }
|
|
201 ADD_CALL_CHAIN(result, ra);
|
|
202 return (GC_store_debug_info(result, (word)lb, s, (word)i));
|
|
203 }
|
|
204
|
|
205 /* Similar to GC_gcj_malloc, but the size is in words, and we don't */
|
|
206 /* adjust it. The size is assumed to be such that it can be */
|
|
207 /* allocated as a small object. */
|
|
208 void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
|
|
209 {
|
|
210 ptr_t op;
|
|
211 ptr_t * opp;
|
|
212 DCL_LOCK_STATE;
|
|
213
|
|
214 opp = &(GC_gcjobjfreelist[lw]);
|
|
215 LOCK();
|
|
216 op = *opp;
|
|
217 if( EXPECT(op == 0, 0) ) {
|
|
218 op = (ptr_t)GC_clear_stack(
|
|
219 GC_generic_malloc_words_small_inner(lw, GC_gcj_kind));
|
|
220 if (0 == op) {
|
|
221 UNLOCK();
|
|
222 return GC_oom_fn(WORDS_TO_BYTES(lw));
|
|
223 }
|
|
224 } else {
|
|
225 *opp = obj_link(op);
|
|
226 GC_words_allocd += lw;
|
|
227 }
|
|
228 *(void **)op = ptr_to_struct_containing_descr;
|
|
229 UNLOCK();
|
|
230 return((GC_PTR) op);
|
|
231 }
|
|
232
|
|
233 /* And a debugging version of the above: */
|
|
234 void * GC_debug_gcj_fast_malloc(size_t lw,
|
|
235 void * ptr_to_struct_containing_descr,
|
|
236 GC_EXTRA_PARAMS)
|
|
237 {
|
|
238 GC_PTR result;
|
|
239 size_t lb = WORDS_TO_BYTES(lw);
|
|
240
|
|
241 /* We clone the code from GC_debug_gcj_malloc, so that we */
|
|
242 /* dont end up with extra frames on the stack, which could */
|
|
243 /* confuse the backtrace. */
|
|
244 LOCK();
|
|
245 result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
|
|
246 if (result == 0) {
|
|
247 UNLOCK();
|
|
248 GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (",
|
|
249 (unsigned long) lw,
|
|
250 (unsigned long) ptr_to_struct_containing_descr);
|
|
251 GC_err_puts(s);
|
|
252 GC_err_printf1(":%ld)\n", (unsigned long)i);
|
|
253 return GC_oom_fn(WORDS_TO_BYTES(lw));
|
|
254 }
|
|
255 *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
|
|
256 UNLOCK();
|
|
257 if (!GC_debugging_started) {
|
|
258 GC_start_debugging();
|
|
259 }
|
|
260 ADD_CALL_CHAIN(result, ra);
|
|
261 return (GC_store_debug_info(result, (word)lb, s, (word)i));
|
|
262 }
|
|
263
|
|
264 void * GC_gcj_malloc_ignore_off_page(size_t lb,
|
|
265 void * ptr_to_struct_containing_descr)
|
|
266 {
|
|
267 register ptr_t op;
|
|
268 register ptr_t * opp;
|
|
269 register word lw;
|
|
270 DCL_LOCK_STATE;
|
|
271
|
|
272 if( SMALL_OBJ(lb) ) {
|
|
273 # ifdef MERGE_SIZES
|
|
274 lw = GC_size_map[lb];
|
|
275 # else
|
|
276 lw = ALIGNED_WORDS(lb);
|
|
277 # endif
|
|
278 opp = &(GC_gcjobjfreelist[lw]);
|
|
279 LOCK();
|
|
280 if( (op = *opp) == 0 ) {
|
|
281 op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
|
|
282 # ifdef MERGE_SIZES
|
|
283 lw = GC_size_map[lb]; /* May have been uninitialized. */
|
|
284 # endif
|
|
285 } else {
|
|
286 *opp = obj_link(op);
|
|
287 GC_words_allocd += lw;
|
|
288 }
|
|
289 *(void **)op = ptr_to_struct_containing_descr;
|
|
290 UNLOCK();
|
|
291 } else {
|
|
292 op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
|
|
293 if (0 != op) {
|
|
294 *(void **)op = ptr_to_struct_containing_descr;
|
|
295 }
|
|
296 UNLOCK();
|
|
297 }
|
|
298 return((GC_PTR) op);
|
|
299 }
|
|
300
|
|
301 #else
|
|
302
|
|
303 char GC_no_gcj_support;
|
|
304
|
|
305 #endif /* GC_GCJ_SUPPORT */
|