]>
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 | /* | |
20 | * This is an allocator interface tuned for gcj (the GNU/Cygnus 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 structur 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 "gc_priv.h" | |
40 | #include "gc_mark.h" | |
41 | #include "include/gc_gcj.h" | |
42 | #include "dbg_mlc.h" | |
43 | ||
44 | GC_bool GC_gcj_malloc_initialized = FALSE; | |
45 | ||
46 | int GC_gcj_kind; /* Object kind for objects with descriptors */ | |
47 | /* in "vtable". */ | |
48 | int GC_gcj_debug_kind; /* The kind of objects that is always marked */ | |
49 | /* with a mark proc call. */ | |
50 | ||
51 | ptr_t * GC_gcjobjfreelist; | |
52 | ptr_t * GC_gcjdebugobjfreelist; | |
53 | ||
54 | void * GC_default_oom_action(void) { return 0; } | |
55 | ||
56 | void * (*GC_oom_action)(void) = GC_default_oom_action; | |
57 | ||
58 | /* Caller does not hold allocation lock. */ | |
59 | void GC_init_gcj_malloc(int mp_index, void * /* really mark_proc */mp) | |
60 | { | |
61 | register int i; | |
62 | DCL_LOCK_STATE; | |
63 | ||
64 | GC_init(); /* In case it's not already done. */ | |
65 | DISABLE_SIGNALS(); | |
66 | LOCK(); | |
67 | if (GC_gcj_malloc_initialized) { | |
68 | UNLOCK(); | |
69 | ENABLE_SIGNALS(); | |
70 | return; | |
71 | } | |
72 | GC_gcj_malloc_initialized = TRUE; | |
73 | GC_mark_procs[mp_index] = (mark_proc)mp; | |
74 | if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index"); | |
75 | /* Set up object kind gcj-style indirect descriptor. */ | |
76 | GC_gcjobjfreelist = (ptr_t *) | |
77 | GC_generic_malloc_inner((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE); | |
78 | if (GC_gcjobjfreelist == 0) ABORT("Couldn't allocate GC_gcjobjfreelist"); | |
79 | BZERO(GC_gcjobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t)); | |
80 | GC_gcj_kind = GC_n_kinds++; | |
81 | GC_obj_kinds[GC_gcj_kind].ok_freelist = GC_gcjobjfreelist; | |
82 | GC_obj_kinds[GC_gcj_kind].ok_reclaim_list = 0; | |
83 | GC_obj_kinds[GC_gcj_kind].ok_descriptor = | |
84 | (((word)(-MARK_DESCR_OFFSET - INDIR_PER_OBJ_BIAS)) | DS_PER_OBJECT); | |
85 | GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = FALSE; | |
86 | GC_obj_kinds[GC_gcj_kind].ok_init = TRUE; | |
87 | /* Set up object kind for objects that require mark proc call. */ | |
88 | GC_gcjdebugobjfreelist = (ptr_t *) | |
89 | GC_generic_malloc_inner((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE); | |
90 | if (GC_gcjdebugobjfreelist == 0) | |
91 | ABORT("Couldn't allocate GC_gcjdebugobjfreelist"); | |
92 | BZERO(GC_gcjdebugobjfreelist, (MAXOBJSZ+1)*sizeof(ptr_t)); | |
93 | GC_gcj_debug_kind = GC_n_kinds++; | |
94 | GC_obj_kinds[GC_gcj_debug_kind].ok_freelist = GC_gcjdebugobjfreelist; | |
95 | GC_obj_kinds[GC_gcj_debug_kind].ok_reclaim_list = 0; | |
96 | GC_obj_kinds[GC_gcj_debug_kind].ok_descriptor = | |
97 | MAKE_PROC(mp_index, 1 /* allocated with debug info */); | |
98 | GC_obj_kinds[GC_gcj_debug_kind].ok_relocate_descr = FALSE; | |
99 | GC_obj_kinds[GC_gcj_debug_kind].ok_init = TRUE; | |
100 | UNLOCK(); | |
101 | ENABLE_SIGNALS(); | |
102 | } | |
103 | ||
104 | ptr_t GC_clear_stack(); | |
105 | ||
106 | #define GENERAL_MALLOC(lb,k) \ | |
107 | (GC_PTR)GC_clear_stack(GC_generic_malloc_inner((word)lb, k)) | |
108 | ||
109 | #define GENERAL_MALLOC_IOP(lb,k) \ | |
110 | (GC_PTR)GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k)) | |
111 | ||
112 | /* Allocate an object, clear it, and store the pointer to the */ | |
113 | /* type structure (vtable in gcj). */ | |
114 | /* This adds a byte at the end of the object if GC_malloc would.*/ | |
115 | void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr) | |
116 | { | |
117 | register ptr_t op; | |
118 | register ptr_t * opp; | |
119 | register word lw; | |
120 | DCL_LOCK_STATE; | |
121 | ||
122 | if( SMALL_OBJ(lb) ) { | |
123 | # ifdef MERGE_SIZES | |
124 | lw = GC_size_map[lb]; | |
125 | # else | |
126 | lw = ALIGNED_WORDS(lb); | |
127 | # endif | |
128 | opp = &(GC_gcjobjfreelist[lw]); | |
129 | LOCK(); | |
130 | if( (op = *opp) == 0 ) { | |
131 | op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind); | |
132 | if (0 == op) { | |
133 | UNLOCK(); | |
134 | return(GC_oom_action()); | |
135 | } | |
136 | # ifdef MERGE_SIZES | |
137 | lw = GC_size_map[lb]; /* May have been uninitialized. */ | |
138 | # endif | |
139 | } else { | |
140 | *opp = obj_link(op); | |
141 | GC_words_allocd += lw; | |
142 | FASTUNLOCK(); | |
143 | } | |
144 | *(void **)op = ptr_to_struct_containing_descr; | |
145 | UNLOCK(); | |
146 | } else { | |
147 | LOCK(); | |
148 | op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind); | |
149 | if (0 == op) { | |
150 | UNLOCK(); | |
151 | return(GC_oom_action()); | |
152 | } | |
153 | *(void **)op = ptr_to_struct_containing_descr; | |
154 | UNLOCK(); | |
155 | } | |
156 | return((GC_PTR) op); | |
157 | } | |
158 | ||
159 | /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ | |
160 | /* with GC_gcj_debug_kind. */ | |
161 | GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr, | |
162 | GC_EXTRA_PARAMS) | |
163 | { | |
164 | GC_PTR result; | |
165 | ||
166 | /* We clone the code from GC_debug_gcj_malloc, so that we */ | |
167 | /* dont end up with extra frames on the stack, which could */ | |
168 | /* confuse the backtrace. */ | |
169 | LOCK(); | |
170 | result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind); | |
171 | if (result == 0) { | |
172 | UNLOCK(); | |
173 | GC_err_printf2("GC_debug_gcj_malloc(%ld, 0x%lx) returning NIL (", | |
174 | (unsigned long) lb, | |
175 | (unsigned long) ptr_to_struct_containing_descr); | |
176 | GC_err_puts(s); | |
177 | GC_err_printf1(":%ld)\n", (unsigned long)i); | |
178 | return(GC_oom_action()); | |
179 | } | |
180 | *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr; | |
181 | UNLOCK(); | |
182 | if (!GC_debugging_started) { | |
183 | GC_start_debugging(); | |
184 | } | |
185 | ADD_CALL_CHAIN(result, ra); | |
186 | return (GC_store_debug_info(result, (word)lb, s, (word)i)); | |
187 | } | |
188 | ||
189 | /* Similar to GC_gcj_malloc, but the size is in words, and we don't */ | |
190 | /* adjust it. The size is assumed to be such that it can be */ | |
191 | /* allocated as a small object. */ | |
192 | void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr) | |
193 | { | |
194 | ptr_t op; | |
195 | ptr_t * opp; | |
196 | DCL_LOCK_STATE; | |
197 | ||
198 | opp = &(GC_gcjobjfreelist[lw]); | |
199 | LOCK(); | |
200 | if( (op = *opp) == 0 ) { | |
201 | op = (ptr_t)GC_clear_stack( | |
202 | GC_generic_malloc_words_small_inner(lw, GC_gcj_kind)); | |
203 | if (0 == op) { | |
204 | UNLOCK(); | |
205 | return(GC_oom_action()); | |
206 | } | |
207 | } else { | |
208 | *opp = obj_link(op); | |
209 | GC_words_allocd += lw; | |
210 | } | |
211 | *(void **)op = ptr_to_struct_containing_descr; | |
212 | UNLOCK(); | |
213 | return((GC_PTR) op); | |
214 | } | |
215 | ||
216 | /* And a debugging version of the above: */ | |
217 | void * GC_debug_gcj_fast_malloc(size_t lw, | |
218 | void * ptr_to_struct_containing_descr, | |
219 | GC_EXTRA_PARAMS) | |
220 | { | |
221 | GC_PTR result; | |
222 | size_t lb = WORDS_TO_BYTES(lw); | |
223 | ||
224 | /* We clone the code from GC_debug_gcj_malloc, so that we */ | |
225 | /* dont end up with extra frames on the stack, which could */ | |
226 | /* confuse the backtrace. */ | |
227 | LOCK(); | |
228 | result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind); | |
229 | if (result == 0) { | |
230 | UNLOCK(); | |
231 | GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (", | |
232 | (unsigned long) lw, | |
233 | (unsigned long) ptr_to_struct_containing_descr); | |
234 | GC_err_puts(s); | |
235 | GC_err_printf1(":%ld)\n", (unsigned long)i); | |
236 | return(GC_oom_action()); | |
237 | } | |
238 | *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr; | |
239 | UNLOCK(); | |
240 | if (!GC_debugging_started) { | |
241 | GC_start_debugging(); | |
242 | } | |
243 | ADD_CALL_CHAIN(result, ra); | |
244 | return (GC_store_debug_info(result, (word)lb, s, (word)i)); | |
245 | } | |
246 | ||
247 | void * GC_gcj_malloc_ignore_off_page(size_t lb, | |
248 | void * ptr_to_struct_containing_descr) | |
249 | { | |
250 | register ptr_t op; | |
251 | register ptr_t * opp; | |
252 | register word lw; | |
253 | DCL_LOCK_STATE; | |
254 | ||
255 | if( SMALL_OBJ(lb) ) { | |
256 | # ifdef MERGE_SIZES | |
257 | lw = GC_size_map[lb]; | |
258 | # else | |
259 | lw = ALIGNED_WORDS(lb); | |
260 | # endif | |
261 | opp = &(GC_gcjobjfreelist[lw]); | |
262 | LOCK(); | |
263 | if( (op = *opp) == 0 ) { | |
264 | op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind); | |
265 | # ifdef MERGE_SIZES | |
266 | lw = GC_size_map[lb]; /* May have been uninitialized. */ | |
267 | # endif | |
268 | } else { | |
269 | *opp = obj_link(op); | |
270 | GC_words_allocd += lw; | |
271 | FASTUNLOCK(); | |
272 | } | |
273 | *(void **)op = ptr_to_struct_containing_descr; | |
274 | UNLOCK(); | |
275 | } else { | |
276 | op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind); | |
277 | if (0 != op) { | |
278 | *(void **)op = ptr_to_struct_containing_descr; | |
279 | } | |
280 | UNLOCK(); | |
281 | } | |
282 | return((GC_PTR) op); | |
283 | } | |
284 | ||
179977c1 BM |
285 | #else |
286 | ||
287 | char GC_no_gcj_support; | |
288 | ||
0eebf9e5 | 289 | #endif /* GC_GCJ_SUPPORT */ |