pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:38:   /* These defaults are only guesses and hardly tested at all. Please improve. */   double gc_garbage_ratio_low = 0.2;   double gc_time_ratio = 0.05;   double gc_garbage_ratio_high = 0.5;   double gc_min_time_ratio = 1.0/10000.0; /* Martys constant. */      /* This slowness factor approximately corresponds to the average over    * the last ten gc rounds. (0.9 == 1 - 1/10) */   double gc_average_slowness = 0.9;    + /* High-level callbacks. +  * NB: These are initialized from builtin.cmod. +  */ + /* Callback called when gc() starts. */ + struct svalue gc_pre_cb; +  + /* Callback called when the mark and sweep phase of the gc() is done. */ + struct svalue gc_post_cb; +  + /* Callback called for each object that is to be destructed explicitly +  * by the gc(). +  */ + struct svalue gc_destruct_cb; +  + /* Callback called when the gc() is about to exit. */ + struct svalue gc_done_cb; +    /* The gc will free all things with no external nonweak references    * that isn't referenced by live objects. An object is considered    * "live" if it contains code that must be executed when it is    * destructed; see gc_object_is_live for details. Live objects without    * external references are then destructed and garbage collected with    * normal refcount garbing (which might leave dead garbage around for    * the next gc). These live objects are destructed in an order that    * tries to be as well defined as possible using several rules:    *    * o If an object A references B single way, then A is destructed
pike.git/src/gc.c:3458:   #endif    num_allocs = 0;    saved_alloc_threshold = GC_MIN_ALLOC_THRESHOLD;    if (gc_evaluator_callback) {    remove_callback (gc_evaluator_callback);    gc_evaluator_callback = NULL;    }    return 0;    }    +  if (!SAFE_IS_ZERO(&gc_pre_cb)) { +  safe_apply_svalue(&gc_pre_cb, 0, 1); +  pop_stack(); +  } +    #ifdef DEBUG_MALLOC    if(debug_options & GC_RESET_DMALLOC)    reset_debug_malloc();   #endif    init_gc();    gc_generation++;    Pike_in_gc=GC_PASS_PREPARE;    gc_start_time = get_cpu_time();    gc_start_real_time = get_real_time();   #ifdef GC_DEBUG
pike.git/src/gc.c:3780:    pre_kill_objs = num_objects;    if (Pike_interpreter.evaluator_stack && !gc_destruct_everything) {    objs -= num_objects;    warn_bad_cycles();    objs += num_objects;    }   #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)    destroy_count = 0;   #endif    +  if (!SAFE_IS_ZERO(&gc_post_cb)) { +  safe_apply_svalue(&gc_post_cb, 0, 1); +  pop_stack(); +  } +     {    enum object_destruct_reason reason =   #ifdef DO_PIKE_CLEANUP    gc_destruct_everything ? DESTRUCT_CLEANUP :   #endif    DESTRUCT_GC;      #ifdef PIKE_DEBUG    {    struct gc_rec_frame *r;
pike.git/src/gc.c:3836:    GC_VERBOSE_DO(    fprintf(stderr, "| Killing %p with %d refs", o, o->refs);    if (o->prog) {    INT_TYPE line;    struct pike_string *file = get_program_line (o->prog, &line);    fprintf(stderr, ", prog %s:%d\n", file->str, line);    free_string(file);    }    else fputs(", is destructed\n", stderr);    ); +  if (!SAFE_IS_ZERO(&gc_destruct_cb)) { +  ref_push_object(o); +  safe_apply_svalue(&gc_destruct_cb, 1, 1); +  pop_stack(); +  }       destruct_object (o, reason);    free_object(o);    gc_free_extra_ref(o);   #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)    destroy_count++;   #endif    really_free_gc_rec_frame (kill_list);    kill_list = next;    }
pike.git/src/gc.c:4113: Inside #if defined(ALWAYS_GC)
  #ifdef ALWAYS_GC    ADD_GC_CALLBACK();   #else    if(d_flag > 3) ADD_GC_CALLBACK();   #endif      #ifdef DO_PIKE_CLEANUP    if (gc_destruct_everything)    return destroy_count;   #endif +  +  if (!SAFE_IS_ZERO(&gc_done_cb)) { +  push_int(unreferenced); +  safe_apply_svalue(&gc_done_cb, 1, 1); +  pop_stack(); +  } +     return unreferenced;   }      /*! @decl mapping(string:int|float) gc_status()    *! @belongs Debug    *!    *! Get statistics from the garbage collector.    *!    *! @returns    *! A mapping with the following content will be returned: