| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- /**
- * The object that handles actions generated by a SwitchIRBuilder, which
- * will be either an IRBuilder or an IRBuilderAsmJs
- */
- struct SwitchAdapter {
- virtual void AddBranchInstr(IR::BranchInstr * instr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false) = 0;
- virtual void AddInstr(IR::Instr * instr, uint32 offset) = 0;
- virtual void CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false) = 0;
- virtual void ConvertToBailOut(IR::Instr * instr, IR::BailOutKind kind) = 0;
- };
- /**
- * Handles delegating actions generated by a SwitchIRBuilder to an IRBuilder
- */
- struct IRBuilderSwitchAdapter : public SwitchAdapter {
- private:
- IRBuilder * m_builder;
- public:
- IRBuilderSwitchAdapter(IRBuilder * builder)
- : m_builder(builder) {}
- virtual void AddBranchInstr(IR::BranchInstr * instr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false);
- virtual void AddInstr(IR::Instr * instr, uint32 offset);
- virtual void CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false);
- virtual void ConvertToBailOut(IR::Instr * instr, IR::BailOutKind kind);
- };
- /**
- * Handles delegating actions generated by a SwitchIRBuilder to an IRBuilderAsmJs
- */
- struct IRBuilderAsmJsSwitchAdapter : public SwitchAdapter {
- private:
- IRBuilderAsmJs * m_builder;
- public:
- IRBuilderAsmJsSwitchAdapter(IRBuilderAsmJs * builder)
- : m_builder(builder) {}
- virtual void AddBranchInstr(IR::BranchInstr * instr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false);
- virtual void AddInstr(IR::Instr * instr, uint32 offset);
- virtual void CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset, bool clearBackEdge = false);
- virtual void ConvertToBailOut(IR::Instr * instr, IR::BailOutKind kind);
- };
- /**
- * Handles construction of switch statements, with appropriate optimizations
- */
- class SwitchIRBuilder {
- private:
- typedef JsUtil::List<CaseNode*, JitArenaAllocator> CaseNodeList;
- typedef JsUtil::List<Js::JavascriptString *, JitArenaAllocator> StrSwitchCaseList;
- SwitchAdapter* m_adapter;
- Func* m_func;
- JitArenaAllocator* m_tempAlloc;
- CaseNodeList* m_caseNodes;
- bool m_seenOnlySingleCharStrCaseNodes;
- IR::Instr * m_profiledSwitchInstr;
- bool m_isAsmJs;
- bool m_switchOptBuildBail; //bool refers to whether the bail out has to be generated or not
- bool m_switchIntDynProfile; // bool refers to whether dynamic profile info says that the switch expression is an integer or not
- bool m_switchStrDynProfile; // bool refers to whether dynamic profile info says that the switch expression is an string or not
- BVSparse<JitArenaAllocator> * m_intConstSwitchCases;
- StrSwitchCaseList * m_strConstSwitchCases;
- Js::OpCode m_eqOp;
- Js::OpCode m_ltOp;
- Js::OpCode m_leOp;
- Js::OpCode m_gtOp;
- Js::OpCode m_geOp;
- Js::OpCode m_subOp;
- public:
- SwitchIRBuilder(SwitchAdapter * adapter)
- : m_adapter(adapter)
- , m_profiledSwitchInstr(nullptr)
- , m_switchOptBuildBail(false)
- , m_switchIntDynProfile(false)
- , m_switchStrDynProfile(false)
- , m_isAsmJs(false)
- , m_seenOnlySingleCharStrCaseNodes(true) {}
- void Init(Func * func, JitArenaAllocator * tempAlloc, bool isAsmJs);
- void BeginSwitch();
- void EndSwitch(uint32 offset, uint32 targetOffset);
- void SetProfiledInstruction(IR::Instr * instr, Js::ProfileId profileId);
- void OnCase(IR::RegOpnd * src1Opnd, IR::RegOpnd * src2Opnd, uint32 offset, uint32 targetOffset);
- void FlushCases(uint32 targetOffset);
- void RefineCaseNodes();
- void ResetCaseNodes();
- void BuildCaseBrInstr(uint32 targetOffset);
- void BuildBinaryTraverseInstr(int start, int end, uint32 defaultLeafBranch);
- void BuildLinearTraverseInstr(int start, int end, uint32 defaultLeafBranch);
- void BuildEmptyCasesInstr(CaseNode* currCaseNode, uint32 defaultLeafBranch);
- void BuildOptimizedIntegerCaseInstrs(uint32 targetOffset);
- void BuildMultiBrCaseInstrForStrings(uint32 targetOffset);
- void FixUpMultiBrJumpTable(IR::MultiBranchInstr * multiBranchInstr, uint32 targetOffset);
- void TryBuildBinaryTreeOrMultiBrForSwitchInts(IR::MultiBranchInstr * &multiBranchInstr, uint32 fallthrOffset,
- int startjmpTableIndex, int endjmpTableIndex, int startBinaryTravIndex, uint32 targetOffset);
- bool TestAndAddStringCaseConst(Js::JavascriptString * str);
- void BuildBailOnNotInteger();
- void BuildBailOnNotString();
- IR::MultiBranchInstr * BuildMultiBrCaseInstrForInts(uint32 start, uint32 end, uint32 targetOffset);
- };
|