ff950e5c2cbaace0ff69571d3de6ecbb8c72b33e
[cacao.git] / src / mm / boehm-gc / gcj_mlc.c
1 /*
2  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
3  * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
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 #include "config.h"
18
19 #ifdef GC_GCJ_SUPPORT
20
21 /*
22  * This is an allocator interface tuned for gcj (the GNU static
23  * java compiler).
24  *
25  * Each allocated object has a pointer in its first word to a vtable,
26  * which for our purposes is simply a structure describing the type of
27  * the object.
28  * This descriptor structure contains a GC marking descriptor at offset
29  * MARK_DESCR_OFFSET.
30  *
31  * It is hoped that this interface may also be useful for other systems,
32  * possibly with some tuning of the constants.  But the immediate goal
33  * is to get better gcj performance.
34  *
35  * We assume:
36  *  1) We have an ANSI conforming C compiler.
37  *  2) Counting on explicit initialization of this interface is OK.
38  *  3) FASTLOCK is not a significant win.
39  */
40
41 #include "private/gc_pmark.h"
42 #include "gc_gcj.h"
43 #include "private/dbg_mlc.h"
44
45 GC_bool GC_gcj_malloc_initialized = FALSE;
46
47 int GC_gcj_kind;        /* Object kind for objects with descriptors     */
48                         /* in "vtable".                                 */
49 int GC_gcj_debug_kind;  /* The kind of objects that is always marked    */
50                         /* with a mark proc call.                       */
51
52 ptr_t * GC_gcjobjfreelist;
53 ptr_t * GC_gcjdebugobjfreelist;
54
55 /* Caller does not hold allocation lock. */
56 void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
57 {
58     register int i;
59     GC_bool ignore_gcj_info;
60     DCL_LOCK_STATE;
61
62     GC_init();  /* In case it's not already done.       */
63     LOCK();
64     if (GC_gcj_malloc_initialized) {
65       UNLOCK();
66       return;
67     }
68     GC_gcj_malloc_initialized = TRUE;
69     ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
70     if (GC_print_stats && ignore_gcj_info) {
71         GC_log_printf("Gcj-style type information is disabled!\n");
72     }
73     GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
74     GC_mark_procs[mp_index] = (GC_mark_proc)mp;
75     if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
76     /* Set up object kind gcj-style indirect descriptor. */
77       GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
78       if (ignore_gcj_info) {
79         /* Use a simple length-based descriptor, thus forcing a fully   */
80         /* conservative scan.                                           */
81         GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
82                                         (0 | GC_DS_LENGTH),
83                                         TRUE, TRUE);
84       } else {
85         GC_gcj_kind = GC_new_kind_inner(
86                         (void **)GC_gcjobjfreelist,
87                         (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
88                          | GC_DS_PER_OBJECT),
89                         FALSE, TRUE);
90       }
91     /* Set up object kind for objects that require mark proc call.      */
92       if (ignore_gcj_info) {
93         GC_gcj_debug_kind = GC_gcj_kind;
94         GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
95       } else {
96         GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
97         GC_gcj_debug_kind = GC_new_kind_inner(
98                                 (void **)GC_gcjdebugobjfreelist,
99                                 GC_MAKE_PROC(mp_index,
100                                              1 /* allocated with debug info */),
101                                 FALSE, TRUE);
102       }
103     UNLOCK();
104 }
105
106 void * GC_clear_stack(void *);
107
108 #define GENERAL_MALLOC(lb,k) \
109     GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
110     
111 #define GENERAL_MALLOC_IOP(lb,k) \
112     GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
113
114 /* We need a mechanism to release the lock and invoke finalizers.       */
115 /* We don't really have an opportunity to do this on a rarely executed  */
116 /* path on which the lock is not held.  Thus we check at a              */
117 /* rarely executed point at which it is safe to release the lock.       */
118 /* We do this even where we could just call GC_INVOKE_FINALIZERS,       */
119 /* since it's probably cheaper and certainly more uniform.              */
120 /* FIXME - Consider doing the same elsewhere?                           */
121 static void maybe_finalize()
122 {
123    static int last_finalized_no = 0;
124
125    if (GC_gc_no == last_finalized_no) return;
126    if (!GC_is_initialized) return;
127    UNLOCK();
128    GC_INVOKE_FINALIZERS();
129    last_finalized_no = GC_gc_no;
130    LOCK();
131 }
132
133 /* Allocate an object, clear it, and store the pointer to the   */
134 /* type structure (vtable in gcj).                              */
135 /* This adds a byte at the end of the object if GC_malloc would.*/
136 #ifdef THREAD_LOCAL_ALLOC
137   void * GC_core_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
138 #else
139   void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
140 #endif
141 {
142     ptr_t op;
143     ptr_t * opp;
144     word lg;
145     DCL_LOCK_STATE;
146
147     if(SMALL_OBJ(lb)) {
148         lg = GC_size_map[lb];
149         opp = &(GC_gcjobjfreelist[lg]);
150         LOCK();
151         op = *opp;
152         if(EXPECT(op == 0, 0)) {
153             maybe_finalize();
154             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
155             if (0 == op) {
156                 UNLOCK();
157                 return(GC_oom_fn(lb));
158             }
159         } else {
160             *opp = obj_link(op);
161             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
162         }
163         *(void **)op = ptr_to_struct_containing_descr;
164         GC_ASSERT(((void **)op)[1] == 0);
165         UNLOCK();
166     } else {
167         LOCK();
168         maybe_finalize();
169         op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
170         if (0 == op) {
171             UNLOCK();
172             return(GC_oom_fn(lb));
173         }
174         *(void **)op = ptr_to_struct_containing_descr;
175         UNLOCK();
176     }
177     return((void *) op);
178 }
179
180 /* Similar to GC_gcj_malloc, but add debug info.  This is allocated     */
181 /* with GC_gcj_debug_kind.                                              */
182 void * GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
183                            GC_EXTRA_PARAMS)
184 {
185     void * result;
186
187     /* We're careful to avoid extra calls, which could           */
188     /* confuse the backtrace.                                   */
189     LOCK();
190     maybe_finalize();
191     result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
192     if (result == 0) {
193         UNLOCK();
194         GC_err_printf("GC_debug_gcj_malloc(%ld, %p) returning NIL (",
195                       (unsigned long)lb, ptr_to_struct_containing_descr);
196         GC_err_puts(s);
197         GC_err_printf(":%d)\n", i);
198         return(GC_oom_fn(lb));
199     }
200     *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
201     UNLOCK();
202     if (!GC_debugging_started) {
203         GC_start_debugging();
204     }
205     ADD_CALL_CHAIN(result, ra);
206     return (GC_store_debug_info(result, (word)lb, s, (word)i));
207 }
208
209 void * GC_gcj_malloc_ignore_off_page(size_t lb,
210                                      void * ptr_to_struct_containing_descr) 
211 {
212     ptr_t op;
213     ptr_t * opp;
214     word lg;
215     DCL_LOCK_STATE;
216
217     if(SMALL_OBJ(lb)) {
218         lg = GC_size_map[lb];
219         opp = &(GC_gcjobjfreelist[lg]);
220         LOCK();
221         if( (op = *opp) == 0 ) {
222             maybe_finalize();
223             op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
224             lg = GC_size_map[lb];       /* May have been uninitialized. */
225         } else {
226             *opp = obj_link(op);
227             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
228         }
229         *(void **)op = ptr_to_struct_containing_descr;
230         UNLOCK();
231     } else {
232         LOCK();
233         maybe_finalize();
234         op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
235         if (0 != op) {
236           *(void **)op = ptr_to_struct_containing_descr;
237         }
238         UNLOCK();
239     }
240     return((void *) op);
241 }
242
243 #else
244
245 char GC_no_gcj_support;
246
247 #endif  /* GC_GCJ_SUPPORT */