Back to index

plt-scheme  4.2.1
gcj_mlc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
00003  * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to use or copy this program
00009  * for any purpose,  provided the above notices are retained on all copies.
00010  * Permission to modify the code and to distribute modified code is granted,
00011  * provided the above notices are retained, and a notice that the code was
00012  * modified is included with the above copyright notice.
00013  *
00014  */
00015 /* Boehm, July 31, 1995 5:02 pm PDT */
00016 
00017 #ifdef GC_GCJ_SUPPORT
00018 
00019 /*
00020  * This is an allocator interface tuned for gcj (the GNU static
00021  * java compiler).
00022  *
00023  * Each allocated object has a pointer in its first word to a vtable,
00024  * which for our purposes is simply a structure describing the type of
00025  * the object.
00026  * This descriptor structure contains a GC marking descriptor at offset
00027  * MARK_DESCR_OFFSET.
00028  *
00029  * It is hoped that this interface may also be useful for other systems,
00030  * possibly with some tuning of the constants.  But the immediate goal
00031  * is to get better gcj performance.
00032  *
00033  * We assume:
00034  *  1) We have an ANSI conforming C compiler.
00035  *  2) Counting on explicit initialization of this interface is OK.
00036  *  3) FASTLOCK is not a significant win.
00037  */
00038 
00039 #include "private/gc_pmark.h"
00040 #include "gc_gcj.h"
00041 #include "private/dbg_mlc.h"
00042 
00043 GC_bool GC_gcj_malloc_initialized = FALSE;
00044 
00045 int GC_gcj_kind;     /* Object kind for objects with descriptors     */
00046                      /* in "vtable".                                  */
00047 int GC_gcj_debug_kind;      /* The kind of objects that is always marked     */
00048                      /* with a mark proc call.                 */
00049 
00050 ptr_t * GC_gcjobjfreelist;
00051 ptr_t * GC_gcjdebugobjfreelist;
00052 
00053 /* Caller does not hold allocation lock. */
00054 void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
00055 {
00056     register int i;
00057     GC_bool ignore_gcj_info;
00058     DCL_LOCK_STATE;
00059 
00060     GC_init();       /* In case it's not already done.  */
00061     DISABLE_SIGNALS();
00062     LOCK();
00063     if (GC_gcj_malloc_initialized) {
00064       UNLOCK();
00065       ENABLE_SIGNALS();
00066       return;
00067     }
00068     GC_gcj_malloc_initialized = TRUE;
00069     ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
00070 #   ifdef CONDPRINT
00071       if (GC_print_stats && ignore_gcj_info) {
00072         GC_printf0("Gcj-style type information is disabled!\n");
00073       }
00074 #   endif
00075     GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
00076     GC_mark_procs[mp_index] = (GC_mark_proc)mp;
00077     if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
00078     /* Set up object kind gcj-style indirect descriptor. */
00079       GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
00080       if (ignore_gcj_info) {
00081        /* Use a simple length-based descriptor, thus forcing a fully  */
00082        /* conservative scan.                                          */
00083        GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
00084                                    (0 | GC_DS_LENGTH),
00085                                     TRUE, TRUE);
00086       } else {
00087        GC_gcj_kind = GC_new_kind_inner(
00088                      (void **)GC_gcjobjfreelist,
00089                      (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
00090                       | GC_DS_PER_OBJECT),
00091                      FALSE, TRUE);
00092       }
00093     /* Set up object kind for objects that require mark proc call.    */
00094       if (ignore_gcj_info) {
00095        GC_gcj_debug_kind = GC_gcj_kind;
00096         GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
00097       } else {
00098         GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
00099        GC_gcj_debug_kind = GC_new_kind_inner(
00100                             (void **)GC_gcjdebugobjfreelist,
00101                             GC_MAKE_PROC(mp_index,
00102                                         1 /* allocated with debug info */),
00103                             FALSE, TRUE);
00104       }
00105     UNLOCK();
00106     ENABLE_SIGNALS();
00107 }
00108 
00109 ptr_t GC_clear_stack();
00110 
00111 #define GENERAL_MALLOC(lb,k) \
00112     (GC_PTR)GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
00113     
00114 #define GENERAL_MALLOC_IOP(lb,k) \
00115     (GC_PTR)GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
00116 
00117 /* We need a mechanism to release the lock and invoke finalizers.     */
00118 /* We don't really have an opportunity to do this on a rarely executed       */
00119 /* path on which the lock is not held.  Thus we check at a            */
00120 /* rarely executed point at which it is safe to release the lock.     */
00121 /* We do this even where we could just call GC_INVOKE_FINALIZERS,     */
00122 /* since it's probably cheaper and certainly more uniform.            */
00123 /* FIXME - Consider doing the same elsewhere?                         */
00124 static void maybe_finalize()
00125 {
00126    static int last_finalized_no = 0;
00127 
00128    if (GC_gc_no == last_finalized_no) return;
00129    if (!GC_is_initialized) return;
00130    UNLOCK();
00131    GC_INVOKE_FINALIZERS();
00132    last_finalized_no = GC_gc_no;
00133    LOCK();
00134 }
00135 
00136 /* Allocate an object, clear it, and store the pointer to the  */
00137 /* type structure (vtable in gcj).                      */
00138 /* This adds a byte at the end of the object if GC_malloc would.*/
00139 void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
00140 {
00141 register ptr_t op;
00142 register ptr_t * opp;
00143 register word lw;
00144 DCL_LOCK_STATE;
00145 
00146     if( EXPECT(SMALL_OBJ(lb), 1) ) {
00147 #       ifdef MERGE_SIZES
00148          lw = GC_size_map[lb];
00149 #      else
00150          lw = ALIGNED_WORDS(lb);
00151 #       endif
00152        opp = &(GC_gcjobjfreelist[lw]);
00153        LOCK();
00154        op = *opp;
00155         if(EXPECT(op == 0, 0)) {
00156            maybe_finalize();
00157             op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
00158            if (0 == op) {
00159               UNLOCK();
00160               return(GC_oom_fn(lb));
00161            }
00162 #          ifdef MERGE_SIZES
00163               lw = GC_size_map[lb];       /* May have been uninitialized.    */
00164 #          endif
00165         } else {
00166             *opp = obj_link(op);
00167             GC_words_allocd += lw;
00168         }
00169        *(void **)op = ptr_to_struct_containing_descr;
00170        GC_ASSERT(((void **)op)[1] == 0);
00171        UNLOCK();
00172     } else {
00173        LOCK();
00174        maybe_finalize();
00175        op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
00176        if (0 == op) {
00177            UNLOCK();
00178            return(GC_oom_fn(lb));
00179        }
00180        *(void **)op = ptr_to_struct_containing_descr;
00181        UNLOCK();
00182     }
00183     return((GC_PTR) op);
00184 }
00185 
00186 /* Similar to GC_gcj_malloc, but add debug info.  This is allocated   */
00187 /* with GC_gcj_debug_kind.                                     */
00188 GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
00189                         GC_EXTRA_PARAMS)
00190 {
00191     GC_PTR result;
00192 
00193     /* We're careful to avoid extra calls, which could          */
00194     /* confuse the backtrace.                                  */
00195     LOCK();
00196     maybe_finalize();
00197     result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
00198     if (result == 0) {
00199        UNLOCK();
00200         GC_err_printf2("GC_debug_gcj_malloc(%ld, 0x%lx) returning NIL (",
00201                      (unsigned long) lb,
00202                      (unsigned long) ptr_to_struct_containing_descr);
00203         GC_err_puts(s);
00204         GC_err_printf1(":%ld)\n", (unsigned long)i);
00205         return(GC_oom_fn(lb));
00206     }
00207     *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
00208     UNLOCK();
00209     if (!GC_debugging_started) {
00210        GC_start_debugging();
00211     }
00212     ADD_CALL_CHAIN(result, ra);
00213     return (GC_store_debug_info(result, (word)lb, s, (word)i));
00214 }
00215 
00216 /* Similar to GC_gcj_malloc, but the size is in words, and we don't   */
00217 /* adjust it.  The size is assumed to be such that it can be   */
00218 /* allocated as a small object.                                */
00219 void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
00220 {
00221 ptr_t op;
00222 ptr_t * opp;
00223 DCL_LOCK_STATE;
00224 
00225     opp = &(GC_gcjobjfreelist[lw]);
00226     LOCK();
00227     op = *opp;
00228     if( EXPECT(op == 0, 0) ) {
00229        maybe_finalize();
00230         op = (ptr_t)GC_clear_stack(
00231               GC_generic_malloc_words_small_inner(lw, GC_gcj_kind));
00232        if (0 == op) {
00233            UNLOCK();
00234            return GC_oom_fn(WORDS_TO_BYTES(lw));
00235        }
00236     } else {
00237         *opp = obj_link(op);
00238         GC_words_allocd += lw;
00239     }
00240     *(void **)op = ptr_to_struct_containing_descr;
00241     UNLOCK();
00242     return((GC_PTR) op);
00243 }
00244 
00245 /* And a debugging version of the above:  */
00246 void * GC_debug_gcj_fast_malloc(size_t lw,
00247                             void * ptr_to_struct_containing_descr,
00248                             GC_EXTRA_PARAMS)
00249 {
00250     GC_PTR result;
00251     size_t lb = WORDS_TO_BYTES(lw);
00252 
00253     /* We clone the code from GC_debug_gcj_malloc, so that we  */
00254     /* dont end up with extra frames on the stack, which could */
00255     /* confuse the backtrace.                                  */
00256     LOCK();
00257     maybe_finalize();
00258     result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
00259     if (result == 0) {
00260        UNLOCK();
00261         GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (",
00262                      (unsigned long) lw,
00263                      (unsigned long) ptr_to_struct_containing_descr);
00264         GC_err_puts(s);
00265         GC_err_printf1(":%ld)\n", (unsigned long)i);
00266         return GC_oom_fn(WORDS_TO_BYTES(lw));
00267     }
00268     *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
00269     UNLOCK();
00270     if (!GC_debugging_started) {
00271        GC_start_debugging();
00272     }
00273     ADD_CALL_CHAIN(result, ra);
00274     return (GC_store_debug_info(result, (word)lb, s, (word)i));
00275 }
00276 
00277 void * GC_gcj_malloc_ignore_off_page(size_t lb,
00278                                  void * ptr_to_struct_containing_descr) 
00279 {
00280 register ptr_t op;
00281 register ptr_t * opp;
00282 register word lw;
00283 DCL_LOCK_STATE;
00284 
00285     if( SMALL_OBJ(lb) ) {
00286 #       ifdef MERGE_SIZES
00287          lw = GC_size_map[lb];
00288 #      else
00289          lw = ALIGNED_WORDS(lb);
00290 #       endif
00291        opp = &(GC_gcjobjfreelist[lw]);
00292        LOCK();
00293         if( (op = *opp) == 0 ) {
00294            maybe_finalize();
00295             op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
00296 #          ifdef MERGE_SIZES
00297               lw = GC_size_map[lb];       /* May have been uninitialized.    */
00298 #          endif
00299         } else {
00300             *opp = obj_link(op);
00301             GC_words_allocd += lw;
00302         }
00303        *(void **)op = ptr_to_struct_containing_descr;
00304        UNLOCK();
00305     } else {
00306        LOCK();
00307        maybe_finalize();
00308         op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
00309         if (0 != op) {
00310           *(void **)op = ptr_to_struct_containing_descr;
00311        }
00312         UNLOCK();
00313     }
00314     return((GC_PTR) op);
00315 }
00316 
00317 #else
00318 
00319 char GC_no_gcj_support;
00320 
00321 #endif  /* GC_GCJ_SUPPORT */