static void gc_mark_objects(MVM_VirtualMachine *mvm) { MVM_Object *obj; int i; for (obj = mvm->heap.header; obj; obj = obj->next) { gc_reset_mark(obj); } for (i = 0; i < mvm->static_v.variable_count; i++) { if (mvm->executable->global_variable[i].type->basic_type == MVM_STRING_TYPE || (mvm->executable->global_variable[i].type->derive != NULL && (mvm->executable->global_variable[i].type->derive[0].tag == MVM_ARRAY_DERIVE))) { gc_mark(mvm->static_v.variable[i].object); } } for (i = 0; i < mvm->stack.stack_pointer; i++) { if (mvm->stack.pointer_flags[i]) { gc_mark(mvm->stack.stack[i].object); } } }
void mark_stack_and_registers(void) { /* Works on many architecture/C-compilers. */ void**stack_pointer; /* Use to traverse the stack and registers assuming that `setjmp' will save registers in the C stack. */ jmp_buf stack_top; /* The jmp_buf buffer is in the C stack. */ (void)setjmp(stack_top); /* To fill the C stack with registers. */ stack_pointer=((void**)(&stack_top)); if (stack_pointer > stack_bottom){ /* Addresses increase as the stack grows (add some printf here to see if this is true on your architecture). */ stack_pointer+=(sizeof(jmp_buf)/sizeof(void*)); /* To traverse the jmp_buf as well. */ for ( ; stack_pointer >= stack_bottom; stack_pointer--) { gc_mark(*stack_pointer); } } else { /* Addresses decrease as the stack grows (add some printf here to see if this is true on your architecture). */ for ( ; stack_pointer <= stack_bottom; stack_pointer++) { gc_mark(*stack_pointer); } } }
lref_t port_gc_mark(lref_t obj) { gc_mark(PORT_PINFO(obj)->port_name); gc_mark(PORT_PINFO(obj)->user_object); return PORT_USER_OBJECT(obj); }
static void gc_mark_objects(CRB_Interpreter *inter) { CRB_Object *obj; Variable *v; CRB_LocalEnvironment *lv; int i; for (obj = inter->heap.header; obj; obj = obj->next) { gc_reset_mark(obj); } for (v = inter->variable; v; v = v->next) { if (dkc_is_object_value(v->value.type)) { gc_mark(v->value.u.object); } } for (lv = inter->top_environment; lv; lv = lv->next) { for (v = lv->variable; v; v = v->next) { if (dkc_is_object_value(v->value.type)) { gc_mark(v->value.u.object); } } gc_mark_ref_in_native_method(lv); } for (i = 0; i < inter->stack.stack_pointer; i++) { if (dkc_is_object_value(inter->stack.stack[i].type)) { gc_mark(inter->stack.stack[i].u.object); } } }
/* Garbage collector */ void gcollect(void) { int i, n, p; /* mark */ for (i = 0; i < t_symb_free; i++) gc_mark(t_symb_val[i]); for (i = 0; i < t_symb_free; i++) gc_mark(t_symb_fval[i]); for (i = 0; i < t_stack_ptr; i++) gc_mark(t_stack[i]); /* sweep */ t_cons_free = -1; for (i = 0, n = 0; i != NCONS; i++){ if ((t_cons_car[i] & D_GC_MARK) == 0){ /* collect */ n++; if (t_cons_free == -1){ t_cons_free = i; } else { t_cons_car[p] = i; } t_cons_car[i] = i; p = i; } t_cons_car[i] &= ~D_GC_MARK; /* clear mark */ } if (n == 0){ /* no more cells... */ printf(errmsg_no_memory); quit(); } }
lref_t fasl_reader_gc_mark(lref_t obj) { for (size_t ii = 0; ii < FAST_LOAD_STACK_DEPTH; ii++) gc_mark(FASL_READER_STREAM(obj)->stack[ii]); gc_mark(FASL_READER_STREAM(obj)->accum); return FASL_READER_STREAM(obj)->table; }
static void gc_scan_name_frame (Sophon_VM *vm, Sophon_NameFrame *frame) { if (frame->frame.bottom) gc_mark(vm, (Sophon_GCObject*)(frame->frame.bottom)); gc_mark(vm, (Sophon_GCObject*)frame->name); sophon_value_mark(vm, frame->v); }
void gc_mark(Object * object) { if (gc_header(object)->marked == 0) { gc_header(object)->marked = 1; if (is_atom(object) == 0) { gc_mark(car(object)); gc_mark(cdr(object)); } } }
void jl_gc_collect(void) { size_t actual_allocd = allocd_bytes; total_allocd_bytes += allocd_bytes; allocd_bytes = 0; if (is_gc_enabled) { JL_SIGATOMIC_BEGIN(); jl_in_gc = 1; #if defined(GCTIME) || defined(GC_FINAL_STATS) double t0 = clock_now(); #endif gc_mark(); #ifdef GCTIME JL_PRINTF(JL_STDERR, "mark time %.3f ms\n", (clock_now()-t0)*1000); #endif #if defined(MEMPROFILE) all_pool_stats(); big_obj_stats(); #endif #ifdef GCTIME t0 = clock_now(); #endif sweep_weak_refs(); gc_sweep(); #ifdef GCTIME JL_PRINTF(JL_STDERR, "sweep time %.3f ms\n", (clock_now()-t0)*1000); #endif int nfinal = to_finalize.len; run_finalizers(); jl_in_gc = 0; JL_SIGATOMIC_END(); #if defined(GC_FINAL_STATS) total_gc_time += (clock_now()-t0); total_freed_bytes += freed_bytes; #endif #ifdef OBJPROFILE print_obj_profile(); htable_reset(&obj_counts, 0); #endif // tune collect interval based on current live ratio #if defined(MEMPROFILE) jl_printf(JL_STDERR, "allocd %ld, freed %ld, interval %ld, ratio %.2f\n", actual_allocd, freed_bytes, collect_interval, (double)freed_bytes/(double)actual_allocd); #endif if (freed_bytes < (7*(actual_allocd/10))) { if (collect_interval <= 2*(max_collect_interval/5)) collect_interval = 5*(collect_interval/2); } else { collect_interval = default_collect_interval; } freed_bytes = 0; // if a lot of objects were finalized, re-run GC to finish freeing // their storage if possible. if (nfinal > 100000) jl_gc_collect(); } }
void jl_gc_collect(void) { allocd_bytes = 0; if (is_gc_enabled) { JL_SIGATOMIC_BEGIN(); #ifdef GCTIME double t0 = clock_now(); #endif gc_mark(); #ifdef GCTIME ios_printf(ios_stderr, "mark time %.3f ms\n", (clock_now()-t0)*1000); #endif #if defined(MEMPROFILE) all_pool_stats(); big_obj_stats(); #endif #ifdef GCTIME t0 = clock_now(); #endif sweep_weak_refs(); gc_sweep(); #ifdef GCTIME ios_printf(ios_stderr, "sweep time %.3f ms\n", (clock_now()-t0)*1000); #endif run_finalizers(); JL_SIGATOMIC_END(); #ifdef OBJPROFILE print_obj_profile(); htable_reset(&obj_counts, 0); #endif } }
static void gc_scan_decl_frame (Sophon_VM *vm, Sophon_DeclFrame *frame) { Sophon_Value *v, *vlast; sophon_hash_for_each(vm, &frame->var_hash, gc_mark_value_entry, NULL); if (frame->func) gc_scan_func(vm, frame->func); v = frame->v; vlast = v + frame->vbuf_size; while (v < vlast) { sophon_value_mark(vm, *v); v++; } if (frame->frame.bottom) gc_mark(vm, (Sophon_GCObject*)(frame->frame.bottom)); sophon_value_mark(vm, frame->callerv); sophon_value_mark(vm, frame->calleev); sophon_value_mark(vm, frame->thisv); sophon_value_mark(vm, frame->argsv); }
/* Perform a mark_and_compact garbage collection, moving all live objects * to the start of the heap. Anything that we don't mark is dead. * * 1. Walk object graph starting from roots, marking live objects. * * 2. Walk all live objects and compute their forwarding addresses starting from start_of_heap. * * 3. Alter all non-NULL roots to point to the object's forwarding address. * * 4. For each live object: * a) alter all non-NULL managed pointer fields to point to the forwarding addresses. * b) unmark object * * 5. Physically move object to forwarding address towards front of heap and reset marked. * * This phase must be last as the object stores the forwarding address. When we move, * we overwrite objects and could kill a forwarding address in a live object. */ void gc() { if (DEBUG) printf("GC\n"); gc_mark(); // TODO: add next_live field to heap_object to avoid walking all objects to find live // oops actually must move objects from low to high ptr addresses. // reallocate all live objects starting from start_of_heap if (DEBUG) printf("FORWARD\n"); next_free_forwarding = heap; foreach_live(realloc_object); // for each marked (live) object, record forwarding address // make sure all roots point at new object addresses update_roots(); // can't move objects before updating roots; roots point at *old* location if (DEBUG) printf("UPDATE PTR FIELDS\n"); foreach_live(update_ptr_fields); // Now that we know where to move objects, update and move objects if (DEBUG) printf("COMPACT\n"); // TODO: can this be foreach_live()? foreach_object(move_live_objects_to_forwarding_addr); // also visits the dead to wack p->magic // reset highwater mark *after* we've moved everything around; foreach_object() uses next_free next_free = next_free_forwarding; // next object to be allocated would occur here if (DEBUG) printf("DONE GC\n"); }
static void gc_scan_with_frame (Sophon_VM *vm, Sophon_WithFrame *frame) { if (frame->frame.bottom) gc_mark(vm, (Sophon_GCObject*)(frame->frame.bottom)); sophon_value_mark(vm, frame->withv); }
void gc_collect() { gc_wait(); gc_mark(); gc_sweep(); last_collect = _systime_millis; gc_checktime = 0; gc_signal(); }
void gc(void) { fprintf(stderr, "%s\n", "running gc..."); gc_mark(); gc_sweep(); fprintf(stderr, "%s\n", "finished gc"); }
/* when marking a list node also mark it's successors */ void node_mark(void* object) { if (!object) return; Node n = (Node)object; gc_mark(node_mark,n->next); }
void gc_mark( VALUE value ) { if( !IS_PTR_VALUE(value) ) { return; } if( FLAG_TEST( value, FLAG_GC_MARK ) ) { return; } if( RANY(value)->as.free.flags == 0 ) { return; } FLAG_SET( value, FLAG_GC_MARK ); gc_mark( R_BASIC(value)->klass ); switch(VALUE_TYPE(value)) { case TYPE_STRING: break; case TYPE_ARRAY: { int i; for( i=0; i< R_ARRAY(value)->len; ++i ) { gc_mark( R_ARRAY(value)->ptr[i] ); } break; } case TYPE_CLASS: gc_mark( (VALUE)(R_CLASS(value)->super) ); var_tbl_mark( R_CLASS(value)->ival_tbl ); var_tbl_mark( R_CLASS(value)->method_tbl ); break; case TYPE_OBJECT: gc_mark( (VALUE)(R_BASIC(value)->klass) ); var_tbl_mark( R_OBJECT(value)->ival_tbl ); break; case TYPE_METHOD: break; default: rabbit_bug("(GC MARK)未対応型のオブジェクトが送られてきました(type %d)", VALUE_TYPE(value) ); } }
static void gc_mark_value_entry (Sophon_VM *vm, Sophon_HashEntry *ent, Sophon_Ptr data) { Sophon_String *name = (Sophon_String*)ent->key; Sophon_Value value = (Sophon_Value)ent->value; gc_mark(vm, (Sophon_GCObject*)name); sophon_value_mark(vm, value); }
void mark_stack_and_registers(void){ void**stack_pointer; jmp_buf stack_top; (void)setjmp(stack_top); stack_pointer=((void**)(&stack_top)); stack_pointer+=((sizeof(jmp_buf)/sizeof(void*))-1); for(; stack_pointer >= stack_bottom; stack_pointer--) gc_mark(*stack_pointer); }
static void gc_mark_ref_in_native_method(CRB_LocalEnvironment *env) { RefInNativeFunc *ref; for (ref = env->ref_in_native_method; ref; ref = ref->next) { gc_mark(ref->object); } }
/* mark recursively */ void gc_mark(long s) { for ( ; D_GET_TAG(s) == TAG_CONS; s = l_cdr(s)){ if ((t_cons_car[D_GET_DATA(s)] & D_GC_MARK) != 0) /* visited before */ return; t_cons_car[D_GET_DATA(s)] |= D_GC_MARK; /* mark */ gc_mark(l_car(s)); /* visit car part */ } }
/* String:string(const source[] = "") */ static cell AMX_NATIVE_CALL n_bstring(AMX *amx,cell *params) { cell hstr = 0; char *cstr; amx_StrParam(amx, params[1], cstr); if (cstr != NULL) hstr = (cell)cstr2bstr(cstr); VERIFY( gc_mark(hstr) ); return hstr; }
void mark_stack_and_registers (void) { void** max = stack_bottom + 10; /* stack_bottom correction here. */ void** stack_pointer; jmp_buf registers; (void)setjmp(registers); stack_pointer = ((void**)(®isters)); while (stack_pointer < max) { gc_mark(*(stack_pointer++)); } }
void gc_collect() { int prev_num = heap_num; //printf("gc %p ptr %p\n", &prev_num+1, ptr);// スタックトップ gc_mark(get_stack_top(), NULL); gc_sweep(); heap_max = prev_num * 2; debug("Collected %d objects, %d remaining.\n", prev_num - heap_num, heap_num); }
void mark_stack_and_registers (void) { void** max = stack_bottom + 5; /* [4..1065] seems to be a valid range for MS C++ */ void** stack_pointer; jmp_buf stack_top; (void)setjmp(stack_top); stack_pointer = ((void**)(&stack_top)); while (stack_pointer < max) { gc_mark(*(stack_pointer++)); } }
static void *gc_alloc(int size) { void *o = gc_alloc_space(size); if(NULL == o) { gc_clear_mark(); gc_mark(); o = gc_alloc_space(size); if (o == NULL) { if (DEBUG) printf("memory is full"); return NULL; } } return o; }
void gc_collect() { long prev_num = vm->heap_num; debug2("gc mark\n"); gc_mark(); debug2("gc sweep\n"); gc_sweep(NULL); vm->heap_max = prev_num * 2; debug("Collected %ld objects, %ld remaining.\n", prev_num - vm->heap_num, vm->heap_num); }
static void gc_scan_array (Sophon_VM *vm, Sophon_Array *arr) { Sophon_Value *v, *vlast; if (arr->ref) gc_mark(vm, arr->ref); v = arr->v; vlast = v + arr->len; while (v < vlast) { sophon_value_mark(vm, *v); v++; } }
int gc_num_live_objects() { // gc_unmark(); gc_mark(); int n = 0; void *p = heap; while (p >= heap && p < next_free) { // for each marked (live) object, record forwarding address if (((heap_object *)p)->marked) { n++; } p = p + ((heap_object *)p)->size; } gc_unmark(); return n; }
void jl_gc_collect(void) { allocd_bytes = 0; if (is_gc_enabled) { freed_bytes = 0; JL_SIGATOMIC_BEGIN(); #if defined(GCTIME) || defined(GC_FINAL_STATS) double t0 = clock_now(); #endif gc_mark(); #ifdef GCTIME JL_PRINTF(JL_STDERR, "mark time %.3f ms\n", (clock_now()-t0)*1000); #endif #if defined(MEMPROFILE) all_pool_stats(); big_obj_stats(); #endif #ifdef GCTIME t0 = clock_now(); #endif sweep_weak_refs(); gc_sweep(); #ifdef GCTIME JL_PRINTF(JL_STDERR, "sweep time %.3f ms\n", (clock_now()-t0)*1000); #endif run_finalizers(); JL_SIGATOMIC_END(); #if defined(GC_FINAL_STATS) total_gc_time += (clock_now()-t0); total_freed_bytes += freed_bytes; #endif #ifdef OBJPROFILE print_obj_profile(); htable_reset(&obj_counts, 0); #endif // tune collect interval based on current live ratio if (freed_bytes < ((2*collect_interval)/5)) { if (collect_interval <= (2*max_collect_interval)/5) collect_interval = (5*collect_interval)/2; } else { collect_interval = default_collect_interval; } } }