1 /* -----------------------------------------------------------------------------
3 * (c) The University of Glasgow 2006-2017
5 * Introspection into GHC's heap representation
7 * ---------------------------------------------------------------------------*/
14 #include "Capability.h"
17 StgWord
heap_view_closureSize(StgClosure
*closure
) {
18 ASSERT(LOOKS_LIKE_CLOSURE_PTR(closure
));
19 return closure_sizeW(closure
);
23 heap_view_closure_ptrs_in_large_bitmap(StgClosure
*ptrs
[], StgWord
*nptrs
24 , StgClosure
**p
, StgLargeBitmap
*large_bitmap
32 for (i
= 0; i
< size
; b
++) {
33 bitmap
= large_bitmap
->bitmap
[b
];
34 j
= stg_min(size
-i
, BITS_IN(W_
));
36 for (; j
> 0; j
--, p
++) {
37 if ((bitmap
& 1) == 0) {
38 ptrs
[(*nptrs
)++] = *p
;
45 void heap_view_closure_ptrs_in_pap_payload(StgClosure
*ptrs
[], StgWord
*nptrs
46 , StgClosure
*fun
, StgClosure
**payload
, StgWord size
) {
48 const StgFunInfoTable
*fun_info
;
50 fun_info
= get_fun_itbl(UNTAG_CLOSURE(fun
));
51 // ASSERT(fun_info->i.type != PAP);
52 StgClosure
**p
= payload
;
54 switch (fun_info
->f
.fun_type
) {
56 bitmap
= BITMAP_BITS(fun_info
->f
.b
.bitmap
);
59 heap_view_closure_ptrs_in_large_bitmap(ptrs
, nptrs
, payload
,
60 GET_FUN_LARGE_BITMAP(fun_info
), size
);
63 heap_view_closure_ptrs_in_large_bitmap(ptrs
, nptrs
, payload
,
64 BCO_BITMAP(fun
), size
);
67 bitmap
= BITMAP_BITS(stg_arg_bitmaps
[fun_info
->f
.fun_type
]);
70 if ((bitmap
& 1) == 0) {
71 ptrs
[(*nptrs
)++] = *p
;
82 StgWord
collect_pointers(StgClosure
*closure
, StgClosure
*ptrs
[]) {
84 const StgInfoTable
*info
= get_itbl(closure
);
90 barf("Invalid Object");
117 end
= closure
->payload
+ info
->layout
.payload
.ptrs
;
118 for (StgClosure
**ptr
= closure
->payload
; ptr
< end
; ptr
++) {
119 ptrs
[nptrs
++] = *ptr
;
130 end
= ((StgThunk
*)closure
)->payload
+ info
->layout
.payload
.ptrs
;
131 for (StgClosure
**ptr
= ((StgThunk
*)closure
)->payload
; ptr
< end
; ptr
++) {
132 ptrs
[nptrs
++] = *ptr
;
137 ptrs
[nptrs
++] = ((StgSelector
*)closure
)->selectee
;
141 ptrs
[nptrs
++] = ((StgAP
*)closure
)->fun
;
142 heap_view_closure_ptrs_in_pap_payload(ptrs
, &nptrs
,
143 ((StgAP
*)closure
)->fun
,
144 ((StgAP
*)closure
)->payload
,
145 ((StgAP
*)closure
)->n_args
);
149 ptrs
[nptrs
++] = ((StgPAP
*)closure
)->fun
;
150 heap_view_closure_ptrs_in_pap_payload(ptrs
, &nptrs
,
151 ((StgPAP
*)closure
)->fun
,
152 ((StgPAP
*)closure
)->payload
,
153 ((StgPAP
*)closure
)->n_args
);
157 ptrs
[nptrs
++] = ((StgAP_STACK
*)closure
)->fun
;
159 The payload is a stack, which consists of a mixture of pointers
160 and non-pointers. We can't simply pretend it's all pointers,
161 because that will cause crashes in the GC later. We could
162 traverse the stack and extract pointers and non-pointers, but that
163 would be complicated, so let's just ignore the payload for now.
169 ptrs
[nptrs
++] = (StgClosure
*)((StgBCO
*)closure
)->instrs
;
170 ptrs
[nptrs
++] = (StgClosure
*)((StgBCO
*)closure
)->literals
;
171 ptrs
[nptrs
++] = (StgClosure
*)((StgBCO
*)closure
)->ptrs
;
177 ptrs
[nptrs
++] = (StgClosure
*) ACQUIRE_LOAD(&((StgInd
*)closure
)->indirectee
);
180 case MUT_ARR_PTRS_CLEAN
:
181 case MUT_ARR_PTRS_DIRTY
:
182 case MUT_ARR_PTRS_FROZEN_CLEAN
:
183 case MUT_ARR_PTRS_FROZEN_DIRTY
:
184 for (i
= 0; i
< ((StgMutArrPtrs
*)closure
)->ptrs
; ++i
) {
185 ptrs
[nptrs
++] = ((StgMutArrPtrs
*)closure
)->payload
[i
];
189 case SMALL_MUT_ARR_PTRS_CLEAN
:
190 case SMALL_MUT_ARR_PTRS_DIRTY
:
191 case SMALL_MUT_ARR_PTRS_FROZEN_CLEAN
:
192 case SMALL_MUT_ARR_PTRS_FROZEN_DIRTY
:
193 for (i
= 0; i
< ((StgSmallMutArrPtrs
*)closure
)->ptrs
; ++i
) {
194 ptrs
[nptrs
++] = ((StgSmallMutArrPtrs
*)closure
)->payload
[i
];
200 ptrs
[nptrs
++] = ((StgMutVar
*)closure
)->var
;
204 ptrs
[nptrs
++] = (StgClosure
*)((StgMVar
*)closure
)->head
;
205 ptrs
[nptrs
++] = (StgClosure
*)((StgMVar
*)closure
)->tail
;
206 ptrs
[nptrs
++] = ((StgMVar
*)closure
)->value
;
209 ASSERT((StgClosure
*)((StgTSO
*)closure
)->_link
!= NULL
);
210 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->_link
;
212 ASSERT((StgClosure
*)((StgTSO
*)closure
)->global_link
!= NULL
);
213 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->global_link
;
215 ASSERT((StgClosure
*)((StgTSO
*)closure
)->stackobj
!= NULL
);
216 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->stackobj
;
218 ASSERT((StgClosure
*)((StgTSO
*)closure
)->trec
!= NULL
);
219 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->trec
;
221 ASSERT((StgClosure
*)((StgTSO
*)closure
)->blocked_exceptions
!= NULL
);
222 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->blocked_exceptions
;
224 ASSERT((StgClosure
*)((StgTSO
*)closure
)->bq
!= NULL
);
225 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->bq
;
227 if ((StgClosure
*)((StgTSO
*)closure
)->label
!= NULL
) {
228 ptrs
[nptrs
++] = (StgClosure
*)((StgTSO
*)closure
)->label
;
233 StgWeak
*w
= (StgWeak
*)closure
;
234 ptrs
[nptrs
++] = (StgClosure
*) w
->cfinalizers
;
235 ptrs
[nptrs
++] = (StgClosure
*) w
->key
;
236 ptrs
[nptrs
++] = (StgClosure
*) w
->value
;
237 ptrs
[nptrs
++] = (StgClosure
*) w
->finalizer
;
238 // link may be NULL which is not a valid GC pointer
240 ptrs
[nptrs
++] = (StgClosure
*) w
->link
;
246 // See the note in AP_STACK about the stack chunk.
251 StgBlockingQueue
*bq
= (StgBlockingQueue
*) closure
;
252 ptrs
[nptrs
++] = (StgClosure
*) bq
->link
;
253 ptrs
[nptrs
++] = bq
->bh
;
254 ptrs
[nptrs
++] = (StgClosure
*) bq
->owner
;
255 ptrs
[nptrs
++] = (StgClosure
*) bq
->queue
;
260 fprintf(stderr
,"closurePtrs: Cannot handle type %s yet\n",
261 closure_type_names
[info
->type
]);
268 StgMutArrPtrs
*heap_view_closurePtrs(Capability
*cap
, StgClosure
*closure
) {
269 ASSERT(LOOKS_LIKE_CLOSURE_PTR(closure
));
271 StgWord size
= heap_view_closureSize(closure
);
273 // First collect all pointers here, with the comfortable memory bound
274 // of the whole closure. Afterwards we know how many pointers are in
275 // the closure and then we can allocate space on the heap and copy them
276 // there. Note that we cannot allocate this on the C stack as the closure
277 // may be, e.g., a large array.
278 StgClosure
**ptrs
= (StgClosure
**) stgMallocBytes(sizeof(StgClosure
*) * size
, "heap_view_closurePtrs");
279 StgWord nptrs
= collect_pointers(closure
, ptrs
);
281 size
= nptrs
+ mutArrPtrsCardTableSize(nptrs
);
283 (StgMutArrPtrs
*)allocate(cap
, sizeofW(StgMutArrPtrs
) + size
);
284 TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs
), nptrs
, 0);
285 SET_HDR(arr
, &stg_MUT_ARR_PTRS_FROZEN_CLEAN_info
, cap
->r
.rCCCS
);
289 for (StgWord i
= 0; i
<nptrs
; i
++) {
290 arr
->payload
[i
] = ptrs
[i
];