Optimize struct element initialization
[hiphop-php.git] / hphp / runtime / vm / ringbuffer-print.cpp
blob3b9e2a9fd5b48830699e1f337f703b8fd35801cd
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 case RBTypeAPCHandleEnqueue:
90 auto& info = e->apcHandleInfo;
91 std::cerr << " (" << info.handle << ", " << info.value << ")\n";
92 break;
94 case RBTypeAPCHandleDelete:
96 auto& info = e->apcHandleInfo;
97 std::cerr << " (" << info.handle << ", " << info.value << ")\n";
98 break;
100 default: {
101 auto& info = e->vmPoint;
102 std::cerr <<
103 folly::format(msgFormat,
104 showShort(SrcKey::fromAtomicInt(info.sk)),
105 info.data);
106 break;
111 // From gdb:
112 // (gdb) set language c++
113 // (gdb) call HPHP::Trace::dumpRingBuffer(100)
115 // or
117 // (gdb) call HPHP::Trace::dumpRingBufferMasked(100,
118 // (1 << HPHP::Trace::RBTypeFuncEntry))
119 void dumpRingBufferMasked(int numEntries, uint32_t types, uint32_t threadId) {
120 if (!g_ring_ptr) return;
121 int startIdx = (g_ringIdx.load() - numEntries) % kMaxRBEntries;
122 while (startIdx < 0) {
123 startIdx += kMaxRBEntries;
125 assertx(startIdx >= 0 && startIdx < kMaxRBEntries);
126 int numDumped = 0;
127 for (int i = 0; i < kMaxRBEntries && numDumped < numEntries; i++) {
128 RingBufferEntry* rb = &g_ring_ptr[(startIdx + i) % kMaxRBEntries];
129 if ((1 << rb->type) & types &&
130 (!threadId || threadId == rb->threadId)) {
131 numDumped++;
132 dumpEntry(rb);
137 KEEP_SECTION
138 void dumpRingBuffer(int numEntries, uint32_t threadId) {
139 dumpRingBufferMasked(numEntries, -1u, threadId);