Synopsis - Cross-Reference

File: /src/Synopsis/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
 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 */