diff --git a/C/exec.c b/C/exec.c index 8bca7977d..fd1f73a46 100644 --- a/C/exec.c +++ b/C/exec.c @@ -1607,6 +1607,7 @@ Yap_InitYaamRegs(void) MutableList = Yap_NewTimedVar(TermNil); AttsMutableList = Yap_NewTimedVar(MkIntTerm(0)); #endif + GcGeneration = Yap_NewTimedVar(MkIntTerm(0)); #if defined(YAPOR) || defined(THREADS) PP = NULL; WPP = NULL; diff --git a/C/grow.c b/C/grow.c index a315cf4f9..ef56dce02 100644 --- a/C/grow.c +++ b/C/grow.c @@ -159,6 +159,7 @@ SetHeapRegs(void) if (WokenGoals) WokenGoals = AbsAppl(PtoGloAdjust(RepAppl(WokenGoals))); #endif + GcGeneration = AbsAppl(PtoGloAdjust(RepAppl(GcGeneration))); } static void @@ -209,6 +210,7 @@ SetStackRegs(void) if (WokenGoals) WokenGoals = AbsAppl(PtoGloAdjust(RepAppl(WokenGoals))); #endif + GcGeneration = AbsAppl(PtoGloAdjust(RepAppl(GcGeneration))); } static void diff --git a/C/heapgc.c b/C/heapgc.c index d3a500cf5..3e10cae2e 100644 --- a/C/heapgc.c +++ b/C/heapgc.c @@ -34,7 +34,7 @@ static char SccsId[] = "%W% %G%"; /* global variables for garbage collection */ /* in a single gc */ -static unsigned long int total_marked; /* number of heap objects marked */ +static unsigned long int total_marked, total_oldies; /* number of heap objects marked */ #if DEBUG #ifdef COROUTINING @@ -55,6 +55,8 @@ static CELL *prev_HB; static tr_fr_ptr new_TR; +static CELL *HGEN; + STATIC_PROTO(void push_registers, (Int, yamop *)); STATIC_PROTO(void marking_phase, (tr_fr_ptr, CELL *, yamop *, CELL *)); STATIC_PROTO(void compaction_phase, (tr_fr_ptr, CELL *, yamop *, CELL *)); @@ -231,7 +233,7 @@ insort(CELL *a[], Int p, Int q) key = a[j]; i = j; - + while (i > p && a[i-1] > key) { a[i] = a[i-1]; i --; @@ -379,6 +381,8 @@ push_registers(Int num_regs, yamop *nextop) } al = al->NextArrayE; } + TrailTerm(TR) = GcGeneration; + TR++; #ifdef COROUTINING TrailTerm(TR) = WokenGoals; TrailTerm(TR+1) = MutableList; @@ -429,6 +433,7 @@ pop_registers(Int num_regs, yamop *nextop) } al = al->NextArrayE; } + GcGeneration = TrailTerm(ptr++); #ifdef COROUTINING #ifdef MULTI_ASSIGNMENT_VARIABLES WokenGoals = TrailTerm(ptr++); @@ -1071,13 +1076,17 @@ mark_variable(CELL_PTR current) unsigned int arity; begin: - ccur = *current; if (MARKED_PTR(current)) { POP_CONTINUATION(); } MARK(current); - total_marked++; + if (current >= H0 && current < H) { + total_marked++; + if (current < HGEN) + total_oldies++; + } PUSH_POINTER(current); + ccur = *current; next = GET_NEXT(ccur); if (IsVarTerm(ccur)) { @@ -1086,6 +1095,7 @@ mark_variable(CELL_PTR current) CELL cnext; /* do variable shunting between variables in the global */ cnext = *next; + if (!MARKED_PTR(next)) { if (IsVarTerm(cnext) && (CELL)next == cnext) { /* new global variable to new global variable */ @@ -1116,7 +1126,11 @@ mark_variable(CELL_PTR current) UNMARK(current); #endif *current = cnext; - total_marked--; + if (current >= H0 && current < H) { + total_marked--; + if (current < HGEN) + total_oldies--; + } POP_POINTER(); } else { #ifdef INSTRUMENT_GC @@ -1133,7 +1147,11 @@ mark_variable(CELL_PTR current) #if GC_NO_TAGS UNMARK(current); #endif - total_marked--; + if (current >= H0 && current < H) { + total_marked--; + if (current < HGEN) + total_oldies--; + } POP_POINTER(); } else #endif @@ -1207,6 +1225,9 @@ mark_variable(CELL_PTR current) #if GC_NO_TAGS MARK(next+2); #endif + if (next >= H0 && next < HGEN) { + total_oldies+=3; + } total_marked += 3; PUSH_POINTER(next); PUSH_POINTER(next+1); @@ -1214,6 +1235,9 @@ mark_variable(CELL_PTR current) POP_CONTINUATION(); case (CELL)FunctorDouble: MARK(next); + if (next >= H0 && next < HGEN) { + total_oldies+=2+SIZEOF_DOUBLE/SIZEOF_LONG_INT; + } total_marked += 2+SIZEOF_DOUBLE/SIZEOF_LONG_INT; PUSH_POINTER(next); PUSH_POINTER(next+1); @@ -1231,6 +1255,11 @@ mark_variable(CELL_PTR current) case (CELL)FunctorBigInt: MARK(next); /* size is given by functor + friends */ + if (next >= H0 && next < HGEN) { + total_oldies+=2+ + (sizeof(MP_INT)+ + (((MP_INT *)(next+1))->_mp_alloc*sizeof(mp_limb_t)))/CellSize; + } total_marked += 2+ (sizeof(MP_INT)+ (((MP_INT *)(next+1))->_mp_alloc*sizeof(mp_limb_t)))/CellSize; @@ -1260,6 +1289,9 @@ mark_variable(CELL_PTR current) arity = ArityOfFunctor((Functor)(cnext)); MARK(next); ++total_marked; + if (next >= H0 && next < HGEN) { + ++total_oldies; + } PUSH_POINTER(next); current = next+1; PUSH_CONTINUATION(current+1,arity-1); @@ -1310,7 +1342,6 @@ mark_external_reference(CELL *ptr) { CELL_PTR *old = iptop; #endif mark_variable(ptr); - total_marked--; POPSWAP_POINTER(old); } else { MARK(ptr); @@ -1327,7 +1358,6 @@ mark_external_reference2(CELL *ptr) { CELL_PTR *old = iptop; #endif mark_variable(ptr); - total_marked--; POPSWAP_POINTER(old); } else { mark_code(ptr,next); @@ -2746,15 +2776,17 @@ update_relocation_chain(CELL_PTR current, CELL_PTR dest) #if GC_NO_TAGS int rmarked = RMARKED(current); + UNRMARK(current); while (rmarked) { CELL current_tag; next = GET_NEXT(ccur); current_tag = TAG(ccur); ccur = *next; - rmarked = RMARKED(next); + rmarked = RMARKED(next); + UNRMARK(next); *next = (CELL) dest | current_tag; - /* UNRMARK(next); we are not going to use this */ } + *current = ccur; #elif TAGS_FAST_OPS while (RMARKED(current)) { register CELL cnext; @@ -2839,34 +2871,6 @@ set_next_hb(choiceptr gc_B) } } -static void -fast_compact(CELL *current) -{ - /* all cells are marked */ - CELL_PTR top = current; - - for (; current >= H0; current--) { - CELL ccell = *current; - CELL_PTR next; - - if ( - IN_BETWEEN(EndSpecials, ccell, MAX_SPECIALS_TAG) /* two first pages */ - && IsVarTerm(ccell) - ) { - int nofcells = (UNMARK_CELL(*current)-EndSpecials) / sizeof(CELL); - current -= nofcells ; - ccell = *current; - } - update_relocation_chain(current, current); - next = GET_NEXT(ccell); - if (next > top && next < H) { - /* push into reloc. */ - into_relocation_chain(current, next); - } - UNMARK(current); - } -} - /* * move marked objects on the heap upwards over unmarked objects, and reset * all pointers to point to new locations @@ -2895,21 +2899,10 @@ compact_heap(void) gl_depfr = LOCAL_top_dep_fr; #endif /* TABLING */ dest = (CELL_PTR) H0 + total_marked - 1; + for (current = H - 1; current >= start_from; current--) { if (MARKED_PTR(current)) { CELL ccell = UNMARK_CELL(*current); - if (FALSE && current == dest) { -#ifdef DEBUG - found_marked+=1+(current-H0); -#endif /* DEBUG */ - fast_compact(current); - start_from = current+1; - if (in_garbage > 0) { - current[1] = in_garbage; - in_garbage = 0; - } - break; - } if ( IN_BETWEEN(EndSpecials, ccell, MAX_SPECIALS_TAG) /* two first pages */ && IsVarTerm(ccell) @@ -3312,6 +3305,24 @@ marking_phase(tr_fr_ptr old_TR, CELL *current_env, yamop *curp, CELL *max) #endif } +static void +sweep_oldgen(CELL *max, CELL *base) +{ + CELL *ptr = base; + long int nof = 0; + while (ptr < max) { + if (MARKED_PTR(ptr)) { + nof++; + UNMARK(ptr); + if (HEAP_PTR(*ptr)) { + into_relocation_chain(ptr, GET_NEXT(*ptr)); + } + } + ptr++; + } + /* fprintf(stderr,"found %d, %p-%p\n", nof, base, max); */ +} + #ifdef COROUTINING static void sweep_delays(CELL *max) @@ -3338,6 +3349,23 @@ sweep_delays(CELL *max) static void compaction_phase(tr_fr_ptr old_TR, CELL *current_env, yamop *curp, CELL *max) { + CELL *CurrentH0 = NULL; + + int icompact = (iptop < (CELL_PTR *)ASP && 10*total_marked < H-H0); + + if (icompact) { + /* we are going to reuse the total space */ + if (HGEN != H0) { + /* undo optimisation */ + total_marked += total_oldies; + } + } else { + if (HGEN != H0) { + CurrentH0 = H0; + H0 = HGEN; + sweep_oldgen(HGEN, CurrentH0); + } + } #ifdef COROUTINING sweep_delays(max); #endif @@ -3345,19 +3373,25 @@ compaction_phase(tr_fr_ptr old_TR, CELL *current_env, yamop *curp, CELL *max) sweep_choicepoints(B); sweep_trail(B, old_TR); #ifdef HYBRID_SCHEME + if (icompact) { #ifdef DEBUG - if (total_marked + if (total_marked #ifdef COROUTINING - -total_smarked + -total_smarked #endif - != iptop-(CELL_PTR *)H && iptop < (CELL_PTR *)ASP -1024) - fprintf(Yap_stderr,"%% Oops on iptop-H (%ld) vs %ld\n", (unsigned long int)(iptop-(CELL_PTR *)H), total_marked); + != iptop-(CELL_PTR *)H && iptop < (CELL_PTR *)ASP -1024) + fprintf(Yap_stderr,"%% Oops on iptop-H (%ld) vs %ld\n", (unsigned long int)(iptop-(CELL_PTR *)H), total_marked); #endif - if (iptop < (CELL_PTR *)ASP && 10*total_marked < H-H0) { -#ifdef INSTRUMENT_GC +#if DEBUGX int effectiveness = (((H-H0)-total_marked)*100)/(H-H0); fprintf(Yap_stderr,"%% using pointers (%d)\n", effectiveness); #endif + if (CurrentH0) { + H0 = CurrentH0; + HGEN = H0; + total_marked += total_oldies; + CurrentH0 = NULL; + } quicksort((CELL_PTR *)H, 0, (iptop-(CELL_PTR *)H)-1); adjust_cp_hbs(); icompact_heap(); @@ -3375,6 +3409,9 @@ compaction_phase(tr_fr_ptr old_TR, CELL *current_env, yamop *curp, CELL *max) #endif compact_heap(); } + if (CurrentH0) { + H0 = CurrentH0; + } } static Int @@ -3385,7 +3422,7 @@ do_gc(Int predarity, CELL *current_env, yamop *nextop) tr_fr_ptr old_TR = NULL; UInt m_time, c_time, time_start, gc_time; CELL *max; - Int effectiveness; + Int effectiveness, tot; int gc_trace; if (setjmp(Yap_gc_restore) == 2) { @@ -3472,6 +3509,7 @@ do_gc(Int predarity, CELL *current_env, yamop *nextop) #endif time_start = Yap_cputime(); total_marked = 0; + total_oldies = 0; #ifdef COROUTING total_smarked = 0; #endif @@ -3499,22 +3537,33 @@ do_gc(Int predarity, CELL *current_env, yamop *nextop) iptop = (CELL_PTR *)H; #endif /* get the number of active registers */ + HGEN = H0+IntegerOfTerm(Yap_ReadTimedVar(GcGeneration)); + /* fprintf(stderr,"HGEN is %ld, %p, %p/%p\n", IntegerOfTerm(Yap_ReadTimedVar(GcGeneration)), HGEN, H,H0);*/ YAPEnterCriticalSection(); OldTR = (tr_fr_ptr)(old_TR = TR); push_registers(predarity, nextop); marking_phase(old_TR, current_env, nextop, max); + if (total_oldies > ((HGEN-H0)*8)/10) { + total_marked -= total_oldies; + tot = total_marked+(HGEN-H0); + } else { + HGEN = H0; + tot = total_marked; + } m_time = Yap_cputime(); gc_time = m_time-time_start; if (heap_cells) { if (heap_cells > 1000000) - effectiveness = (heap_cells-total_marked)/(heap_cells/100); + effectiveness = (heap_cells-tot)/(heap_cells/100); else - effectiveness = 100*(heap_cells-total_marked)/heap_cells; + effectiveness = 100*(heap_cells-tot)/heap_cells; } else effectiveness = 0; if (gc_verbose) { fprintf(Yap_stderr, "%% Mark: Recovered %ld cells of %ld (%ld%%) in %g sec\n", - (long int)(heap_cells-total_marked), (long int)heap_cells, (long int)effectiveness, (double)(m_time-time_start)/1000); + (long int)tot, (long int)heap_cells, (long int)effectiveness, (double)(m_time-time_start)/1000); + if (HGEN-H0) + fprintf(Yap_stderr,"%% previous generation has size %lu, with %lu (%ld%%) unmarked\n", HGEN-H0, (HGEN-H0)-total_oldies, 100*((HGEN-H0)-total_oldies)/(HGEN-H0)); #ifdef INSTRUMENT_GC { int i; @@ -3523,7 +3572,7 @@ do_gc(Int predarity, CELL *current_env, yamop *nextop) fprintf(Yap_stderr, "%% chain[%d]=%lu\n", i, chain[i]); } } - put_type_info((unsigned long int)total_marked); + put_type_info((unsigned long int)tot); fprintf(Yap_stderr,"%% %lu/%ld before and %lu/%ld after\n", old_vars, (unsigned long int)(B->cp_h-H0), new_vars, (unsigned long int)(H-B->cp_h)); fprintf(Yap_stderr,"%% %ld choicepoints\n", num_bs); } @@ -3535,13 +3584,15 @@ do_gc(Int predarity, CELL *current_env, yamop *nextop) pop_registers(predarity, nextop); TR = new_TR; YAPLeaveCriticalSection(); + /* fprintf(Yap_stderr,"NEW HGEN %ld (%ld)\n", H-H0, HGEN-H0);*/ + Yap_UpdateTimedVar(GcGeneration, MkIntegerTerm(H-H0)); c_time = Yap_cputime(); if (gc_verbose) { fprintf(Yap_stderr, "%% Compress: took %g sec\n", (double)(c_time-time_start)/1000); } gc_time += (c_time-time_start); TotGcTime += gc_time; - TotGcRecovered += heap_cells-total_marked; + TotGcRecovered += heap_cells-tot; if (gc_verbose) { fprintf(Yap_stderr, "%% GC %d took %g sec, total of %g sec doing GC so far.\n", GcCalls, (double)gc_time/1000, (double)TotGcTime/1000); fprintf(Yap_stderr, "%% Left %ld cells free in stacks.\n", diff --git a/C/save.c b/C/save.c index 1c4a60c21..0015626e7 100644 --- a/C/save.c +++ b/C/save.c @@ -417,6 +417,7 @@ save_regs(int mode) #ifdef DEPTH_LIMIT putout(DEPTH); #endif + putout(GcGeneration); } /* The operand base */ putcellptr(CellPtr(XREGS)); @@ -812,6 +813,9 @@ get_regs(int flag) if (Yap_ErrorMessage) return -1; #endif + GcGeneration = get_cell(); + if (Yap_ErrorMessage) + return -1; } /* Get the old bases */ OldXREGS = get_cellptr(); diff --git a/C/tracer.c b/C/tracer.c index 452ae56f3..07491af4d 100644 --- a/C/tracer.c +++ b/C/tracer.c @@ -120,8 +120,6 @@ low_level_trace(yap_low_level_port port, PredEntry *pred, CELL *args) /* extern int gc_calls; */ vsc_count++; - if (vsc_count < 487000) - return; #ifdef COMMENTED // if (vsc_count == 218280) // vsc_xstop = 1; diff --git a/H/Heap.h b/H/Heap.h index 0ca84d9fd..1e64a87d4 100644 --- a/H/Heap.h +++ b/H/Heap.h @@ -10,7 +10,7 @@ * File: Heap.h * * mods: * * comments: Heap Init Structure * -* version: $Id: Heap.h,v 1.83 2005-09-09 17:24:39 vsc Exp $ * +* version: $Id: Heap.h,v 1.84 2005-09-21 03:49:33 vsc Exp $ * *************************************************************************/ /* information that can be stored in Code Space */ @@ -86,6 +86,7 @@ typedef struct worker_local_struct { Term atts_mutable_list; #endif /* gc_stuff */ + Term gc_generation; /* global stack limit at last generation */ unsigned int gc_calls; /* number of times GC has been called */ Int tot_gc_time; /* total time spent in GC */ Int tot_gc_recovered; /* number of heap objects in all garbage collections */ @@ -732,6 +733,7 @@ struct various_codes *Yap_heap_regs; #define MutableList Yap_heap_regs->wl[worker_id].mutable_list #define AttsMutableList Yap_heap_regs->wl[worker_id].atts_mutable_list #endif +#define GcGeneration Yap_heap_regs->wl[worker_id].gc_generation #define GcCalls Yap_heap_regs->wl[worker_id].gc_calls #define TotGcTime Yap_heap_regs->wl[worker_id].tot_gc_time #define TotGcRecovered Yap_heap_regs->wl[worker_id].tot_gc_recovered @@ -769,6 +771,7 @@ struct various_codes *Yap_heap_regs; #define MutableList Yap_heap_regs->wl.mutable_list #define AttsMutableList Yap_heap_regs->wl.atts_mutable_list #endif +#define GcGeneration Yap_heap_regs->wl.gc_generation #define GcCalls Yap_heap_regs->wl.gc_calls #define TotGcTime Yap_heap_regs->wl.tot_gc_time #define TotGcRecovered Yap_heap_regs->wl.tot_gc_recovered