void LDV_recordDead( StgClosure *c, nat size ) { void *id; nat t; counter *ctr; if (era > 0 && closureSatisfiesConstraints(c)) { size -= sizeofW(StgProfHeader); ASSERT(LDVW(c) != 0); if ((LDVW((c)) & LDV_STATE_MASK) == LDV_STATE_CREATE) { t = (LDVW((c)) & LDV_CREATE_MASK) >> LDV_SHIFT; if (t < era) { if (RtsFlags.ProfFlags.bioSelector == NULL) { censuses[t].void_total += (long)size; censuses[era].void_total -= (long)size; ASSERT(censuses[t].void_total < censuses[t].not_used); } else { id = closureIdentity(c); ctr = lookupHashTable(censuses[t].hash, (StgWord)id); ASSERT( ctr != NULL ); ctr->c.ldv.void_total += (long)size; ctr = lookupHashTable(censuses[era].hash, (StgWord)id); if (ctr == NULL) { ctr = arenaAlloc(censuses[era].arena, sizeof(counter)); initLDVCtr(ctr); insertHashTable(censuses[era].hash, (StgWord)id, ctr); ctr->identity = id; ctr->next = censuses[era].ctrs; censuses[era].ctrs = ctr; } ctr->c.ldv.void_total -= (long)size; } } } else {
STATIC_INLINE GNUC_ATTR_HOT void copy_tag(StgClosure **p, const StgInfoTable *info, StgClosure *src, nat size, nat gen_no, StgWord tag) { StgPtr to, from; nat i; to = alloc_for_copy(size,gen_no); from = (StgPtr)src; to[0] = (W_)info; for (i = 1; i < size; i++) { // unroll for small i to[i] = from[i]; } // if (to+size+2 < bd->start + BLOCK_SIZE_W) { // __builtin_prefetch(to + size + 2, 1); // } #if defined(PARALLEL_GC) { const StgInfoTable *new_info; new_info = (const StgInfoTable *)cas((StgPtr)&src->header.info, (W_)info, MK_FORWARDING_PTR(to)); if (new_info != info) { #ifdef PROFILING // We copied this object at the same time as another // thread. We'll evacuate the object again and the copy // we just made will be discarded at the next GC, but we // may have copied it after the other thread called // SET_EVACUAEE_FOR_LDV(), which would confuse the LDV // profiler when it encounters this closure in // processHeapClosureForDead. So we reset the LDVW field // here. LDVW(to) = 0; #endif return evacuate(p); // does the failed_to_evac stuff } else { *p = TAG_CLOSURE(tag,(StgClosure*)to); } } #else src->header.info = (const StgInfoTable *)MK_FORWARDING_PTR(to); *p = TAG_CLOSURE(tag,(StgClosure*)to); #endif #ifdef PROFILING // We store the size of the just evacuated object in the LDV word so that // the profiler can guess the position of the next object later. // This is safe only if we are sure that no other thread evacuates // the object again, so we cannot use copy_tag_nolock when PROFILING. SET_EVACUAEE_FOR_LDV(from, size); #endif }