00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #include <sys/types.h> 
00022 #include <assert.h>
00023 #include <errno.h>
00024 
00025 #include <new> 
00026 
00027 
00028 
00029 #if !defined(__osf__)
00030 #include <used_gc_flags.h>
00031 #endif
00032 
00033 
00034 #include <gc.h>
00035 
00036 #if defined(THREAD_LOCAL_ALLOC)
00037 extern "C"
00038 {
00039 #include <gc_local_alloc.h>
00040 }
00041 #endif
00042 
00043 #if defined(__osf__)
00044 
00045 extern "C" void GC_add_roots(void *low, void *high_plus_1);
00046 #endif
00047 
00048 #include "Basics.H"    
00049 
00050 using std::cerr;
00051 using std::endl;
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 struct pre_init_block
00085 {
00086   struct pre_init_block *next;
00087   size_t size;
00088 };
00089 static struct pre_init_block *pre_init_blocks = 0;
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 class ArrayOffsetCalc
00100 {
00101 private:
00102   
00103   
00104   struct _dummy
00105   {
00106     int i;
00107 
00108     _dummy() throw() : i(1) {}
00109 
00110     
00111     
00112     void *operator new[](size_t size, void **block_start)
00113     {
00114       void *result;
00115       result = malloc(size);
00116       *block_start = result;
00117       return result;
00118     }
00119 
00120     
00121     
00122     
00123     void operator delete[](void *p, void **block_start) { free(p); }
00124 
00125     
00126     void operator delete[](void *p) { free(p); }
00127 
00128     
00129     
00130     
00131     ~_dummy() { i = -1; }
00132   };
00133 
00134   
00135   
00136   
00137   
00138   
00139   
00140   struct _dummy2
00141   {
00142     unsigned long long uniqueid[2];
00143     _dummy nameA;
00144 
00145     void *operator new[](size_t size, void **block_start)
00146     {
00147       void *result;
00148       result = malloc(size);
00149       *block_start = result;
00150       return result;
00151     }
00152     void operator delete[](void *p, void **block_start) { free(p); }
00153     void operator delete[](void *p) { free(p); }
00154   };
00155 
00156 public:
00157   
00158   
00159 
00160   static unsigned int value()
00161   {
00162     
00163     void *bs;
00164     _dummy *as = new (&bs) _dummy[1];
00165     delete [] as;
00166     
00167     return (((char *) as) - ((char *) bs));
00168   }
00169 
00170   static unsigned int value2()
00171   {
00172     void *bs;
00173     _dummy2 *as = new (&bs) _dummy2[1];
00174     delete [] as;
00175     return (((char *) as) - ((char *) bs));
00176   }
00177 };
00178 
00179 
00180 
00181 static char *mygetenv (const char *env_name, bool vbose)
00182 {
00183   char *val = getenv(env_name);
00184   if (vbose && val != NULL)
00185     cerr << "GC_ENV: Detected " << val << " in ENV variable named: " << env_name << endl;
00186 
00187   return val;
00188 }
00189 
00190 
00191 
00192 static int getenv_unum (const char *env_name, unsigned long *result, bool vbose)
00193 {
00194   
00195   
00196   
00197   
00198   
00199 
00200   char *end_cnvt, *env_val;
00201   unsigned long t_val;
00202 
00203   if ((env_val = mygetenv(env_name, vbose)) == NULL)
00204     return 0;    
00205 
00206   errno = 0;      
00207   t_val = strtoul(env_val,&end_cnvt,10);
00208   if (errno == ERANGE)
00209     return 3;    
00210 
00211   if (env_val == end_cnvt ||  
00212       *end_cnvt != 0)      
00213     return 2;    
00214 
00215   *result = t_val;
00216   return 1;
00217 }
00218 
00219 
00220 
00221 class BasicsGCInit {
00222 public:
00223   static bool done;
00224   BasicsGCInit() throw ()
00225   {
00226     GC_init();
00227 
00228     
00229     
00230     
00231     
00232 
00233 #if !defined(ALL_INTERIOR_POINTERS) && defined(GC_REGISTER_DISPLACEMENT)
00234     
00235     
00236     GC_REGISTER_DISPLACEMENT(1);
00237 
00238     
00239     
00240     GC_REGISTER_DISPLACEMENT(ArrayOffsetCalc::value());
00241     GC_REGISTER_DISPLACEMENT(ArrayOffsetCalc::value2());
00242 
00243     
00244     
00245     
00246     
00247     GC_REGISTER_DISPLACEMENT(4);
00248     GC_REGISTER_DISPLACEMENT(8);
00249 #endif
00250 
00251 #if !defined(ALL_INTERIOR_POINTERS) && defined(__GNUC__) && (__GNUC__ >= 3)
00252     
00253     
00254     
00255     
00256     
00257     
00258 
00259 # if !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ < 4)
00260     
00261     putenv("GLIBCPP_FORCE_NEW=1");
00262 # endif
00263 # if !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 4)
00264     
00265     putenv("GLIBCXX_FORCE_NEW=1");
00266 # endif
00267 
00268 #endif
00269 
00270 #if !defined(__osf__)
00271     
00272 
00273     bool vbose = false;
00274     int tstat;
00275 
00276     if (mygetenv("GC_ENV_VERBOSE", 1) != NULL)
00277        vbose = true;
00278 
00279     
00280     if ((tstat = getenv_unum("GC_MAX_RETRIES", &GC_max_retries, vbose)) > 1)
00281        cerr << "WARNING: Non-numeric or huge value in GC_MAX_RETRIES was ignored. value= " << getenv("GC_MAX_RETRIES") << endl;
00282 
00283     if (GC_max_retries > 10)
00284        GC_max_retries = 10;    
00285 
00286     if (GC_max_retries < 1)
00287        GC_max_retries = 1;    
00288 
00289     if (vbose && tstat)
00290         cerr << "GC_ENV: GC_max_retires finally set to: " << GC_max_retries << endl;
00291 
00292     
00293     if ((tstat = getenv_unum("GC_FREE_SPACE_DIVISOR", &GC_free_space_divisor, vbose)) > 1)
00294         cerr << "WARNING: Non-numeric or huge value in GC_FREE_SPACE_DIVISOR was ignored. value= " << getenv("GC_FREE_SPACE_DIVISOR") << endl;
00295 
00296     if (GC_free_space_divisor < 3)
00297        GC_free_space_divisor = 3;    
00298 
00299     if (GC_free_space_divisor > 100)
00300        GC_free_space_divisor = 100;    
00301 
00302     if (vbose && tstat)
00303         cerr << "GC_ENV: GC_free_space_divisor finally set to: " << GC_free_space_divisor << endl;
00304 
00305     if (mygetenv("GC_DONT_EXPAND", vbose) != NULL)
00306        
00307        GC_dont_expand = 1;    
00308 
00309     
00310 #endif
00311 
00312     BasicsGCInit::done = true;
00313     
00314     
00315     struct pre_init_block *cur = pre_init_blocks;
00316     while(cur)
00317       {
00318         char *real_block = ((char *) (cur+1));
00319         GC_add_roots(real_block, real_block+cur->size);
00320         cur = cur->next;
00321       }
00322   }
00323 };
00324 bool BasicsGCInit::done = false;
00325 static BasicsGCInit gcInit; 
00326 
00327 
00328 
00329 
00330 static void *early_alloc(size_t size)
00331 {
00332   
00333   
00334   struct pre_init_block *result_block =
00335     (struct pre_init_block *) ::malloc(sizeof(struct pre_init_block) +
00336                                        size);
00337   result_block->next = pre_init_blocks;
00338   result_block->size = size;
00339   pre_init_blocks = result_block;
00340   return ((void *) (result_block+1));
00341 }
00342 
00343 
00344 
00345 
00346 static void *ptrfree_alloc(size_t size,
00347                            const char *file, unsigned int line)
00348 {
00349   void *result;
00350 
00351   
00352   
00353   
00354   if(!BasicsGCInit::done)
00355     return early_alloc(size);
00356 
00357   
00358   
00359   
00360 #if defined(GC_MALLOC_ATOMIC)
00361 # if defined(GC_DEBUG)
00362   
00363   result = GC_debug_malloc_atomic_ignore_off_page(size, file, line);
00364 # else
00365 #  if defined(THREAD_LOCAL_ALLOC)
00366   
00367   
00368   if(size < 1024)
00369     result = GC_local_malloc_atomic(size);
00370   else
00371 #  endif
00372     
00373     
00374     
00375     
00376     
00377     
00378 
00379     result = GC_malloc_atomic_ignore_off_page(size);
00380 # endif
00381 #elif defined(__digital__)
00382   result = GC_malloc_ptrfree(size);
00383 #else
00384 # error Which garbage collector are we using?
00385 #endif
00386 
00387   
00388   
00389   
00390   
00391   if(result == 0)
00392     {
00393       cerr << "Out of memory trying to allocate " << size << " bytes at "
00394            << file << ":" << line << endl;
00395       abort();
00396     }
00397   return result;
00398 }
00399 
00400 
00401 
00402 
00403 static void *normal_alloc(size_t size,
00404                           const char *file, unsigned int line)
00405 {
00406   void *result;
00407 
00408   
00409   
00410   
00411   if(!BasicsGCInit::done)
00412     return early_alloc(size);
00413 
00414 #if defined(GC_MALLOC_ATOMIC)
00415 # if defined(GC_DEBUG)
00416   
00417   result = GC_debug_malloc_ignore_off_page(size, file, line);
00418 # else
00419 #  if defined(THREAD_LOCAL_ALLOC)
00420   
00421   
00422   if(size < 1024)
00423     result = GC_local_malloc(size);
00424   else
00425 #  endif
00426     result = GC_malloc_ignore_off_page(size);
00427 # endif
00428 #elif defined(__digital__)
00429   result = GC_malloc(size);
00430 #else
00431 # error Which garbage collector are we using?
00432 #endif
00433 
00434   
00435   
00436   
00437   
00438   if(result == 0)
00439     {
00440       cerr << "Out of memory trying to allocate " << size << " bytes at "
00441            << file << ":" << line << endl;
00442       abort();
00443     }
00444   return result;
00445 }
00446 
00447 Basics::gc_no_pointers_t Basics::gc_no_pointers;
00448 
00449 void *operator new(size_t size, Basics::gc_no_pointers_t unused,
00450                    const char *file, unsigned int line)
00451 {
00452   return ptrfree_alloc(size, file, line);
00453 }
00454 
00455 void *operator new[](size_t size, Basics::gc_no_pointers_t unused,
00456                      const char *file, unsigned int line)
00457 {
00458   return ptrfree_alloc(size, file, line);
00459 }
00460 
00461 void* operator new(size_t size,
00462                    const char *file, unsigned int line)
00463 {
00464   return normal_alloc(size, file, line);
00465 }
00466 
00467 void* operator new[](size_t size,
00468                      const char *file, unsigned int line)
00469 {
00470   return normal_alloc(size, file, line);
00471 }
00472 
00473 
00474 
00475 
00476 void* operator new(size_t size) throw(std::bad_alloc)
00477 {
00478   return normal_alloc(size, "<UNKNOWN>", 0);
00479 }
00480 
00481 void* operator new[](size_t size) throw(std::bad_alloc)
00482 {
00483   return normal_alloc(size, "<UNKNOWN>", 0);
00484 }
00485 
00486 
00487 
00488 void operator delete(void *p) {  }
00489 void operator delete[](void *p) {  }
00490