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_CodeGenerator_h
8 #define jit_CodeGenerator_h
9 
10 #include "jit/IonCaches.h"
11 #if defined(JS_ION_PERF)
12 # include "jit/PerfSpewer.h"
13 #endif
14 
15 #if defined(JS_CODEGEN_X86)
16 # include "jit/x86/CodeGenerator-x86.h"
17 #elif defined(JS_CODEGEN_X64)
18 # include "jit/x64/CodeGenerator-x64.h"
19 #elif defined(JS_CODEGEN_ARM)
20 # include "jit/arm/CodeGenerator-arm.h"
21 #elif defined(JS_CODEGEN_ARM64)
22 # include "jit/arm64/CodeGenerator-arm64.h"
23 #elif defined(JS_CODEGEN_MIPS32)
24 # include "jit/mips32/CodeGenerator-mips32.h"
25 #elif defined(JS_CODEGEN_MIPS64)
26 # include "jit/mips64/CodeGenerator-mips64.h"
27 #elif defined(JS_CODEGEN_NONE)
28 # include "jit/none/CodeGenerator-none.h"
29 #else
30 #error "Unknown architecture!"
31 #endif
32 
33 namespace js {
34 namespace jit {
35 
36 class OutOfLineTestObject;
37 class OutOfLineNewArray;
38 class OutOfLineNewObject;
39 class CheckOverRecursedFailure;
40 class OutOfLineInterruptCheckImplicit;
41 class OutOfLineUnboxFloatingPoint;
42 class OutOfLineStoreElementHole;
43 class OutOfLineTypeOfV;
44 class OutOfLineUpdateCache;
45 class OutOfLineCallPostWriteBarrier;
46 class OutOfLineIsCallable;
47 class OutOfLineRegExpExec;
48 class OutOfLineRegExpTest;
49 class OutOfLineLambdaArrow;
50 
51 class CodeGenerator : public CodeGeneratorSpecific
52 {
53     void generateArgumentsChecks(bool bailout = true);
54     bool generateBody();
55 
56     ConstantOrRegister toConstantOrRegister(LInstruction* lir, size_t n, MIRType type);
57 
58   public:
59     CodeGenerator(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm = nullptr);
60     ~CodeGenerator();
61 
62   public:
63     bool generate();
64     bool generateAsmJS(AsmJSFunctionOffsets *offsets);
65     bool link(JSContext* cx, CompilerConstraintList* constraints);
66     bool linkSharedStubs(JSContext* cx);
67 
68     void visitOsiPoint(LOsiPoint* lir);
69     void visitGoto(LGoto* lir);
70     void visitTableSwitch(LTableSwitch* ins);
71     void visitTableSwitchV(LTableSwitchV* ins);
72     void visitCloneLiteral(LCloneLiteral* lir);
73     void visitParameter(LParameter* lir);
74     void visitCallee(LCallee* lir);
75     void visitIsConstructing(LIsConstructing* lir);
76     void visitStart(LStart* lir);
77     void visitReturn(LReturn* ret);
78     void visitDefVar(LDefVar* lir);
79     void visitDefLexical(LDefLexical* lir);
80     void visitDefFun(LDefFun* lir);
81     void visitOsrEntry(LOsrEntry* lir);
82     void visitOsrScopeChain(LOsrScopeChain* lir);
83     void visitOsrValue(LOsrValue* lir);
84     void visitOsrReturnValue(LOsrReturnValue* lir);
85     void visitOsrArgumentsObject(LOsrArgumentsObject* lir);
86     void visitStackArgT(LStackArgT* lir);
87     void visitStackArgV(LStackArgV* lir);
88     void visitMoveGroup(LMoveGroup* group);
89     void visitValueToInt32(LValueToInt32* lir);
90     void visitValueToDouble(LValueToDouble* lir);
91     void visitValueToFloat32(LValueToFloat32* lir);
92     void visitFloat32ToDouble(LFloat32ToDouble* lir);
93     void visitDoubleToFloat32(LDoubleToFloat32* lir);
94     void visitInt32ToFloat32(LInt32ToFloat32* lir);
95     void visitInt32ToDouble(LInt32ToDouble* lir);
96     void emitOOLTestObject(Register objreg, Label* ifTruthy, Label* ifFalsy, Register scratch);
97     void visitTestOAndBranch(LTestOAndBranch* lir);
98     void visitTestVAndBranch(LTestVAndBranch* lir);
99     void visitFunctionDispatch(LFunctionDispatch* lir);
100     void visitObjectGroupDispatch(LObjectGroupDispatch* lir);
101     void visitBooleanToString(LBooleanToString* lir);
102     void emitIntToString(Register input, Register output, Label* ool);
103     void visitIntToString(LIntToString* lir);
104     void visitDoubleToString(LDoubleToString* lir);
105     void visitValueToString(LValueToString* lir);
106     void visitValueToObjectOrNull(LValueToObjectOrNull* lir);
107     void visitInteger(LInteger* lir);
108     void visitRegExp(LRegExp* lir);
109     void visitRegExpExec(LRegExpExec* lir);
110     void visitOutOfLineRegExpExec(OutOfLineRegExpExec* ool);
111     void visitRegExpTest(LRegExpTest* lir);
112     void visitOutOfLineRegExpTest(OutOfLineRegExpTest* ool);
113     void visitRegExpReplace(LRegExpReplace* lir);
114     void visitStringReplace(LStringReplace* lir);
115     void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
116     void visitBinarySharedStub(LBinarySharedStub* lir);
117     void visitUnarySharedStub(LUnarySharedStub* lir);
118     void visitLambda(LLambda* lir);
119     void visitOutOfLineLambdaArrow(OutOfLineLambdaArrow* ool);
120     void visitLambdaArrow(LLambdaArrow* lir);
121     void visitLambdaForSingleton(LLambdaForSingleton* lir);
122     void visitPointer(LPointer* lir);
123     void visitKeepAliveObject(LKeepAliveObject* lir);
124     void visitSlots(LSlots* lir);
125     void visitLoadSlotT(LLoadSlotT* lir);
126     void visitLoadSlotV(LLoadSlotV* lir);
127     void visitStoreSlotT(LStoreSlotT* lir);
128     void visitStoreSlotV(LStoreSlotV* lir);
129     void visitElements(LElements* lir);
130     void visitConvertElementsToDoubles(LConvertElementsToDoubles* lir);
131     void visitMaybeToDoubleElement(LMaybeToDoubleElement* lir);
132     void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir);
133     void visitGuardObjectIdentity(LGuardObjectIdentity* guard);
134     void visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir);
135     void visitGuardUnboxedExpando(LGuardUnboxedExpando* lir);
136     void visitLoadUnboxedExpando(LLoadUnboxedExpando* lir);
137     void visitTypeBarrierV(LTypeBarrierV* lir);
138     void visitTypeBarrierO(LTypeBarrierO* lir);
139     void visitMonitorTypes(LMonitorTypes* lir);
140     void visitPostWriteBarrierO(LPostWriteBarrierO* lir);
141     void visitPostWriteBarrierV(LPostWriteBarrierV* lir);
142     void visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier* ool);
143     void visitCallNative(LCallNative* call);
144     void emitCallInvokeFunction(LInstruction* call, Register callereg,
145                                 bool isConstructing, uint32_t argc,
146                                 uint32_t unusedStack);
147     void visitCallGeneric(LCallGeneric* call);
148     void emitCallInvokeFunctionShuffleNewTarget(LCallKnown *call,
149                                                 Register calleeReg,
150                                                 uint32_t numFormals,
151                                                 uint32_t unusedStack);
152     void visitCallKnown(LCallKnown* call);
153     template<typename T> void emitApplyGeneric(T* apply);
154     template<typename T> void emitCallInvokeFunction(T* apply, Register extraStackSize);
155     void emitAllocateSpaceForApply(Register argcreg, Register extraStackSpace, Label* end);
156     void emitCopyValuesForApply(Register argvSrcBase, Register argvIndex, Register copyreg,
157                                 size_t argvSrcOffset, size_t argvDstOffset);
158     void emitPopArguments(Register extraStackSize);
159     void emitPushArguments(LApplyArgsGeneric* apply, Register extraStackSpace);
160     void visitApplyArgsGeneric(LApplyArgsGeneric* apply);
161     void emitPushArguments(LApplyArrayGeneric* apply, Register extraStackSpace);
162     void visitApplyArrayGeneric(LApplyArrayGeneric* apply);
163     void visitBail(LBail* lir);
164     void visitUnreachable(LUnreachable* unreachable);
165     void visitEncodeSnapshot(LEncodeSnapshot* lir);
166     void visitGetDynamicName(LGetDynamicName* lir);
167     void visitCallDirectEval(LCallDirectEval* lir);
168     void visitDoubleToInt32(LDoubleToInt32* lir);
169     void visitFloat32ToInt32(LFloat32ToInt32* lir);
170     void visitNewArrayCallVM(LNewArray* lir);
171     void visitNewArray(LNewArray* lir);
172     void visitOutOfLineNewArray(OutOfLineNewArray* ool);
173     void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
174     void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
175     void visitNewObjectVMCall(LNewObject* lir);
176     void visitNewObject(LNewObject* lir);
177     void visitOutOfLineNewObject(OutOfLineNewObject* ool);
178     void visitNewTypedObject(LNewTypedObject* lir);
179     void visitSimdBox(LSimdBox* lir);
180     void visitSimdUnbox(LSimdUnbox* lir);
181     void visitNewDeclEnvObject(LNewDeclEnvObject* lir);
182     void visitNewCallObject(LNewCallObject* lir);
183     void visitNewSingletonCallObject(LNewSingletonCallObject* lir);
184     void visitNewStringObject(LNewStringObject* lir);
185     void visitNewDerivedTypedObject(LNewDerivedTypedObject* lir);
186     void visitInitElem(LInitElem* lir);
187     void visitInitElemGetterSetter(LInitElemGetterSetter* lir);
188     void visitMutateProto(LMutateProto* lir);
189     void visitInitProp(LInitProp* lir);
190     void visitInitPropGetterSetter(LInitPropGetterSetter* lir);
191     void visitCreateThis(LCreateThis* lir);
192     void visitCreateThisWithProto(LCreateThisWithProto* lir);
193     void visitCreateThisWithTemplate(LCreateThisWithTemplate* lir);
194     void visitCreateArgumentsObject(LCreateArgumentsObject* lir);
195     void visitGetArgumentsObjectArg(LGetArgumentsObjectArg* lir);
196     void visitSetArgumentsObjectArg(LSetArgumentsObjectArg* lir);
197     void visitReturnFromCtor(LReturnFromCtor* lir);
198     void visitComputeThis(LComputeThis* lir);
199     void visitArrayLength(LArrayLength* lir);
200     void visitSetArrayLength(LSetArrayLength* lir);
201     void visitTypedArrayLength(LTypedArrayLength* lir);
202     void visitTypedArrayElements(LTypedArrayElements* lir);
203     void visitSetDisjointTypedElements(LSetDisjointTypedElements* lir);
204     void visitTypedObjectElements(LTypedObjectElements* lir);
205     void visitSetTypedObjectOffset(LSetTypedObjectOffset* lir);
206     void visitTypedObjectDescr(LTypedObjectDescr* ins);
207     void visitStringLength(LStringLength* lir);
208     void visitSubstr(LSubstr* lir);
209     void visitInitializedLength(LInitializedLength* lir);
210     void visitSetInitializedLength(LSetInitializedLength* lir);
211     void visitUnboxedArrayLength(LUnboxedArrayLength* lir);
212     void visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir);
213     void visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir);
214     void visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir);
215     void visitNotO(LNotO* ins);
216     void visitNotV(LNotV* ins);
217     void visitBoundsCheck(LBoundsCheck* lir);
218     void visitBoundsCheckRange(LBoundsCheckRange* lir);
219     void visitBoundsCheckLower(LBoundsCheckLower* lir);
220     void visitLoadFixedSlotV(LLoadFixedSlotV* ins);
221     void visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* lir);
222     void visitLoadFixedSlotT(LLoadFixedSlotT* ins);
223     void visitStoreFixedSlotV(LStoreFixedSlotV* ins);
224     void visitStoreFixedSlotT(LStoreFixedSlotT* ins);
225     void emitGetPropertyPolymorphic(LInstruction* lir, Register obj,
226                                     Register scratch, const TypedOrValueRegister& output);
227     void visitGetPropertyPolymorphicV(LGetPropertyPolymorphicV* ins);
228     void visitGetPropertyPolymorphicT(LGetPropertyPolymorphicT* ins);
229     void emitSetPropertyPolymorphic(LInstruction* lir, Register obj,
230                                     Register scratch, const ConstantOrRegister& value);
231     void visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV* ins);
232     void visitArraySplice(LArraySplice* splice);
233     void visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins);
234     void visitAbsI(LAbsI* lir);
235     void visitAtan2D(LAtan2D* lir);
236     void visitHypot(LHypot* lir);
237     void visitPowI(LPowI* lir);
238     void visitPowD(LPowD* lir);
239     void visitMathFunctionD(LMathFunctionD* ins);
240     void visitMathFunctionF(LMathFunctionF* ins);
241     void visitModD(LModD* ins);
242     void visitMinMaxI(LMinMaxI* lir);
243     void visitBinaryV(LBinaryV* lir);
244     void emitCompareS(LInstruction* lir, JSOp op, Register left, Register right, Register output);
245     void visitCompareS(LCompareS* lir);
246     void visitCompareStrictS(LCompareStrictS* lir);
247     void visitCompareVM(LCompareVM* lir);
248     void visitIsNullOrLikeUndefinedV(LIsNullOrLikeUndefinedV* lir);
249     void visitIsNullOrLikeUndefinedT(LIsNullOrLikeUndefinedT* lir);
250     void visitIsNullOrLikeUndefinedAndBranchV(LIsNullOrLikeUndefinedAndBranchV* lir);
251     void visitIsNullOrLikeUndefinedAndBranchT(LIsNullOrLikeUndefinedAndBranchT* lir);
252     void emitConcat(LInstruction* lir, Register lhs, Register rhs, Register output);
253     void visitConcat(LConcat* lir);
254     void visitCharCodeAt(LCharCodeAt* lir);
255     void visitFromCharCode(LFromCharCode* lir);
256     void visitSinCos(LSinCos *lir);
257     void visitStringSplit(LStringSplit* lir);
258     void visitFunctionEnvironment(LFunctionEnvironment* lir);
259     void visitCallGetProperty(LCallGetProperty* lir);
260     void visitCallGetElement(LCallGetElement* lir);
261     void visitCallSetElement(LCallSetElement* lir);
262     void visitCallInitElementArray(LCallInitElementArray* lir);
263     void visitThrow(LThrow* lir);
264     void visitTypeOfV(LTypeOfV* lir);
265     void visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool);
266     void visitToIdV(LToIdV* lir);
267     template<typename T> void emitLoadElementT(LLoadElementT* lir, const T& source);
268     void visitLoadElementT(LLoadElementT* lir);
269     void visitLoadElementV(LLoadElementV* load);
270     void visitLoadElementHole(LLoadElementHole* lir);
271     void visitLoadUnboxedPointerV(LLoadUnboxedPointerV* lir);
272     void visitLoadUnboxedPointerT(LLoadUnboxedPointerT* lir);
273     void visitUnboxObjectOrNull(LUnboxObjectOrNull* lir);
274     void visitStoreElementT(LStoreElementT* lir);
275     void visitStoreElementV(LStoreElementV* lir);
276     void visitStoreElementHoleT(LStoreElementHoleT* lir);
277     void visitStoreElementHoleV(LStoreElementHoleV* lir);
278     void visitStoreUnboxedPointer(LStoreUnboxedPointer* lir);
279     void visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir);
280     void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj,
281                            Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
282     void visitArrayPopShiftV(LArrayPopShiftV* lir);
283     void visitArrayPopShiftT(LArrayPopShiftT* lir);
284     void emitArrayPush(LInstruction* lir, const MArrayPush* mir, Register obj,
285                        ConstantOrRegister value, Register elementsTemp, Register length);
286     void visitArrayPushV(LArrayPushV* lir);
287     void visitArrayPushT(LArrayPushT* lir);
288     void visitArrayConcat(LArrayConcat* lir);
289     void visitArraySlice(LArraySlice* lir);
290     void visitArrayJoin(LArrayJoin* lir);
291     void visitLoadUnboxedScalar(LLoadUnboxedScalar* lir);
292     void visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole* lir);
293     void visitStoreUnboxedScalar(LStoreUnboxedScalar* lir);
294     void visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole* lir);
295     void visitAtomicIsLockFree(LAtomicIsLockFree* lir);
296     void visitGuardSharedTypedArray(LGuardSharedTypedArray* lir);
297     void visitClampIToUint8(LClampIToUint8* lir);
298     void visitClampDToUint8(LClampDToUint8* lir);
299     void visitClampVToUint8(LClampVToUint8* lir);
300     void visitCallIteratorStart(LCallIteratorStart* lir);
301     void visitIteratorStart(LIteratorStart* lir);
302     void visitIteratorMore(LIteratorMore* lir);
303     void visitIsNoIterAndBranch(LIsNoIterAndBranch* lir);
304     void visitIteratorEnd(LIteratorEnd* lir);
305     void visitArgumentsLength(LArgumentsLength* lir);
306     void visitGetFrameArgument(LGetFrameArgument* lir);
307     void visitSetFrameArgumentT(LSetFrameArgumentT* lir);
308     void visitSetFrameArgumentC(LSetFrameArgumentC* lir);
309     void visitSetFrameArgumentV(LSetFrameArgumentV* lir);
310     void visitRunOncePrologue(LRunOncePrologue* lir);
311     void emitRest(LInstruction* lir, Register array, Register numActuals,
312                   Register temp0, Register temp1, unsigned numFormals,
313                   JSObject* templateObject, bool saveAndRestore, Register resultreg);
314     void visitRest(LRest* lir);
315     void visitCallSetProperty(LCallSetProperty* ins);
316     void visitCallDeleteProperty(LCallDeleteProperty* lir);
317     void visitCallDeleteElement(LCallDeleteElement* lir);
318     void visitBitNotV(LBitNotV* lir);
319     void visitBitOpV(LBitOpV* lir);
320     void emitInstanceOf(LInstruction* ins, JSObject* prototypeObject);
321     void visitIn(LIn* ins);
322     void visitInArray(LInArray* ins);
323     void visitInstanceOfO(LInstanceOfO* ins);
324     void visitInstanceOfV(LInstanceOfV* ins);
325     void visitCallInstanceOf(LCallInstanceOf* ins);
326     void visitGetDOMProperty(LGetDOMProperty* lir);
327     void visitGetDOMMemberV(LGetDOMMemberV* lir);
328     void visitGetDOMMemberT(LGetDOMMemberT* lir);
329     void visitSetDOMProperty(LSetDOMProperty* lir);
330     void visitCallDOMNative(LCallDOMNative* lir);
331     void visitCallGetIntrinsicValue(LCallGetIntrinsicValue* lir);
332     void visitIsCallable(LIsCallable* lir);
333     void visitOutOfLineIsCallable(OutOfLineIsCallable* ool);
334     void visitIsObject(LIsObject* lir);
335     void visitIsObjectAndBranch(LIsObjectAndBranch* lir);
336     void visitHasClass(LHasClass* lir);
337     void visitAsmJSParameter(LAsmJSParameter* lir);
338     void visitAsmJSReturn(LAsmJSReturn* ret);
339     void visitAsmJSVoidReturn(LAsmJSVoidReturn* ret);
340     void visitLexicalCheck(LLexicalCheck* ins);
341     void visitThrowRuntimeLexicalError(LThrowRuntimeLexicalError* ins);
342     void visitGlobalNameConflictsCheck(LGlobalNameConflictsCheck* ins);
343     void visitDebugger(LDebugger* ins);
344     void visitNewTarget(LNewTarget* ins);
345     void visitArrowNewTarget(LArrowNewTarget* ins);
346     void visitCheckReturn(LCheckReturn* ins);
347     void visitCheckObjCoercible(LCheckObjCoercible* ins);
348 
349     void visitCheckOverRecursed(LCheckOverRecursed* lir);
350     void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);
351 
352     void visitInterruptCheckImplicit(LInterruptCheckImplicit* ins);
353     void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins);
354 
355     void visitUnboxFloatingPoint(LUnboxFloatingPoint* lir);
356     void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint* ool);
357     void visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool);
358 
359     void loadJSScriptForBlock(MBasicBlock* block, Register reg);
360     void loadOutermostJSScript(Register reg);
361 
362     // Inline caches visitors.
363     void visitOutOfLineCache(OutOfLineUpdateCache* ool);
364 
365     void visitGetPropertyCacheV(LGetPropertyCacheV* ins);
366     void visitGetPropertyCacheT(LGetPropertyCacheT* ins);
367     void visitBindNameCache(LBindNameCache* ins);
368     void visitCallSetProperty(LInstruction* ins);
369     void visitSetPropertyCache(LSetPropertyCache* ins);
370     void visitGetNameCache(LGetNameCache* ins);
371 
372     void visitGetPropertyIC(OutOfLineUpdateCache* ool, DataPtr<GetPropertyIC>& ic);
373     void visitSetPropertyIC(OutOfLineUpdateCache* ool, DataPtr<SetPropertyIC>& ic);
374     void visitBindNameIC(OutOfLineUpdateCache* ool, DataPtr<BindNameIC>& ic);
375     void visitNameIC(OutOfLineUpdateCache* ool, DataPtr<NameIC>& ic);
376 
377     void visitAssertRangeI(LAssertRangeI* ins);
378     void visitAssertRangeD(LAssertRangeD* ins);
379     void visitAssertRangeF(LAssertRangeF* ins);
380     void visitAssertRangeV(LAssertRangeV* ins);
381 
382     void visitAssertResultV(LAssertResultV* ins);
383     void visitAssertResultT(LAssertResultT* ins);
384     void emitAssertResultV(const ValueOperand output, const TemporaryTypeSet* typeset);
385     void emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset);
386 
387     void visitInterruptCheck(LInterruptCheck* lir);
388     void visitAsmJSInterruptCheck(LAsmJSInterruptCheck* lir);
389     void visitRecompileCheck(LRecompileCheck* ins);
390 
391     void visitRandom(LRandom* ins);
392 
extractScriptCounts()393     IonScriptCounts* extractScriptCounts() {
394         IonScriptCounts* counts = scriptCounts_;
395         scriptCounts_ = nullptr;  // prevent delete in dtor
396         return counts;
397     }
398 
399   private:
400     void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
401                              ConstantOrRegister id, TypedOrValueRegister output,
402                              bool monitoredResult, bool allowDoubleResult,
403                              jsbytecode* profilerLeavePc);
404     void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
405                              Register temp, Register tempUnbox, FloatRegister tempDouble,
406                              FloatRegister tempF32, ConstantOrRegister id, ConstantOrRegister value,
407                              bool strict, bool needsTypeBarrier, bool guardHoles,
408                              jsbytecode* profilerLeavePc);
409 
410     bool generateBranchV(const ValueOperand& value, Label* ifTrue, Label* ifFalse, FloatRegister fr);
411 
412     void emitLambdaInit(Register resultReg, Register scopeChainReg,
413                         const LambdaFunctionInfo& info);
414 
415     void emitFilterArgumentsOrEval(LInstruction* lir, Register string, Register temp1,
416                                    Register temp2);
417 
418     IonScriptCounts* maybeCreateScriptCounts();
419 
420     // This function behaves like testValueTruthy with the exception that it can
421     // choose to let control flow fall through when the object is truthy, as
422     // an optimization. Use testValueTruthy when it's required to branch to one
423     // of the two labels.
424     void testValueTruthyKernel(const ValueOperand& value,
425                                const LDefinition* scratch1, const LDefinition* scratch2,
426                                FloatRegister fr,
427                                Label* ifTruthy, Label* ifFalsy,
428                                OutOfLineTestObject* ool,
429                                MDefinition* valueMIR);
430 
431     // Test whether value is truthy or not and jump to the corresponding label.
432     // If the value can be an object that emulates |undefined|, |ool| must be
433     // non-null; otherwise it may be null (and the scratch definitions should
434     // be bogus), in which case an object encountered here will always be
435     // truthy.
436     void testValueTruthy(const ValueOperand& value,
437                          const LDefinition* scratch1, const LDefinition* scratch2,
438                          FloatRegister fr,
439                          Label* ifTruthy, Label* ifFalsy,
440                          OutOfLineTestObject* ool,
441                          MDefinition* valueMIR);
442 
443     // This function behaves like testObjectEmulatesUndefined with the exception
444     // that it can choose to let control flow fall through when the object
445     // doesn't emulate undefined, as an optimization. Use the regular
446     // testObjectEmulatesUndefined when it's required to branch to one of the
447     // two labels.
448     void testObjectEmulatesUndefinedKernel(Register objreg,
449                                            Label* ifEmulatesUndefined,
450                                            Label* ifDoesntEmulateUndefined,
451                                            Register scratch, OutOfLineTestObject* ool);
452 
453     // Test whether an object emulates |undefined|.  If it does, jump to
454     // |ifEmulatesUndefined|; the caller is responsible for binding this label.
455     // If it doesn't, fall through; the label |ifDoesntEmulateUndefined| (which
456     // must be initially unbound) will be bound at this point.
457     void branchTestObjectEmulatesUndefined(Register objreg,
458                                            Label* ifEmulatesUndefined,
459                                            Label* ifDoesntEmulateUndefined,
460                                            Register scratch, OutOfLineTestObject* ool);
461 
462     // Test whether an object emulates |undefined|, and jump to the
463     // corresponding label.
464     //
465     // This method should be used when subsequent code can't be laid out in a
466     // straight line; if it can, branchTest* should be used instead.
467     void testObjectEmulatesUndefined(Register objreg,
468                                      Label* ifEmulatesUndefined,
469                                      Label* ifDoesntEmulateUndefined,
470                                      Register scratch, OutOfLineTestObject* ool);
471 
472     // Branch to target unless obj has an emptyObjectElements or emptyObjectElementsShared
473     // elements pointer.
474     void branchIfNotEmptyObjectElements(Register obj, Label* target);
475 
476     // Get a label for the start of block which can be used for jumping, in
477     // place of jumpToBlock.
478     Label* getJumpLabelForBranch(MBasicBlock* block);
479 
480     void emitStoreElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType,
481                                Register elements, const LAllocation* index,
482                                int32_t offsetAdjustment);
483 
484     // Bailout if an element about to be written to is a hole.
485     void emitStoreHoleCheck(Register elements, const LAllocation* index, int32_t offsetAdjustment,
486                             LSnapshot* snapshot);
487 
488     void emitAssertRangeI(const Range* r, Register input);
489     void emitAssertRangeD(const Range* r, FloatRegister input, FloatRegister temp);
490 
491     Vector<CodeOffset, 0, JitAllocPolicy> ionScriptLabels_;
492 
493     struct SharedStub {
494         ICStub::Kind kind;
495         IonICEntry entry;
496         CodeOffset label;
497 
SharedStubSharedStub498         SharedStub(ICStub::Kind kind, IonICEntry entry, CodeOffset label)
499           : kind(kind), entry(entry), label(label)
500         {}
501     };
502 
503     Vector<SharedStub, 0, SystemAllocPolicy> sharedStubs_;
504 
505     void branchIfInvalidated(Register temp, Label* invalidated);
506 
507 #ifdef DEBUG
508     void emitDebugResultChecks(LInstruction* ins);
509     void emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mir);
510     void emitValueResultChecks(LInstruction* lir, MDefinition* mir);
511 #endif
512 
513     // Script counts created during code generation.
514     IonScriptCounts* scriptCounts_;
515 
516 #if defined(JS_ION_PERF)
517     PerfSpewer perfSpewer_;
518 #endif
519 
520     // This integer is a bit mask of all SimdTypeDescr::Type indexes.  When a
521     // MSimdBox instruction is encoded, it might have either been created by
522     // IonBuilder, or by the Eager Simd Unbox phase.
523     //
524     // As the template objects are weak references, the JitCompartment is using
525     // Read Barriers, but such barrier cannot be used during the compilation. To
526     // work around this issue, the barriers are captured during
527     // CodeGenerator::link.
528     //
529     // Instead of saving the pointers, we just save the index of the Read
530     // Barriered objects in a bit mask.
531     uint32_t simdRefreshTemplatesDuringLink_;
532 
533     void registerSimdTemplate(InlineTypedObject* templateObject);
534     void captureSimdTemplate(JSContext* cx);
535 };
536 
537 } // namespace jit
538 } // namespace js
539 
540 #endif /* jit_CodeGenerator_h */
541