📄 ggc.c
字号:
ptr_within(ppt, global_old_heap, global_old_hend)))) { /* * An entry in the list of externals for a PRIVATE heap points to * the shared message area. This is WRONG! */ abort();#endif } else { /* Object has not been moved - deref it */ erts_deref_node_entry(ptr->node); *prev = ptr = ptr->next; } } ASSERT(*prev == NULL);}#ifndef HYBRID /* FIND ME! */static voidsweep_proc_funs(Process *p, int fullsweep){ ErlFunThing** prev; ErlFunThing* 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.funs; ptr = erts_global_offheap.funs; } else#endif { bot = OLD_HEAP(p); top = OLD_HEND(p); prev = &MSO(p).funs; ptr = MSO(p).funs; } while (ptr) { Eterm* ppt = (Eterm *) ptr; if (MY_IS_MOVED(*ppt)) { /* Object is alive */ ErlFunThing* ro = (ErlFunThing *) fun_val(*ppt); *prev = ro; /* Patch to moved pos */ prev = &ro->next; ptr = ro->next; } else if (fullsweep == 0 && ( ptr_within(ppt, bot, top)#ifdef HYBRID || (!(ma_gc_flags & GC_GLOBAL) && ( ptr_within(ppt, global_heap, global_hend) || ptr_within(ppt, global_old_heap, global_old_hend)))#endif )) { /* * Object resides on old heap, and we just did a * generational collection - keep object in list. */ prev = &ptr->next; ptr = ptr->next; } else { /* Object has not been moved - deref it */ ErlFunEntry* fe = ptr->fe; *prev = ptr = ptr->next; if (erts_refc_dectest(&fe->refc, 0) == 0) { erts_erase_fun_entry(fe); } } } ASSERT(*prev == NULL);}#endifstatic voidsweep_proc_bins(Process *p, int fullsweep){ ProcBin** prev; ProcBin* ptr; Binary* bptr; Eterm* bot; Eterm* top;#ifdef HYBRID if (ma_gc_flags & GC_GLOBAL) { bot = global_old_heap; top = global_old_hend; prev = &erts_global_offheap.mso; ptr = erts_global_offheap.mso; } else#endif { bot = OLD_HEAP(p); top = OLD_HEND(p); prev = &MSO(p).mso; ptr = MSO(p).mso; } /* * Note: In R7 we no longer force a fullsweep when we find binaries * on the old heap. The reason is that with the introduction of the * bit syntax we can expect binaries to be used a lot more. Note that * in earlier releases a brand new binary (or any other term) could * be put on the old heap during a gen-gc fullsweep, but this is * no longer the case in R7. */ while (ptr) { Eterm* ppt = (Eterm *) ptr; if (MY_IS_MOVED(*ppt)) { /* Object is alive */ ProcBin* ro = (ProcBin*) binary_val(*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 the 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) || ptr_within(ppt, global_old_heap, global_old_hend)))) { /* * An entry in the list of binaries for a PRIVATE heap points * to the shared message area. This is WRONG! */ abort();#endif } else { /* Object has not been moved - deref it */ *prev = ptr->next; bptr = ptr->val; if (erts_refc_dectest(&bptr->refc, 0) == 0) { if (bptr->flags & BIN_FLAG_MATCH_PROG) { erts_match_set_free(bptr); } else { erts_bin_free(bptr); } } ptr = *prev; } } ASSERT(*prev == NULL);}voiderts_gc_info(ErtsGCInfo *gcip){ if (gcip) { erts_smp_spin_lock(&info_lck); gcip->garbage_collections = garbage_cols; gcip->reclaimed = reclaimed; erts_smp_spin_unlock(&info_lck); }}extern void erts_init_ggc(void); /* Avoid warning... */ voiderts_init_ggc(void) /*called from erl_gc.c:erts_init_gc() */{ erts_smp_spinlock_init(&info_lck, "gc_info"); garbage_cols = 0; reclaimed = 0;}/************************************************************** *//* DEBUG routines *//****************************************************************/#ifdef DEBUGstatic voidcheck_mbuf_sz(Process *p){ ErlHeapFragment *bp; Uint sz; for (sz = 0, bp = MBUF(p); bp; bp = bp->next) sz += (Uint) bp->size; ASSERT(sz == MBUF_SIZE(p));}#endif#ifdef HARDDEBUGint within(Eterm *ptr, Process *p){ ErlHeapFragment* bp = MBUF(p); if (HEAP_START(p) <= ptr && ptr < HEAP_TOP(p)) { return 1; } if (OLD_HEAP(p) && (OLD_HEAP(p) <= ptr && ptr < OLD_HEND(p))) { return 1; }#ifdef HYBRID if (global_heap <= ptr && ptr < global_htop) { return 1; } if (global_old_heap <= ptr && ptr < global_old_hend) { return 1; }#ifdef INCREMENTAL if (inc_fromspc <= ptr && ptr < inc_fromend) { return 1; }#endif#endif while (bp != NULL) { if (bp->mem <= ptr && ptr < bp->mem + bp->size) { return 1; } bp = bp->next; }#if HIPE if(in_area(ptr,(char*)hipe_constants_start, (char*)hipe_constants_next - (char*)hipe_constants_start)) return 1;#endif return 0;}static voidcheck_pointer(Process* p, Eterm obj, int back_pointers_allowed, char *msg){ if (back_pointers_allowed && !within(ptr_val(obj), p)) { erl_exit(1, "%T: %s, line %d: %s: bad address %x\n", p->id, __FILE__, __LINE__, msg, obj); } else if (!back_pointers_allowed && !ptr_within(ptr_val(obj), OLD_HEAP(p), OLD_HEND(p)) ) { if (within(ptr_val(obj), p)) { erl_exit(1, "%T: %s, line %d: %s: back pointer %x\n", p->id, __FILE__, __LINE__, msg, obj); } else { erl_exit(1, "%T: %s, line %d: %s: bad address %x\n", p->id, __FILE__, __LINE__, msg, obj); } }}static voidcheck_binary(Process *p, Eterm obj, char* msg){ Eterm* ptr = binary_val(obj); int btype = thing_subtag(*ptr); ASSERT(is_thing(*ptr)); if (*ptr == DEBUG_BAD_WORD) { erl_exit(1, "%T: Clobbered binary left\n", p->id); } check_pointer(p, obj, 1, msg); switch (btype) { case REFC_BINARY_SUBTAG: { ProcBin *bp = (ProcBin*)binary_val(obj); if (bp->size > 0xffffffff) { erl_exit(1, "%T: check_binary: %s: LARGE binary found %x\n", p->id, msg, obj); } if (bp->bytes == 0) { erl_exit(1, "%T: check_binary: %s: NULL binary found %x\n", p->id, msg, obj); } if (erts_refc_read(&bp->val->refc, 0) <= 0) { erl_exit(1, "Bad refc in binary\n"); } } break; case HEAP_BINARY_SUBTAG: /* TODO */ break; case SUB_BINARY_SUBTAG: /* TODO */ break; default: erl_exit(1, "Unknown subtag in thing binary \n"); }}static voidcheck_stack(Process *p, char *msg){ Eterm* sp; Eterm* stack_end; int stack_size; int sz; sp = p->stop; stack_end = p->hend; sz = p->hend - p->htop; stack_size = stack_end - sp; if (sp < p->htop) { erl_exit(1, "%T: Overrun stack and heap\n", p->id); } for (sp = p->stop; sp < p->hend; sp++) { if (is_not_catch(*sp)) { ; } }}intchk_sys(void){ Process *p = *process_tab; int i, res = 0; for (i = 0; i < erts_max_processes; i++) { if ((p = process_tab[i]) != NULL) { res++; check_stack(p, "chk"); } } return res;}voidcheck_bins(Process *p){ ProcBin *pb = MSO(p).mso; while (pb) { check_binary(p, make_binary((Eterm*) pb), "CHECK"); pb = pb->next; } return;}#endif /* HARDDEBUG */#endif /* HEAP_FRAG_ELIM_TEST */#if defined(HYBRID) && defined(DEBUG)static void print_roots(Rootset *rootset, int n) /* FIND ME! */{ fprintf(stderr,"-- Rootset --\n\r"); while (n--) { int i = rootset[n].n; while (i--) { Eterm* g_ptr = rootset[n].v[i]; Uint g_sz = rootset[n].sz[i]; while (g_sz--) { Eterm gval = *g_ptr++; fprintf(stderr,"Root: 0x%08x\n\r",(int)gval); } } } fprintf(stderr,"-------------\n\r");}#endif#if defined(HYBRID) && !defined(INCREMENTAL)/*************************************************************************** * * * Garbage collection of the Message Area * * * ***************************************************************************/static void ma_gen_gc(Process*, int, Eterm*, int);static voidma_offset_off_heap(Process* p, Eterm* low, Eterm* high, int offs){ if (erts_global_offheap.mso && ptr_within((Eterm *)erts_global_offheap.mso, low, high)) { Eterm** uptr = (Eterm**) &erts_global_offheap.mso; *uptr += offs; }#ifndef HYBRID /* FIND ME! */ if (erts_global_offheap.funs && ptr_within((Eterm *)erts_global_offheap.funs, low, high)) { Eterm** uptr = (Eterm**) &erts_global_offheap.funs; *uptr += offs; }#endif if (erts_global_offheap.externals && ptr_within((Eterm *)erts_global_offheap.externals, low, high)) { Eterm** uptr = (Eterm**) &erts_global_offheap.externals; *uptr += offs; }}static voidma_offset_rootset(Process *cp, Sint offs, Eterm* low, Eterm* high, Eterm* objv, int nobj){ Uint i; Uint n = erts_num_active_procs; Process *p; for (i = 0; i < n; i++) { p = erts_active_procs[i]; 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_heap(p->heap, p->htop - p->heap, offs, low, high); offset_heap_ptr(p->rrma, p->nrr, offs, low, high); offset_nstack(p, offs, low, high); offset_off_heap(p, low, high, offs); if (p->old_heap) offset_heap(p->old_heap, p->old_htop - p->old_heap, offs, low, high); if (p != cp ) { if (p->arity > 0) offset_heap_ptr(p->arg_reg, p->arity, offs, low, high); } else if (nobj > 0) { offset_heap_ptr(objv, nobj, offs, low, high); }#ifdef DEBUG if (p->nrr > 0) { int i; for (i = 0; i < p->nrr; i++) { if (p->rrsrc[i] != NULL) { ASSERT(*(p->rrsrc[i]) == p->rrma[i]); } } }#endif } ma_offset_off_heap(p, low, high, offs);}#if defined(HIPE)#define MA_GENSWEEP_NSTACK(p,old_htop,n_htop) \ do { \ Eterm *tmp_old_htop = old_htop; \ Eterm *tmp_n_htop = n_htop; \ ma_gensweep_nstack((p),&tmp_old_htop,&tmp_n_htop); \ old_htop = tmp_old_htop; \ n_htop = tmp_n_htop; \ } while(0)/* * offset_nstack() can ignore the descriptor-based traversal the other * nstack procedures use and simply call offset_heap_ptr() instead. * This relies on two facts: * 1. The only live non-Erlang terms on an nstack are return addresses, * and they will be skipped thanks to the low/high range check. * 2. Dead values, even if mistaken for pointers into the low/high area, * can be offset safely since they won't be dereferenced. * * XXX: WARNING: If HiPE starts storing other non-Erlang values on the * nstack, such as floats, then this will have to be changed. */#else /* !HIPE */#define ma_fulls
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -