Reland D23318594 and D23318592 add recordbasenativesp instr
[hiphop-php.git] / hphp / runtime / vm / ringbuffer-print.cpp
blob1ea332aec3e3d83aaa5bd5d66b769b3a0950ee59
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/runtime/vm/ringbuffer-print.h"
18 #include <iostream>
20 #include <folly/Format.h>
22 #include "hphp/runtime/vm/jit/service-requests.h"
23 #include "hphp/runtime/vm/srckey.h"
25 namespace HPHP { namespace Trace {
27 void dumpEntry(const RingBufferEntry* e) {
28 if (e->type == RBTypeUninit) return;
30 std::cerr <<
31 folly::format("{:#x} {:10} {:20}",
32 e->threadId, e->seq, ringbufferName(e->type));
33 auto const msgFormat = "{:50} {:#16x}\n";
35 switch (e->type) {
36 case RBTypeUninit: return;
37 case RBTypeMsg:
38 case RBTypeFuncPrologue: {
39 auto& info = e->msg;
40 // The strings in thread-private ring buffers are not null-terminated;
41 // we also can't trust their length, since they might wrap around.
42 auto len = std::min(size_t(info.len), strlen(info.msg));
44 // We append our own newline so ignore any newlines in the msg.
45 while (len > 0 && info.msg[len - 1] == '\n') --len;
46 std::cerr <<
47 folly::format(msgFormat,
48 folly::StringPiece(info.msg, info.msg + len),
49 info.truncatedRip);
50 break;
52 case RBTypeFuncEntry:
53 case RBTypeFuncExit: {
54 static __thread int indentDepth = 0;
55 // Quick and dirty attempt at dtrace -F style function nesting.
56 // Looks like:
58 // ... FuncEntry caller
59 // ... FuncEntry callee
60 // ... FuncExit callee
61 // ... FuncExit caller
63 // Take this indentation with a grain of salt; it's only reliable
64 // within a single thread, and since we still miss some function
65 // entries and exits can get confused.
66 auto& info = e->msg;
67 indentDepth -= e->type == RBTypeFuncExit;
68 if (indentDepth < 0) indentDepth = 0;
69 auto const indentedName =
70 folly::sformat("{}{}", std::string(indentDepth * 4, ' '), info.msg);
71 std::cerr << folly::format(msgFormat,
72 indentedName, info.truncatedRip);
73 indentDepth += e->type == RBTypeFuncEntry;
74 break;
76 case RBTypeServiceReq: {
77 auto& info = e->vmPoint;
78 auto req = static_cast<jit::ServiceRequest>(info.sk);
79 std::cerr << folly::format(msgFormat,
80 jit::svcreq::to_name(req), info.data);
81 break;
83 case RBTypeGeneric: {
84 auto& info = e->generic;
85 std::cerr << folly::format(msgFormat, info.name, info.data);
86 break;
88 default: {
89 auto& info = e->vmPoint;
90 std::cerr <<
91 folly::format(msgFormat,
92 showShort(SrcKey::fromAtomicInt(info.sk)),
93 info.data);
94 break;
99 // From gdb:
100 // (gdb) set language c++
101 // (gdb) call HPHP::Trace::dumpRingBuffer(100)
103 // or
105 // (gdb) call HPHP::Trace::dumpRingBufferMasked(100,
106 // (1 << HPHP::Trace::RBTypeFuncEntry))
107 void dumpRingBufferMasked(int numEntries, uint32_t types, uint32_t threadId) {
108 if (!g_ring_ptr) return;
109 int startIdx = (g_ringIdx.load() - numEntries) % kMaxRBEntries;
110 while (startIdx < 0) {
111 startIdx += kMaxRBEntries;
113 assertx(startIdx >= 0 && startIdx < kMaxRBEntries);
114 int numDumped = 0;
115 for (int i = 0; i < kMaxRBEntries && numDumped < numEntries; i++) {
116 RingBufferEntry* rb = &g_ring_ptr[(startIdx + i) % kMaxRBEntries];
117 if ((1 << rb->type) & types &&
118 (!threadId || threadId == rb->threadId)) {
119 numDumped++;
120 dumpEntry(rb);
125 KEEP_SECTION
126 void dumpRingBuffer(int numEntries, uint32_t threadId) {
127 dumpRingBufferMasked(numEntries, -1u, threadId);