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/func-guard-arm.h"
19 #include "hphp/runtime/vm/jit/abi-arm.h"
20 #include "hphp/runtime/vm/jit/translator.h"
21 #include "hphp/runtime/vm/jit/smashable-instr-arm.h"
22 #include "hphp/runtime/vm/jit/tc.h"
23 #include "hphp/runtime/vm/jit/unique-stubs.h"
24 #include "hphp/runtime/vm/jit/vasm-reg.h"
26 #include "hphp/util/data-block.h"
28 #include "hphp/vixl/a64/constants-a64.h"
29 #include "hphp/vixl/a64/macro-assembler-a64.h"
31 namespace HPHP
{ namespace jit
{ namespace arm
{
33 ///////////////////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////////////////
39 ALWAYS_INLINE
bool isPrologueStub(TCA addr
) {
40 return addr
== tc::ustubs().fcallHelperThunk
;
43 vixl::Register
X(Vreg64 r
) {
44 PhysReg
pr(r
.asReg());
48 vixl::MemOperand
M(Vptr p
) {
49 assertx(p
.base
.isValid() && !p
.index
.isValid());
50 return X(p
.base
)[p
.disp
];
53 ///////////////////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////////////////
59 void emitFuncGuard(const Func
* func
, CodeBlock
& cb
, CGMeta
& fixups
) {
60 vixl::MacroAssembler a
{ cb
};
62 vixl::Label target_data
;
63 auto const begin
= cb
.frontier();
65 assertx(arm::abi(CodeKind::Prologue
).gpUnreserved
.contains(vixl::x0
));
67 emitSmashableMovq(cb
, fixups
, uint64_t(func
), vixl::x0
);
68 a
. Ldr (rAsm
, M(rvmfp()[AROFF(m_func
)]));
69 a
. Cmp (vixl::x0
, rAsm
);
70 a
. B (&after
, convertCC(CC_Z
));
72 // Although an address this unique stub should never change, so we don't
73 // need to mark it as an address.
74 poolLiteral(cb
, fixups
,
75 (uint64_t)makeTarget32(tc::ustubs().funcPrologueRedispatch
),
77 a
. bind (&target_data
);
78 a
. Ldr (rAsm_w
, &target_data
);
86 TCA
funcGuardFromPrologue(TCA prologue
, const Func
* /*func*/) {
87 if (!isPrologueStub(prologue
)) {
88 // Typically a func guard is a smashable movq followed by an ldr, cmp, b.eq,
89 // ldr, and a br. However, relocation can shorten the sequence, or even
90 // increase it (turning the ldr into mov+movk), so search backwards until
91 // the smashable movq is found.
92 for (int length
= 0; length
<= vixl::kInstructionSize
* 6; length
+= 4) {
93 TCA inst
= prologue
- (smashableMovqLen() + length
);
94 if (possiblySmashableMovq(inst
)) return inst
;
101 bool funcGuardMatches(TCA guard
, const Func
* func
) {
102 if (isPrologueStub(guard
)) return false;
103 return smashableMovqImm(guard
) == reinterpret_cast<uintptr_t>(func
);
106 void clobberFuncGuard(TCA guard
, const Func
* /*func*/) {
110 ///////////////////////////////////////////////////////////////////////////////