[Patch Doc] Update documentation for __fp16 type
[official-gcc.git] / libgo / runtime / heapdump.c
blob80d2b7bf85006c2a78da57785e5be89a6fc018b9
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Implementation of runtime/debug.WriteHeapDump. Writes all
6 // objects in the heap plus additional info (roots, threads,
7 // finalizers, etc.) to a file.
9 // The format of the dumped file is described at
10 // http://code.google.com/p/go-wiki/wiki/heapdump13
12 #include "runtime.h"
13 #include "arch.h"
14 #include "malloc.h"
15 #include "mgc0.h"
16 #include "go-type.h"
18 #define hash __hash
19 #define KindNoPointers GO_NO_POINTERS
21 enum {
22 FieldKindEol = 0,
23 FieldKindPtr = 1,
24 FieldKindString = 2,
25 FieldKindSlice = 3,
26 FieldKindIface = 4,
27 FieldKindEface = 5,
29 TagEOF = 0,
30 TagObject = 1,
31 TagOtherRoot = 2,
32 TagType = 3,
33 TagGoRoutine = 4,
34 TagStackFrame = 5,
35 TagParams = 6,
36 TagFinalizer = 7,
37 TagItab = 8,
38 TagOSThread = 9,
39 TagMemStats = 10,
40 TagQueuedFinalizer = 11,
41 TagData = 12,
42 TagBss = 13,
43 TagDefer = 14,
44 TagPanic = 15,
45 TagMemProf = 16,
46 TagAllocSample = 17,
48 TypeInfo_Conservative = 127,
51 // static uintptr* playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg);
52 // static void dumpfields(uintptr *prog);
53 static void dumpefacetypes(void *obj, uintptr size, const Type *type, uintptr kind);
55 // fd to write the dump to.
56 static uintptr dumpfd;
58 // buffer of pending write data
59 enum {
60 BufSize = 4096,
62 static byte buf[BufSize];
63 static uintptr nbuf;
65 static void
66 hwrite(const byte *data, uintptr len)
68 if(len + nbuf <= BufSize) {
69 runtime_memmove(buf + nbuf, data, len);
70 nbuf += len;
71 return;
73 runtime_write(dumpfd, buf, nbuf);
74 if(len >= BufSize) {
75 runtime_write(dumpfd, data, len);
76 nbuf = 0;
77 } else {
78 runtime_memmove(buf, data, len);
79 nbuf = len;
83 static void
84 flush(void)
86 runtime_write(dumpfd, buf, nbuf);
87 nbuf = 0;
90 // Cache of types that have been serialized already.
91 // We use a type's hash field to pick a bucket.
92 // Inside a bucket, we keep a list of types that
93 // have been serialized so far, most recently used first.
94 // Note: when a bucket overflows we may end up
95 // serializing a type more than once. That's ok.
96 enum {
97 TypeCacheBuckets = 256, // must be a power of 2
98 TypeCacheAssoc = 4,
100 typedef struct TypeCacheBucket TypeCacheBucket;
101 struct TypeCacheBucket {
102 const Type *t[TypeCacheAssoc];
104 static TypeCacheBucket typecache[TypeCacheBuckets];
106 // dump a uint64 in a varint format parseable by encoding/binary
107 static void
108 dumpint(uint64 v)
110 byte buf[10];
111 int32 n;
112 n = 0;
113 while(v >= 0x80) {
114 buf[n++] = v | 0x80;
115 v >>= 7;
117 buf[n++] = v;
118 hwrite(buf, n);
121 static void
122 dumpbool(bool b)
124 dumpint(b ? 1 : 0);
127 // dump varint uint64 length followed by memory contents
128 static void
129 dumpmemrange(const byte *data, uintptr len)
131 dumpint(len);
132 hwrite(data, len);
135 static void
136 dumpstr(String s)
138 dumpmemrange(s.str, s.len);
141 static void
142 dumpcstr(const int8 *c)
144 dumpmemrange((const byte*)c, runtime_findnull((const byte*)c));
147 // dump information for a type
148 static void
149 dumptype(const Type *t)
151 TypeCacheBucket *b;
152 int32 i, j;
154 if(t == nil) {
155 return;
158 // If we've definitely serialized the type before,
159 // no need to do it again.
160 b = &typecache[t->hash & (TypeCacheBuckets-1)];
161 if(t == b->t[0]) return;
162 for(i = 1; i < TypeCacheAssoc; i++) {
163 if(t == b->t[i]) {
164 // Move-to-front
165 for(j = i; j > 0; j--) {
166 b->t[j] = b->t[j-1];
168 b->t[0] = t;
169 return;
172 // Might not have been dumped yet. Dump it and
173 // remember we did so.
174 for(j = TypeCacheAssoc-1; j > 0; j--) {
175 b->t[j] = b->t[j-1];
177 b->t[0] = t;
179 // dump the type
180 dumpint(TagType);
181 dumpint((uintptr)t);
182 dumpint(t->__size);
183 if(t->__uncommon == nil || t->__uncommon->__pkg_path == nil || t->__uncommon->__name == nil) {
184 dumpstr(*t->__reflection);
185 } else {
186 dumpint(t->__uncommon->__pkg_path->len + 1 + t->__uncommon->__name->len);
187 hwrite(t->__uncommon->__pkg_path->str, t->__uncommon->__pkg_path->len);
188 hwrite((const byte*)".", 1);
189 hwrite(t->__uncommon->__name->str, t->__uncommon->__name->len);
191 dumpbool(t->__size > PtrSize || (t->__code & KindNoPointers) == 0);
192 // dumpfields((uintptr*)t->gc + 1);
195 // returns true if object is scannable
196 static bool
197 scannable(byte *obj)
199 uintptr *b, off, shift;
201 off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start; // word offset
202 b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
203 shift = off % wordsPerBitmapWord;
204 return ((*b >> shift) & bitScan) != 0;
207 // dump an object
208 static void
209 dumpobj(byte *obj, uintptr size, const Type *type, uintptr kind)
211 if(type != nil) {
212 dumptype(type);
213 dumpefacetypes(obj, size, type, kind);
216 dumpint(TagObject);
217 dumpint((uintptr)obj);
218 dumpint((uintptr)type);
219 dumpint(kind);
220 dumpmemrange(obj, size);
223 static void
224 dumpotherroot(const char *description, byte *to)
226 dumpint(TagOtherRoot);
227 dumpcstr((const int8 *)description);
228 dumpint((uintptr)to);
231 static void
232 dumpfinalizer(byte *obj, FuncVal *fn, const FuncType* ft, const PtrType *ot)
234 dumpint(TagFinalizer);
235 dumpint((uintptr)obj);
236 dumpint((uintptr)fn);
237 dumpint((uintptr)fn->fn);
238 dumpint((uintptr)ft);
239 dumpint((uintptr)ot);
242 typedef struct ChildInfo ChildInfo;
243 struct ChildInfo {
244 // Information passed up from the callee frame about
245 // the layout of the outargs region.
246 uintptr argoff; // where the arguments start in the frame
247 uintptr arglen; // size of args region
248 BitVector args; // if args.n >= 0, pointer map of args region
250 byte *sp; // callee sp
251 uintptr depth; // depth in call stack (0 == most recent)
254 static void
255 dumpgoroutine(G *gp)
257 // ChildInfo child;
258 Defer *d;
259 Panic *p;
261 dumpint(TagGoRoutine);
262 dumpint((uintptr)gp);
263 dumpint((uintptr)0);
264 dumpint(gp->goid);
265 dumpint(gp->gopc);
266 dumpint(gp->atomicstatus);
267 dumpbool(gp->issystem);
268 dumpbool(gp->isbackground);
269 dumpint(gp->waitsince);
270 dumpstr(gp->waitreason);
271 dumpint((uintptr)0);
272 dumpint((uintptr)gp->m);
273 dumpint((uintptr)gp->_defer);
274 dumpint((uintptr)gp->_panic);
276 // dump stack
277 // child.args.n = -1;
278 // child.arglen = 0;
279 // child.sp = nil;
280 // child.depth = 0;
281 // if(!ScanStackByFrames)
282 // runtime_throw("need frame info to dump stacks");
283 // runtime_gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, dumpframe, &child, false);
285 // dump defer & panic records
286 for(d = gp->_defer; d != nil; d = d->link) {
287 dumpint(TagDefer);
288 dumpint((uintptr)d);
289 dumpint((uintptr)gp);
290 dumpint((uintptr)d->arg);
291 dumpint((uintptr)d->frame);
292 dumpint((uintptr)d->pfn);
293 dumpint((uintptr)0);
294 dumpint((uintptr)d->link);
296 for (p = gp->_panic; p != nil; p = p->link) {
297 dumpint(TagPanic);
298 dumpint((uintptr)p);
299 dumpint((uintptr)gp);
300 dumpint((uintptr)p->arg._type);
301 dumpint((uintptr)p->arg.data);
302 dumpint((uintptr)0);
303 dumpint((uintptr)p->link);
307 static void
308 dumpgs(void)
310 G *gp;
311 uint32 i;
313 // goroutines & stacks
314 for(i = 0; i < runtime_allglen; i++) {
315 gp = runtime_allg[i];
316 switch(gp->atomicstatus){
317 default:
318 runtime_printf("unexpected G.status %d\n", gp->atomicstatus);
319 runtime_throw("mark - bad status");
320 case _Gdead:
321 break;
322 case _Grunnable:
323 case _Gsyscall:
324 case _Gwaiting:
325 dumpgoroutine(gp);
326 break;
331 static void
332 finq_callback(FuncVal *fn, void *obj, const FuncType *ft, const PtrType *ot)
334 dumpint(TagQueuedFinalizer);
335 dumpint((uintptr)obj);
336 dumpint((uintptr)fn);
337 dumpint((uintptr)fn->fn);
338 dumpint((uintptr)ft);
339 dumpint((uintptr)ot);
343 static void
344 dumproots(void)
346 MSpan *s, **allspans;
347 uint32 spanidx;
348 Special *sp;
349 SpecialFinalizer *spf;
350 byte *p;
352 // data segment
353 // dumpint(TagData);
354 // dumpint((uintptr)data);
355 // dumpmemrange(data, edata - data);
356 // dumpfields((uintptr*)gcdata + 1);
358 // bss segment
359 // dumpint(TagBss);
360 // dumpint((uintptr)bss);
361 // dumpmemrange(bss, ebss - bss);
362 // dumpfields((uintptr*)gcbss + 1);
364 // MSpan.types
365 allspans = runtime_mheap.allspans;
366 for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
367 s = allspans[spanidx];
368 if(s->state == MSpanInUse) {
369 // The garbage collector ignores type pointers stored in MSpan.types:
370 // - Compiler-generated types are stored outside of heap.
371 // - The reflect package has runtime-generated types cached in its data structures.
372 // The garbage collector relies on finding the references via that cache.
373 switch(s->types.compression) {
374 case MTypes_Empty:
375 case MTypes_Single:
376 break;
377 case MTypes_Words:
378 case MTypes_Bytes:
379 dumpotherroot("runtime type info", (byte*)s->types.data);
380 break;
383 // Finalizers
384 for(sp = s->specials; sp != nil; sp = sp->next) {
385 if(sp->kind != KindSpecialFinalizer)
386 continue;
387 spf = (SpecialFinalizer*)sp;
388 p = (byte*)((s->start << PageShift) + spf->offset);
389 dumpfinalizer(p, spf->fn, spf->ft, spf->ot);
394 // Finalizer queue
395 runtime_iterate_finq(finq_callback);
398 // Bit vector of free marks.
399 // Needs to be as big as the largest number of objects per span.
400 static byte hfree[PageSize/8];
402 static void
403 dumpobjs(void)
405 uintptr i, j, size, n, off, shift, *bitp, bits, ti, kind;
406 MSpan *s;
407 MLink *l;
408 byte *p;
409 const Type *t;
411 for(i = 0; i < runtime_mheap.nspan; i++) {
412 s = runtime_mheap.allspans[i];
413 if(s->state != MSpanInUse)
414 continue;
415 p = (byte*)(s->start << PageShift);
416 size = s->elemsize;
417 n = (s->npages << PageShift) / size;
418 if(n > PageSize/8)
419 runtime_throw("free array doesn't have enough entries");
420 for(l = s->freelist; l != nil; l = l->next) {
421 hfree[((byte*)l - p) / size] = true;
423 for(j = 0; j < n; j++, p += size) {
424 if(hfree[j]) {
425 hfree[j] = false;
426 continue;
428 off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;
429 bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
430 shift = off % wordsPerBitmapWord;
431 bits = *bitp >> shift;
433 // Skip FlagNoGC allocations (stacks)
434 if((bits & bitAllocated) == 0)
435 continue;
437 // extract type and kind
438 ti = runtime_gettype(p);
439 t = (Type*)(ti & ~(uintptr)(PtrSize-1));
440 kind = ti & (PtrSize-1);
442 // dump it
443 if(kind == TypeInfo_Chan)
444 t = ((const ChanType*)t)->__element_type; // use element type for chan encoding
445 if(t == nil && scannable(p))
446 kind = TypeInfo_Conservative; // special kind for conservatively scanned objects
447 dumpobj(p, size, t, kind);
452 static void
453 dumpparams(void)
455 byte *x;
457 dumpint(TagParams);
458 x = (byte*)1;
459 if(*(byte*)&x == 1)
460 dumpbool(false); // little-endian ptrs
461 else
462 dumpbool(true); // big-endian ptrs
463 dumpint(PtrSize);
464 dumpint(hchanSize);
465 dumpint((uintptr)runtime_mheap.arena_start);
466 dumpint((uintptr)runtime_mheap.arena_used);
467 dumpint(0);
468 dumpcstr((const int8 *)"");
469 dumpint(runtime_ncpu);
472 static void
473 dumpms(void)
475 M *mp;
477 for(mp = runtime_allm; mp != nil; mp = mp->alllink) {
478 dumpint(TagOSThread);
479 dumpint((uintptr)mp);
480 dumpint(mp->id);
481 dumpint(0);
485 static void
486 dumpmemstats(void)
488 int32 i;
490 dumpint(TagMemStats);
491 dumpint(mstats()->alloc);
492 dumpint(mstats()->total_alloc);
493 dumpint(mstats()->sys);
494 dumpint(mstats()->nlookup);
495 dumpint(mstats()->nmalloc);
496 dumpint(mstats()->nfree);
497 dumpint(mstats()->heap_alloc);
498 dumpint(mstats()->heap_sys);
499 dumpint(mstats()->heap_idle);
500 dumpint(mstats()->heap_inuse);
501 dumpint(mstats()->heap_released);
502 dumpint(mstats()->heap_objects);
503 dumpint(mstats()->stacks_inuse);
504 dumpint(mstats()->stacks_sys);
505 dumpint(mstats()->mspan_inuse);
506 dumpint(mstats()->mspan_sys);
507 dumpint(mstats()->mcache_inuse);
508 dumpint(mstats()->mcache_sys);
509 dumpint(mstats()->buckhash_sys);
510 dumpint(mstats()->gc_sys);
511 dumpint(mstats()->other_sys);
512 dumpint(mstats()->next_gc);
513 dumpint(mstats()->last_gc);
514 dumpint(mstats()->pause_total_ns);
515 for(i = 0; i < 256; i++)
516 dumpint(mstats()->pause_ns[i]);
517 dumpint(mstats()->numgc);
520 static void
521 dumpmemprof_callback(Bucket *b, uintptr nstk, Location *stk, uintptr size, uintptr allocs, uintptr frees)
523 uintptr i, pc;
524 byte buf[20];
526 dumpint(TagMemProf);
527 dumpint((uintptr)b);
528 dumpint(size);
529 dumpint(nstk);
530 for(i = 0; i < nstk; i++) {
531 pc = stk[i].pc;
532 if(stk[i].function.len == 0) {
533 runtime_snprintf(buf, sizeof(buf), "%X", (uint64)pc);
534 dumpcstr((int8*)buf);
535 dumpcstr((const int8*)"?");
536 dumpint(0);
537 } else {
538 dumpstr(stk[i].function);
539 dumpstr(stk[i].filename);
540 dumpint(stk[i].lineno);
543 dumpint(allocs);
544 dumpint(frees);
547 static FuncVal dumpmemprof_callbackv = {(void(*)(void))dumpmemprof_callback};
549 static void
550 dumpmemprof(void)
552 MSpan *s, **allspans;
553 uint32 spanidx;
554 Special *sp;
555 SpecialProfile *spp;
556 byte *p;
558 runtime_iterate_memprof(&dumpmemprof_callbackv);
560 allspans = runtime_mheap.allspans;
561 for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
562 s = allspans[spanidx];
563 if(s->state != MSpanInUse)
564 continue;
565 for(sp = s->specials; sp != nil; sp = sp->next) {
566 if(sp->kind != KindSpecialProfile)
567 continue;
568 spp = (SpecialProfile*)sp;
569 p = (byte*)((s->start << PageShift) + spp->offset);
570 dumpint(TagAllocSample);
571 dumpint((uintptr)p);
572 dumpint((uintptr)spp->b);
577 static void
578 mdump(G *gp)
580 const byte *hdr;
581 uintptr i;
582 MSpan *s;
584 // make sure we're done sweeping
585 for(i = 0; i < runtime_mheap.nspan; i++) {
586 s = runtime_mheap.allspans[i];
587 if(s->state == MSpanInUse)
588 runtime_MSpan_EnsureSwept(s);
591 runtime_memclr((byte*)&typecache[0], sizeof(typecache));
592 hdr = (const byte*)"go1.3 heap dump\n";
593 hwrite(hdr, runtime_findnull(hdr));
594 dumpparams();
595 dumpobjs();
596 dumpgs();
597 dumpms();
598 dumproots();
599 dumpmemstats();
600 dumpmemprof();
601 dumpint(TagEOF);
602 flush();
604 gp->param = nil;
605 gp->atomicstatus = _Grunning;
606 runtime_gogo(gp);
609 void runtime_debug_WriteHeapDump(uintptr)
610 __asm__(GOSYM_PREFIX "runtime_debug.WriteHeapDump");
612 void
613 runtime_debug_WriteHeapDump(uintptr fd)
615 M *m;
616 G *g;
618 // Stop the world.
619 runtime_acquireWorldsema();
620 m = runtime_m();
621 m->gcing = 1;
622 m->locks++;
623 runtime_stopTheWorldWithSema();
625 // Update stats so we can dump them.
626 // As a side effect, flushes all the MCaches so the MSpan.freelist
627 // lists contain all the free objects.
628 runtime_updatememstats(nil);
630 // Set dump file.
631 dumpfd = fd;
633 // Call dump routine on M stack.
634 g = runtime_g();
635 g->atomicstatus = _Gwaiting;
636 g->waitreason = runtime_gostringnocopy((const byte*)"dumping heap");
637 runtime_mcall(mdump);
639 // Reset dump file.
640 dumpfd = 0;
642 // Start up the world again.
643 m->gcing = 0;
644 runtime_releaseWorldsema();
645 runtime_startTheWorldWithSema();
646 m->locks--;
649 // Runs the specified gc program. Calls the callback for every
650 // pointer-like field specified by the program and passes to the
651 // callback the kind and offset of that field within the object.
652 // offset is the offset in the object of the start of the program.
653 // Returns a pointer to the opcode that ended the gc program (either
654 // GC_END or GC_ARRAY_NEXT).
656 static uintptr*
657 playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg)
659 uintptr len, elemsize, i, *end;
661 for(;;) {
662 switch(prog[0]) {
663 case GC_END:
664 return prog;
665 case GC_PTR:
666 callback(arg, FieldKindPtr, offset + prog[1]);
667 prog += 3;
668 break;
669 case GC_APTR:
670 callback(arg, FieldKindPtr, offset + prog[1]);
671 prog += 2;
672 break;
673 case GC_ARRAY_START:
674 len = prog[2];
675 elemsize = prog[3];
676 end = nil;
677 for(i = 0; i < len; i++) {
678 end = playgcprog(offset + prog[1] + i * elemsize, prog + 4, callback, arg);
679 if(end[0] != GC_ARRAY_NEXT)
680 runtime_throw("GC_ARRAY_START did not have matching GC_ARRAY_NEXT");
682 prog = end + 1;
683 break;
684 case GC_ARRAY_NEXT:
685 return prog;
686 case GC_CALL:
687 playgcprog(offset + prog[1], (uintptr*)((byte*)prog + *(int32*)&prog[2]), callback, arg);
688 prog += 3;
689 break;
690 case GC_CHAN_PTR:
691 callback(arg, FieldKindPtr, offset + prog[1]);
692 prog += 3;
693 break;
694 case GC_STRING:
695 callback(arg, FieldKindString, offset + prog[1]);
696 prog += 2;
697 break;
698 case GC_EFACE:
699 callback(arg, FieldKindEface, offset + prog[1]);
700 prog += 2;
701 break;
702 case GC_IFACE:
703 callback(arg, FieldKindIface, offset + prog[1]);
704 prog += 2;
705 break;
706 case GC_SLICE:
707 callback(arg, FieldKindSlice, offset + prog[1]);
708 prog += 3;
709 break;
710 case GC_REGION:
711 playgcprog(offset + prog[1], (uintptr*)prog[3] + 1, callback, arg);
712 prog += 4;
713 break;
714 default:
715 runtime_printf("%D\n", (uint64)prog[0]);
716 runtime_throw("bad gc op");
721 static void
722 dump_callback(void *p, uintptr kind, uintptr offset)
724 USED(&p);
725 dumpint(kind);
726 dumpint(offset);
729 // dumpint() the kind & offset of each field in an object.
730 static void
731 dumpfields(uintptr *prog)
733 playgcprog(0, prog, dump_callback, nil);
734 dumpint(FieldKindEol);
737 static void
738 dumpeface_callback(void *p, uintptr kind, uintptr offset)
740 Eface *e;
742 if(kind != FieldKindEface)
743 return;
744 e = (Eface*)((byte*)p + offset);
745 dumptype(e->__type_descriptor);
749 // The heap dump reader needs to be able to disambiguate
750 // Eface entries. So it needs to know every type that might
751 // appear in such an entry. The following two routines accomplish
752 // that.
754 // Dump all the types that appear in the type field of
755 // any Eface contained in obj.
756 static void
757 dumpefacetypes(void *obj __attribute__ ((unused)), uintptr size, const Type *type, uintptr kind)
759 uintptr i;
761 switch(kind) {
762 case TypeInfo_SingleObject:
763 //playgcprog(0, (uintptr*)type->gc + 1, dumpeface_callback, obj);
764 break;
765 case TypeInfo_Array:
766 for(i = 0; i <= size - type->__size; i += type->__size) {
767 //playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
769 break;
770 case TypeInfo_Chan:
771 if(type->__size == 0) // channels may have zero-sized objects in them
772 break;
773 for(i = hchanSize; i <= size - type->__size; i += type->__size) {
774 //playgcprog(i, (uintptr*)type->gc + 1, dumpeface_callback, obj);
776 break;