/src/mozilla-central/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 | | * vim: set ts=8 sts=4 et sw=4 tw=99: |
3 | | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef jit_x86_shared_CodeGenerator_x86_shared_h |
8 | | #define jit_x86_shared_CodeGenerator_x86_shared_h |
9 | | |
10 | | #include "jit/shared/CodeGenerator-shared.h" |
11 | | |
12 | | namespace js { |
13 | | namespace jit { |
14 | | |
15 | | class CodeGeneratorX86Shared; |
16 | | class OutOfLineBailout; |
17 | | class OutOfLineUndoALUOperation; |
18 | | class OutOfLineLoadTypedArrayOutOfBounds; |
19 | | class MulNegativeZeroCheck; |
20 | | class ModOverflowCheck; |
21 | | class ReturnZero; |
22 | | class OutOfLineTableSwitch; |
23 | | |
24 | | using OutOfLineWasmTruncateCheck = OutOfLineWasmTruncateCheckBase<CodeGeneratorX86Shared>; |
25 | | |
26 | | class CodeGeneratorX86Shared : public CodeGeneratorShared |
27 | | { |
28 | | friend class MoveResolverX86; |
29 | | |
30 | | template <typename T> |
31 | | void bailout(const T& t, LSnapshot* snapshot); |
32 | | |
33 | | protected: |
34 | | CodeGeneratorX86Shared(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm); |
35 | | |
36 | | // Load a NaN or zero into a register for an out of bounds AsmJS or static |
37 | | // typed array load. |
38 | | class OutOfLineLoadTypedArrayOutOfBounds : public OutOfLineCodeBase<CodeGeneratorX86Shared> |
39 | | { |
40 | | AnyRegister dest_; |
41 | | Scalar::Type viewType_; |
42 | | public: |
43 | | OutOfLineLoadTypedArrayOutOfBounds(AnyRegister dest, Scalar::Type viewType) |
44 | | : dest_(dest), viewType_(viewType) |
45 | 0 | {} |
46 | | |
47 | 0 | AnyRegister dest() const { return dest_; } |
48 | 0 | Scalar::Type viewType() const { return viewType_; } |
49 | 0 | void accept(CodeGeneratorX86Shared* codegen) override { |
50 | 0 | codegen->visitOutOfLineLoadTypedArrayOutOfBounds(this); |
51 | 0 | } |
52 | | }; |
53 | | |
54 | | NonAssertingLabel deoptLabel_; |
55 | | |
56 | | Operand ToOperand(const LAllocation& a); |
57 | | Operand ToOperand(const LAllocation* a); |
58 | | Operand ToOperand(const LDefinition* def); |
59 | | |
60 | | #ifdef JS_PUNBOX64 |
61 | | Operand ToOperandOrRegister64(const LInt64Allocation input); |
62 | | #else |
63 | | Register64 ToOperandOrRegister64(const LInt64Allocation input); |
64 | | #endif |
65 | | |
66 | | MoveOperand toMoveOperand(LAllocation a) const; |
67 | | |
68 | | void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot); |
69 | | void bailoutIf(Assembler::DoubleCondition condition, LSnapshot* snapshot); |
70 | | void bailoutFrom(Label* label, LSnapshot* snapshot); |
71 | | void bailout(LSnapshot* snapshot); |
72 | | |
73 | | template <typename T1, typename T2> |
74 | 0 | void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { |
75 | 0 | masm.cmpPtr(lhs, rhs); |
76 | 0 | bailoutIf(c, snapshot); |
77 | 0 | } |
78 | 0 | void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot* snapshot) { |
79 | 0 | masm.testPtr(lhs, rhs); |
80 | 0 | bailoutIf(c, snapshot); |
81 | 0 | } |
82 | | template <typename T1, typename T2> |
83 | 0 | void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { |
84 | 0 | masm.cmp32(lhs, rhs); |
85 | 0 | bailoutIf(c, snapshot); |
86 | 0 | } Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Register, js::jit::Imm32>(js::jit::AssemblerX86Shared::Condition, js::jit::Register, js::jit::Imm32, js::jit::LSnapshot*) Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Address, js::jit::Imm32>(js::jit::AssemblerX86Shared::Condition, js::jit::Address, js::jit::Imm32, js::jit::LSnapshot*) Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Register, js::jit::Register>(js::jit::AssemblerX86Shared::Condition, js::jit::Register, js::jit::Register, js::jit::LSnapshot*) Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Address, js::jit::Register>(js::jit::AssemblerX86Shared::Condition, js::jit::Address, js::jit::Register, js::jit::LSnapshot*) |
87 | | template <typename T1, typename T2> |
88 | 0 | void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { |
89 | 0 | masm.test32(lhs, rhs); |
90 | 0 | bailoutIf(c, snapshot); |
91 | 0 | } |
92 | 0 | void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) { |
93 | 0 | masm.test32(reg, Imm32(0xFF)); |
94 | 0 | bailoutIf(Assembler::Zero, snapshot); |
95 | 0 | } |
96 | 0 | void bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot* snapshot) { |
97 | 0 | // vcvttsd2si returns 0x80000000 on failure. Test for it by |
98 | 0 | // subtracting 1 and testing overflow. The other possibility is to test |
99 | 0 | // equality for INT_MIN after a comparison, but 1 costs fewer bytes to |
100 | 0 | // materialize. |
101 | 0 | masm.vcvttsd2si(src, dest); |
102 | 0 | masm.cmp32(dest, Imm32(1)); |
103 | 0 | bailoutIf(Assembler::Overflow, snapshot); |
104 | 0 | } |
105 | 0 | void bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot* snapshot) { |
106 | 0 | // Same trick as explained in the above comment. |
107 | 0 | masm.vcvttss2si(src, dest); |
108 | 0 | masm.cmp32(dest, Imm32(1)); |
109 | 0 | bailoutIf(Assembler::Overflow, snapshot); |
110 | 0 | } |
111 | | |
112 | | bool generateOutOfLineCode(); |
113 | | |
114 | | void emitCompare(MCompare::CompareType type, const LAllocation* left, const LAllocation* right); |
115 | | |
116 | | // Emits a branch that directs control flow to the true block if |cond| is |
117 | | // true, and the false block if |cond| is false. |
118 | | void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse, |
119 | | Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond); |
120 | | void emitBranch(Assembler::DoubleCondition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse); |
121 | | |
122 | | void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value, |
123 | | MBasicBlock* ifTrue, MBasicBlock* ifFalse) |
124 | 0 | { |
125 | 0 | cond = masm.testNull(cond, value); |
126 | 0 | emitBranch(cond, ifTrue, ifFalse); |
127 | 0 | } |
128 | | void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand& value, |
129 | | MBasicBlock* ifTrue, MBasicBlock* ifFalse) |
130 | 0 | { |
131 | 0 | cond = masm.testUndefined(cond, value); |
132 | 0 | emitBranch(cond, ifTrue, ifFalse); |
133 | 0 | } |
134 | | void testObjectEmitBranch(Assembler::Condition cond, const ValueOperand& value, |
135 | | MBasicBlock* ifTrue, MBasicBlock* ifFalse) |
136 | 0 | { |
137 | 0 | cond = masm.testObject(cond, value); |
138 | 0 | emitBranch(cond, ifTrue, ifFalse); |
139 | 0 | } |
140 | | |
141 | | void testZeroEmitBranch(Assembler::Condition cond, Register reg, |
142 | | MBasicBlock* ifTrue, MBasicBlock* ifFalse) |
143 | 0 | { |
144 | 0 | MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); |
145 | 0 | masm.cmpPtr(reg, ImmWord(0)); |
146 | 0 | emitBranch(cond, ifTrue, ifFalse); |
147 | 0 | } |
148 | | |
149 | | void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base); |
150 | | |
151 | | void generateInvalidateEpilogue(); |
152 | | |
153 | | void canonicalizeIfDeterministic(Scalar::Type type, const LAllocation* value); |
154 | | |
155 | | public: |
156 | | // Out of line visitors. |
157 | | void visitOutOfLineBailout(OutOfLineBailout* ool); |
158 | | void visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation* ool); |
159 | | void visitMulNegativeZeroCheck(MulNegativeZeroCheck* ool); |
160 | | void visitModOverflowCheck(ModOverflowCheck* ool); |
161 | | void visitReturnZero(ReturnZero* ool); |
162 | | void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); |
163 | | void visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds* ool); |
164 | | void visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* ool); |
165 | | }; |
166 | | |
167 | | // An out-of-line bailout thunk. |
168 | | class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorX86Shared> |
169 | | { |
170 | | LSnapshot* snapshot_; |
171 | | |
172 | | public: |
173 | | explicit OutOfLineBailout(LSnapshot* snapshot) |
174 | | : snapshot_(snapshot) |
175 | 201 | { } |
176 | | |
177 | | void accept(CodeGeneratorX86Shared* codegen) override; |
178 | | |
179 | 201 | LSnapshot* snapshot() const { |
180 | 201 | return snapshot_; |
181 | 201 | } |
182 | | }; |
183 | | |
184 | | } // namespace jit |
185 | | } // namespace js |
186 | | |
187 | | #endif /* jit_x86_shared_CodeGenerator_x86_shared_h */ |