2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/tc.h"
18 #include "hphp/runtime/vm/jit/tc-internal.h"
20 #include "hphp/runtime/base/rds.h"
21 #include "hphp/runtime/base/runtime-option.h"
23 #include "hphp/runtime/vm/jit/code-cache.h"
24 #include "hphp/runtime/vm/jit/mcgen.h"
25 #include "hphp/runtime/vm/jit/prof-data.h"
26 #include "hphp/runtime/vm/jit/trans-db.h"
28 #include "hphp/util/data-block.h"
29 #include "hphp/util/build-info.h"
31 #include <folly/Format.h>
37 namespace HPHP::jit::tc
{
41 bool dumpTCCode(folly::StringPiece filename
) {
42 #define OPEN_FILE(F, SUFFIX) \
43 auto const F ## name = folly::to<std::string>(filename, SUFFIX); \
44 FILE* F = fopen(F ## name .c_str(),"wb"); \
45 if (F == nullptr) return false; \
46 SCOPE_EXIT{ fclose(F); };
48 OPEN_FILE(aFile
, "_a");
49 OPEN_FILE(acoldFile
, "_acold");
50 OPEN_FILE(afrozenFile
, "_afrozen");
54 // dump starting from the main region
56 auto writeBlock
= [&](const CodeBlock
& cb
, FILE* file
) {
58 auto const count
= cb
.used();
59 result
= fwrite(cb
.base(), 1, count
, file
) == count
;
63 writeBlock(code().main(), aFile
);
64 writeBlock(code().cold(), acoldFile
);
65 writeBlock(code().frozen(), afrozenFile
);
70 auto const dataPath
= RuntimeOption::EvalDumpTCPath
+ "/tc_data.txt.gz";
71 gzFile tcDataFile
= gzopen(dataPath
.c_str(), "w");
72 if (!tcDataFile
) return false;
73 SCOPE_EXIT
{ gzclose(tcDataFile
); };
75 if (!gzprintf(tcDataFile
,
80 "acold.frontier = %p\n"
82 "afrozen.frontier = %p\n\n",
83 repoSchemaId().begin(),
84 code().main().base(), code().main().frontier(),
85 code().cold().base(), code().cold().frontier(),
86 code().frozen().base(), code().frozen().frontier())) {
90 if (!gzprintf(tcDataFile
, "total_translations = %zu\n\n",
91 transdb::getNumTranslations())) {
95 // Print all translations, including their execution counters. If global
96 // counters are disabled (default), fall back to using ProfData, covering
97 // only profiling translations.
98 if (transdb::enabled()) {
99 // Admin requests do not automatically init ProfData, so do it explicitly.
100 // No need for matching exit call; data is immortal with trans DB enabled.
101 requestInitProfData();
103 const TransRec invalid
;
104 assertx(!invalid
.isValid());
105 for (TransID t
= 0; t
< transdb::getNumTranslations(); t
++) {
106 auto transRec
= transdb::getTransRec(t
);
107 if (!transRec
) transRec
= &invalid
;
108 auto const ret
= gzputs(tcDataFile
, transRec
->print().c_str());
117 ////////////////////////////////////////////////////////////////////////////////
121 return RuntimeOption::EvalDumpTC
||
122 RuntimeOption::EvalDumpIR
||
123 RuntimeOption::EvalDumpRegion
||
124 RuntimeOption::EvalDumpInlDecision
||
125 RuntimeOption::EvalDumpCallTargets
||
126 RuntimeOption::EvalDumpLayoutCFG
||
127 RuntimeOption::EvalDumpVBC
;
130 bool dump(bool ignoreLease
/* = false */) {
131 if (!mcgen::initialized()) return false;
133 std::unique_lock
<SimpleMutex
> codeLock
;
134 std::unique_lock
<SimpleMutex
> metaLock
;
136 codeLock
= lockCode();
137 metaLock
= lockMetadata();
139 return dumpTCData() &&
140 dumpTCCode(RuntimeOption::EvalDumpTCPath
+ "/tc_dump");
143 std::vector
<UsageInfo
> getUsageInfo() {
144 std::vector
<UsageInfo
> tcUsageInfo
;
146 code().forEachBlock([&] (const char* name
, const CodeBlock
& a
) {
147 tcUsageInfo
.emplace_back(UsageInfo
{
148 std::string("code.") + name
,
154 tcUsageInfo
.emplace_back(UsageInfo
{
156 code().data().used(),
157 code().data().capacity(),
160 tcUsageInfo
.emplace_back(UsageInfo
{
163 RuntimeOption::EvalRDSSize
* 3 / 4,
166 tcUsageInfo
.emplace_back(UsageInfo
{
168 rds::usedLocalBytes(),
169 RuntimeOption::EvalRDSSize
* 3 / 4,
172 tcUsageInfo
.emplace_back(UsageInfo
{
174 rds::usedPersistentBytes(),
175 RuntimeOption::EvalRDSSize
/ 4,
181 std::string
getTCSpace() {
183 size_t total_size
= 0;
184 size_t total_capacity
= 0;
186 auto const add_row
= [&] (const UsageInfo
& ui
) {
187 auto const percent
= ui
.capacity
? 100 * ui
.used
/ ui
.capacity
: 0;
189 usage
+= folly::format(
190 "mcg: {:9} bytes ({}%) in {}\n",
191 ui
.used
, percent
, ui
.name
195 total_size
+= ui
.used
;
196 total_capacity
+= ui
.capacity
;
200 auto const uis
= getUsageInfo();
201 std::for_each(uis
.begin(), uis
.end(), add_row
);
202 add_row(UsageInfo
{ "total", total_size
, total_capacity
, false });
207 std::string
getTCAddrs() {
210 code().forEachBlock([&] (const char* name
, const CodeBlock
& a
) {
211 addrs
+= folly::format("{}: {}\n", name
, a
.base()).str();
216 std::vector
<TCMemInfo
> getTCMemoryUsage() {
217 std::vector
<TCMemInfo
> ret
;
219 [&](const char* name
, const CodeBlock
& a
) {
220 ret
.emplace_back(TCMemInfo
{