codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / vm / jit / trans-rec.cpp
blob218fbf70864ad0cf6cdade29379a8374877c4826
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 +----------------------------------------------------------------------+
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,
27 TransID transID,
28 TransKind _kind,
29 TCA _aStart,
30 uint32_t _aLen,
31 TCA _acoldStart,
32 uint32_t _acoldLen,
33 TCA _afrozenStart,
34 uint32_t _afrozenLen,
35 RegionDescPtr region,
36 std::vector<TransBCMapping> _bcMapping,
37 Annotations&& _annotations,
38 bool _hasLoop)
39 : bcMapping(_bcMapping)
40 , annotations(std::move(_annotations))
41 , funcName(_src.func()->fullName()->data())
42 , src(_src)
43 , md5(_src.func()->unit()->md5())
44 , aStart(_aStart)
45 , acoldStart(_acoldStart)
46 , afrozenStart(_afrozenStart)
47 , aLen(_aLen)
48 , acoldLen(_acoldLen)
49 , afrozenLen(_afrozenLen)
50 , bcStart(_src.offset())
51 , id(transID)
52 , kind(_kind)
53 , hasLoop(_hasLoop)
55 if (funcName.empty()) funcName = "Pseudo-main";
57 if (!region) return;
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));
72 void
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);
86 auto newAnnotation =
87 folly::sformat(
88 "file:{}:{}:{}",
89 saved.fileName, saved.offset, saved.length);
90 std::swap(annotation.second, newAnnotation);
91 } else {
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()) {
110 unlink(fileName);
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) {
118 fclose(file);
119 return saved;
121 auto const& content = annotation.second;
122 if (compress) {
123 gzFile compressedFile = gzdopen(fileno(file), "a");
124 if (!compressedFile) {
125 fclose(file);
126 return saved;
128 auto rv = gzputs(compressedFile, content.c_str());
129 if (rv > 0) saved.length = rv;
130 gzclose(compressedFile);
131 } else {
132 if (fputs(content.c_str(), file) >= 0) {
133 saved.length = content.length();
135 fclose(file);
138 return saved;
141 std::string
142 TransRec::print(uint64_t profCount) const {
143 if (!isValid()) return "Translation -1 {\n}\n\n";
145 std::string ret;
146 std::string funcName = src.func()->fullName()->data();
148 // Split up the call to prevent template explosion
149 folly::format(
150 &ret,
151 "Translation {} {{\n"
152 " src.md5 = {}\n"
153 " src.funcId = {}\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(),
163 src.offset(),
164 blocks.size());
166 for (auto const& block : blocks) {
167 folly::format(
168 &ret,
169 " {} {} {}\n",
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);
179 folly::format(
180 &ret,
181 " kind = {} ({})\n"
182 " hasLoop = {:d}\n"
183 " aStart = {}\n"
184 " aLen = {:#x}\n"
185 " coldStart = {}\n"
186 " coldLen = {:#x}\n"
187 " frozenStart = {}\n"
188 " frozenLen = {:#x}\n",
189 static_cast<uint32_t>(kind), show(kind),
190 hasLoop,
191 aStart, aLen,
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);
204 } else {
205 folly::format(&ret, " annotations = {}\n", annotations.size());
207 for (auto const& annotation : annotations) {
208 folly::format(&ret, " [\"{}\"] = {}\n",
209 annotation.first, annotation.second);
212 folly::format(
213 &ret,
214 " profCount = {}\n"
215 " bcMapping = {}\n",
216 profCount, bcMapping.size());
218 for (auto const& info : bcMapping) {
219 folly::format(
220 &ret,
221 " {} {} {} {} {}\n",
222 info.md5, info.bcStart,
223 info.aStart, info.acoldStart, info.afrozenStart);
226 ret += "}\n\n";
227 return ret;
230 Offset TransRec::bcPast() const {
231 return blocks.empty() ? 0 : blocks.back().bcPast;