js/src/jit/mips/CodeGenerator-mips.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:b9fe68b0e5d6
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_mips_CodeGenerator_mips_h
8 #define jit_mips_CodeGenerator_mips_h
9
10 #include "jit/mips/Assembler-mips.h"
11 #include "jit/shared/CodeGenerator-shared.h"
12
13 namespace js {
14 namespace jit {
15
16 class OutOfLineBailout;
17 class OutOfLineTableSwitch;
18
19 class CodeGeneratorMIPS : public CodeGeneratorShared
20 {
21 friend class MoveResolverMIPS;
22
23 CodeGeneratorMIPS *thisFromCtor() {
24 return this;
25 }
26
27 protected:
28 // Label for the common return path.
29 NonAssertingLabel returnLabel_;
30 NonAssertingLabel deoptLabel_;
31
32 inline Address ToAddress(const LAllocation &a) {
33 MOZ_ASSERT(a.isMemory());
34 int32_t offset = ToStackOffset(&a);
35
36 // The way the stack slots work, we assume that everything from
37 // depth == 0 downwards is writable however, since our frame is
38 // included in this, ensure that the frame gets skipped.
39 if (gen->compilingAsmJS())
40 offset -= AlignmentMidPrologue;
41
42 return Address(StackPointer, offset);
43 }
44
45 inline Address ToAddress(const LAllocation *a) {
46 return ToAddress(*a);
47 }
48
49 inline Operand ToOperand(const LAllocation &a) {
50 if (a.isGeneralReg())
51 return Operand(a.toGeneralReg()->reg());
52 if (a.isFloatReg())
53 return Operand(a.toFloatReg()->reg());
54
55 MOZ_ASSERT(a.isMemory());
56 int32_t offset = ToStackOffset(&a);
57
58 // The way the stack slots work, we assume that everything from
59 // depth == 0 downwards is writable however, since our frame is
60 // included in this, ensure that the frame gets skipped.
61 if (gen->compilingAsmJS())
62 offset -= AlignmentMidPrologue;
63
64 return Operand(StackPointer, offset);
65 }
66 inline Operand ToOperand(const LAllocation *a) {
67 return ToOperand(*a);
68 }
69 inline Operand ToOperand(const LDefinition *def) {
70 return ToOperand(def->output());
71 }
72
73 MoveOperand toMoveOperand(const LAllocation *a) const;
74
75 template <typename T1, typename T2>
76 bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
77 bool goodBailout;
78 Label skip;
79 masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(c), ShortJump);
80 goodBailout = bailout(snapshot);
81 masm.bind(&skip);
82 return goodBailout;
83 }
84 template<typename T>
85 bool bailoutCmp32(Assembler::Condition c, Operand lhs, T rhs, LSnapshot *snapshot) {
86 if (lhs.getTag() == Operand::REG)
87 return bailoutCmp32(c, lhs.toReg(), rhs, snapshot);
88 if (lhs.getTag() == Operand::MEM)
89 return bailoutCmp32(c, lhs.toAddress(), rhs, snapshot);
90 MOZ_ASSUME_UNREACHABLE("Invalid operand tag.");
91 return false;
92 }
93 template<typename T>
94 bool bailoutTest32(Assembler::Condition c, Register lhs, T rhs, LSnapshot *snapshot) {
95 Label bail;
96 masm.branchTest32(c, lhs, rhs, &bail);
97 return bailoutFrom(&bail, snapshot);
98 }
99 template <typename T1, typename T2>
100 bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
101 return bailoutCmp32(c, lhs, rhs, snapshot);
102 }
103 bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) {
104 Label bail;
105 masm.branchTestPtr(c, lhs, rhs, &bail);
106 return bailoutFrom(&bail, snapshot);
107 }
108
109 bool bailoutFrom(Label *label, LSnapshot *snapshot);
110 bool bailout(LSnapshot *snapshot);
111
112 protected:
113 bool generatePrologue();
114 bool generateEpilogue();
115 bool generateOutOfLineCode();
116
117 template <typename T>
118 void branchToBlock(Register lhs, T rhs, MBasicBlock *mir, Assembler::Condition cond)
119 {
120 Label *label = mir->lir()->label();
121 if (Label *oolEntry = labelForBackedgeWithImplicitCheck(mir)) {
122 // Note: the backedge is initially a jump to the next instruction.
123 // It will be patched to the target block's label during link().
124 RepatchLabel rejoin;
125 CodeOffsetJump backedge;
126 Label skip;
127
128 masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(cond), ShortJump);
129 backedge = masm.jumpWithPatch(&rejoin);
130 masm.bind(&rejoin);
131 masm.bind(&skip);
132
133 if (!patchableBackedges_.append(PatchableBackedgeInfo(backedge, label, oolEntry)))
134 MOZ_CRASH();
135 } else {
136 masm.ma_b(lhs, rhs, label, cond);
137 }
138 }
139 void branchToBlock(Assembler::FloatFormat fmt, FloatRegister lhs, FloatRegister rhs,
140 MBasicBlock *mir, Assembler::DoubleCondition cond);
141
142 // Emits a branch that directs control flow to the true block if |cond| is
143 // true, and the false block if |cond| is false.
144 template <typename T>
145 void emitBranch(Register lhs, T rhs, Assembler::Condition cond,
146 MBasicBlock *mirTrue, MBasicBlock *mirFalse)
147 {
148 if (isNextBlock(mirFalse->lir())) {
149 branchToBlock(lhs, rhs, mirTrue, cond);
150 } else {
151 branchToBlock(lhs, rhs, mirFalse, Assembler::InvertCondition(cond));
152 jumpToBlock(mirTrue);
153 }
154 }
155 void testNullEmitBranch(Assembler::Condition cond, const ValueOperand &value,
156 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
157 {
158 emitBranch(value.typeReg(), (Imm32)ImmType(JSVAL_TYPE_NULL), cond, ifTrue, ifFalse);
159 }
160 void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand &value,
161 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
162 {
163 emitBranch(value.typeReg(), (Imm32)ImmType(JSVAL_TYPE_UNDEFINED), cond, ifTrue, ifFalse);
164 }
165
166 bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
167
168 public:
169 // Instruction visitors.
170 virtual bool visitMinMaxD(LMinMaxD *ins);
171 virtual bool visitAbsD(LAbsD *ins);
172 virtual bool visitAbsF(LAbsF *ins);
173 virtual bool visitSqrtD(LSqrtD *ins);
174 virtual bool visitSqrtF(LSqrtF *ins);
175 virtual bool visitAddI(LAddI *ins);
176 virtual bool visitSubI(LSubI *ins);
177 virtual bool visitBitNotI(LBitNotI *ins);
178 virtual bool visitBitOpI(LBitOpI *ins);
179
180 virtual bool visitMulI(LMulI *ins);
181
182 virtual bool visitDivI(LDivI *ins);
183 virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
184 virtual bool visitModI(LModI *ins);
185 virtual bool visitModPowTwoI(LModPowTwoI *ins);
186 virtual bool visitModMaskI(LModMaskI *ins);
187 virtual bool visitPowHalfD(LPowHalfD *ins);
188 virtual bool visitShiftI(LShiftI *ins);
189 virtual bool visitUrshD(LUrshD *ins);
190
191 virtual bool visitTestIAndBranch(LTestIAndBranch *test);
192 virtual bool visitCompare(LCompare *comp);
193 virtual bool visitCompareAndBranch(LCompareAndBranch *comp);
194 virtual bool visitTestDAndBranch(LTestDAndBranch *test);
195 virtual bool visitTestFAndBranch(LTestFAndBranch *test);
196 virtual bool visitCompareD(LCompareD *comp);
197 virtual bool visitCompareF(LCompareF *comp);
198 virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp);
199 virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp);
200 virtual bool visitCompareB(LCompareB *lir);
201 virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir);
202 virtual bool visitCompareV(LCompareV *lir);
203 virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir);
204 virtual bool visitBitAndAndBranch(LBitAndAndBranch *lir);
205 virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
206 virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
207 virtual bool visitNotI(LNotI *ins);
208 virtual bool visitNotD(LNotD *ins);
209 virtual bool visitNotF(LNotF *ins);
210
211 virtual bool visitMathD(LMathD *math);
212 virtual bool visitMathF(LMathF *math);
213 virtual bool visitFloor(LFloor *lir);
214 virtual bool visitFloorF(LFloorF *lir);
215 virtual bool visitRound(LRound *lir);
216 virtual bool visitRoundF(LRoundF *lir);
217 virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
218 virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
219
220 // Out of line visitors.
221 bool visitOutOfLineBailout(OutOfLineBailout *ool);
222 bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
223
224 protected:
225 ValueOperand ToValue(LInstruction *ins, size_t pos);
226 ValueOperand ToOutValue(LInstruction *ins);
227 ValueOperand ToTempValue(LInstruction *ins, size_t pos);
228
229 // Functions for LTestVAndBranch.
230 Register splitTagForTest(const ValueOperand &value);
231
232 void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
233 const Register &elements, const LAllocation *index);
234
235 public:
236 CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
237
238 public:
239 bool visitBox(LBox *box);
240 bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
241 bool visitUnbox(LUnbox *unbox);
242 bool visitValue(LValue *value);
243 bool visitDouble(LDouble *ins);
244 bool visitFloat32(LFloat32 *ins);
245
246 bool visitLoadSlotV(LLoadSlotV *load);
247 bool visitLoadSlotT(LLoadSlotT *load);
248 bool visitStoreSlotT(LStoreSlotT *load);
249
250 bool visitLoadElementT(LLoadElementT *load);
251
252 bool visitGuardShape(LGuardShape *guard);
253 bool visitGuardObjectType(LGuardObjectType *guard);
254 bool visitGuardClass(LGuardClass *guard);
255 bool visitImplicitThis(LImplicitThis *lir);
256
257 bool visitInterruptCheck(LInterruptCheck *lir);
258
259 bool visitNegI(LNegI *lir);
260 bool visitNegD(LNegD *lir);
261 bool visitNegF(LNegF *lir);
262 bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
263 bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
264 bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
265 bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
266 bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins);
267 bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins);
268 bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins);
269 bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
270
271 bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
272
273 bool visitForkJoinGetSlice(LForkJoinGetSlice *ins);
274
275 bool generateInvalidateEpilogue();
276 protected:
277 void postAsmJSCall(LAsmJSCall *lir) {}
278
279 bool visitEffectiveAddress(LEffectiveAddress *ins);
280 bool visitUDiv(LUDiv *ins);
281 bool visitUMod(LUMod *ins);
282 };
283
284 typedef CodeGeneratorMIPS CodeGeneratorSpecific;
285
286 // An out-of-line bailout thunk.
287 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorMIPS>
288 {
289 LSnapshot *snapshot_;
290 uint32_t frameSize_;
291
292 public:
293 OutOfLineBailout(LSnapshot *snapshot, uint32_t frameSize)
294 : snapshot_(snapshot),
295 frameSize_(frameSize)
296 { }
297
298 bool accept(CodeGeneratorMIPS *codegen);
299
300 LSnapshot *snapshot() const {
301 return snapshot_;
302 }
303 };
304
305 } // namespace jit
306 } // namespace js
307
308 #endif /* jit_mips_CodeGenerator_mips_h */

mercurial