📄 ggc.c
字号:
MOVE_CONS(ptr,val,n_htop,n_hp++); }#ifdef HYBRID } else if (ptr_within(ptr,g_start,g_end) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr,go_start,go_end)) { RRMA_STORE(p,gval,n_hp); ++n_hp;#endif } else { ASSERT(within(ptr, p)); ++n_hp; } continue; } case TAG_PRIMARY_HEADER: { if (header_is_thing(gval)) { if (header_is_bin_matchstate(gval)) { ErlBinMatchState *ms = (ErlBinMatchState *) n_hp; ErlBinMatchBuffer *mb = &(ms->mb); Eterm* orig; orig = &(mb->orig); ptr = boxed_val((mb->orig)); val = *ptr; if (in_area(ptr, water_start, water_size)) { /* Orig is in high water*/ if (MY_IS_MOVED(val)) { ASSERT(is_boxed(val)); *orig = val; mb->base=binary_bytes((mb->orig)); } else { MOVE_BOXED(ptr,val,n_htop,orig); mb->base=binary_bytes((mb->orig)); } }#ifdef HYBRID else if (ptr_within(ptr,g_start,g_end) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr,go_start,go_end)) { RRMA_STORE(p,gval,n_hp); }#endif else { ASSERT(within(ptr, p)); } } n_hp += (thing_arityval(gval)+1); } else n_hp++; continue; } default: { ++n_hp; continue; } } } return n_htop;}/* * This function sweeps both the remainder of the new heap * as well as the remainder of the old heap after the first pass * of the generational collector gen_gc(). */static Eterm*gen_cheney_old(Process *p, Eterm* from, Eterm** to, Eterm* low, Eterm* high, Eterm* old_htop, Eterm* objv, int nobj){ /* printf("small New heap: 0x%08lx Old heap: 0x%08lx\n", (Uint)from,(Uint)OLD_HEAP(p)); */ Eterm* n_hp; Eterm* n_htop; Eterm* oh_start; Eterm* oh_end; char* water_start = (char *)low; Uint water_size = (char *)high - water_start; Eterm* ptr; Eterm val; Eterm gval;#if HIPE char *const_start = (char*)hipe_constants_start; unsigned long const_size = (char*)hipe_constants_next - const_start;#endif#ifdef HYBRID Eterm *g_heap = global_heap; Eterm *g_htop = global_htop; Eterm *go_heap = global_old_heap; Eterm *go_htop = global_old_hend;#endif#ifdef INCREMENTAL Eterm *i_heap = inc_fromspc; Eterm *i_hend = inc_fromend;#endif n_hp = from; n_htop = *to; oh_start = OLD_HEAP(p); oh_end = OLD_HEND(p); while (n_hp != n_htop) { gval = *n_hp; switch (primary_tag(gval)) { case TAG_PRIMARY_BOXED: { ptr = boxed_val(gval); val = *ptr; if (ptr_within(ptr, oh_start, oh_end)) { n_hp++; }#ifdef HYBRID else if( ptr_within(ptr, g_heap, g_htop) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr, go_heap, go_htop) ) { RRMA_STORE(p,gval,n_hp); ++n_hp; }#endif#if HIPE else if( in_area(ptr, const_start, const_size) ) { ++n_hp; }#endif else if (MY_IS_MOVED(val)) { ASSERT(is_boxed(val)); *n_hp++ = val; } else if (in_area(ptr, water_start, water_size)) { /* Make object old */ MOVE_BOXED(ptr,val,old_htop,n_hp++); } else { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,n_hp++); } continue; } case TAG_PRIMARY_LIST: { ptr = list_val(gval); val = *ptr; if (ptr_within(ptr, oh_start, oh_end)) { n_hp++; }#ifdef HYBRID else if( ptr_within(ptr, g_heap, g_htop) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr, go_heap, go_htop) ) { RRMA_STORE(p,gval,n_hp); ++n_hp; }#endif#if HIPE else if( in_area(ptr, const_start, const_size) ) { ++n_hp; }#endif else if (is_non_value(val)) { *n_hp++ = ptr[1]; } else if (in_area(ptr, water_start, water_size)) { /* Make object old */ MOVE_CONS(ptr,val,old_htop,n_hp++); } else { ASSERT(within(ptr, p)); MOVE_CONS(ptr,val,n_htop,n_hp++); } continue; } case TAG_PRIMARY_HEADER: { if (header_is_thing(gval)) { if (header_is_bin_matchstate(gval)) { ErlBinMatchState *ms = (ErlBinMatchState *) n_hp; ErlBinMatchBuffer *mb = &(ms->mb); Eterm* orig; orig = &(mb->orig); ptr = boxed_val((mb->orig)); val = *ptr; if (ptr_within(ptr, oh_start, oh_end)) {} /* Orig is in old heap no changes needed*/#ifdef HYBRID else if( ptr_within(ptr, g_heap, g_htop) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr, go_heap, go_htop) ) { RRMA_STORE(p,gval,n_hp); }#endif#if HIPE else if( in_area(ptr, const_start, const_size) ) {} /* Orig is in constant area no changes needed*/#endif else if (MY_IS_MOVED(val)) { *orig = val; mb->base=binary_bytes(val); } else if (in_area(ptr, water_start, water_size)) { MOVE_BOXED(ptr,val,old_htop,orig); mb->base=binary_bytes((mb->orig)); } else { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,orig); mb->base=binary_bytes(*orig); } } n_hp += (thing_arityval(gval)+1); } else n_hp++; continue; } default: { n_hp++; continue; } } } /* Now set the parameter pointers for the caller */ *to = n_htop; return old_htop;}/* * Garbage collect the heap. However, all objects pointing * to the old generation heap may be left as is. * Every other turn, we remember the position on the heap * that turned out to be the heap top, every other second turn * we tenure all live objects that reside below that water mark. * This means that we only tenure objects that have survived at * least two collections.*/#include "hipe_debug.h"static voidgen_gc(Process *p, int new_sz, Eterm* objv, int nobj){ Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */ Eterm* n_hstart; Eterm* n_htop; int n; Eterm* ptr; Eterm val; Eterm gval; Eterm* oh_start = OLD_HEAP(p); Eterm* oh_end = OLD_HEND(p); Eterm* old_htop = OLD_HTOP(p); Eterm* low_water = HEAP_START(p); Eterm* high_water = HIGH_WATER(p); Eterm* tmp;#if HIPE char *const_start = (char*)hipe_constants_start; unsigned long const_size = (char*)hipe_constants_next - const_start;#endif#ifdef HYBRID Eterm *g_heap = global_heap; Eterm *g_htop = global_htop; Eterm *go_heap = global_old_heap; Eterm *go_htop = global_old_hend;#endif#ifdef INCREMENTAL Eterm *i_heap = inc_fromspc; Eterm *i_hend = inc_fromend;#endif VERBOSE(DEBUG_PRIVATE_GC,("Generational GC\n")); /* If flip is true, we need to tenure all (live) objects */ /* within the watermarks, if flip is 0, we need to alloc a */ /* new new_heap and copy all live objects to the new new_heap */ /* that is to not tenure any objects at all */ n_hstart = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*new_sz); n_htop = n_hstart; n = setup_rootset(p, objv, nobj, &rootset); GENSWEEP_NSTACK(p, old_htop, n_htop); while (n--) { Eterm* g_ptr = rootset.v[n]; Uint g_sz = rootset.sz[n]; while (g_sz--) { gval = *g_ptr; switch (primary_tag(gval)) { case TAG_PRIMARY_BOXED: { ptr = boxed_val(gval); val = *ptr; if (ptr_within(ptr, oh_start, oh_end)) { g_ptr++; }#ifdef HYBRID else if( ptr_within(ptr, g_heap, g_htop) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr, go_heap, go_htop) ) { ++g_ptr; }#endif#if HIPE else if( in_area(ptr, const_start, const_size) ) { ++g_ptr; }#endif else if (MY_IS_MOVED(val)) { ASSERT(is_boxed(val)); *g_ptr++ = val; } else if (ptr_within(ptr, low_water, high_water)) { MOVE_BOXED(ptr,val,old_htop,g_ptr++); } else { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,g_ptr++); } continue; } case TAG_PRIMARY_LIST: { ptr = list_val(gval); val = *ptr; if (ptr_within(ptr, oh_start, oh_end)) { g_ptr++; }#ifdef HYBRID else if( ptr_within(ptr, g_heap, g_htop) ||#ifdef INCREMENTAL ptr_within(ptr, i_heap, i_hend) ||#endif ptr_within(ptr, go_heap, go_htop) ) { ++g_ptr; }#endif#if HIPE else if( in_area(ptr, const_start, const_size) ) { ++g_ptr; }#endif else if (is_non_value(val)) { *g_ptr++ = ptr[1]; } else if (ptr_within(ptr, low_water, high_water)) { MOVE_CONS(ptr,val,old_htop,g_ptr++); } else { ASSERT(within(ptr, p)); MOVE_CONS(ptr,val,n_htop,g_ptr++); } continue; } default: { g_ptr++; continue; } } } } /* * Now all references in the rootset point to the new heap. However, * most references on the new heap point to the old heap so the next stage * is to scan through the new heap evacuating data from the old heap * until all is changed. */ tmp = n_htop; old_htop = gen_cheney_old(p, n_hstart, &tmp, low_water, high_water, old_htop, objv, nobj); n_htop = tmp; /* * And also if we have been tenuring, references on the second generation * may point to the old (soon to be deleted) heap. */ if (OLD_HTOP(p) < old_htop) { if (MBUF(p) == NULL) { old_htop = gen_cheney(p, HEAP_START(p), HEAP_END(p), OLD_HTOP(p), old_htop); } else { tmp = old_htop; (void) gen_cheney_old(p, OLD_HTOP(p), &tmp, OLD_HEAP(p), OLD_HEAP(p), NULL, NULL, 0); old_htop = tmp; } } OLD_HTOP(p) = old_htop; restore_rootset(p, &rootset); if (MSO(p).mso) { sweep_proc_bins(p, 0); }#ifndef HYBRID /* FIND ME! */ if (MSO(p).funs) { sweep_proc_funs(p, 0); }#endif if (MSO(p).externals) { sweep_proc_externals(p, 0); } remove_message_buffers(p); HIGH_WATER(p) = (HEAP_START(p) != HIGH_WATER(p)) ? n_hstart : n_htop; /* * Now we got to move the stack to the top of the new heap... */ n = HEAP_END(p) - p->stop; sys_memcpy(n_hstart + new_sz - n, p->stop, n * sizeof(Eterm));#ifdef DEBUG sys_memset(HEAP_START(p), DEBUG_BAD_BYTE, HEAP_SIZE(p) * sizeof(Eterm));#endif ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void *) HEAP_START(p), HEAP_SIZE(p)*sizeof(Eterm)); HEAP_START(p) = n_hstart; HEAP_TOP(p) = n_htop; HEAP_SIZE(p) = new_sz; HEAP_END(p) = n_hstart + new_sz; p->stop = HEAP_END(p) - n;#ifdef INCREMENTAL p->scan_top = HEAP_TOP(p);#endif}static voidsweep_proc_externals(Process *p, int fullsweep){ ExternalThing** prev; ExternalThing* ptr; Eterm* bot; Eterm* top;#ifdef HYBRID if (ma_gc_flags & GC_GLOBAL) { bot = global_old_heap; top = global_old_hend; prev = &erts_global_offheap.externals; ptr = erts_global_offheap.externals; } else#endif { bot = OLD_HEAP(p); top = OLD_HEND(p); prev = &MSO(p).externals; ptr = MSO(p).externals; } while (ptr) { Eterm* ppt = (Eterm *) ptr; if (MY_IS_MOVED(*ppt)) { /* Object is alive */ ExternalThing* ro = external_thing_ptr(*ppt); *prev = ro; /* Patch to moved pos */ prev = &ro->next; ptr = ro->next; } else if (fullsweep == 0 && ptr_within(ppt, bot, top)) { /* * Object resides on old heap, and we just did a * generational collection - keep object in list. */ prev = &ptr->next; ptr = ptr->next;#ifdef HYBRID } else if (fullsweep == 0 && (!(ma_gc_flags & GC_GLOBAL) && (ptr_within(ppt, global_heap, global_hend) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -