Move io_tests to folly/io/async/test
[hiphop-php.git] / hphp / tools / tc-print / mappers.cpp
blobfe6f55b6efb39c1374aed9ac43481e3a427f73e0
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/tools/tc-print/mappers.h"
18 #include <cstdio>
19 #include <string>
20 #include <assert.h>
21 #include <algorithm>
22 #include <iomanip>
24 #include "hphp/runtime/vm/jit/translator.h"
26 #include "hphp/tools/tc-print/offline-code.h"
27 #include "hphp/tools/tc-print/tc-print.h"
29 namespace HPHP { namespace jit {
31 #define EXT_OPCODES \
32 EXT_OP(TraceletGuard) \
33 EXT_OP(FuncPrologue) \
34 EXT_OP(FuncEntry)
36 enum ExtOp {
37 ExtOpStart = Op_count + 1,
38 #define EXT_OP(name) ExtOp##name ,
39 EXT_OPCODES
40 #undef EXT_OP
41 ExtOpEnd
44 /* Utilities */
46 std::string extOpcodeToString(ExtOpcode eOpcode) {
47 static const char* extOpNames[] = {
48 #define EXT_OP(name) #name ,
49 EXT_OPCODES
50 #undef EXT_OP
51 "Invalid"
54 if (eOpcode < (ExtOpcode)ExtOpStart) {
55 return opcodeToName((Op)eOpcode);
58 if (eOpcode > (ExtOpcode)ExtOpStart && eOpcode < (ExtOpcode)ExtOpEnd) {
59 return extOpNames[eOpcode - ExtOpStart - 1];
62 return "Invalid";
65 std::vector<std::pair<std::string,ExtOpcode>> getValidOpcodeNames() {
66 std::vector<std::pair<std::string,ExtOpcode>> ret;
67 for (size_t i = 0; i < Op_count; i++) {
68 ret.push_back(make_pair(extOpcodeToString(ExtOp(i)), i));
70 for (ExtOpcode i = ExtOpStart + 1; i < ExtOpEnd; i++) {
71 ret.push_back(make_pair(extOpcodeToString(i), i));
73 return ret;
76 ExtOpcode stringToExtOpcode(std::string s) {
77 static std::vector<std::pair<std::string, ExtOpcode>>
78 validOpcodes = getValidOpcodeNames();
79 for (size_t i = 0; i < validOpcodes.size(); i++) {
80 if (validOpcodes[i].first == s) {
81 return validOpcodes[i].second;
84 return 0;
87 std::string tcRegionToString(TCRegion tcr) {
88 always_assert(tcr < TCRCount);
89 return TCRegionString[tcr];
92 /* AddrToBcMapper */
94 static const size_t kMaxErrStrLen = 1000;
95 static char errBuff[kMaxErrStrLen];
97 bool isTraceletGuard(TCA addr, const TransRec* trec) {
98 always_assert(!trec->bcMapping.empty());
100 if ((addr >= trec->aStart && addr < trec->bcMapping[0].aStart) ||
101 (addr >= trec->acoldStart && addr < trec->bcMapping[0].acoldStart)) {
102 return true;
105 return false;
108 struct ExtOpcodeResult { bool valid; ExtOpcode opcode; };
109 ExtOpcodeResult getExtOpcode(TCA addr, const TransRec* trec) {
111 always_assert(trec);
113 if (trec->kind == TransKind::LivePrologue ||
114 trec->kind == TransKind::ProfPrologue ||
115 trec->kind == TransKind::OptPrologue) {
116 return {true, ExtOpFuncPrologue};
118 if (isTraceletGuard(addr, trec)) {
119 return {true, ExtOpTraceletGuard};
122 const std::vector<TransBCMapping>& bcMap = trec->bcMapping;
123 always_assert(!bcMap.empty());
124 size_t numBCs = bcMap.size() - 1; // account for the sentinel
126 for (size_t i = 0; i < numBCs; i++) {
127 if ((bcMap[i].aStart <= addr && bcMap[i+1].aStart > addr) ||
128 (bcMap[i].acoldStart <= addr && bcMap[i+1].acoldStart > addr) ||
129 (bcMap[i].afrozenStart <= addr && bcMap[i+1].afrozenStart > addr)) {
130 if (bcMap[i].sk.funcEntry()) return {true, ExtOpFuncEntry};
131 auto const func = bcMap[i].sk.func();
132 always_assert(func);
133 return {true, (ExtOpcode)func->getOp(bcMap[i].sk.offset())};
137 snprintf(errBuff, kMaxErrStrLen, "getExtOpcode: no opcode for %p", addr);
138 error(std::string(errBuff));
139 return {false};
142 Optional<ExtOpcode>
143 AddrToBcMapper::operator()(const TCA& addr) {
144 TransID tid = transData->getTransContaining(addr);
145 if (tid == INVALID_ID) return std::nullopt;
147 const TransRec* trec = transData->getTransRec(tid);
148 Unit* unit = g_repo->getUnit(trec->sn);
149 if (!unit) return std::nullopt;
151 auto r = getExtOpcode(addr, trec);
152 always_assert(r.valid);
153 return make_optional(r.opcode);
156 /* AddrToTransFragmentMapper */
158 TransFragment
159 AddrToTransFragmentMapper::extractTransFragment(TCA addr, ExtOpcode opcode) {
160 TransID tid = tdata->getTransContaining(addr);
161 always_assert(tid != INVALID_ID);
163 const TransRec* trec = tdata->getTransRec(tid);
164 always_assert(!trec->bcMapping.empty());
166 TransFragment tfragment;
167 tfragment.tid = tid;
169 switch (opcode) {
170 case ExtOpTraceletGuard:
171 tfragment.aStart = trec->aStart;
172 tfragment.aLen = trec->bcMapping[0].aStart - trec->aStart;
173 tfragment.acoldStart = trec->acoldStart;
174 tfragment.acoldLen = trec->bcMapping[0].acoldStart -
175 trec->acoldStart;
176 tfragment.afrozenStart = trec->afrozenStart;
177 tfragment.afrozenLen = trec->bcMapping[0].afrozenStart -
178 trec->afrozenStart;
179 break;
181 case ExtOpFuncPrologue:
182 always_assert(trec->kind == TransKind::LivePrologue ||
183 trec->kind == TransKind::ProfPrologue ||
184 trec->kind == TransKind::OptPrologue);
186 tfragment.aStart = trec->aStart;
187 tfragment.aLen = trec->aLen;
188 tfragment.acoldStart = trec->acoldStart;
189 tfragment.acoldLen = trec->acoldLen;
190 tfragment.afrozenStart = trec->afrozenStart;
191 tfragment.afrozenLen = trec->afrozenLen;
192 break;
194 case ExtOpFuncEntry:
195 default:
196 bool found = false;
197 size_t nele = trec->bcMapping.size() - 1;
199 for (size_t i = 0; i < nele; i++) {
200 if ((trec->bcMapping[i].aStart <= addr &&
201 addr < trec->bcMapping[i+1].aStart) ||
202 (trec->bcMapping[i].acoldStart <= addr &&
203 addr < trec->bcMapping[i+1].acoldStart)) {
205 found = true;
207 tfragment.aStart = trec->bcMapping[i].aStart;
208 tfragment.aLen = trec->bcMapping[i+1].aStart -
209 trec->bcMapping[i].aStart;
210 tfragment.acoldStart = trec->bcMapping[i].acoldStart;
211 tfragment.acoldLen = trec->bcMapping[i+1].acoldStart -
212 trec->bcMapping[i].acoldStart;
213 tfragment.afrozenStart = trec->bcMapping[i].afrozenStart;
214 tfragment.afrozenLen = trec->bcMapping[i+1].afrozenStart -
215 trec->bcMapping[i].afrozenStart;
217 break;
221 always_assert(found);
224 return tfragment;
227 Optional<TransFragment>
228 AddrToTransFragmentMapper::operator()(const TCA& addr) {
229 AddrToBcMapper bcMapper(tdata);
230 Optional<ExtOpcode> opcode = bcMapper(addr);
231 if (!opcode || (*opcode) != filterBy) return std::nullopt;
232 return extractTransFragment(addr, *opcode);