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 +----------------------------------------------------------------------+
16 #include "hphp/tools/tc-print/mappers.h"
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
{
32 EXT_OP(TraceletGuard) \
33 EXT_OP(FuncPrologue) \
37 ExtOpStart
= Op_count
+ 1,
38 #define EXT_OP(name) ExtOp##name ,
46 std::string
extOpcodeToString(ExtOpcode eOpcode
) {
47 static const char* extOpNames
[] = {
48 #define EXT_OP(name) #name ,
54 if (eOpcode
< (ExtOpcode
)ExtOpStart
) {
55 return opcodeToName((Op
)eOpcode
);
58 if (eOpcode
> (ExtOpcode
)ExtOpStart
&& eOpcode
< (ExtOpcode
)ExtOpEnd
) {
59 return extOpNames
[eOpcode
- ExtOpStart
- 1];
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
));
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
;
87 std::string
tcRegionToString(TCRegion tcr
) {
88 always_assert(tcr
< TCRCount
);
89 return TCRegionString
[tcr
];
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
)) {
108 struct ExtOpcodeResult
{ bool valid
; ExtOpcode opcode
; };
109 ExtOpcodeResult
getExtOpcode(TCA addr
, const TransRec
* 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();
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
));
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 */
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
;
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
-
176 tfragment
.afrozenStart
= trec
->afrozenStart
;
177 tfragment
.afrozenLen
= trec
->bcMapping
[0].afrozenStart
-
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
;
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
)) {
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
;
221 always_assert(found
);
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
);