diff options
Diffstat (limited to 'js/src/jit/CodeGenerator.h')
-rw-r--r-- | js/src/jit/CodeGenerator.h | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h new file mode 100644 index 000000000..8f4bcc813 --- /dev/null +++ b/js/src/jit/CodeGenerator.h @@ -0,0 +1,593 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_CodeGenerator_h +#define jit_CodeGenerator_h + +#include "jit/IonCaches.h" +#if defined(JS_ION_PERF) +# include "jit/PerfSpewer.h" +#endif + +#if defined(JS_CODEGEN_X86) +# include "jit/x86/CodeGenerator-x86.h" +#elif defined(JS_CODEGEN_X64) +# include "jit/x64/CodeGenerator-x64.h" +#elif defined(JS_CODEGEN_ARM) +# include "jit/arm/CodeGenerator-arm.h" +#elif defined(JS_CODEGEN_ARM64) +# include "jit/arm64/CodeGenerator-arm64.h" +#elif defined(JS_CODEGEN_MIPS32) +# include "jit/mips32/CodeGenerator-mips32.h" +#elif defined(JS_CODEGEN_MIPS64) +# include "jit/mips64/CodeGenerator-mips64.h" +#elif defined(JS_CODEGEN_NONE) +# include "jit/none/CodeGenerator-none.h" +#else +#error "Unknown architecture!" +#endif + +namespace js { +namespace jit { + +class OutOfLineTestObject; +class OutOfLineNewArray; +class OutOfLineNewObject; +class CheckOverRecursedFailure; +class OutOfLineInterruptCheckImplicit; +class OutOfLineUnboxFloatingPoint; +class OutOfLineStoreElementHole; +class OutOfLineTypeOfV; +class OutOfLineUpdateCache; +class OutOfLineCallPostWriteBarrier; +class OutOfLineCallPostWriteElementBarrier; +class OutOfLineIsCallable; +class OutOfLineIsConstructor; +class OutOfLineRegExpMatcher; +class OutOfLineRegExpSearcher; +class OutOfLineRegExpTester; +class OutOfLineRegExpPrototypeOptimizable; +class OutOfLineRegExpInstanceOptimizable; +class OutOfLineLambdaArrow; +class OutOfLineNaNToZero; + +class CodeGenerator final : public CodeGeneratorSpecific +{ + void generateArgumentsChecks(bool bailout = true); + MOZ_MUST_USE bool generateBody(); + + ConstantOrRegister toConstantOrRegister(LInstruction* lir, size_t n, MIRType type); + + public: + CodeGenerator(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm = nullptr); + ~CodeGenerator(); + + public: + MOZ_MUST_USE bool generate(); + MOZ_MUST_USE bool generateWasm(wasm::SigIdDesc sigId, wasm::TrapOffset trapOffset, + wasm::FuncOffsets *offsets); + MOZ_MUST_USE bool link(JSContext* cx, CompilerConstraintList* constraints); + MOZ_MUST_USE bool linkSharedStubs(JSContext* cx); + + void visitOsiPoint(LOsiPoint* lir); + void visitGoto(LGoto* lir); + void visitTableSwitch(LTableSwitch* ins); + void visitTableSwitchV(LTableSwitchV* ins); + void visitCloneLiteral(LCloneLiteral* lir); + void visitParameter(LParameter* lir); + void visitCallee(LCallee* lir); + void visitIsConstructing(LIsConstructing* lir); + void visitStart(LStart* lir); + void visitReturn(LReturn* ret); + void visitDefVar(LDefVar* lir); + void visitDefLexical(LDefLexical* lir); + void visitDefFun(LDefFun* lir); + void visitOsrEntry(LOsrEntry* lir); + void visitOsrEnvironmentChain(LOsrEnvironmentChain* lir); + void visitOsrValue(LOsrValue* lir); + void visitOsrReturnValue(LOsrReturnValue* lir); + void visitOsrArgumentsObject(LOsrArgumentsObject* lir); + void visitStackArgT(LStackArgT* lir); + void visitStackArgV(LStackArgV* lir); + void visitMoveGroup(LMoveGroup* group); + void visitValueToInt32(LValueToInt32* lir); + void visitValueToDouble(LValueToDouble* lir); + void visitValueToFloat32(LValueToFloat32* lir); + void visitFloat32ToDouble(LFloat32ToDouble* lir); + void visitDoubleToFloat32(LDoubleToFloat32* lir); + void visitInt32ToFloat32(LInt32ToFloat32* lir); + void visitInt32ToDouble(LInt32ToDouble* lir); + void emitOOLTestObject(Register objreg, Label* ifTruthy, Label* ifFalsy, Register scratch); + void visitTestOAndBranch(LTestOAndBranch* lir); + void visitTestVAndBranch(LTestVAndBranch* lir); + void visitFunctionDispatch(LFunctionDispatch* lir); + void visitObjectGroupDispatch(LObjectGroupDispatch* lir); + void visitBooleanToString(LBooleanToString* lir); + void emitIntToString(Register input, Register output, Label* ool); + void visitIntToString(LIntToString* lir); + void visitDoubleToString(LDoubleToString* lir); + void visitValueToString(LValueToString* lir); + void visitValueToObjectOrNull(LValueToObjectOrNull* lir); + void visitInteger(LInteger* lir); + void visitInteger64(LInteger64* lir); + void visitRegExp(LRegExp* lir); + void visitRegExpMatcher(LRegExpMatcher* lir); + void visitOutOfLineRegExpMatcher(OutOfLineRegExpMatcher* ool); + void visitRegExpSearcher(LRegExpSearcher* lir); + void visitOutOfLineRegExpSearcher(OutOfLineRegExpSearcher* ool); + void visitRegExpTester(LRegExpTester* lir); + void visitOutOfLineRegExpTester(OutOfLineRegExpTester* ool); + void visitRegExpPrototypeOptimizable(LRegExpPrototypeOptimizable* lir); + void visitOutOfLineRegExpPrototypeOptimizable(OutOfLineRegExpPrototypeOptimizable* ool); + void visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* lir); + void visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOptimizable* ool); + void visitGetFirstDollarIndex(LGetFirstDollarIndex* lir); + void visitStringReplace(LStringReplace* lir); + void emitSharedStub(ICStub::Kind kind, LInstruction* lir); + void visitBinarySharedStub(LBinarySharedStub* lir); + void visitUnarySharedStub(LUnarySharedStub* lir); + void visitNullarySharedStub(LNullarySharedStub* lir); + void visitLambda(LLambda* lir); + void visitOutOfLineLambdaArrow(OutOfLineLambdaArrow* ool); + void visitLambdaArrow(LLambdaArrow* lir); + void visitLambdaForSingleton(LLambdaForSingleton* lir); + void visitPointer(LPointer* lir); + void visitKeepAliveObject(LKeepAliveObject* lir); + void visitSlots(LSlots* lir); + void visitLoadSlotT(LLoadSlotT* lir); + void visitLoadSlotV(LLoadSlotV* lir); + void visitStoreSlotT(LStoreSlotT* lir); + void visitStoreSlotV(LStoreSlotV* lir); + void visitElements(LElements* lir); + void visitConvertElementsToDoubles(LConvertElementsToDoubles* lir); + void visitMaybeToDoubleElement(LMaybeToDoubleElement* lir); + void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir); + void visitGuardObjectIdentity(LGuardObjectIdentity* guard); + void visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir); + void visitGuardUnboxedExpando(LGuardUnboxedExpando* lir); + void visitLoadUnboxedExpando(LLoadUnboxedExpando* lir); + void visitTypeBarrierV(LTypeBarrierV* lir); + void visitTypeBarrierO(LTypeBarrierO* lir); + void visitMonitorTypes(LMonitorTypes* lir); + void emitPostWriteBarrier(const LAllocation* obj); + void emitPostWriteBarrier(Register objreg); + template <class LPostBarrierType> + void visitPostWriteBarrierCommonO(LPostBarrierType* lir, OutOfLineCode* ool); + template <class LPostBarrierType> + void visitPostWriteBarrierCommonV(LPostBarrierType* lir, OutOfLineCode* ool); + void visitPostWriteBarrierO(LPostWriteBarrierO* lir); + void visitPostWriteElementBarrierO(LPostWriteElementBarrierO* lir); + void visitPostWriteBarrierV(LPostWriteBarrierV* lir); + void visitPostWriteElementBarrierV(LPostWriteElementBarrierV* lir); + void visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier* ool); + void visitOutOfLineCallPostWriteElementBarrier(OutOfLineCallPostWriteElementBarrier* ool); + void visitCallNative(LCallNative* call); + void emitCallInvokeFunction(LInstruction* call, Register callereg, + bool isConstructing, uint32_t argc, + uint32_t unusedStack); + void visitCallGeneric(LCallGeneric* call); + void emitCallInvokeFunctionShuffleNewTarget(LCallKnown *call, + Register calleeReg, + uint32_t numFormals, + uint32_t unusedStack); + void visitCallKnown(LCallKnown* call); + template<typename T> void emitApplyGeneric(T* apply); + template<typename T> void emitCallInvokeFunction(T* apply, Register extraStackSize); + void emitAllocateSpaceForApply(Register argcreg, Register extraStackSpace, Label* end); + void emitCopyValuesForApply(Register argvSrcBase, Register argvIndex, Register copyreg, + size_t argvSrcOffset, size_t argvDstOffset); + void emitPopArguments(Register extraStackSize); + void emitPushArguments(LApplyArgsGeneric* apply, Register extraStackSpace); + void visitApplyArgsGeneric(LApplyArgsGeneric* apply); + void emitPushArguments(LApplyArrayGeneric* apply, Register extraStackSpace); + void visitApplyArrayGeneric(LApplyArrayGeneric* apply); + void visitBail(LBail* lir); + void visitUnreachable(LUnreachable* unreachable); + void visitEncodeSnapshot(LEncodeSnapshot* lir); + void visitGetDynamicName(LGetDynamicName* lir); + void visitCallDirectEval(LCallDirectEval* lir); + void visitDoubleToInt32(LDoubleToInt32* lir); + void visitFloat32ToInt32(LFloat32ToInt32* lir); + void visitNewArrayCallVM(LNewArray* lir); + void visitNewArray(LNewArray* lir); + void visitOutOfLineNewArray(OutOfLineNewArray* ool); + void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir); + void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir); + void visitNewTypedArray(LNewTypedArray* lir); + void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir); + void visitNewObjectVMCall(LNewObject* lir); + void visitNewObject(LNewObject* lir); + void visitOutOfLineNewObject(OutOfLineNewObject* ool); + void visitNewTypedObject(LNewTypedObject* lir); + void visitSimdBox(LSimdBox* lir); + void visitSimdUnbox(LSimdUnbox* lir); + void visitNewNamedLambdaObject(LNewNamedLambdaObject* lir); + void visitNewCallObject(LNewCallObject* lir); + void visitNewSingletonCallObject(LNewSingletonCallObject* lir); + void visitNewStringObject(LNewStringObject* lir); + void visitNewDerivedTypedObject(LNewDerivedTypedObject* lir); + void visitInitElem(LInitElem* lir); + void visitInitElemGetterSetter(LInitElemGetterSetter* lir); + void visitMutateProto(LMutateProto* lir); + void visitInitProp(LInitProp* lir); + void visitInitPropGetterSetter(LInitPropGetterSetter* lir); + void visitCreateThis(LCreateThis* lir); + void visitCreateThisWithProto(LCreateThisWithProto* lir); + void visitCreateThisWithTemplate(LCreateThisWithTemplate* lir); + void visitCreateArgumentsObject(LCreateArgumentsObject* lir); + void visitGetArgumentsObjectArg(LGetArgumentsObjectArg* lir); + void visitSetArgumentsObjectArg(LSetArgumentsObjectArg* lir); + void visitReturnFromCtor(LReturnFromCtor* lir); + void visitComputeThis(LComputeThis* lir); + void visitArrayLength(LArrayLength* lir); + void visitSetArrayLength(LSetArrayLength* lir); + void visitGetNextEntryForIterator(LGetNextEntryForIterator* lir); + void visitTypedArrayLength(LTypedArrayLength* lir); + void visitTypedArrayElements(LTypedArrayElements* lir); + void visitSetDisjointTypedElements(LSetDisjointTypedElements* lir); + void visitTypedObjectElements(LTypedObjectElements* lir); + void visitSetTypedObjectOffset(LSetTypedObjectOffset* lir); + void visitTypedObjectDescr(LTypedObjectDescr* ins); + void visitStringLength(LStringLength* lir); + void visitSubstr(LSubstr* lir); + void visitInitializedLength(LInitializedLength* lir); + void visitSetInitializedLength(LSetInitializedLength* lir); + void visitUnboxedArrayLength(LUnboxedArrayLength* lir); + void visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir); + void visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir); + void visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir); + void visitNotO(LNotO* ins); + void visitNotV(LNotV* ins); + void visitBoundsCheck(LBoundsCheck* lir); + void visitBoundsCheckRange(LBoundsCheckRange* lir); + void visitBoundsCheckLower(LBoundsCheckLower* lir); + void visitLoadFixedSlotV(LLoadFixedSlotV* ins); + void visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* lir); + void visitLoadFixedSlotT(LLoadFixedSlotT* ins); + void visitStoreFixedSlotV(LStoreFixedSlotV* ins); + void visitStoreFixedSlotT(LStoreFixedSlotT* ins); + void emitGetPropertyPolymorphic(LInstruction* lir, Register obj, + Register scratch, const TypedOrValueRegister& output); + void visitGetPropertyPolymorphicV(LGetPropertyPolymorphicV* ins); + void visitGetPropertyPolymorphicT(LGetPropertyPolymorphicT* ins); + void emitSetPropertyPolymorphic(LInstruction* lir, Register obj, + Register scratch, const ConstantOrRegister& value); + void visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV* ins); + void visitArraySplice(LArraySplice* splice); + void visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins); + void visitAbsI(LAbsI* lir); + void visitAtan2D(LAtan2D* lir); + void visitHypot(LHypot* lir); + void visitPowI(LPowI* lir); + void visitPowD(LPowD* lir); + void visitMathFunctionD(LMathFunctionD* ins); + void visitMathFunctionF(LMathFunctionF* ins); + void visitModD(LModD* ins); + void visitMinMaxI(LMinMaxI* lir); + void visitBinaryV(LBinaryV* lir); + void emitCompareS(LInstruction* lir, JSOp op, Register left, Register right, Register output); + void visitCompareS(LCompareS* lir); + void visitCompareStrictS(LCompareStrictS* lir); + void visitCompareVM(LCompareVM* lir); + void visitIsNullOrLikeUndefinedV(LIsNullOrLikeUndefinedV* lir); + void visitIsNullOrLikeUndefinedT(LIsNullOrLikeUndefinedT* lir); + void visitIsNullOrLikeUndefinedAndBranchV(LIsNullOrLikeUndefinedAndBranchV* lir); + void visitIsNullOrLikeUndefinedAndBranchT(LIsNullOrLikeUndefinedAndBranchT* lir); + void emitConcat(LInstruction* lir, Register lhs, Register rhs, Register output); + void visitConcat(LConcat* lir); + void visitCharCodeAt(LCharCodeAt* lir); + void visitFromCharCode(LFromCharCode* lir); + void visitFromCodePoint(LFromCodePoint* lir); + void visitSinCos(LSinCos *lir); + void visitStringSplit(LStringSplit* lir); + void visitFunctionEnvironment(LFunctionEnvironment* lir); + void visitCallGetProperty(LCallGetProperty* lir); + void visitCallGetElement(LCallGetElement* lir); + void visitCallSetElement(LCallSetElement* lir); + void visitCallInitElementArray(LCallInitElementArray* lir); + void visitThrow(LThrow* lir); + void visitTypeOfV(LTypeOfV* lir); + void visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool); + void visitToAsync(LToAsync* lir); + void visitToIdV(LToIdV* lir); + template<typename T> void emitLoadElementT(LLoadElementT* lir, const T& source); + void visitLoadElementT(LLoadElementT* lir); + void visitLoadElementV(LLoadElementV* load); + void visitLoadElementHole(LLoadElementHole* lir); + void visitLoadUnboxedPointerV(LLoadUnboxedPointerV* lir); + void visitLoadUnboxedPointerT(LLoadUnboxedPointerT* lir); + void visitUnboxObjectOrNull(LUnboxObjectOrNull* lir); + void visitStoreElementT(LStoreElementT* lir); + void visitStoreElementV(LStoreElementV* lir); + template <typename T> void emitStoreElementHoleT(T* lir); + template <typename T> void emitStoreElementHoleV(T* lir); + void visitStoreElementHoleT(LStoreElementHoleT* lir); + void visitStoreElementHoleV(LStoreElementHoleV* lir); + void visitFallibleStoreElementV(LFallibleStoreElementV* lir); + void visitFallibleStoreElementT(LFallibleStoreElementT* lir); + void visitStoreUnboxedPointer(LStoreUnboxedPointer* lir); + void visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir); + void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj, + Register elementsTemp, Register lengthTemp, TypedOrValueRegister out); + void visitArrayPopShiftV(LArrayPopShiftV* lir); + void visitArrayPopShiftT(LArrayPopShiftT* lir); + void emitArrayPush(LInstruction* lir, const MArrayPush* mir, Register obj, + const ConstantOrRegister& value, Register elementsTemp, Register length); + void visitArrayPushV(LArrayPushV* lir); + void visitArrayPushT(LArrayPushT* lir); + void visitArraySlice(LArraySlice* lir); + void visitArrayJoin(LArrayJoin* lir); + void visitLoadUnboxedScalar(LLoadUnboxedScalar* lir); + void visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole* lir); + void visitStoreUnboxedScalar(LStoreUnboxedScalar* lir); + void visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole* lir); + void visitAtomicIsLockFree(LAtomicIsLockFree* lir); + void visitGuardSharedTypedArray(LGuardSharedTypedArray* lir); + void visitClampIToUint8(LClampIToUint8* lir); + void visitClampDToUint8(LClampDToUint8* lir); + void visitClampVToUint8(LClampVToUint8* lir); + void visitCallIteratorStartV(LCallIteratorStartV* lir); + void visitCallIteratorStartO(LCallIteratorStartO* lir); + void visitIteratorStartO(LIteratorStartO* lir); + void visitIteratorMore(LIteratorMore* lir); + void visitIsNoIterAndBranch(LIsNoIterAndBranch* lir); + void visitIteratorEnd(LIteratorEnd* lir); + void visitArgumentsLength(LArgumentsLength* lir); + void visitGetFrameArgument(LGetFrameArgument* lir); + void visitSetFrameArgumentT(LSetFrameArgumentT* lir); + void visitSetFrameArgumentC(LSetFrameArgumentC* lir); + void visitSetFrameArgumentV(LSetFrameArgumentV* lir); + void visitRunOncePrologue(LRunOncePrologue* lir); + void emitRest(LInstruction* lir, Register array, Register numActuals, + Register temp0, Register temp1, unsigned numFormals, + JSObject* templateObject, bool saveAndRestore, Register resultreg); + void visitRest(LRest* lir); + void visitCallSetProperty(LCallSetProperty* ins); + void visitCallDeleteProperty(LCallDeleteProperty* lir); + void visitCallDeleteElement(LCallDeleteElement* lir); + void visitBitNotV(LBitNotV* lir); + void visitBitOpV(LBitOpV* lir); + void emitInstanceOf(LInstruction* ins, JSObject* prototypeObject); + void visitIn(LIn* ins); + void visitInArray(LInArray* ins); + void visitInstanceOfO(LInstanceOfO* ins); + void visitInstanceOfV(LInstanceOfV* ins); + void visitCallInstanceOf(LCallInstanceOf* ins); + void visitGetDOMProperty(LGetDOMProperty* lir); + void visitGetDOMMemberV(LGetDOMMemberV* lir); + void visitGetDOMMemberT(LGetDOMMemberT* lir); + void visitSetDOMProperty(LSetDOMProperty* lir); + void visitCallDOMNative(LCallDOMNative* lir); + void visitCallGetIntrinsicValue(LCallGetIntrinsicValue* lir); + void visitCallBindVar(LCallBindVar* lir); + void visitIsCallable(LIsCallable* lir); + void visitOutOfLineIsCallable(OutOfLineIsCallable* ool); + void visitIsConstructor(LIsConstructor* lir); + void visitOutOfLineIsConstructor(OutOfLineIsConstructor* ool); + void visitIsObject(LIsObject* lir); + void visitIsObjectAndBranch(LIsObjectAndBranch* lir); + void visitHasClass(LHasClass* lir); + void visitWasmParameter(LWasmParameter* lir); + void visitWasmParameterI64(LWasmParameterI64* lir); + void visitWasmReturn(LWasmReturn* ret); + void visitWasmReturnI64(LWasmReturnI64* ret); + void visitWasmReturnVoid(LWasmReturnVoid* ret); + void visitLexicalCheck(LLexicalCheck* ins); + void visitThrowRuntimeLexicalError(LThrowRuntimeLexicalError* ins); + void visitGlobalNameConflictsCheck(LGlobalNameConflictsCheck* ins); + void visitDebugger(LDebugger* ins); + void visitNewTarget(LNewTarget* ins); + void visitArrowNewTarget(LArrowNewTarget* ins); + void visitCheckReturn(LCheckReturn* ins); + void visitCheckIsObj(LCheckIsObj* ins); + void visitCheckObjCoercible(LCheckObjCoercible* ins); + void visitDebugCheckSelfHosted(LDebugCheckSelfHosted* ins); + void visitNaNToZero(LNaNToZero* ins); + void visitOutOfLineNaNToZero(OutOfLineNaNToZero* ool); + + void visitCheckOverRecursed(LCheckOverRecursed* lir); + void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool); + + void visitUnboxFloatingPoint(LUnboxFloatingPoint* lir); + void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint* ool); + void visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool); + + void loadJSScriptForBlock(MBasicBlock* block, Register reg); + void loadOutermostJSScript(Register reg); + + // Inline caches visitors. + void visitOutOfLineCache(OutOfLineUpdateCache* ool); + + void visitGetPropertyCacheV(LGetPropertyCacheV* ins); + void visitGetPropertyCacheT(LGetPropertyCacheT* ins); + void visitBindNameCache(LBindNameCache* ins); + void visitCallSetProperty(LInstruction* ins); + void visitSetPropertyCache(LSetPropertyCache* ins); + void visitGetNameCache(LGetNameCache* ins); + + void visitGetPropertyIC(OutOfLineUpdateCache* ool, DataPtr<GetPropertyIC>& ic); + void visitSetPropertyIC(OutOfLineUpdateCache* ool, DataPtr<SetPropertyIC>& ic); + void visitBindNameIC(OutOfLineUpdateCache* ool, DataPtr<BindNameIC>& ic); + void visitNameIC(OutOfLineUpdateCache* ool, DataPtr<NameIC>& ic); + + void visitAssertRangeI(LAssertRangeI* ins); + void visitAssertRangeD(LAssertRangeD* ins); + void visitAssertRangeF(LAssertRangeF* ins); + void visitAssertRangeV(LAssertRangeV* ins); + + void visitAssertResultV(LAssertResultV* ins); + void visitAssertResultT(LAssertResultT* ins); + void emitAssertResultV(const ValueOperand output, const TemporaryTypeSet* typeset); + void emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset); + + void visitInterruptCheck(LInterruptCheck* lir); + void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins); + void visitWasmTrap(LWasmTrap* lir); + void visitWasmBoundsCheck(LWasmBoundsCheck* ins); + void visitRecompileCheck(LRecompileCheck* ins); + void visitRotate(LRotate* ins); + + void visitRandom(LRandom* ins); + void visitSignExtend(LSignExtend* ins); + +#ifdef DEBUG + void emitDebugForceBailing(LInstruction* lir); +#endif + + IonScriptCounts* extractScriptCounts() { + IonScriptCounts* counts = scriptCounts_; + scriptCounts_ = nullptr; // prevent delete in dtor + return counts; + } + + private: + void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg, + const ConstantOrRegister& id, TypedOrValueRegister output, + bool monitoredResult, bool allowDoubleResult, + jsbytecode* profilerLeavePc); + void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg, + Register temp, Register tempUnbox, FloatRegister tempDouble, + FloatRegister tempF32, const ConstantOrRegister& id, + const ConstantOrRegister& value, + bool strict, bool needsTypeBarrier, bool guardHoles, + jsbytecode* profilerLeavePc); + + MOZ_MUST_USE bool generateBranchV(const ValueOperand& value, Label* ifTrue, Label* ifFalse, + FloatRegister fr); + + void emitLambdaInit(Register resultReg, Register envChainReg, + const LambdaFunctionInfo& info); + + void emitFilterArgumentsOrEval(LInstruction* lir, Register string, Register temp1, + Register temp2); + + template <class IteratorObject, class OrderedHashTable> + void emitGetNextEntryForIterator(LGetNextEntryForIterator* lir); + + template <class OrderedHashTable> + void emitLoadIteratorValues(Register result, Register temp, Register front); + + IonScriptCounts* maybeCreateScriptCounts(); + + // This function behaves like testValueTruthy with the exception that it can + // choose to let control flow fall through when the object is truthy, as + // an optimization. Use testValueTruthy when it's required to branch to one + // of the two labels. + void testValueTruthyKernel(const ValueOperand& value, + const LDefinition* scratch1, const LDefinition* scratch2, + FloatRegister fr, + Label* ifTruthy, Label* ifFalsy, + OutOfLineTestObject* ool, + MDefinition* valueMIR); + + // Test whether value is truthy or not and jump to the corresponding label. + // If the value can be an object that emulates |undefined|, |ool| must be + // non-null; otherwise it may be null (and the scratch definitions should + // be bogus), in which case an object encountered here will always be + // truthy. + void testValueTruthy(const ValueOperand& value, + const LDefinition* scratch1, const LDefinition* scratch2, + FloatRegister fr, + Label* ifTruthy, Label* ifFalsy, + OutOfLineTestObject* ool, + MDefinition* valueMIR); + + // This function behaves like testObjectEmulatesUndefined with the exception + // that it can choose to let control flow fall through when the object + // doesn't emulate undefined, as an optimization. Use the regular + // testObjectEmulatesUndefined when it's required to branch to one of the + // two labels. + void testObjectEmulatesUndefinedKernel(Register objreg, + Label* ifEmulatesUndefined, + Label* ifDoesntEmulateUndefined, + Register scratch, OutOfLineTestObject* ool); + + // Test whether an object emulates |undefined|. If it does, jump to + // |ifEmulatesUndefined|; the caller is responsible for binding this label. + // If it doesn't, fall through; the label |ifDoesntEmulateUndefined| (which + // must be initially unbound) will be bound at this point. + void branchTestObjectEmulatesUndefined(Register objreg, + Label* ifEmulatesUndefined, + Label* ifDoesntEmulateUndefined, + Register scratch, OutOfLineTestObject* ool); + + // Test whether an object emulates |undefined|, and jump to the + // corresponding label. + // + // This method should be used when subsequent code can't be laid out in a + // straight line; if it can, branchTest* should be used instead. + void testObjectEmulatesUndefined(Register objreg, + Label* ifEmulatesUndefined, + Label* ifDoesntEmulateUndefined, + Register scratch, OutOfLineTestObject* ool); + + // Branch to target unless obj has an emptyObjectElements or emptyObjectElementsShared + // elements pointer. + void branchIfNotEmptyObjectElements(Register obj, Label* target); + + void emitStoreElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType, + Register elements, const LAllocation* index, + int32_t offsetAdjustment); + + // Bailout if an element about to be written to is a hole. + void emitStoreHoleCheck(Register elements, const LAllocation* index, int32_t offsetAdjustment, + LSnapshot* snapshot); + + void emitAssertRangeI(const Range* r, Register input); + void emitAssertRangeD(const Range* r, FloatRegister input, FloatRegister temp); + + void maybeEmitGlobalBarrierCheck(const LAllocation* maybeGlobal, OutOfLineCode* ool); + + Vector<CodeOffset, 0, JitAllocPolicy> ionScriptLabels_; + + struct SharedStub { + ICStub::Kind kind; + IonICEntry entry; + CodeOffset label; + + SharedStub(ICStub::Kind kind, IonICEntry entry, CodeOffset label) + : kind(kind), entry(entry), label(label) + {} + }; + + Vector<SharedStub, 0, SystemAllocPolicy> sharedStubs_; + + void branchIfInvalidated(Register temp, Label* invalidated); + +#ifdef DEBUG + void emitDebugResultChecks(LInstruction* ins); + void emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mir); + void emitValueResultChecks(LInstruction* lir, MDefinition* mir); +#endif + + // Script counts created during code generation. + IonScriptCounts* scriptCounts_; + +#if defined(JS_ION_PERF) + PerfSpewer perfSpewer_; +#endif + + // This integer is a bit mask of all SimdTypeDescr::Type indexes. When a + // MSimdBox instruction is encoded, it might have either been created by + // IonBuilder, or by the Eager Simd Unbox phase. + // + // As the template objects are weak references, the JitCompartment is using + // Read Barriers, but such barrier cannot be used during the compilation. To + // work around this issue, the barriers are captured during + // CodeGenerator::link. + // + // Instead of saving the pointers, we just save the index of the Read + // Barriered objects in a bit mask. + uint32_t simdRefreshTemplatesDuringLink_; + + void registerSimdTemplate(SimdType simdType); + void captureSimdTemplate(JSContext* cx); +}; + +} // namespace jit +} // namespace js + +#endif /* jit_CodeGenerator_h */ |