void scheduleFinalizers(Capability *cap, StgWeak *list) { StgWeak *w; StgTSO *t; StgMutArrPtrs *arr; StgWord size; nat n, i; Task *task; task = myTask(); if (task != NULL) { task->running_finalizers = rtsTrue; } // count number of finalizers, and kill all the weak pointers first... n = 0; for (w = list; w; w = w->link) { StgArrWords *farr; // Better not be a DEAD_WEAK at this stage; the garbage // collector removes DEAD_WEAKs from the weak pointer list. ASSERT(w->header.info != &stg_DEAD_WEAK_info); if (w->finalizer != &stg_NO_FINALIZER_closure) { n++; } farr = (StgArrWords *)UNTAG_CLOSURE(w->cfinalizer); if ((StgClosure *)farr != &stg_NO_FINALIZER_closure) runCFinalizer((void *)farr->payload[0], (void *)farr->payload[1], (void *)farr->payload[2], farr->payload[3]); #ifdef PROFILING // A weak pointer is inherently used, so we do not need to call // LDV_recordDead(). // // Furthermore, when PROFILING is turned on, dead weak // pointers are exactly as large as weak pointers, so there is // no need to fill the slop, either. See stg_DEAD_WEAK_info // in StgMiscClosures.hc. #endif SET_HDR(w, &stg_DEAD_WEAK_info, w->header.prof.ccs); } if (task != NULL) { task->running_finalizers = rtsFalse; } // No finalizers to run? if (n == 0) return; debugTrace(DEBUG_weak, "weak: batching %d finalizers", n); size = n + mutArrPtrsCardTableSize(n); arr = (StgMutArrPtrs *)allocate(cap, sizeofW(StgMutArrPtrs) + size); TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs), n, 0); SET_HDR(arr, &stg_MUT_ARR_PTRS_FROZEN_info, CCS_SYSTEM); arr->ptrs = n; arr->size = size; n = 0; for (w = list; w; w = w->link) { if (w->finalizer != &stg_NO_FINALIZER_closure) { arr->payload[n] = w->finalizer; n++; } } // set all the cards to 1 for (i = n; i < size; i++) { arr->payload[i] = (StgClosure *)(W_)(-1); } t = createIOThread(cap, RtsFlags.GcFlags.initialStkSize, rts_apply(cap, rts_apply(cap, (StgClosure *)runFinalizerBatch_closure, rts_mkInt(cap,n)), (StgClosure *)arr) ); scheduleThread(cap,t); }
StgMutArrPtrs *gtc_heap_view_closurePtrs(Capability *cap, StgClosure *closure) { ASSERT(LOOKS_LIKE_CLOSURE_PTR(closure)); StgWord size = gtc_heap_view_closureSize(closure); StgWord nptrs = 0; StgWord i; // First collect all pointers here, with the comfortable memory bound // of the whole closure. Afterwards we know how many pointers are in // the closure and then we can allocate space on the heap and copy them // there StgClosure *ptrs[size]; StgClosure **end; StgClosure **ptr; StgInfoTable *info = get_itbl(closure); StgThunkInfoTable *thunk_info; StgFunInfoTable *fun_info; switch (info->type) { case INVALID_OBJECT: barf("Invalid Object"); break; // No pointers case ARR_WORDS: break; // Default layout case CONSTR_1_0: case CONSTR_0_1: case CONSTR_2_0: case CONSTR_1_1: case CONSTR_0_2: case CONSTR: case CONSTR_STATIC: case CONSTR_NOCAF_STATIC: case PRIM: case FUN: case FUN_1_0: case FUN_0_1: case FUN_1_1: case FUN_2_0: case FUN_0_2: case FUN_STATIC: end = closure->payload + info->layout.payload.ptrs; for (ptr = closure->payload; ptr < end; ptr++) { ptrs[nptrs++] = *ptr; } break; case THUNK: case THUNK_1_0: case THUNK_0_1: case THUNK_1_1: case THUNK_2_0: case THUNK_0_2: case THUNK_STATIC: end = ((StgThunk *)closure)->payload + info->layout.payload.ptrs; for (ptr = ((StgThunk *)closure)->payload; ptr < end; ptr++) { ptrs[nptrs++] = *ptr; } break; case THUNK_SELECTOR: ptrs[nptrs++] = ((StgSelector *)closure)->selectee; break; case AP: ptrs[nptrs++] = ((StgAP *)closure)->fun; gtc_heap_view_closure_ptrs_in_pap_payload(ptrs, &nptrs, ((StgAP *)closure)->fun, ((StgAP *)closure)->payload, ((StgAP *)closure)->n_args); break; case PAP: ptrs[nptrs++] = ((StgPAP *)closure)->fun; gtc_heap_view_closure_ptrs_in_pap_payload(ptrs, &nptrs, ((StgPAP *)closure)->fun, ((StgPAP *)closure)->payload, ((StgPAP *)closure)->n_args); break; case AP_STACK: ptrs[nptrs++] = ((StgAP_STACK *)closure)->fun; for (i = 0; i < ((StgAP_STACK *)closure)->size; ++i) { ptrs[nptrs++] = ((StgAP_STACK *)closure)->payload[i]; } break; case BCO: ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->instrs; ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->literals; ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->ptrs; break; case IND: case IND_PERM: case IND_STATIC: case BLACKHOLE: ptrs[nptrs++] = (StgClosure *)(((StgInd *)closure)->indirectee); break; case MUT_ARR_PTRS_CLEAN: case MUT_ARR_PTRS_DIRTY: case MUT_ARR_PTRS_FROZEN: case MUT_ARR_PTRS_FROZEN0: for (i = 0; i < ((StgMutArrPtrs *)closure)->ptrs; ++i) { ptrs[nptrs++] = ((StgMutArrPtrs *)closure)->payload[i]; } break; case MUT_VAR_CLEAN: ptrs[nptrs++] = ((StgMutVar *)closure)->var; break; case MVAR_DIRTY: case MVAR_CLEAN: ptrs[nptrs++] = (StgClosure *)((StgMVar *)closure)->head; ptrs[nptrs++] = (StgClosure *)((StgMVar *)closure)->tail; ptrs[nptrs++] = ((StgMVar *)closure)->value; break; default: //fprintf(stderr,"closurePtrs: Cannot handle type %s yet\n", gtc_heap_view_closure_type_names[info->type]); break; } size = nptrs + mutArrPtrsCardTableSize(nptrs); StgMutArrPtrs *arr = (StgMutArrPtrs *)allocate(cap, sizeofW(StgMutArrPtrs) + size); TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs), nptrs, 0); SET_HDR(arr, &stg_MUT_ARR_PTRS_FROZEN_info, CCCS); arr->ptrs = nptrs; arr->size = size; for (i = 0; i<nptrs; i++) { arr->payload[i] = ptrs[i]; } return arr; }