perf: Key the interpreter symbol cache by Name rather than FastString
[ghc.git] / rts / Heap.c
blob85ff1e360bdb7f4a5953a67b41249b909a011c6f
1 /* -----------------------------------------------------------------------------
3 * (c) The University of Glasgow 2006-2017
5 * Introspection into GHC's heap representation
7 * ---------------------------------------------------------------------------*/
9 #include "Rts.h"
10 #include "RtsAPI.h"
11 #include "RtsUtils.h"
12 #include "RtsFlags.h"
14 #include "Capability.h"
15 #include "Printer.h"
17 StgWord heap_view_closureSize(StgClosure *closure) {
18 ASSERT(LOOKS_LIKE_CLOSURE_PTR(closure));
19 return closure_sizeW(closure);
22 static void
23 heap_view_closure_ptrs_in_large_bitmap(StgClosure *ptrs[], StgWord *nptrs
24 , StgClosure **p, StgLargeBitmap *large_bitmap
25 , uint32_t size )
27 uint32_t i, j, b;
28 StgWord bitmap;
30 b = 0;
32 for (i = 0; i < size; b++) {
33 bitmap = large_bitmap->bitmap[b];
34 j = stg_min(size-i, BITS_IN(W_));
35 i += j;
36 for (; j > 0; j--, p++) {
37 if ((bitmap & 1) == 0) {
38 ptrs[(*nptrs)++] = *p;
40 bitmap = bitmap >> 1;
45 void heap_view_closure_ptrs_in_pap_payload(StgClosure *ptrs[], StgWord *nptrs
46 , StgClosure *fun, StgClosure **payload, StgWord size) {
47 StgWord bitmap;
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) {
55 case ARG_GEN:
56 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
57 goto small_bitmap;
58 case ARG_GEN_BIG:
59 heap_view_closure_ptrs_in_large_bitmap(ptrs, nptrs, payload,
60 GET_FUN_LARGE_BITMAP(fun_info), size);
61 break;
62 case ARG_BCO:
63 heap_view_closure_ptrs_in_large_bitmap(ptrs, nptrs, payload,
64 BCO_BITMAP(fun), size);
65 break;
66 default:
67 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
68 small_bitmap:
69 while (size > 0) {
70 if ((bitmap & 1) == 0) {
71 ptrs[(*nptrs)++] = *p;
73 bitmap = bitmap >> 1;
74 p++;
75 size--;
77 break;
81 // See Heap.h
82 StgWord collect_pointers(StgClosure *closure, StgClosure *ptrs[]) {
83 StgClosure **end;
84 const StgInfoTable *info = get_itbl(closure);
85 StgWord nptrs = 0;
86 StgWord i;
88 switch (info->type) {
89 case INVALID_OBJECT:
90 barf("Invalid Object");
91 break;
93 // No pointers
94 case ARR_WORDS:
95 case STACK:
96 break;
98 // Default layout
99 case CONSTR_1_0:
100 case CONSTR_0_1:
101 case CONSTR_2_0:
102 case CONSTR_1_1:
103 case CONSTR_0_2:
104 case CONSTR:
105 case CONSTR_NOCAF:
108 case PRIM:
110 case FUN:
111 case FUN_1_0:
112 case FUN_0_1:
113 case FUN_1_1:
114 case FUN_2_0:
115 case FUN_0_2:
116 case FUN_STATIC:
117 end = closure->payload + info->layout.payload.ptrs;
118 for (StgClosure **ptr = closure->payload; ptr < end; ptr++) {
119 ptrs[nptrs++] = *ptr;
121 break;
123 case THUNK:
124 case THUNK_1_0:
125 case THUNK_0_1:
126 case THUNK_1_1:
127 case THUNK_2_0:
128 case THUNK_0_2:
129 case THUNK_STATIC:
130 end = ((StgThunk *)closure)->payload + info->layout.payload.ptrs;
131 for (StgClosure **ptr = ((StgThunk *)closure)->payload; ptr < end; ptr++) {
132 ptrs[nptrs++] = *ptr;
134 break;
136 case THUNK_SELECTOR:
137 ptrs[nptrs++] = ((StgSelector *)closure)->selectee;
138 break;
140 case AP:
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);
146 break;
148 case PAP:
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);
154 break;
156 case AP_STACK:
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.
164 See #15375.
166 break;
168 case BCO:
169 ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->instrs;
170 ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->literals;
171 ptrs[nptrs++] = (StgClosure *)((StgBCO *)closure)->ptrs;
172 break;
174 case IND:
175 case IND_STATIC:
176 case BLACKHOLE:
177 ptrs[nptrs++] = (StgClosure *) ACQUIRE_LOAD(&((StgInd *)closure)->indirectee);
178 break;
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];
187 break;
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];
196 break;
198 case MUT_VAR_CLEAN:
199 case MUT_VAR_DIRTY:
200 ptrs[nptrs++] = ((StgMutVar *)closure)->var;
201 break;
202 case MVAR_DIRTY:
203 case MVAR_CLEAN:
204 ptrs[nptrs++] = (StgClosure *)((StgMVar *)closure)->head;
205 ptrs[nptrs++] = (StgClosure *)((StgMVar *)closure)->tail;
206 ptrs[nptrs++] = ((StgMVar *)closure)->value;
207 break;
208 case TSO:
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;
231 break;
232 case WEAK: {
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
239 if (w->link) {
240 ptrs[nptrs++] = (StgClosure *) w->link;
242 break;
245 case CONTINUATION:
246 // See the note in AP_STACK about the stack chunk.
247 break;
249 case BLOCKING_QUEUE:
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;
256 break;
259 default:
260 fprintf(stderr,"closurePtrs: Cannot handle type %s yet\n",
261 closure_type_names[info->type]);
262 break;
265 return nptrs;
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);
282 StgMutArrPtrs *arr =
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);
286 arr->ptrs = nptrs;
287 arr->size = size;
289 for (StgWord i = 0; i<nptrs; i++) {
290 arr->payload[i] = ptrs[i];
292 stgFree(ptrs);
294 return arr;