Synopsis - Cross-Reference
File: /src/Synopsis/gc/gcj_mlc.c1/* 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 43GC_bool GC_gcj_malloc_initialized = FALSE; 44 45int GC_gcj_kind; /* Object kind for objects with descriptors */ 46 /* in "vtable". */ 47int GC_gcj_debug_kind; /* The kind of objects that is always marked */ 48 /* with a mark proc call. */ 49 50ptr_t * GC_gcjobjfreelist; 51ptr_t * GC_gcjdebugobjfreelist; 52 53/* Caller does not hold allocation lock. */ 54void 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 104void * 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? */ 119static 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. */ 180void * 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 207void * 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 243char GC_no_gcj_support; 244 245#endif /* GC_GCJ_SUPPORT */