56fc1ec1ac20e7ef82259627ff8c3cc1be9688b7
[cacao.git] / src / mm / boehm.c
1 /* mm/boehm.c - interface for boehm gc
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Stefan Ring
28
29    $Id: boehm.c 1378 2004-08-01 22:34:16Z stefan $
30
31 */
32
33 #if defined(USE_THREADS) && defined(NATIVE_THREADS) && defined(__LINUX__)
34 #define GC_LINUX_THREADS
35 #endif
36 #if defined(USE_THREADS) && defined(NATIVE_THREADS) && defined(__IRIX__)
37 #define GC_IRIX_THREADS
38 #endif
39
40 #include "options.h"
41 #include "asmpart.h"
42 #include "boehm.h"
43 #include "builtin.h"
44 #include "exceptions.h"
45 #include "global.h"
46 #include "loader.h"
47 #include "native.h"
48 #include "tables.h"
49 #include "threads/thread.h"
50 #include "toolbox/logging.h"
51 #include "boehm-gc/include/gc.h"
52
53
54 static bool in_gc_out_of_memory = false;    /* is GC out of memory?           */
55
56
57 static void
58 #ifdef __GNUC__
59         __attribute__ ((unused))
60 #endif
61 *stackcall_twoargs(struct otherstackcall *p)
62 {
63         return (*p->p2)(p->p, p->l);
64 }
65
66
67 static void *stackcall_malloc(void *p, u4 bytelength)
68 {
69         return GC_MALLOC(bytelength);
70 }
71
72
73 static void *stackcall_malloc_atomic(void *p, u4 bytelength)
74 {
75         return GC_MALLOC_ATOMIC(bytelength);
76 }
77
78
79 static void *stackcall_malloc_uncollectable(void *p, u4 bytelength)
80 {
81         return GC_MALLOC_UNCOLLECTABLE(bytelength);
82 }
83
84
85 static void *stackcall_realloc(void *p, u4 bytelength)
86 {
87         return GC_REALLOC(p, bytelength);
88 }
89
90 static void *stackcall_free(void *p, u4 bytelength)
91 {
92         GC_FREE(p);
93         return NULL;
94 }
95
96
97 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
98 #define MAINTHREADCALL(r,m,pp,ll) \
99         if (currentThread == NULL || currentThread == mainThread) { \
100                 r = m(pp, ll); \
101         } else { \
102                 struct otherstackcall sc; \
103                 sc.p2 = m; \
104                 sc.p = pp; \
105                 sc.l = ll; \
106                 r = (*asm_switchstackandcall)(CONTEXT(mainThread).usedStackTop, \
107                                 stackcall_twoargs, \
108                                 (void**)&(CONTEXT(currentThread).usedStackTop), &sc); \
109         }
110 #else
111 #define MAINTHREADCALL(r,m,pp,ll) \
112         { r = m(pp, ll); }
113 #endif
114
115
116 void *heap_alloc_uncollectable(u4 bytelength)
117 {
118         void *result;
119         MAINTHREADCALL(result, stackcall_malloc_uncollectable, NULL, bytelength);
120         return result;
121 }
122
123
124 void runboehmfinalizer(void *o, void *p)
125 {
126         java_objectheader *ob = (java_objectheader *) o;
127
128         asm_calljavafunction(ob->vftbl->class->finalizer, ob, NULL, NULL, NULL);
129         
130         /* if we had an exception in the finalizer, ignore it */
131         *exceptionptr = NULL;
132 }
133
134
135 void *heap_allocate(u4 bytelength, bool references, methodinfo *finalizer)
136 {
137         void *result;
138
139         if (references) {
140                 MAINTHREADCALL(result, stackcall_malloc, NULL, bytelength);
141
142         } else {
143                 MAINTHREADCALL(result, stackcall_malloc_atomic, NULL, bytelength);
144         }
145
146         if (!result) {
147                 return NULL;
148         }
149
150         if (finalizer)
151                 GC_REGISTER_FINALIZER(result, runboehmfinalizer, 0, 0, 0);
152
153         return (u1*) result;
154 }
155
156
157 void *heap_reallocate(void *p, u4 bytelength)
158 {
159         void *result;
160
161         MAINTHREADCALL(result, stackcall_realloc, p, bytelength);
162
163         return result;
164 }
165
166 void heap_free(void *p)
167 {
168         void *result;
169
170         MAINTHREADCALL(result, stackcall_free, p, 0);
171 }
172
173 static void gc_ignore_warnings(char *msg, GC_word arg)
174 {
175 }
176
177 void gc_init(u4 heapmaxsize, u4 heapstartsize)
178 {
179         size_t heapcurrentsize;
180
181         GC_INIT();
182
183         /* set the maximal heap size */
184         GC_set_max_heap_size(heapmaxsize);
185
186         /* set the initial heap size */
187         heapcurrentsize = GC_get_heap_size();
188         if (heapstartsize > heapcurrentsize) {
189                 GC_expand_hp(heapstartsize - heapcurrentsize);
190         }
191
192         /* define OOM function */
193         GC_oom_fn = gc_out_of_memory;
194
195         /* suppress warnings */
196         GC_set_warn_proc(gc_ignore_warnings);
197 }
198
199
200 void gc_call()
201 {
202         if (collectverbose)
203                 dolog("Garbage Collection:  previous/now = %d / %d ",
204                           0, 0);
205
206         GC_gcollect();
207 }
208
209
210 s8 gc_get_heap_size()
211 {
212         return GC_get_heap_size();
213 }
214
215
216 s8 gc_get_free_bytes()
217 {
218         return GC_get_free_bytes();
219 }
220
221
222 s8 gc_get_max_heap_size()
223 {
224         return GC_get_max_heap_size();
225 }
226
227
228 void gc_invoke_finalizers()
229 {
230         GC_invoke_finalizers();
231 }
232
233
234 void gc_finalize_all()
235 {
236         GC_finalize_all();
237 }
238
239
240 /* gc_out_of_memory ************************************************************
241
242    This function is called when boehm detects that it is OOM.
243
244 *******************************************************************************/
245
246 void *gc_out_of_memory()
247 {
248         /* if this happens, we are REALLY out of memory */
249
250         if (in_gc_out_of_memory) {
251                 /* this is all we can do... */
252                 throw_cacao_exception_exit(string_java_lang_InternalError,
253                                                                    "Out of memory");
254         }
255
256         in_gc_out_of_memory = true;
257
258         /* try to release some memory */
259
260         gc_call();
261
262         /* now instantiate the exception */
263
264         *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
265
266         in_gc_out_of_memory = false;
267
268         return NULL;
269 }
270
271
272 /*
273  * These are local overrides for various environment variables in Emacs.
274  * Please do not remove this and leave it at the end of the file, where
275  * Emacs will automagically detect them.
276  * ---------------------------------------------------------------------
277  * Local variables:
278  * mode: c
279  * indent-tabs-mode: t
280  * c-basic-offset: 4
281  * tab-width: 4
282  * End:
283  */