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/trans-rec.h"
19 #include "hphp/runtime/vm/jit/translator-inline.h"
20 #include "hphp/runtime/vm/jit/prof-data.h"
22 #include <unordered_map>
24 namespace HPHP
{ namespace jit
{
26 TransRec::TransRec(SrcKey _src
,
36 std::vector
<TransBCMapping
> _bcMapping
,
37 Annotations
&& _annotations
,
39 : bcMapping(_bcMapping
)
40 , annotations(std::move(_annotations
))
41 , funcName(_src
.func()->fullName()->data())
43 , md5(_src
.func()->unit()->md5())
45 , acoldStart(_acoldStart
)
46 , afrozenStart(_afrozenStart
)
49 , afrozenLen(_afrozenLen
)
50 , bcStart(_src
.offset())
55 if (funcName
.empty()) funcName
= "Pseudo-main";
59 assertx(!region
->empty());
60 for (auto& block
: region
->blocks()) {
61 auto sk
= block
->start();
62 blocks
.emplace_back(Block
{sk
.unit()->md5(), sk
.offset(),
63 block
->last().advanced().offset()});
66 auto& firstBlock
= *region
->blocks().front();
67 for (auto const& pred
: firstBlock
.typePreConditions()) {
68 guards
.emplace_back(show(pred
));
73 TransRec::optimizeForMemory() {
74 // Dump large annotations to disk.
75 for (int i
= 0 ; i
< annotations
.size(); ++i
) {
76 auto& annotation
= annotations
[i
];
77 if (annotation
.second
.find_first_of('\n') != std::string::npos
||
78 annotation
.second
.size() > 72) {
79 auto saved
= writeAnnotation(annotation
, /* compress */ true);
80 if (saved
.length
> 0) {
81 // Strip directory name from the file name.
82 size_t pos
= saved
.fileName
.find_last_of('/');
83 if (pos
!= std::string::npos
) {
84 saved
.fileName
= saved
.fileName
.substr(pos
+1);
89 saved
.fileName
, saved
.offset
, saved
.length
);
90 std::swap(annotation
.second
, newAnnotation
);
92 annotation
.second
= "<unknown: write failed>";
98 TransRec::SavedAnnotation
99 TransRec::writeAnnotation(const Annotation
& annotation
, bool compress
) {
100 static std::unordered_map
<std::string
, bool> fileWritten
;
101 SavedAnnotation saved
= {
102 folly::sformat("/tmp/tc_annotations.txt{}", compress
? ".gz" : ""),
106 auto const fileName
= saved
.fileName
.c_str();
108 auto result
= fileWritten
.find(saved
.fileName
);
109 if (result
== fileWritten
.end()) {
111 fileWritten
[saved
.fileName
] = true;
114 FILE* file
= fopen(fileName
, "a");
115 if (!file
) return saved
;
116 saved
.offset
= lseek(fileno(file
), 0, SEEK_END
);
117 if (saved
.offset
== (off_t
)-1) {
121 auto const& content
= annotation
.second
;
123 gzFile compressedFile
= gzdopen(fileno(file
), "a");
124 if (!compressedFile
) {
128 auto rv
= gzputs(compressedFile
, content
.c_str());
129 if (rv
> 0) saved
.length
= rv
;
130 gzclose(compressedFile
);
132 if (fputs(content
.c_str(), file
) >= 0) {
133 saved
.length
= content
.length();
142 TransRec::print(uint64_t profCount
) const {
143 if (!isValid()) return "Translation -1 {\n}\n\n";
146 std::string funcName
= src
.func()->fullName()->data();
148 // Split up the call to prevent template explosion
151 "Translation {} {{\n"
154 " src.funcName = {}\n"
155 " src.resumed = {}\n"
156 " src.hasThis = {}\n"
157 " src.bcStart = {}\n"
158 " src.blocks = {}\n",
159 id
, md5
, src
.funcID(),
160 funcName
.empty() ? "Pseudo-main" : funcName
,
161 (int32_t)src
.resumed(),
162 (int32_t)src
.hasThis(),
166 for (auto const& block
: blocks
) {
170 block
.md5
, block
.bcStart
, block
.bcPast
);
173 folly::format( &ret
, " src.guards = {}\n", guards
.size());
175 for (auto const& guard
: guards
) {
176 folly::format( &ret
, " {}\n", guard
);
187 " frozenStart = {}\n"
188 " frozenLen = {:#x}\n",
189 static_cast<uint32_t>(kind
), show(kind
),
192 acoldStart
, acoldLen
,
193 afrozenStart
, afrozenLen
);
195 // Prepend any target profile data to annotations list.
196 if (auto const profD
= profData()) {
197 auto targetProfs
= profD
->getTargetProfiles(id
);
198 folly::format(&ret
, " annotations = {}\n",
199 annotations
.size() + targetProfs
.size());
200 for (auto const& tProf
: targetProfs
) {
201 folly::format(&ret
, " [\"TargetProfile {}: {}\"] = {}\n",
202 tProf
.key
.bcOff
, tProf
.key
.name
->data(), tProf
.debugInfo
);
205 folly::format(&ret
, " annotations = {}\n", annotations
.size());
207 for (auto const& annotation
: annotations
) {
208 folly::format(&ret
, " [\"{}\"] = {}\n",
209 annotation
.first
, annotation
.second
);
216 profCount
, bcMapping
.size());
218 for (auto const& info
: bcMapping
) {
222 info
.md5
, info
.bcStart
,
223 info
.aStart
, info
.acoldStart
, info
.afrozenStart
);
230 Offset
TransRec::bcPast() const {
231 return blocks
.empty() ? 0 : blocks
.back().bcPast
;