]>
Commit | Line | Data |
---|---|---|
0eebf9e5 BM |
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 | /* | |
9110a741 | 20 | * This is an allocator interface tuned for gcj (the GNU static |
0eebf9e5 BM |
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. | |
9110a741 | 26 | * This descriptor structure contains a GC marking descriptor at offset |
0eebf9e5 BM |
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 | ||
9110a741 BM |
39 | #include "private/gc_pmark.h" |
40 | #include "gc_gcj.h" | |
41 | #include "private/dbg_mlc.h" | |
0eebf9e5 BM |
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 | ||
0eebf9e5 | 53 | /* Caller does not hold allocation lock. */ |
9110a741 | 54 | void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp) |
0eebf9e5 BM |
55 | { |
56 | register int i; | |
79f777fd | 57 | GC_bool ignore_gcj_info; |
0eebf9e5 BM |
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; | |
79f777fd BM |
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 | |
9110a741 | 75 | GC_mark_procs[mp_index] = (GC_mark_proc)mp; |
0eebf9e5 BM |
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 *) | |
9110a741 | 79 | GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE); |
0eebf9e5 BM |
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; | |
79f777fd BM |
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 | } | |
0eebf9e5 BM |
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 *) | |
9110a741 | 99 | GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE); |
0eebf9e5 BM |
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; | |
79f777fd BM |
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 | } | |
0eebf9e5 BM |
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 | ||
9110a741 | 137 | if( EXPECT(SMALL_OBJ(lb), 1) ) { |
0eebf9e5 BM |
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(); | |
9110a741 BM |
145 | op = *opp; |
146 | if( EXPECT(op == 0, 0)) { | |
0eebf9e5 BM |
147 | op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind); |
148 | if (0 == op) { | |
149 | UNLOCK(); | |
9110a741 | 150 | return(GC_oom_fn(lb)); |
0eebf9e5 BM |
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; | |
0eebf9e5 BM |
158 | } |
159 | *(void **)op = ptr_to_struct_containing_descr; | |
30c3de1f | 160 | GC_ASSERT(((void **)op)[1] == 0); |
0eebf9e5 BM |
161 | UNLOCK(); |
162 | } else { | |
163 | LOCK(); | |
164 | op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind); | |
165 | if (0 == op) { | |
166 | UNLOCK(); | |
9110a741 | 167 | return(GC_oom_fn(lb)); |
0eebf9e5 BM |
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); | |
9110a741 | 194 | return(GC_oom_fn(lb)); |
0eebf9e5 BM |
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(); | |
9110a741 BM |
216 | op = *opp; |
217 | if( EXPECT(op == 0, 0) ) { | |
0eebf9e5 BM |
218 | op = (ptr_t)GC_clear_stack( |
219 | GC_generic_malloc_words_small_inner(lw, GC_gcj_kind)); | |
220 | if (0 == op) { | |
221 | UNLOCK(); | |
9110a741 | 222 | return GC_oom_fn(WORDS_TO_BYTES(lw)); |
0eebf9e5 BM |
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); | |
9110a741 | 253 | return GC_oom_fn(WORDS_TO_BYTES(lw)); |
0eebf9e5 BM |
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; | |
0eebf9e5 BM |
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 | ||
179977c1 BM |
301 | #else |
302 | ||
303 | char GC_no_gcj_support; | |
304 | ||
0eebf9e5 | 305 | #endif /* GC_GCJ_SUPPORT */ |