📄 ggc.c
字号:
else#endif { ERL_MESSAGE_TERM(mp) = *v_ptr++; ASSERT((is_nil(*v_ptr) || is_tuple(*v_ptr) || is_atom(*v_ptr))); ERL_MESSAGE_TOKEN(mp) = *v_ptr++; } mp = mp->next; } if (rootset->v_msg != rootset->def_msg) { erts_free(ERTS_ALC_T_MSG_ROOTS, rootset->v_msg); }}#if defined(HYBRID)#ifdef INCREMENTALvoid restore_one_rootset(Process *p, Rootset *rootset){ restore_this_rootset(p, rootset);}#endifvoid restore_rootset(Process *p, Rootset *rootset){ if (ma_gc_flags & GC_GLOBAL) { Uint i, j = 0; Uint n = erts_num_active_procs; for (i = 0; i < n; i++) { p = erts_active_procs[i]; if ((IS_ACTIVE(p) && INC_IS_ACTIVE(p)) || ma_gc_flags & GC_INCLUDE_ALL) { restore_this_rootset(p, &rootset[j++]); } } } else restore_this_rootset(p, rootset);}#elsevoid restore_rootset(Process *p, Rootset *rootset){ restore_this_rootset(p, rootset);}#endif /* HYBRID *//* * Remove all message buffers. */static voidremove_message_buffers(Process* p){ ErlHeapFragment* bp = MBUF(p); MBUF(p) = NULL; MBUF_SIZE(p) = 0; while (bp != NULL) { ErlHeapFragment* next_bp = bp->next;#ifdef DEBUG sys_memset(bp->mem, 0xf9, bp->size*sizeof(Eterm));#endif free_message_buffer(bp); bp = next_bp; }}/* ** This function is used when using fullsweep gc.** This replaces gen_gc for processes that use the** fullsweep algorithm and don't have an old_heap.** Parameters:** p: The process who is being garbage collected.** new_sz: The wanted size of the heap after collecting.** objv: Vector of "extra" objects to be "saved".** nobj: Number of objects in objv.*/static void fullsweep_heap(Process *p, int new_sz, Eterm* objv, int nobj){ Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */ Eterm* n_hstart; /* Start of new heap */ Eterm* n_htop; /* Top of new heap */ Eterm* n_heap; /* The new heap */ Eterm* n_hp; int n;#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 /* Create new, empty heap */ n_heap = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*new_sz); n_hstart = n_htop = n_heap; FLAGS(p) &= ~F_NEED_FULLSWEEP; VERBOSE(DEBUG_PRIVATE_GC,("Fullsweep GC\n"));#ifdef HYBRID p->nrr = 0;#endif n = setup_rootset(p, objv, nobj, &rootset); n_htop = fullsweep_nstack(p, n_htop); while (n--) { Eterm* g_ptr = rootset.v[n]; Eterm g_sz = rootset.sz[n]; while(g_sz--) { Eterm* ptr; Eterm val; Eterm gval = *g_ptr; switch (primary_tag(gval)) { case TAG_PRIMARY_BOXED: { ptr = boxed_val(gval); val = *ptr; if (MY_IS_MOVED(val)) { ASSERT(is_boxed(val)); *g_ptr++ = val; }#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 { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,g_ptr++); } continue; } case TAG_PRIMARY_LIST: { ptr = list_val(gval); val = *ptr; if (is_non_value(val)) *g_ptr++ = ptr[1];#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 { ASSERT(within(ptr, p)); MOVE_CONS(ptr,val,n_htop,g_ptr++); } continue; } default: { g_ptr++; continue; } } } } /* * Now all references on the stack 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 copied. */ n_hp = n_heap; while (n_hp != n_htop) { Eterm* ptr; Eterm val; Eterm gval = *n_hp; switch (primary_tag(gval)) { case TAG_PRIMARY_BOXED: { ptr = boxed_val(gval); val = *ptr; if (MY_IS_MOVED(val)) { ASSERT(is_boxed(val)); *n_hp++ = val; }#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 { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,n_hp++); } continue; } case TAG_PRIMARY_LIST: { ptr = list_val(gval); val = *ptr; if (is_non_value(val)) { *n_hp++ = ptr[1]; }#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 { 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* origptr; origptr = &(mb->orig); ptr = boxed_val(*origptr); val = *ptr; if (MY_IS_MOVED(val)) { *origptr = val; mb->base = binary_bytes(*origptr); }#if HIPE else if( in_area(ptr, const_start, const_size) ) {} /* Orig is in constant area 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#endif else { ASSERT(within(ptr, p)); MOVE_BOXED(ptr,val,n_htop,origptr); mb->base=binary_bytes(*origptr); ptr = boxed_val(*origptr); val = *ptr; } } n_hp += (thing_arityval(gval)+1); } else n_hp++; continue; } default: { n_hp++; continue; } } } restore_rootset(p, &rootset); if (MSO(p).mso) { sweep_proc_bins(p, 1); }#ifndef HYBRID /* FIND ME! */ if (MSO(p).funs) { sweep_proc_funs(p, 1); }#endif if (MSO(p).externals) { sweep_proc_externals(p, 1); } remove_message_buffers(p); if (OLD_HEAP(p) != NULL) {#ifdef DEBUG sys_memset(OLD_HEAP(p), DEBUG_BAD_BYTE, (OLD_HEND(p) - OLD_HEAP(p)) * sizeof(Eterm));#endif ERTS_HEAP_FREE(ERTS_ALC_T_OLD_HEAP, OLD_HEAP(p), (OLD_HEND(p)-OLD_HEAP(p))*sizeof(Eterm)); OLD_HEAP(p) = OLD_HTOP(p) = OLD_HEND(p) = NULL; } /* Move the stack, the beam stack is "in the heap" */ n = HEAP_END(p) - p->stop; sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));#ifdef DEBUG sys_memset(HEAP_START(p), DEBUG_BAD_BYTE, (HEAP_END(p) - HEAP_START(p)) * sizeof(Eterm));#endif ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void *) HEAP_START(p), HEAP_SIZE(p)*sizeof(Eterm)); HEAP_START(p) = n_heap; HEAP_TOP(p) = n_htop; HEAP_SIZE(p) = new_sz; HEAP_END(p) = n_heap + new_sz; p->stop = HEAP_END(p) - n; GEN_GCS(p) = 0; /* * Should we set p->high_water to p->heap or p->htop? * * Setting it to p->htop means that any surviving data will be * placed on the old heap in the next garbage collection. * This setting gives a better estone value, but one can assume * that more garbage is placed on the old heap. * * Setting it to p->heap means that two more garbage collections * are needed to move data to the old heap. */ HIGH_WATER(p) = HEAP_TOP(p);#ifdef INCREMENTAL p->scan_top = HEAP_TOP(p);#endif}voiderts_offset_off_heap(ErlOffHeap *ohp, Sint offs, Eterm* low, Eterm* high){ if (ohp->mso && ptr_within((Eterm *)ohp->mso, low, high)) { Eterm** uptr = (Eterm**) &ohp->mso; *uptr += offs; }#ifndef HYBRID /* FIND ME! */ if (ohp->funs && ptr_within((Eterm *)ohp->funs, low, high)) { Eterm** uptr = (Eterm**) &ohp->funs; *uptr += offs; }#endif if (ohp->externals && ptr_within((Eterm *)ohp->externals, low, high)) { Eterm** uptr = (Eterm**) &ohp->externals; *uptr += offs; }}static voidoffset_off_heap(Process* p, Eterm* low, Eterm* high, Sint offs){ erts_offset_off_heap(&MSO(p), offs, low, high);}static voidoffset_rootset(Process *p, Sint offs, Eterm* low, Eterm* high, Eterm* objv, int nobj){ if (p->dictionary) offset_heap(p->dictionary->data, p->dictionary->used, offs, low, high); if (p->debug_dictionary) offset_heap(p->debug_dictionary->data, p->debug_dictionary->used, offs, low, high); offset_heap(&p->fvalue, 1, offs, low, high); offset_heap(&p->ftrace, 1, offs, low, high); offset_heap(&p->group_leader, 1, offs, low, high); offset_heap(&p->seq_trace_token, 1, offs, low, high); offset_mqueue(p, offs, low, high); offset_heap_ptr(p->stop, (STACK_START(p) - p->stop), offs, low, high); offset_nstack(p, offs, low, high); if (nobj > 0) { offset_heap_ptr(objv, nobj, offs, low, high); } offset_off_heap(p, low, high, offs);#ifdef HYBRID if (p->nrr > 0) { int i; for (i = 0; i < p->nrr; i++) { if (ptr_within(p->rrsrc[i],low,high)) p->rrsrc[i] += offs; } }#endif}/* * Grow the new heap size to 'new_sz'. */static voidgrow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj){ Eterm* new_heap; int heap_size = HEAP_TOP(p) - HEAP_START(p); int stack_size = p->hend - p->stop; Sint offs; ASSERT(HEAP_SIZE(p) < new_sz); new_heap = (Eterm *) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP, (void*)HEAP_START(p), sizeof(Eterm)*(HEAP_SIZE(p)), sizeof(Eterm)*new_sz); VERBOSE(DEBUG_PRIVATE_GC, ("grow_new_heap: FROM %d UPTO %d (used %d)\n", HEAP_SIZE(p), new_sz, heap_size)); if ((offs = new_heap - HEAP_START(p)) == 0) { /* No move. */ HEAP_END(p) = new_heap + new_sz; sys_memmove(p->hend - stack_size, p->stop, stack_size * sizeof(Eterm)); p->stop = p->hend - stack_size; } else { Eterm* prev_stop = p->stop; offset_heap(new_heap, heap_size, offs, HEAP_START(p), HEAP_TOP(p)); HIGH_WATER(p) = new_heap + (HIGH_WATER(p) - HEAP_START(p));#ifdef INCREMENTAL p->scan_top = new_heap + (p->scan_top - HEAP_START(p));#endif HEAP_END(p) = new_heap + new_sz; prev_stop = new_heap + (p->stop - p->heap); p->stop = p->hend - stack_size; sys_memmove(p->stop, prev_stop, stack_size * sizeof(Eterm)); offset_rootset(p, offs, HEAP_START(p), HEAP_TOP(p), objv, nobj); HEAP_TOP(p) = new_heap + heap_size; HEAP_START(p) = new_heap; } HEAP_SIZE(p) = new_sz;}voiderts_shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj){ Eterm* new_heap; int heap_size = HEAP_TOP(p) - HEAP_START(p); Sint offs; int stack_size = p->hend - p->stop; ASSERT(new_sz != 0); ASSERT(new_sz < p->heap_sz); sys_memmove(p->heap + new_sz - stack_size, p->stop, stack_size * sizeof(Eterm)); new_heap = (Eterm *) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP, (void*)p->heap,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -