Back to index

plt-scheme  4.2.1
wxGC.cxx
Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 MrEd interface to various garbage collectors, including the Boehm
00004  collector, SenoraGC, and MzScheme's precise collector.
00005 
00006 Copyright (c) 2004-2009 PLT Scheme Inc.
00007 
00008 *************************************************************************/
00009 
00010 /*************************************************************************
00011 Based On:
00012 
00013 Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
00014  
00015 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00016 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00017  
00018     Last modified on Sat Nov 19 19:31:14 PST 1994 by ellis
00019                   on Sat Jun  8 15:10:00 PST 1994 by boehm
00020 
00021 Permission is hereby granted to copy this code for any purpose,
00022 provided the above notices are retained on all copies.
00023 
00024 Authors: John R. Ellis and Jesse Hull
00025 
00026 **************************************************************************/
00027 /* Boehm, December 20, 1994 7:26 pm PST */
00028 
00029 #include <stddef.h>
00030 #include "wxGC.h"
00031 
00032 /* With extensions, or with x86 Mac OS X, MrEd's `new' gets used by
00033    libraries that shouldn't use it. So we can't define `new' on that
00034    platform. For PPC, we define `new' and `delete' to use malloc() and
00035    free(); for some reason, linking fails in Mac OS X 10.3 if we just
00036    omit `new' and `delete'. There should be no problem under Windows,
00037    due to the way DLL linking works. */
00038 
00039 #ifndef WIN32
00040 # if defined(OS_X) && defined(__POWERPC__)
00041 #  define MALLOC_FOR_BUILTIN_NEW
00042 #  include <stdio.h>
00043 #  include <stdlib.h>
00044 # else
00045 #  define DONT_DEFINE_BUILTIN_NEW
00046 # endif
00047 #endif
00048 
00049 #ifdef COMPACT_BACKTRACE_GC  
00050 # include <stdio.h>
00051 #endif
00052 
00053 #ifdef MPW_CPLUS
00054 extern "C" {
00055   typedef void (*GC_F_PTR)(void *, void *);
00056 }
00057 # define CAST_GCP (GC_F_PTR)
00058 # define CAST_GCPP (GC_F_PTR *)
00059 #else
00060 # define CAST_GCP /* empty */
00061 # define CAST_GCPP /* empty */
00062 #endif
00063 
00064 #ifdef USE_SENORA_GC
00065 struct GC_Set *cpp_objects;
00066 typedef void (*GC_finalization_proc)(void *, void *);
00067 #if SGC_STD_DEBUGGING
00068 # define USE_WXOBJECT_TRACE_COUNTER
00069 #endif
00070 #endif
00071 
00072 #ifndef DONT_DEFINE_BUILTIN_NEW
00073 
00074 void *operator new(size_t size)
00075 {
00076 #ifdef MALLOC_FOR_BUILTIN_NEW
00077   return malloc(size);
00078 #else
00079 # ifdef USE_SENORA_GC
00080   if (!cpp_objects)
00081     cpp_objects = GC_new_set("C++", NULL, NULL, NULL, NULL, NULL, 0);
00082 
00083   return GC_malloc_specific(size, cpp_objects);
00084 # else
00085   return GC_malloc(size);
00086 #endif
00087 #endif
00088 }
00089 
00090 void operator delete(void *obj)
00091 {
00092 #ifdef MALLOC_FOR_BUILTIN_NEW
00093   free(obj);
00094 #endif
00095 }
00096 
00097 #endif
00098 
00099 void gc_cleanup::install_cleanup(void)
00100 {
00101   GC_finalization_proc old_fn;
00102   void *old_data;
00103 
00104 # ifdef MZ_PRECISE_GC
00105 #  define ALLOW_NON_BASE 0
00106 #  define CHECK_BASE 0
00107 # else
00108 #  ifdef wx_xt
00109 #   define ALLOW_NON_BASE 0
00110 #   define CHECK_BASE 0
00111 #  else
00112 #   ifdef WIN32
00113 #    define ALLOW_NON_BASE 0
00114 #    define CHECK_BASE 1
00115 #    define CRASH_ON_NONBASE 1
00116 #   else
00117 #    define ALLOW_NON_BASE 1
00118 #    define CHECK_BASE 0
00119 #   endif
00120 #  endif
00121 # endif
00122 
00123 # if CHECK_BASE || ALLOW_NON_BASE
00124   if (GC_base(this) != (void *)this) {
00125 #  if ALLOW_NON_BASE
00126     return;
00127 #  else
00128 #   ifdef CRASH_ON_NONBASE
00129     *(long *)0x0 = 1;
00130 #   else
00131     printf("Clean-up object is not the base object\n");
00132     abort();
00133 #   endif
00134 #  endif
00135   }
00136 # endif
00137 
00138   GC_register_finalizer_ignore_self(gcOBJ_TO_PTR(this), 
00139                                 CAST_GCP GC_cleanup, NULL, 
00140                                 CAST_GCPP &old_fn, &old_data);
00141 
00142 # if CHECK_BASE
00143   if (old_fn) {
00144 #  ifdef CRASH_ON_NONBASE
00145        *(long *)0x0 = 1;
00146 #  else
00147     printf("Object already has a clean-up\n");
00148     abort();
00149 #  endif
00150   }
00151 # endif
00152 }
00153 
00154 #define SHOW_CLEANUP_TIMES 0
00155 
00156 #if SHOW_CLEANUP_TIMES
00157 extern "C" long scheme_get_process_milliseconds();
00158 #endif
00159 
00160 void GC_cleanup(void *obj, void *)
00161 {
00162   gc *clean = (gc *)gcPTR_TO_OBJ(obj);
00163 
00164 #ifdef MZ_PRECISE_GC
00165 # ifdef COMPACT_BACKTRACE_GC  
00166 #  if SHOW_CLEANUP_TIMES
00167   long start;
00168   start = scheme_get_process_milliseconds();
00169   char *s;
00170   s = clean->gcGetName();
00171   printf("Cleanup: %s\n", s ? s : "???");
00172 #  endif
00173 # endif
00174 
00175   GC_cpp_delete(clean);
00176 
00177 # ifdef COMPACT_BACKTRACE_GC  
00178 #  if SHOW_CLEANUP_TIMES
00179   start = scheme_get_process_milliseconds() - start;
00180   printf("  done %d\n", start);
00181 #  endif
00182 # endif
00183 #else
00184   clean->~gc();
00185 #endif
00186 }
00187 
00188 /**********************************************************************/  
00189 
00190 #ifdef OPERATOR_NEW_ARRAY
00191 # ifndef DONT_DEFINE_BUILTIN_NEW
00192 
00193 void* operator new[](size_t size)
00194 {
00195 #ifdef MALLOC_FOR_BUILTIN_NEW
00196   return malloc(size);
00197 #else
00198 # ifdef USE_SENORA_GC
00199   if (!cpp_objects)
00200     cpp_objects = GC_new_set("C++", NULL, NULL, NULL, NULL, NULL, 0);
00201   
00202   return GC_malloc_specific(size, cpp_objects);
00203 # else
00204   return GC_malloc(size);
00205 # endif
00206 #endif
00207 }
00208   
00209 void operator delete[](void *obj)
00210 {
00211 #ifdef MALLOC_FOR_BUILTIN_NEW
00212   free(obj);
00213 #endif
00214 }
00215 
00216 # endif
00217 #endif
00218 
00219 /**********************************************************************/
00220 
00221 #ifdef USE_SENORA_GC
00222 
00223 struct GC_Set *wx_objects;
00224 
00225 # ifdef USE_WXOBJECT_TRACE_COUNTER
00226 extern void wxTraceCount(void *, int);
00227 extern void wxTracePath(void *, unsigned long, void *);
00228 extern void wxTraceInit(void);
00229 extern void wxTraceDone(void);
00230 extern void wxObjectFinalize(void *);
00231 # endif
00232 
00233 void *GC_cpp_malloc(size_t size)
00234 {
00235   if (!wx_objects)
00236     wx_objects = GC_new_set("wxObjects", 
00237 # ifdef USE_WXOBJECT_TRACE_COUNTER
00238                          wxTraceInit,
00239                          wxTraceDone,
00240                          wxTraceCount,
00241                          wxTracePath,
00242                          wxObjectFinalize,
00243 # else
00244                          NULL, NULL, NULL, NULL, NULL,
00245 # endif
00246                          0);
00247 
00248   return GC_malloc_specific(size, wx_objects);
00249 }
00250 
00251 # ifdef SGC_STD_DEBUGGING
00252 
00253 void GC_cpp_for_each(void (*f)(void *, int, void *), void *data)
00254 {
00255   if (wx_objects)
00256     GC_for_each_element(wx_objects, f, data);
00257 }
00258 
00259 int GC_is_wx_object(void *v)
00260 {
00261   return wx_objects && (GC_set(v) == wx_objects);
00262 }
00263 
00264 # endif
00265 
00266 #endif
00267 
00268 /**********************************************************************/
00269 
00270 #ifdef MZ_PRECISE_GC
00271 
00272 # define ZERO_OUT_DISPATCH 1
00273 
00274 # ifdef COMPACT_BACKTRACE_GC
00275 static char *get_xtagged_name(void *p);
00276 extern char *(*GC_get_xtagged_name)(void *p);
00277 # endif
00278 
00279 typedef struct {
00280   short tag;
00281   short filler_used_for_hashing;
00282   void *val;
00283 } GC_WB;
00284 
00285 void *GC_weak_box_val(void *b)
00286 {
00287   return ((GC_WB *)b)->val;
00288 }
00289 
00290 #include "scheme.h"
00291 
00292 static void mark_cpp_object(void *p)
00293 {
00294   gc *obj = (gc *)p;
00295 
00296 #if ZERO_OUT_DISPATCH
00297   if (*(long *)obj)
00298 #endif
00299     obj->gcMark();
00300 }
00301 
00302 static void fixup_cpp_object(void *p)
00303 {
00304   gc *obj = (gc *)p;
00305 
00306 #if ZERO_OUT_DISPATCH
00307   if (*(long *)obj)
00308 #endif
00309     obj->gcFixup();
00310 }
00311 
00312 static int is_initialized;
00313 
00314 static void initize(void)
00315 {
00316   /* Initialize: */
00317   GC_mark_xtagged = mark_cpp_object;
00318   GC_fixup_xtagged = fixup_cpp_object;
00319 
00320 # ifdef COMPACT_BACKTRACE_GC
00321   GC_get_xtagged_name = get_xtagged_name;
00322 # endif
00323   
00324   is_initialized = 1;
00325 }
00326 
00327 void *GC_cpp_malloc(size_t size)
00328 {
00329   void *p;
00330 
00331   if (!is_initialized)
00332     initize();
00333 
00334   p = GC_malloc_one_xtagged(size);
00335 
00336   return p;
00337 }
00338 
00339 void GC_cpp_delete(gc *v)
00340 {
00341   v->~gc();
00342 #if ZERO_OUT_DISPATCH
00343   ((long *)v)[0] = 0;
00344 #endif
00345 }
00346 
00347 # ifdef COMPACT_BACKTRACE_GC
00348 
00349 static char name_buffer[256];
00350 
00351 static char *get_xtagged_name(void *p)
00352 {
00353   char *s;
00354   s = ((gc *)gcPTR_TO_OBJ(p))->gcGetName();
00355   sprintf(name_buffer, "<%s>", (s ? s : "XTAGGED"));
00356   return name_buffer;
00357 }
00358 
00359 char *gc::gcGetName() {
00360   return NULL;
00361 }
00362 
00363 # endif
00364 
00365 #endif
00366 
00367 /**********************************************************************/
00368 
00369 /* The accounting shadow serves two purposes. First, it allocates
00370    largely untouched atomic memory to reflect the allocation of
00371    bitmaps outside the GC space, so that the nominal allocation total
00372    is related to the total taking into accoun bitmaps. Second, because
00373    bitmaps are released through finalizers, the accounting shadow
00374    forces a GC more frequently than might otherwise happen as the
00375    total size of bitmaps grows. */
00376 
00377 #define INIT_ACCUM_SIZE 1024 * 1024 * 5
00378 #define INIT_ACCUM_COUNT 1000
00379 
00380 static long total, accum = INIT_ACCUM_SIZE;
00381 static int total_count, accum_count = INIT_ACCUM_COUNT;
00382 
00383 void *GC_malloc_accounting_shadow(long a)
00384 {
00385   long *p;
00386   if (a < (long)sizeof(long))
00387     a = sizeof(long);
00388   total += a;
00389   accum -= a;
00390   total_count += 1;
00391   accum_count -= 1;
00392   if (accum <= 0) {
00393     GC_gcollect();
00394     accum = total >> 1;
00395     if (accum < INIT_ACCUM_SIZE)
00396       accum = INIT_ACCUM_SIZE;
00397   }
00398 #ifdef wx_msw
00399   /* Under Windows, the number of bitmaps matters, even if
00400      they're small. */
00401   if (accum_count <= 0) {
00402     GC_gcollect();
00403     accum_count = total_count >> 1;
00404     if (accum_count < INIT_ACCUM_COUNT)
00405       accum_count = INIT_ACCUM_COUNT;
00406   }
00407 #endif
00408   p = (long *)GC_malloc_atomic(a);
00409   *p = a;
00410   return (void *)p;
00411 }
00412 
00413 void GC_free_accounting_shadow(void *p)
00414 {
00415   if (p) {
00416     total -= *(long *)p;
00417     accum += *(long *)p;
00418     total_count -= 1;
00419     accum_count += 1;
00420   }
00421 }