1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/mips/CodeGenerator-mips.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,308 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_mips_CodeGenerator_mips_h 1.11 +#define jit_mips_CodeGenerator_mips_h 1.12 + 1.13 +#include "jit/mips/Assembler-mips.h" 1.14 +#include "jit/shared/CodeGenerator-shared.h" 1.15 + 1.16 +namespace js { 1.17 +namespace jit { 1.18 + 1.19 +class OutOfLineBailout; 1.20 +class OutOfLineTableSwitch; 1.21 + 1.22 +class CodeGeneratorMIPS : public CodeGeneratorShared 1.23 +{ 1.24 + friend class MoveResolverMIPS; 1.25 + 1.26 + CodeGeneratorMIPS *thisFromCtor() { 1.27 + return this; 1.28 + } 1.29 + 1.30 + protected: 1.31 + // Label for the common return path. 1.32 + NonAssertingLabel returnLabel_; 1.33 + NonAssertingLabel deoptLabel_; 1.34 + 1.35 + inline Address ToAddress(const LAllocation &a) { 1.36 + MOZ_ASSERT(a.isMemory()); 1.37 + int32_t offset = ToStackOffset(&a); 1.38 + 1.39 + // The way the stack slots work, we assume that everything from 1.40 + // depth == 0 downwards is writable however, since our frame is 1.41 + // included in this, ensure that the frame gets skipped. 1.42 + if (gen->compilingAsmJS()) 1.43 + offset -= AlignmentMidPrologue; 1.44 + 1.45 + return Address(StackPointer, offset); 1.46 + } 1.47 + 1.48 + inline Address ToAddress(const LAllocation *a) { 1.49 + return ToAddress(*a); 1.50 + } 1.51 + 1.52 + inline Operand ToOperand(const LAllocation &a) { 1.53 + if (a.isGeneralReg()) 1.54 + return Operand(a.toGeneralReg()->reg()); 1.55 + if (a.isFloatReg()) 1.56 + return Operand(a.toFloatReg()->reg()); 1.57 + 1.58 + MOZ_ASSERT(a.isMemory()); 1.59 + int32_t offset = ToStackOffset(&a); 1.60 + 1.61 + // The way the stack slots work, we assume that everything from 1.62 + // depth == 0 downwards is writable however, since our frame is 1.63 + // included in this, ensure that the frame gets skipped. 1.64 + if (gen->compilingAsmJS()) 1.65 + offset -= AlignmentMidPrologue; 1.66 + 1.67 + return Operand(StackPointer, offset); 1.68 + } 1.69 + inline Operand ToOperand(const LAllocation *a) { 1.70 + return ToOperand(*a); 1.71 + } 1.72 + inline Operand ToOperand(const LDefinition *def) { 1.73 + return ToOperand(def->output()); 1.74 + } 1.75 + 1.76 + MoveOperand toMoveOperand(const LAllocation *a) const; 1.77 + 1.78 + template <typename T1, typename T2> 1.79 + bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { 1.80 + bool goodBailout; 1.81 + Label skip; 1.82 + masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(c), ShortJump); 1.83 + goodBailout = bailout(snapshot); 1.84 + masm.bind(&skip); 1.85 + return goodBailout; 1.86 + } 1.87 + template<typename T> 1.88 + bool bailoutCmp32(Assembler::Condition c, Operand lhs, T rhs, LSnapshot *snapshot) { 1.89 + if (lhs.getTag() == Operand::REG) 1.90 + return bailoutCmp32(c, lhs.toReg(), rhs, snapshot); 1.91 + if (lhs.getTag() == Operand::MEM) 1.92 + return bailoutCmp32(c, lhs.toAddress(), rhs, snapshot); 1.93 + MOZ_ASSUME_UNREACHABLE("Invalid operand tag."); 1.94 + return false; 1.95 + } 1.96 + template<typename T> 1.97 + bool bailoutTest32(Assembler::Condition c, Register lhs, T rhs, LSnapshot *snapshot) { 1.98 + Label bail; 1.99 + masm.branchTest32(c, lhs, rhs, &bail); 1.100 + return bailoutFrom(&bail, snapshot); 1.101 + } 1.102 + template <typename T1, typename T2> 1.103 + bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) { 1.104 + return bailoutCmp32(c, lhs, rhs, snapshot); 1.105 + } 1.106 + bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) { 1.107 + Label bail; 1.108 + masm.branchTestPtr(c, lhs, rhs, &bail); 1.109 + return bailoutFrom(&bail, snapshot); 1.110 + } 1.111 + 1.112 + bool bailoutFrom(Label *label, LSnapshot *snapshot); 1.113 + bool bailout(LSnapshot *snapshot); 1.114 + 1.115 + protected: 1.116 + bool generatePrologue(); 1.117 + bool generateEpilogue(); 1.118 + bool generateOutOfLineCode(); 1.119 + 1.120 + template <typename T> 1.121 + void branchToBlock(Register lhs, T rhs, MBasicBlock *mir, Assembler::Condition cond) 1.122 + { 1.123 + Label *label = mir->lir()->label(); 1.124 + if (Label *oolEntry = labelForBackedgeWithImplicitCheck(mir)) { 1.125 + // Note: the backedge is initially a jump to the next instruction. 1.126 + // It will be patched to the target block's label during link(). 1.127 + RepatchLabel rejoin; 1.128 + CodeOffsetJump backedge; 1.129 + Label skip; 1.130 + 1.131 + masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(cond), ShortJump); 1.132 + backedge = masm.jumpWithPatch(&rejoin); 1.133 + masm.bind(&rejoin); 1.134 + masm.bind(&skip); 1.135 + 1.136 + if (!patchableBackedges_.append(PatchableBackedgeInfo(backedge, label, oolEntry))) 1.137 + MOZ_CRASH(); 1.138 + } else { 1.139 + masm.ma_b(lhs, rhs, label, cond); 1.140 + } 1.141 + } 1.142 + void branchToBlock(Assembler::FloatFormat fmt, FloatRegister lhs, FloatRegister rhs, 1.143 + MBasicBlock *mir, Assembler::DoubleCondition cond); 1.144 + 1.145 + // Emits a branch that directs control flow to the true block if |cond| is 1.146 + // true, and the false block if |cond| is false. 1.147 + template <typename T> 1.148 + void emitBranch(Register lhs, T rhs, Assembler::Condition cond, 1.149 + MBasicBlock *mirTrue, MBasicBlock *mirFalse) 1.150 + { 1.151 + if (isNextBlock(mirFalse->lir())) { 1.152 + branchToBlock(lhs, rhs, mirTrue, cond); 1.153 + } else { 1.154 + branchToBlock(lhs, rhs, mirFalse, Assembler::InvertCondition(cond)); 1.155 + jumpToBlock(mirTrue); 1.156 + } 1.157 + } 1.158 + void testNullEmitBranch(Assembler::Condition cond, const ValueOperand &value, 1.159 + MBasicBlock *ifTrue, MBasicBlock *ifFalse) 1.160 + { 1.161 + emitBranch(value.typeReg(), (Imm32)ImmType(JSVAL_TYPE_NULL), cond, ifTrue, ifFalse); 1.162 + } 1.163 + void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand &value, 1.164 + MBasicBlock *ifTrue, MBasicBlock *ifFalse) 1.165 + { 1.166 + emitBranch(value.typeReg(), (Imm32)ImmType(JSVAL_TYPE_UNDEFINED), cond, ifTrue, ifFalse); 1.167 + } 1.168 + 1.169 + bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base); 1.170 + 1.171 + public: 1.172 + // Instruction visitors. 1.173 + virtual bool visitMinMaxD(LMinMaxD *ins); 1.174 + virtual bool visitAbsD(LAbsD *ins); 1.175 + virtual bool visitAbsF(LAbsF *ins); 1.176 + virtual bool visitSqrtD(LSqrtD *ins); 1.177 + virtual bool visitSqrtF(LSqrtF *ins); 1.178 + virtual bool visitAddI(LAddI *ins); 1.179 + virtual bool visitSubI(LSubI *ins); 1.180 + virtual bool visitBitNotI(LBitNotI *ins); 1.181 + virtual bool visitBitOpI(LBitOpI *ins); 1.182 + 1.183 + virtual bool visitMulI(LMulI *ins); 1.184 + 1.185 + virtual bool visitDivI(LDivI *ins); 1.186 + virtual bool visitDivPowTwoI(LDivPowTwoI *ins); 1.187 + virtual bool visitModI(LModI *ins); 1.188 + virtual bool visitModPowTwoI(LModPowTwoI *ins); 1.189 + virtual bool visitModMaskI(LModMaskI *ins); 1.190 + virtual bool visitPowHalfD(LPowHalfD *ins); 1.191 + virtual bool visitShiftI(LShiftI *ins); 1.192 + virtual bool visitUrshD(LUrshD *ins); 1.193 + 1.194 + virtual bool visitTestIAndBranch(LTestIAndBranch *test); 1.195 + virtual bool visitCompare(LCompare *comp); 1.196 + virtual bool visitCompareAndBranch(LCompareAndBranch *comp); 1.197 + virtual bool visitTestDAndBranch(LTestDAndBranch *test); 1.198 + virtual bool visitTestFAndBranch(LTestFAndBranch *test); 1.199 + virtual bool visitCompareD(LCompareD *comp); 1.200 + virtual bool visitCompareF(LCompareF *comp); 1.201 + virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp); 1.202 + virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp); 1.203 + virtual bool visitCompareB(LCompareB *lir); 1.204 + virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir); 1.205 + virtual bool visitCompareV(LCompareV *lir); 1.206 + virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir); 1.207 + virtual bool visitBitAndAndBranch(LBitAndAndBranch *lir); 1.208 + virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir); 1.209 + virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir); 1.210 + virtual bool visitNotI(LNotI *ins); 1.211 + virtual bool visitNotD(LNotD *ins); 1.212 + virtual bool visitNotF(LNotF *ins); 1.213 + 1.214 + virtual bool visitMathD(LMathD *math); 1.215 + virtual bool visitMathF(LMathF *math); 1.216 + virtual bool visitFloor(LFloor *lir); 1.217 + virtual bool visitFloorF(LFloorF *lir); 1.218 + virtual bool visitRound(LRound *lir); 1.219 + virtual bool visitRoundF(LRoundF *lir); 1.220 + virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); 1.221 + virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins); 1.222 + 1.223 + // Out of line visitors. 1.224 + bool visitOutOfLineBailout(OutOfLineBailout *ool); 1.225 + bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool); 1.226 + 1.227 + protected: 1.228 + ValueOperand ToValue(LInstruction *ins, size_t pos); 1.229 + ValueOperand ToOutValue(LInstruction *ins); 1.230 + ValueOperand ToTempValue(LInstruction *ins, size_t pos); 1.231 + 1.232 + // Functions for LTestVAndBranch. 1.233 + Register splitTagForTest(const ValueOperand &value); 1.234 + 1.235 + void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType, 1.236 + const Register &elements, const LAllocation *index); 1.237 + 1.238 + public: 1.239 + CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm); 1.240 + 1.241 + public: 1.242 + bool visitBox(LBox *box); 1.243 + bool visitBoxFloatingPoint(LBoxFloatingPoint *box); 1.244 + bool visitUnbox(LUnbox *unbox); 1.245 + bool visitValue(LValue *value); 1.246 + bool visitDouble(LDouble *ins); 1.247 + bool visitFloat32(LFloat32 *ins); 1.248 + 1.249 + bool visitLoadSlotV(LLoadSlotV *load); 1.250 + bool visitLoadSlotT(LLoadSlotT *load); 1.251 + bool visitStoreSlotT(LStoreSlotT *load); 1.252 + 1.253 + bool visitLoadElementT(LLoadElementT *load); 1.254 + 1.255 + bool visitGuardShape(LGuardShape *guard); 1.256 + bool visitGuardObjectType(LGuardObjectType *guard); 1.257 + bool visitGuardClass(LGuardClass *guard); 1.258 + bool visitImplicitThis(LImplicitThis *lir); 1.259 + 1.260 + bool visitInterruptCheck(LInterruptCheck *lir); 1.261 + 1.262 + bool visitNegI(LNegI *lir); 1.263 + bool visitNegD(LNegD *lir); 1.264 + bool visitNegF(LNegF *lir); 1.265 + bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins); 1.266 + bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins); 1.267 + bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins); 1.268 + bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins); 1.269 + bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins); 1.270 + bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins); 1.271 + bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins); 1.272 + bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins); 1.273 + 1.274 + bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); 1.275 + 1.276 + bool visitForkJoinGetSlice(LForkJoinGetSlice *ins); 1.277 + 1.278 + bool generateInvalidateEpilogue(); 1.279 + protected: 1.280 + void postAsmJSCall(LAsmJSCall *lir) {} 1.281 + 1.282 + bool visitEffectiveAddress(LEffectiveAddress *ins); 1.283 + bool visitUDiv(LUDiv *ins); 1.284 + bool visitUMod(LUMod *ins); 1.285 +}; 1.286 + 1.287 +typedef CodeGeneratorMIPS CodeGeneratorSpecific; 1.288 + 1.289 +// An out-of-line bailout thunk. 1.290 +class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorMIPS> 1.291 +{ 1.292 + LSnapshot *snapshot_; 1.293 + uint32_t frameSize_; 1.294 + 1.295 + public: 1.296 + OutOfLineBailout(LSnapshot *snapshot, uint32_t frameSize) 1.297 + : snapshot_(snapshot), 1.298 + frameSize_(frameSize) 1.299 + { } 1.300 + 1.301 + bool accept(CodeGeneratorMIPS *codegen); 1.302 + 1.303 + LSnapshot *snapshot() const { 1.304 + return snapshot_; 1.305 + } 1.306 +}; 1.307 + 1.308 +} // namespace jit 1.309 +} // namespace js 1.310 + 1.311 +#endif /* jit_mips_CodeGenerator_mips_h */