pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:1:   /*\   ||| This file a part of uLPC, and is copyright by Fredrik Hubinette   ||| uLPC is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/      #include "global.h"      #ifdef GC2 +  + #include "array.h" + #include "list.h" + #include "mapping.h" + #include "object.h" + #include "program.h" +    #include "gc.h"   #include "main.h"      /* Run garbage collect approximate every time we have    * 20 percent of all arrays, objects and programs is    * garbage.    */      #define GC_CONST 20   #define MIN_ALLOC_THRESHOLD 1000 -  + #defien MAX_ALLOC_THRESHOLD 10000000   #define MULTIPLIER 0.9 -  + #define MARKER_CHUNK_SIZE 1023    - void *gc_ptr; - INT32 gc_refs; +    INT32 num_objects;   INT32 num_allocs;   INT32 alloc_threshold = MIN_ALLOC_THRESHOLD;      static double objects_alloced;   static double objects_freed;    -  + #define GC_REFERENCED 1 +  + struct marker + { +  struct marker *next; +  void *marked; +  INT32 refs; +  INT32 flags; + }; +  + struct marker_chunk + { +  struct marker_chunk *next; +  struct marker markers[MARKER_CHUNK_SIZE]; + }; +  + static struct marker_chunk *chunk=0; + static int markers_left_in_chunk=0; +  + static struct marker *new_marker() + { +  if(!markers_left_in_chunk) +  { +  struct marker_chunk *m; +  m=(struct marker_chunk *)xalloc(sizeof(struct marker_chunk)); +  m->next=chunk; +  chunk=m; +  markers_left_in_chunk=MARKER_CHUNK_SIZE; +  } +  markers_left_in_chunk--; +  +  return chunk->markers + markers_left_in_chunk; + } +  + static struct marker **hash=0; + static int hashsize=0; +  + static struct marker *getmark(void *a) + { +  int hashval; +  struct marker *m; +  +  hashval=((long)a)%hashsize; +  +  for(m=hash[hashval];m;m=m->next) +  if(m->marked == a) +  return m; +  +  m=new_marker(); +  m->marked=a; +  m->refs=0; +  m->flags=0; +  m->next=hash[hashval]; +  hash[hashval]=m; +  +  return m; + } +  + void gc_check(void *a) + { +  getmark(a)->refs++; + } +  + int gc_is_referenced(void *a) + { +  struct marker *m; +  m=getmark(a); + #ifdef DEBUG +  if(m->refs > *(INT32 *)a) +  fatal("Ref counts are totally wrong!!!\n"); + #endif +  return m->refs < *(INT32 *)a; + } +  + int gc_mark(void *a) + { +  struct marker *m; +  m=getmark(a); +  +  if(m->flags & GC_REFERENCED) +  { +  return 0; +  }else{ +  m->flags |= GC_REFERENCED; +  return 1; +  } + } +  + int gc_do_free(void *a) + { +  struct marker *m; +  m=getmark(a); +  return !(m->flags & GC_REFERENCED); + } +  + /* Not all of these are primes, but they should be adequate */ + static INT32 hashprimes[] = + { +  31, /* ~ 2^0 = 1 */ +  31, /* ~ 2^1 = 2 */ +  31, /* ~ 2^2 = 4 */ +  31, /* ~ 2^3 = 8 */ +  31, /* ~ 2^4 = 16 */ +  31, /* ~ 2^5 = 32 */ +  61, /* ~ 2^6 = 64 */ +  127, /* ~ 2^7 = 128 */ +  251, /* ~ 2^8 = 256 */ +  541, /* ~ 2^9 = 512 */ +  1151, /* ~ 2^10 = 1024 */ +  2111, /* ~ 2^11 = 2048 */ +  4327, /* ~ 2^12 = 4096 */ +  8803, /* ~ 2^13 = 8192 */ +  17903, /* ~ 2^14 = 16384 */ +  32321, /* ~ 2^15 = 32768 */ +  65599, /* ~ 2^16 = 65536 */ +  133153, /* ~ 2^17 = 131072 */ +  270001, /* ~ 2^18 = 264144 */ +  547453, /* ~ 2^19 = 524288 */ +  1109891, /* ~ 2^20 = 1048576 */ +  2000143, /* ~ 2^21 = 2097152 */ +  4561877, /* ~ 2^22 = 4194304 */ +  9248339, /* ~ 2^23 = 8388608 */ +  16777215, /* ~ 2^24 = 16777216 */ +  33554431, /* ~ 2^25 = 33554432 */ +  67108863, /* ~ 2^26 = 67108864 */ +  134217727, /* ~ 2^27 = 134217728 */ +  268435455, /* ~ 2^28 = 268435456 */ +  536870911, /* ~ 2^29 = 536870912 */ +  1073741823,/* ~ 2^30 = 1073741824 */ +  2147483647,/* ~ 2^31 = 2147483648 */ + }; +    void do_gc()   {    double tmp;    INT32 tmp2; -  +  struct marker_chunk *m;       tmp2=num_objects;      #ifdef DEBUG    if(t_flag)    fprintf(stderr,"Garbage collecting ... ");   #endif       objects_alloced*=MULTIPLIER;    objects_alloced += (double) num_allocs;       objects_freed*=MULTIPLIER;    objects_freed += (double) num_objects;    -  gc_clear_array_marks(); -  gc_clear_object_marks(); -  gc_clear_program_marks(); +     -  +  /* init hash , hashsize will be a prime between num_objects/8 and +  * num_objects/4, this will assure that no re-hashing is needed. +  */ +  hashsize=my_log2(num_objects); +  hashsize-=2; +  if(hashsize<0) hashsize=0; +  hashsize=hashprimes[hashsize]; +  hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize); +  MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize); +  markers_left_in_chunk=0; +     gc_check_all_arrays(); -  +  gc_check_all_lists(); +  gc_check_all_mappings();    gc_check_all_programs();    gc_check_all_objects();    -  +  gc_mark_all_arrays(); +  gc_mark_all_lists(); +  gc_mark_all_mappings(); +  gc_mark_all_programs(); +  gc_mark_all_objects(); +  +  gc_free_all_unreferenced_arrays(); +  gc_free_all_unreferenced_lists(); +  gc_free_all_unreferenced_mappings(); +  gc_free_all_unreferenced_programs(); +  gc_free_all_unreferenced_objects(); +  +  +  /* Free hash table */ +  free((char *)hash); +  while(m=chunk) +  { +  chunk=m->next; +  free((char *)m); +  } +     objects_freed -= (double) num_objects;       tmp=(double)num_objects;    tmp=tmp * GC_CONST/100.0 * (objects_alloced+1.0) / (objects_freed+1.0);       if((int)tmp < alloc_threshold + num_allocs)    {    alloc_threshold=(int)tmp;    }else{    alloc_threshold+=num_allocs;
pike.git/src/gc.c:69:    if(alloc_threshold < MIN_ALLOC_THRESHOLD)    alloc_threshold = MIN_ALLOC_THRESHOLD;    num_allocs=0;      #ifdef DEBUG    if(t_flag)    fprintf(stderr,"done (freed %ld of %ld objects).\n",    (long)(tmp2-num_objects),(long)tmp2);   #endif   } +    #endif    -  -  -  -  -  -  -  -  -  +