Imported Upstream version 1.57.0
[platform/upstream/boost.git] / tools / build / src / engine / 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 #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     LOCK();
62     if (GC_gcj_malloc_initialized) {
63       UNLOCK();
64       return;
65     }
66     GC_gcj_malloc_initialized = TRUE;
67     ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
68     if (GC_print_stats && ignore_gcj_info) {
69         GC_log_printf("Gcj-style type information is disabled!\n");
70     }
71     GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
72     GC_mark_procs[mp_index] = (GC_mark_proc)mp;
73     if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
74     /* Set up object kind gcj-style indirect descriptor. */
75       GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
76       if (ignore_gcj_info) {
77         /* Use a simple length-based descriptor, thus forcing a fully   */
78         /* conservative scan.                                           */
79         GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
80                                         (0 | GC_DS_LENGTH),
81                                         TRUE, TRUE);
82       } else {
83         GC_gcj_kind = GC_new_kind_inner(
84                         (void **)GC_gcjobjfreelist,
85                         (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
86                          | GC_DS_PER_OBJECT),
87                         FALSE, TRUE);
88       }
89     /* Set up object kind for objects that require mark proc call.      */
90       if (ignore_gcj_info) {
91         GC_gcj_debug_kind = GC_gcj_kind;
92         GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
93       } else {
94         GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
95         GC_gcj_debug_kind = GC_new_kind_inner(
96                                 (void **)GC_gcjdebugobjfreelist,
97                                 GC_MAKE_PROC(mp_index,
98                                              1 /* allocated with debug info */),
99                                 FALSE, TRUE);
100       }
101     UNLOCK();
102 }
103
104 void * GC_clear_stack(void *);
105
106 #define GENERAL_MALLOC(lb,k) \
107     GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
108     
109 #define GENERAL_MALLOC_IOP(lb,k) \
110     GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
111
112 /* We need a mechanism to release the lock and invoke finalizers.       */
113 /* We don't really have an opportunity to do this on a rarely executed  */
114 /* path on which the lock is not held.  Thus we check at a              */
115 /* rarely executed point at which it is safe to release the lock.       */
116 /* We do this even where we could just call GC_INVOKE_FINALIZERS,       */
117 /* since it's probably cheaper and certainly more uniform.              */
118 /* FIXME - Consider doing the same elsewhere?                           */
119 static void maybe_finalize()
120 {
121    static int last_finalized_no = 0;
122
123    if (GC_gc_no == last_finalized_no) return;
124    if (!GC_is_initialized) return;
125    UNLOCK();
126    GC_INVOKE_FINALIZERS();
127    last_finalized_no = GC_gc_no;
128    LOCK();
129 }
130
131 /* Allocate an object, clear it, and store the pointer to the   */
132 /* type structure (vtable in gcj).                              */
133 /* This adds a byte at the end of the object if GC_malloc would.*/
134 #ifdef THREAD_LOCAL_ALLOC
135   void * GC_core_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
136 #else
137   void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
138 #endif
139 {
140     ptr_t op;
141     ptr_t * opp;
142     word lg;
143     DCL_LOCK_STATE;
144
145     if(SMALL_OBJ(lb)) {
146         lg = GC_size_map[lb];
147         opp = &(GC_gcjobjfreelist[lg]);
148         LOCK();
149         op = *opp;
150         if(EXPECT(op == 0, 0)) {
151             maybe_finalize();
152             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
153             if (0 == op) {
154                 UNLOCK();
155                 return(GC_oom_fn(lb));
156             }
157         } else {
158             *opp = obj_link(op);
159             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
160         }
161         *(void **)op = ptr_to_struct_containing_descr;
162         GC_ASSERT(((void **)op)[1] == 0);
163         UNLOCK();
164     } else {
165         LOCK();
166         maybe_finalize();
167         op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
168         if (0 == op) {
169             UNLOCK();
170             return(GC_oom_fn(lb));
171         }
172         *(void **)op = ptr_to_struct_containing_descr;
173         UNLOCK();
174     }
175     return((void *) op);
176 }
177
178 /* Similar to GC_gcj_malloc, but add debug info.  This is allocated     */
179 /* with GC_gcj_debug_kind.                                              */
180 void * GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
181                            GC_EXTRA_PARAMS)
182 {
183     void * result;
184
185     /* We're careful to avoid extra calls, which could           */
186     /* confuse the backtrace.                                   */
187     LOCK();
188     maybe_finalize();
189     result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
190     if (result == 0) {
191         UNLOCK();
192         GC_err_printf("GC_debug_gcj_malloc(%ld, %p) returning NIL (",
193                       (unsigned long)lb, ptr_to_struct_containing_descr);
194         GC_err_puts(s);
195         GC_err_printf(":%d)\n", i);
196         return(GC_oom_fn(lb));
197     }
198     *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
199     UNLOCK();
200     if (!GC_debugging_started) {
201         GC_start_debugging();
202     }
203     ADD_CALL_CHAIN(result, ra);
204     return (GC_store_debug_info(result, (word)lb, s, (word)i));
205 }
206
207 void * GC_gcj_malloc_ignore_off_page(size_t lb,
208                                      void * ptr_to_struct_containing_descr) 
209 {
210     ptr_t op;
211     ptr_t * opp;
212     word lg;
213     DCL_LOCK_STATE;
214
215     if(SMALL_OBJ(lb)) {
216         lg = GC_size_map[lb];
217         opp = &(GC_gcjobjfreelist[lg]);
218         LOCK();
219         if( (op = *opp) == 0 ) {
220             maybe_finalize();
221             op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
222             lg = GC_size_map[lb];       /* May have been uninitialized. */
223         } else {
224             *opp = obj_link(op);
225             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
226         }
227         *(void **)op = ptr_to_struct_containing_descr;
228         UNLOCK();
229     } else {
230         LOCK();
231         maybe_finalize();
232         op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
233         if (0 != op) {
234           *(void **)op = ptr_to_struct_containing_descr;
235         }
236         UNLOCK();
237     }
238     return((void *) op);
239 }
240
241 #else
242
243 char GC_no_gcj_support;
244
245 #endif  /* GC_GCJ_SUPPORT */