Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
7 #ifndef jit_mips_CodeGenerator_mips_h
8 #define jit_mips_CodeGenerator_mips_h
10 #include "jit/mips/Assembler-mips.h"
11 #include "jit/shared/CodeGenerator-shared.h"
13 namespace js {
14 namespace jit {
16 class OutOfLineBailout;
17 class OutOfLineTableSwitch;
19 class CodeGeneratorMIPS : public CodeGeneratorShared
20 {
21 friend class MoveResolverMIPS;
23 CodeGeneratorMIPS *thisFromCtor() {
24 return this;
25 }
27 protected:
28 // Label for the common return path.
29 NonAssertingLabel returnLabel_;
30 NonAssertingLabel deoptLabel_;
32 inline Address ToAddress(const LAllocation &a) {
33 MOZ_ASSERT(a.isMemory());
34 int32_t offset = ToStackOffset(&a);
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;
42 return Address(StackPointer, offset);
43 }
45 inline Address ToAddress(const LAllocation *a) {
46 return ToAddress(*a);
47 }
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());
55 MOZ_ASSERT(a.isMemory());
56 int32_t offset = ToStackOffset(&a);
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;
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 }
73 MoveOperand toMoveOperand(const LAllocation *a) const;
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 }
109 bool bailoutFrom(Label *label, LSnapshot *snapshot);
110 bool bailout(LSnapshot *snapshot);
112 protected:
113 bool generatePrologue();
114 bool generateEpilogue();
115 bool generateOutOfLineCode();
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;
128 masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(cond), ShortJump);
129 backedge = masm.jumpWithPatch(&rejoin);
130 masm.bind(&rejoin);
131 masm.bind(&skip);
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);
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 }
166 bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
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);
180 virtual bool visitMulI(LMulI *ins);
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);
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);
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);
220 // Out of line visitors.
221 bool visitOutOfLineBailout(OutOfLineBailout *ool);
222 bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
224 protected:
225 ValueOperand ToValue(LInstruction *ins, size_t pos);
226 ValueOperand ToOutValue(LInstruction *ins);
227 ValueOperand ToTempValue(LInstruction *ins, size_t pos);
229 // Functions for LTestVAndBranch.
230 Register splitTagForTest(const ValueOperand &value);
232 void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
233 const Register &elements, const LAllocation *index);
235 public:
236 CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
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);
246 bool visitLoadSlotV(LLoadSlotV *load);
247 bool visitLoadSlotT(LLoadSlotT *load);
248 bool visitStoreSlotT(LStoreSlotT *load);
250 bool visitLoadElementT(LLoadElementT *load);
252 bool visitGuardShape(LGuardShape *guard);
253 bool visitGuardObjectType(LGuardObjectType *guard);
254 bool visitGuardClass(LGuardClass *guard);
255 bool visitImplicitThis(LImplicitThis *lir);
257 bool visitInterruptCheck(LInterruptCheck *lir);
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);
271 bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
273 bool visitForkJoinGetSlice(LForkJoinGetSlice *ins);
275 bool generateInvalidateEpilogue();
276 protected:
277 void postAsmJSCall(LAsmJSCall *lir) {}
279 bool visitEffectiveAddress(LEffectiveAddress *ins);
280 bool visitUDiv(LUDiv *ins);
281 bool visitUMod(LUMod *ins);
282 };
284 typedef CodeGeneratorMIPS CodeGeneratorSpecific;
286 // An out-of-line bailout thunk.
287 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorMIPS>
288 {
289 LSnapshot *snapshot_;
290 uint32_t frameSize_;
292 public:
293 OutOfLineBailout(LSnapshot *snapshot, uint32_t frameSize)
294 : snapshot_(snapshot),
295 frameSize_(frameSize)
296 { }
298 bool accept(CodeGeneratorMIPS *codegen);
300 LSnapshot *snapshot() const {
301 return snapshot_;
302 }
303 };
305 } // namespace jit
306 } // namespace js
308 #endif /* jit_mips_CodeGenerator_mips_h */