Lower.h 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #define ASSERT_INLINEE_FUNC(instr) Assert(instr->m_func->IsInlinee() ? (instr->m_func != this->m_func) : (instr->m_func == this->m_func))
  7. enum IndirScale : BYTE {
  8. IndirScale1 = 0,
  9. IndirScale2 = 1,
  10. IndirScale4 = 2,
  11. IndirScale8 = 3
  12. };
  13. enum RoundMode : BYTE {
  14. RoundModeTowardZero = 0,
  15. RoundModeTowardInteger = 1,
  16. RoundModeHalfToEven = 2
  17. };
  18. struct Int64RegPair
  19. {
  20. IR::Opnd* high;
  21. IR::Opnd* low;
  22. Int64RegPair(): high(nullptr), low(nullptr) {}
  23. };
  24. #if defined(_M_IX86) || defined(_M_AMD64)
  25. #include "LowerMDShared.h"
  26. #elif defined(_M_ARM) || defined(_M_ARM64)
  27. #include "LowerMD.h"
  28. #endif
  29. #define IR_HELPER_OP_FULL_OR_INPLACE(op) IR::HelperOp_##op##_Full, IR::HelperOp_##op##InPlace
  30. ///---------------------------------------------------------------------------
  31. ///
  32. /// class Lowerer
  33. ///
  34. /// Lower machine independent IR to machine dependent instrs.
  35. ///
  36. ///---------------------------------------------------------------------------
  37. class Lowerer
  38. {
  39. friend class LowererMD;
  40. friend class LowererMDArch;
  41. friend class Encoder;
  42. friend class Func;
  43. friend class ExternalLowerer;
  44. public:
  45. Lowerer(Func * func) : m_func(func), m_lowererMD(func), nextStackFunctionOpnd(nullptr), outerMostLoopLabel(nullptr),
  46. initializedTempSym(nullptr), addToLiveOnBackEdgeSyms(nullptr), currentRegion(nullptr)
  47. #ifndef _M_X64
  48. , m_int64RegPairMap(nullptr)
  49. #endif
  50. {
  51. #ifdef RECYCLER_WRITE_BARRIER_JIT
  52. m_func->m_lowerer = this;
  53. #endif
  54. }
  55. ~Lowerer()
  56. {
  57. #ifdef RECYCLER_WRITE_BARRIER_JIT
  58. m_func->m_lowerer = nullptr;
  59. #endif
  60. }
  61. void Lower();
  62. void LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFastPath, bool defaultDoLoopFastPath);
  63. void LowerPrologEpilog();
  64. void LowerPrologEpilogAsmJs();
  65. void LowerGeneratorResumeJumpTable();
  66. void DoInterruptProbes();
  67. IR::Instr *PreLowerPeepInstr(IR::Instr *instr, IR::Instr **pInstrPrev);
  68. IR::Instr *PeepShl(IR::Instr *instr);
  69. IR::Instr *PeepBrBool(IR::Instr *instr);
  70. uint DoLoopProbeAndNumber(IR::BranchInstr *branchInstr);
  71. void InsertOneLoopProbe(IR::Instr *insertInstr, IR::LabelInstr *loopLabel);
  72. void FinalLower();
  73. void EHBailoutPatchUp();
  74. inline Js::ScriptContext* GetScriptContext()
  75. {
  76. return m_func->GetScriptContext();
  77. }
  78. StackSym * GetTempNumberSym(IR::Opnd * opnd, bool isTempTransferred);
  79. static bool HasSideEffects(IR::Instr *instr);
  80. static bool IsArgSaveRequired(Func *func);
  81. #if DBG
  82. static bool ValidOpcodeAfterLower(IR::Instr* instr, Func * func);
  83. #endif
  84. private:
  85. IR::Instr * LowerNewRegEx(IR::Instr * instr);
  86. void LowerNewScObjectSimple(IR::Instr *instr);
  87. void LowerNewScObjectLiteral(IR::Instr *instr);
  88. IR::Instr * LowerInitCachedFuncs(IR::Instr *instrInit);
  89. IR::Instr * LowerNewScObject(IR::Instr *instr, bool callCtor, bool hasArgs, bool isBaseClassConstructorNewScObject = false);
  90. IR::Instr * LowerNewScObjArray(IR::Instr *instr);
  91. IR::Instr * LowerNewScObjArrayNoArg(IR::Instr *instr);
  92. bool TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::RegOpnd* newObjDst, IR::LabelInstr* helperOrBailoutLabel, IR::LabelInstr* callCtorLabel,
  93. bool& skipNewScObj, bool& returnNewScObj, bool& emitHelper);
  94. void GenerateRecyclerAllocAligned(IR::JnHelperMethod allocHelper, size_t allocSize, IR::RegOpnd* newObjDst, IR::Instr* insertionPointInstr, bool inOpHelper = false);
  95. IR::Instr * LowerGetNewScObject(IR::Instr *const instr);
  96. void LowerGetNewScObjectCommon(IR::RegOpnd *const resultObjOpnd, IR::RegOpnd *const constructorReturnOpnd, IR::RegOpnd *const newObjOpnd, IR::Instr *insertBeforeInstr);
  97. IR::Instr * LowerUpdateNewScObjectCache(IR::Instr * updateInstr, IR::Opnd *dst, IR::Opnd *src1, const bool isCtorFunction);
  98. bool GenerateLdFldWithCachedType(IR::Instr * instrLdFld, bool* continueAsHelperOut, IR::LabelInstr** labelHelperOut, IR::RegOpnd** typeOpndOut);
  99. bool GenerateCheckFixedFld(IR::Instr * instrChkFld);
  100. void GenerateCheckObjType(IR::Instr * instrChkObjType);
  101. void LowerAdjustObjType(IR::Instr * instrAdjustObjType);
  102. bool GenerateNonConfigurableLdRootFld(IR::Instr * instrLdFld);
  103. IR::Instr * LowerProfiledLdFld(IR::JitProfilingInstr *instr);
  104. void LowerProfiledBeginSwitch(IR::JitProfilingInstr *instr);
  105. void LowerFunctionExit(IR::Instr* funcExit);
  106. void LowerFunctionEntry(IR::Instr* funcEntry);
  107. void GenerateNullOutGeneratorFrame(IR::Instr* instrInsert);
  108. void LowerFunctionBodyCallCountChange(IR::Instr *const insertBeforeInstr);
  109. IR::Instr* LowerProfiledNewArray(IR::JitProfilingInstr* instr, bool hasArgs);
  110. IR::Instr * LowerProfiledLdSlot(IR::JitProfilingInstr *instr);
  111. void LowerProfileLdSlot(IR::Opnd *const valueOpnd, Func *const ldSlotFunc, const Js::ProfileId profileId, IR::Instr *const insertBeforeInstr);
  112. void LowerProfiledBinaryOp(IR::JitProfilingInstr* instr, IR::JnHelperMethod meth);
  113. IR::Instr * LowerLdFld(IR::Instr *instr, IR::JnHelperMethod helperMethod, IR::JnHelperMethod polymorphicHelperMethod, bool useInlineCache, IR::LabelInstr *labelBailOut = nullptr, bool isHelper = false);
  114. template<bool isRoot>
  115. IR::Instr* GenerateCompleteLdFld(IR::Instr* instr, bool emitFastPath, IR::JnHelperMethod monoHelperAfterFastPath, IR::JnHelperMethod polyHelperAfterFastPath,
  116. IR::JnHelperMethod monoHelperWithoutFastPath, IR::JnHelperMethod polyHelperWithoutFastPath);
  117. IR::Instr * LowerScopedLdFld(IR::Instr *instr, IR::JnHelperMethod helperMethod, bool withInlineCache);
  118. IR::Instr * LowerScopedLdInst(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  119. IR::Instr * LowerDelFld(IR::Instr *instr, IR::JnHelperMethod helperMethod, bool useInlineCache, bool strictMode);
  120. IR::Instr * LowerIsInst(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  121. IR::Instr * LowerScopedDelFld(IR::Instr *instr, IR::JnHelperMethod helperMethod, bool withInlineCache, bool strictMode);
  122. IR::Instr * LowerNewScFunc(IR::Instr *instr);
  123. IR::Instr * LowerNewScGenFunc(IR::Instr *instr);
  124. IR::Instr* GenerateCompleteStFld(IR::Instr* instr, bool emitFastPath, IR::JnHelperMethod monoHelperAfterFastPath, IR::JnHelperMethod polyHelperAfterFastPath,
  125. IR::JnHelperMethod monoHelperWithoutFastPath, IR::JnHelperMethod polyHelperWithoutFastPath, bool withPutFlags, Js::PropertyOperationFlags flags);
  126. bool GenerateStFldWithCachedType(IR::Instr * instrStFld, bool* continueAsHelperOut, IR::LabelInstr** labelHelperOut, IR::RegOpnd** typeOpndOut);
  127. bool GenerateStFldWithCachedFinalType(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd);
  128. IR::RegOpnd * GenerateCachedTypeCheck(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd,
  129. IR::LabelInstr* labelObjCheckFailed, IR::LabelInstr *labelTypeCheckFailed, IR::LabelInstr *labelSecondChance = nullptr);
  130. void GenerateCachedTypeWithoutPropertyCheck(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, IR::Opnd *typeOpnd, IR::LabelInstr *labelTypeCheckFailed);
  131. void GenerateFixedFieldGuardCheck(IR::Instr *insertPointInstr, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
  132. Js::JitTypePropertyGuard* CreateTypePropertyGuardForGuardedProperties(JITTypeHolder type, IR::PropertySymOpnd* propertySymOpnd);
  133. Js::JitEquivalentTypeGuard* CreateEquivalentTypeGuardAndLinkToGuardedProperties(JITTypeHolder type, IR::PropertySymOpnd* propertySymOpnd);
  134. bool LinkCtorCacheToGuardedProperties(JITTimeConstructorCache* cache);
  135. template<typename LinkFunc>
  136. bool LinkGuardToGuardedProperties(const BVSparse<JitArenaAllocator>* guardedPropOps, LinkFunc link);
  137. void GeneratePropertyGuardCheck(IR::Instr *insertPointInstr, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
  138. IR::Instr * GeneratePropertyGuardCheckBailoutAndLoadType(IR::Instr *insertInstr);
  139. void GenerateNonWritablePropertyCheck(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
  140. void GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, JITTypeHolder initialType, JITTypeHolder finalType);
  141. void GenerateDirectFieldStore(IR::Instr* instrStFld, IR::PropertySymOpnd* propertySymOpnd);
  142. void GenerateAdjustSlots(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, JITTypeHolder initialType, JITTypeHolder finalType);
  143. bool GenerateAdjustBaseSlots(IR::Instr * instrStFld, IR::RegOpnd *baseOpnd, JITTypeHolder initialType, JITTypeHolder finalType);
  144. void GeneratePrototypeCacheInvalidateCheck(IR::PropertySymOpnd *propertySymOpnd, IR::Instr *instrStFld);
  145. void PinTypeRef(JITTypeHolder type, void* typeRef, IR::Instr* instr, Js::PropertyId propertyId);
  146. IR::RegOpnd * GenerateIsBuiltinRecyclableObject(IR::RegOpnd *regOpnd, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, bool checkObjectAndDynamicObject = true, IR::LabelInstr *labelFastExternal = nullptr);
  147. void EnsureStackFunctionListStackSym();
  148. void EnsureZeroLastStackFunctionNext();
  149. void AllocStackClosure();
  150. IR::Instr * GenerateNewStackScFunc(IR::Instr * newScFuncInstr, IR::RegOpnd ** ppEnvOpnd);
  151. void GenerateStackScriptFunctionInit(StackSym * stackSym, Js::FunctionInfoPtrPtr nestedInfo);
  152. void GenerateScriptFunctionInit(IR::RegOpnd * regOpnd, IR::Opnd * vtableAddressOpnd,
  153. Js::FunctionInfoPtrPtr nestedInfo, IR::Opnd * envOpnd, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  154. void GenerateStackScriptFunctionInit(IR::RegOpnd * regOpnd, Js::FunctionInfoPtrPtr nestedInfo, IR::Opnd * envOpnd, IR::Instr * insertBeforeInstr);
  155. IR::Instr * LowerProfiledStFld(IR::JitProfilingInstr * instr, Js::PropertyOperationFlags flags);
  156. IR::Instr * LowerStFld(IR::Instr * stFldInstr, IR::JnHelperMethod helperMethod, IR::JnHelperMethod polymorphicHelperMethod, bool withInlineCache, IR::LabelInstr *ppBailOutLabel = nullptr, bool isHelper = false, bool withPutFlags = false, Js::PropertyOperationFlags flags = Js::PropertyOperation_None);
  157. IR::Instr * LowerScopedStFld(IR::Instr * stFldInstr, IR::JnHelperMethod helperMethod, bool withInlineCache,
  158. bool withPropertyOperationFlags = false, Js::PropertyOperationFlags flags = Js::PropertyOperation_None);
  159. void LowerProfiledLdElemI(IR::JitProfilingInstr *const instr);
  160. void LowerProfiledStElemI(IR::JitProfilingInstr *const instr, const Js::PropertyOperationFlags flags);
  161. IR::Instr * LowerStElemI(IR::Instr *instr, Js::PropertyOperationFlags flags, bool isHelper, IR::JnHelperMethod helperMethod = IR::HelperOp_SetElementI);
  162. IR::Instr * LowerLdElemI(IR::Instr *instr, IR::JnHelperMethod helperMethod, bool isHelper);
  163. void LowerLdLen(IR::Instr *const instr, const bool isHelper);
  164. IR::Instr * LowerMemOp(IR::Instr * instr);
  165. IR::Instr * LowerMemset(IR::Instr * instr, IR::RegOpnd * helperRet);
  166. IR::Instr * LowerMemcopy(IR::Instr * instr, IR::RegOpnd * helperRet);
  167. IR::Instr * LowerLdArrViewElem(IR::Instr * instr);
  168. IR::Instr * LowerStArrViewElem(IR::Instr * instr);
  169. IR::Instr * LowerLdArrViewElemWasm(IR::Instr * instr);
  170. IR::Instr * LowerArrayDetachedCheck(IR::Instr * instr);
  171. IR::Instr * LowerDeleteElemI(IR::Instr *instr, bool strictMode);
  172. IR::Instr * LowerStElemC(IR::Instr *instr);
  173. void LowerLdArrHead(IR::Instr *instr);
  174. IR::Instr * LowerStSlot(IR::Instr *instr);
  175. IR::Instr * LowerStSlotChkUndecl(IR::Instr *instr);
  176. void LowerStLoopBodyCount(IR::Instr* instr);
  177. #if !FLOATVAR
  178. IR::Instr * LowerStSlotBoxTemp(IR::Instr *instr);
  179. #endif
  180. void LowerLdSlot(IR::Instr *instr);
  181. IR::Instr * LowerChkUndecl(IR::Instr *instr);
  182. void GenUndeclChk(IR::Instr *insertInsert, IR::Opnd *opnd);
  183. IR::Instr * LowerStLen(IR::Instr *instr);
  184. IR::Instr * LoadPropertySymAsArgument(IR::Instr *instr, IR::Opnd *fieldSrc);
  185. IR::Instr * LoadFunctionBodyAsArgument(IR::Instr *instr, IR::IntConstOpnd * functionBodySlotOpnd, IR::RegOpnd * envOpnd);
  186. IR::Instr * LoadHelperTemp(IR::Instr * instr, IR::Instr * instrInsert);
  187. IR::Instr * LowerLoadVar(IR::Instr *instr, IR::Opnd *opnd);
  188. void LoadArgumentCount(IR::Instr *const instr);
  189. void LoadStackArgPtr(IR::Instr *const instr);
  190. void LoadArgumentsFromFrame(IR::Instr *const instr);
  191. IR::Instr * LowerUnaryHelper(IR::Instr *instr, IR::JnHelperMethod helperMethod, IR::Opnd* opndBailoutArg = nullptr);
  192. IR::Instr * LowerUnaryHelperMem(IR::Instr *instr, IR::JnHelperMethod helperMethod, IR::Opnd* opndBailoutArg = nullptr);
  193. IR::Instr * LowerUnaryHelperMemWithFuncBody(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  194. IR::Instr * LowerUnaryHelperMemWithFunctionInfo(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  195. IR::Instr * LowerBinaryHelperMemWithFuncBody(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  196. IR::Instr * LowerUnaryHelperMemWithTemp(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  197. IR::Instr * LowerUnaryHelperMemWithTemp2(IR::Instr *instr, IR::JnHelperMethod helperMethod, IR::JnHelperMethod helperMethodWithTemp);
  198. IR::Instr * LowerUnaryHelperMemWithBoolReference(IR::Instr *instr, IR::JnHelperMethod helperMethod, bool useBoolForBailout);
  199. IR::Instr * LowerBinaryHelperMem(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  200. IR::Instr * LowerBinaryHelperMemWithTemp(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  201. IR::Instr * LowerBinaryHelperMemWithTemp2(IR::Instr *instr, IR::JnHelperMethod helperMethod, IR::JnHelperMethod helperMethodWithTemp);
  202. IR::Instr * LowerBinaryHelperMemWithTemp3(IR::Instr *instr, IR::JnHelperMethod helperMethod,
  203. IR::JnHelperMethod helperMethodWithTemp, IR::JnHelperMethod helperMethodLeftDead);
  204. IR::Instr * LowerAddLeftDeadForString(IR::Instr *instr);
  205. IR::Instr * LowerBinaryHelper(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  206. #ifdef ENABLE_WASM
  207. IR::Instr * LowerCheckWasmSignature(IR::Instr * instr);
  208. IR::Instr * LowerLdWasmFunc(IR::Instr* instr);
  209. IR::Instr * LowerGrowWasmMemory(IR::Instr* instr);
  210. #endif
  211. IR::Instr * LowerInitCachedScope(IR::Instr * instr);
  212. IR::Instr * LowerBrBReturn(IR::Instr * instr, IR::JnHelperMethod helperMethod, bool isHelper);
  213. IR::Instr * LowerBrBMem(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  214. IR::Instr * LowerBrOnObject(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  215. IR::Instr * LowerBrCMem(IR::Instr * instr, IR::JnHelperMethod helperMethod, bool noMathFastPath, bool isHelper = true);
  216. IR::Instr * LowerBrFncApply(IR::Instr * instr, IR::JnHelperMethod helperMethod);
  217. IR::Instr * LowerBrProperty(IR::Instr * instr, IR::JnHelperMethod helperMethod);
  218. IR::Instr * LowerBrOnClassConstructor(IR::Instr *instr, IR::JnHelperMethod helperMethod);
  219. IR::Instr* LowerMultiBr(IR::Instr * instr, IR::JnHelperMethod helperMethod);
  220. IR::Instr* LowerMultiBr(IR::Instr * instr);
  221. IR::Instr * LowerElementUndefined(IR::Instr * instr, IR::JnHelperMethod helper);
  222. IR::Instr * LowerElementUndefinedMem(IR::Instr * instr, IR::JnHelperMethod helper);
  223. IR::Instr * LowerElementUndefinedScoped(IR::Instr * instr, IR::JnHelperMethod helper);
  224. IR::Instr * LowerElementUndefinedScopedMem(IR::Instr * instr, IR::JnHelperMethod helper);
  225. IR::Instr * LowerLdElemUndef(IR::Instr * instr);
  226. IR::Instr * LowerRestParameter(IR::Opnd *formalsOpnd, IR::Opnd *dstOpnd, IR::Opnd *excessOpnd, IR::Instr *instr, IR::RegOpnd *generatorArgsPtrOpnd);
  227. IR::Instr * LowerArgIn(IR::Instr *instr);
  228. IR::Instr * LowerArgInAsmJs(IR::Instr *instr);
  229. IR::Instr * LowerProfiledNewScArray(IR::JitProfilingInstr* arrInstr);
  230. IR::Instr * LowerNewScArray(IR::Instr *arrInstr);
  231. IR::Instr * LowerNewScIntArray(IR::Instr *arrInstr);
  232. IR::Instr * LowerNewScFltArray(IR::Instr *arrInstr);
  233. IR::Instr * LowerArraySegmentVars(IR::Instr *instr);
  234. template <typename ArrayType>
  235. BOOL IsSmallObject(uint32 length);
  236. #ifdef ENABLE_DOM_FAST_PATH
  237. void LowerFastInlineDOMFastPathGetter(IR::Instr* getterInstr);
  238. #endif
  239. void GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef);
  240. void GenerateArrayInfoIsNativeIntArrayTest(IR::Instr * instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel);
  241. void GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef);
  242. void GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(IR::Instr * instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel);
  243. bool IsEmitTempDst(IR::Opnd *opnd);
  244. bool IsEmitTempSrc(IR::Opnd *opnd);
  245. bool IsNullOrUndefRegOpnd(IR::RegOpnd *opnd) const;
  246. bool IsConstRegOpnd(IR::RegOpnd *opnd) const;
  247. IR::Instr * GenerateRuntimeError(IR::Instr * insertBeforeInstr, Js::MessageId errorCode, IR::JnHelperMethod helper = IR::JnHelperMethod::HelperOp_RuntimeTypeError);
  248. bool InlineBuiltInLibraryCall(IR::Instr *callInstr);
  249. void LowerInlineBuiltIn(IR::Instr* instr);
  250. intptr_t GetObjRefForBuiltInTarget(IR::RegOpnd * opnd);
  251. bool TryGenerateFastCmSrEq(IR::Instr * instr);
  252. bool TryGenerateFastBrEq(IR::Instr * instr);
  253. bool TryGenerateFastBrNeq(IR::Instr * instr);
  254. bool GenerateFastBrSrEq(IR::Instr * instr, IR::RegOpnd * srcReg1, IR::RegOpnd * srcReg2, IR::Instr ** pInstrPrev, bool noMathFastPath);
  255. bool GenerateFastBrSrNeq(IR::Instr * instr, IR::Instr ** pInstrPrev);
  256. IR::BranchInstr* GenerateFastBrConst(IR::BranchInstr *branchInstr, IR::Opnd * constOpnd, bool isEqual);
  257. bool GenerateFastCondBranch(IR::BranchInstr * instrBranch, bool *pIsHelper);
  258. void GenerateBooleanNegate(IR::Instr * instr, IR::Opnd * srcBool, IR::Opnd * dst);
  259. bool GenerateFastEqBoolInt(IR::Instr * instr, bool *pIsHelper);
  260. bool GenerateFastBrEqLikely(IR::BranchInstr * instrBranch, bool *pNeedHelper);
  261. bool GenerateFastBooleanAndObjectEqLikely(IR::Instr * instr, IR::Opnd *src1, IR::Opnd *src2, IR::LabelInstr * labelHelper, IR::LabelInstr * labelEqualLikely, bool *pNeedHelper);
  262. bool GenerateFastCmEqLikely(IR::Instr * instr, bool *pNeedHelper);
  263. bool GenerateFastBrBool(IR::BranchInstr *const instr);
  264. static IR::Instr *LoadFloatFromNonReg(IR::Opnd * opndOrig, IR::Opnd * regOpnd, IR::Instr * instrInsert);
  265. void LoadInt32FromUntaggedVar(IR::Instr *const instrLoad);
  266. bool GetValueFromIndirOpnd(IR::IndirOpnd *indirOpnd, IR::Opnd **pValueOpnd, IntConstType *pValue);
  267. void GenerateFastBrOnObject(IR::Instr *instr);
  268. void GenerateObjectTypeTest(IR::RegOpnd *srcReg, IR::Instr *instrInsert, IR::LabelInstr *labelHelper);
  269. static IR::LabelInstr* InsertContinueAfterExceptionLabelForDebugger(Func* func, IR::Instr* insertAfterInstr, bool isHelper);
  270. void GenerateObjectHeaderInliningTest(IR::RegOpnd *baseOpnd, IR::LabelInstr * target, IR::Instr *insertBeforeInstr);
  271. // Static tables that will be used by the GetArray* methods below
  272. private:
  273. static const VTableValue VtableAddresses[static_cast<ValueType::TSize>(ObjectType::Count)];
  274. static const uint32 OffsetsOfHeadSegment[static_cast<ValueType::TSize>(ObjectType::Count)];
  275. static const uint32 OffsetsOfLength[static_cast<ValueType::TSize>(ObjectType::Count)];
  276. static const IRType IndirTypes[static_cast<ValueType::TSize>(ObjectType::Count)];
  277. static const BYTE IndirScales[static_cast<ValueType::TSize>(ObjectType::Count)];
  278. private:
  279. static VTableValue GetArrayVtableAddress(const ValueType valueType, bool getVirtual = false);
  280. public:
  281. static uint32 GetArrayOffsetOfHeadSegment(const ValueType valueType);
  282. static uint32 GetArrayOffsetOfLength(const ValueType valueType);
  283. static IRType GetArrayIndirType(const ValueType valueType);
  284. static BYTE GetArrayIndirScale(const ValueType valueType);
  285. static int SimdGetElementCountFromBytes(ValueType arrValueType, uint8 dataWidth);
  286. private:
  287. bool ShouldGenerateArrayFastPath(const IR::Opnd *const arrayOpnd, const bool supportsObjectsWithArrays, const bool supportsTypedArrays, const bool requiresSse2ForFloatArrays) const;
  288. IR::RegOpnd * LoadObjectArray(IR::RegOpnd *const baseOpnd, IR::Instr *const insertBeforeInstr);
  289. IR::RegOpnd * GenerateArrayTest(IR::RegOpnd *const baseOpnd, IR::LabelInstr *const isNotObjectLabel, IR::LabelInstr *const isNotArrayLabel, IR::Instr *const insertBeforeInstr, const bool forceFloat, const bool isStore = false, const bool allowDefiniteArray = false);
  290. void GenerateIsEnabledArraySetElementFastPathCheck(IR::LabelInstr * isDisabledLabel, IR::Instr * const insertBeforeInstr);
  291. void GenerateIsEnabledIntArraySetElementFastPathCheck(IR::LabelInstr * isDisabledLabel, IR::Instr * const insertBeforeInstr);
  292. void GenerateIsEnabledFloatArraySetElementFastPathCheck(IR::LabelInstr * isDisabledLabel, IR::Instr * const insertBeforeInstr);
  293. void GenerateTypeIdCheck(Js::TypeId typeId, IR::RegOpnd * opnd, IR::LabelInstr * labelFail, IR::Instr * insertBeforeInstr, bool generateObjectCheck = true);
  294. void GenerateStringTest(IR::RegOpnd *srcReg, IR::Instr *instrInsert, IR::LabelInstr * failLabel, IR::LabelInstr * succeedLabel = nullptr, bool generateObjectCheck = true);
  295. IR::RegOpnd * GenerateUntagVar(IR::RegOpnd * opnd, IR::LabelInstr * labelFail, IR::Instr * insertBeforeInstr, bool generateTagCheck = true);
  296. void GenerateNotZeroTest( IR::Opnd * opndSrc, IR::LabelInstr * labelZero, IR::Instr * instrInsert);
  297. IR::Opnd * CreateOpndForSlotAccess(IR::Opnd * opnd);
  298. void GenerateSwitchStringLookup(IR::Instr * instr);
  299. void GenerateSingleCharStrJumpTableLookup(IR::Instr * instr);
  300. void LowerJumpTableMultiBranch(IR::MultiBranchInstr * multiBrInstr, IR::RegOpnd * indexOpnd);
  301. void LowerConvNum(IR::Instr *instrLoad, bool noMathFastPath);
  302. void InsertBitTestBranch(IR::Opnd * bitMaskOpnd, IR::Opnd * bitIndex, bool jumpIfBitOn, IR::LabelInstr * targetLabel, IR::Instr * insertBeforeInstr);
  303. void GenerateGetSingleCharString(IR::RegOpnd * charCodeOpnd, IR::Opnd * resultOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * doneLabel, IR::Instr * instr, bool isCodePoint);
  304. void GenerateFastBrBReturn(IR::Instr * instr);
  305. #ifndef _M_X64
  306. void EnsureInt64RegPairMap();
  307. Int64RegPair FindOrCreateInt64Pair(IR::Opnd*);
  308. #endif
  309. public:
  310. static IR::LabelInstr * InsertLabel(const bool isHelper, IR::Instr *const insertBeforeInstr);
  311. static IR::Instr * InsertMove(IR::Opnd *dst, IR::Opnd *src, IR::Instr *const insertBeforeInstr, bool generateWriteBarrier = true);
  312. static IR::Instr * InsertMoveWithBarrier(IR::Opnd *dst, IR::Opnd *src, IR::Instr *const insertBeforeInstr);
  313. #if _M_X64
  314. static IR::Instr * InsertMoveBitCast(IR::Opnd *const dst, IR::Opnd *const src1, IR::Instr *const insertBeforeInstr);
  315. #endif
  316. static IR::BranchInstr * InsertBranch(const Js::OpCode opCode, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  317. static IR::BranchInstr * InsertBranch(const Js::OpCode opCode, const bool isUnsigned, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  318. static IR::Instr * InsertCompare(IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  319. static IR::BranchInstr * InsertCompareBranch(IR::Opnd *const compareSrc1, IR::Opnd *const compareSrc2, Js::OpCode branchOpCode, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr, const bool ignoreNaN = false);
  320. static IR::BranchInstr * InsertCompareBranch(IR::Opnd *compareSrc1, IR::Opnd *compareSrc2, Js::OpCode branchOpCode, const bool isUnsigned, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr, const bool ignoreNaN = false);
  321. static IR::Instr * InsertTest(IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  322. static IR::BranchInstr * InsertTestBranch(IR::Opnd *const testSrc1, IR::Opnd *const testSrc2, const Js::OpCode branchOpCode, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  323. static IR::BranchInstr * InsertTestBranch(IR::Opnd *const testSrc1, IR::Opnd *const testSrc2, const Js::OpCode branchOpCode, const bool isUnsigned, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  324. static IR::Instr * InsertAdd(const bool needFlags, IR::Opnd *const dst, IR::Opnd *src1, IR::Opnd *src2, IR::Instr *const insertBeforeInstr);
  325. static IR::Instr * InsertSub(const bool needFlags, IR::Opnd *const dst, IR::Opnd *src1, IR::Opnd *src2, IR::Instr *const insertBeforeInstr);
  326. static IR::Instr * InsertLea(IR::RegOpnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr, bool postRegAlloc = false);
  327. static IR::Instr * InsertXor(IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  328. static IR::Instr * InsertAnd(IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  329. static IR::Instr * InsertOr(IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  330. static IR::Instr * InsertShift(const Js::OpCode opCode, const bool needFlags, IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, IR::Instr *const insertBeforeInstr);
  331. static IR::Instr * InsertShiftBranch(const Js::OpCode shiftOpCode, IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, const Js::OpCode branchOpCode, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  332. static IR::Instr * InsertShiftBranch(const Js::OpCode shiftOpCode, IR::Opnd *const dst, IR::Opnd *const src1, IR::Opnd *const src2, const Js::OpCode branchOpCode, const bool isUnsigned, IR::LabelInstr *const target, IR::Instr *const insertBeforeInstr);
  333. static IR::Instr * InsertConvertFloat32ToFloat64(IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr);
  334. static IR::Instr * InsertConvertFloat64ToFloat32(IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr);
  335. public:
  336. static void InsertDecUInt32PreventOverflow(IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr, IR::Instr * *const onOverflowInsertBeforeInstrRef = nullptr);
  337. void InsertFloatCheckForZeroOrNanBranch(IR::Opnd *const src, const bool branchOnZeroOrNan, IR::LabelInstr *const target, IR::LabelInstr *const fallthroughLabel, IR::Instr *const insertBeforeInstr);
  338. public:
  339. static IR::HelperCallOpnd* CreateHelperCallOpnd(IR::JnHelperMethod helperMethod, int helperArgCount, Func* func);
  340. static IR::Opnd * GetMissingItemOpnd(IRType type, Func *func);
  341. static IR::Opnd * GetImplicitCallFlagsOpnd(Func * func);
  342. inline static IR::IntConstOpnd* MakeCallInfoConst(ushort flags, int32 argCount, Func* func) {
  343. #ifdef _M_X64
  344. // This was defined differently for x64
  345. Js::CallInfo callInfo = Js::CallInfo((Js::CallFlags)flags, (unsigned __int16)argCount);
  346. return IR::IntConstOpnd::New(*((IntConstType *)((void *)&callInfo)), TyInt32, func, true);
  347. #else
  348. AssertMsg(!(argCount & 0xFF000000), "Too many arguments"); //final 8 bits are for flags
  349. AssertMsg(!(flags & ~0xFF), "Flags are invalid!"); //8 bits for flags
  350. return IR::IntConstOpnd::New(argCount | (flags << 24), TyMachReg, func, true);
  351. #endif
  352. }
  353. private:
  354. IR::IndirOpnd * GenerateFastElemICommon(
  355. IR::Instr * ldElem,
  356. bool isStore,
  357. IR::IndirOpnd * indirOpnd,
  358. IR::LabelInstr * labelHelper,
  359. IR::LabelInstr * labelCantUseArray,
  360. IR::LabelInstr *labelFallthrough,
  361. bool * pIsTypedArrayElement,
  362. bool * pIsStringIndex,
  363. bool *emitBailoutRef,
  364. IR::LabelInstr **pLabelSegmentLengthIncreased = nullptr,
  365. bool checkArrayLengthOverflow = true,
  366. bool forceGenerateFastPath = false,
  367. bool returnLength = false,
  368. IR::LabelInstr *bailOutLabelInstr = nullptr,
  369. bool * indirOpndOverflowed = nullptr);
  370. IR::IndirOpnd * GenerateFastElemIIntIndexCommon(
  371. IR::Instr * ldElem,
  372. bool isStore,
  373. IR::IndirOpnd * indirOpnd,
  374. IR::LabelInstr * labelHelper,
  375. IR::LabelInstr * labelCantUseArray,
  376. IR::LabelInstr *labelFallthrough,
  377. bool * pIsTypedArrayElement,
  378. bool *emitBailoutRef,
  379. IR::LabelInstr **pLabelSegmentLengthIncreased,
  380. bool checkArrayLengthOverflow,
  381. bool forceGenerateFastPath = false,
  382. bool returnLength = false,
  383. IR::LabelInstr *bailOutLabelInstr = nullptr,
  384. bool * indirOpndOverflowed = nullptr);
  385. bool GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef);
  386. bool GenerateFastStElemI(IR::Instr *& StElem, bool *instrIsInHelperBlockRef);
  387. bool GenerateFastLdLen(IR::Instr *ldLen, bool *instrIsInHelperBlockRef);
  388. bool GenerateFastInlineGlobalObjectParseInt(IR::Instr *instr);
  389. bool GenerateFastInlineStringFromCharCode(IR::Instr* instr);
  390. bool GenerateFastInlineStringFromCodePoint(IR::Instr* instr);
  391. void GenerateFastInlineStringCodePointAt(IR::Instr* doneLabel, Func* func, IR::Opnd *strLength, IR::Opnd *srcIndex, IR::RegOpnd *lowerChar, IR::RegOpnd *strPtr);
  392. bool GenerateFastInlineStringCharCodeAt(IR::Instr* instr, Js::BuiltinFunction index);
  393. bool GenerateFastInlineStringReplace(IR::Instr* instr);
  394. void GenerateFastInlineArrayPush(IR::Instr * instr);
  395. void GenerateFastInlineArrayPop(IR::Instr * instr);
  396. void GenerateFastInlineStringSplitMatch(IR::Instr * instr);
  397. void GenerateFastInlineMathImul(IR::Instr* instr);
  398. void GenerateFastInlineMathClz(IR::Instr* instr);
  399. void GenerateCtz(IR::Instr* instr);
  400. void GeneratePopCnt(IR::Instr* instr);
  401. void GenerateThrowUnreachable(IR::Instr* instr);
  402. void GenerateTruncWithCheck(IR::Instr* instr);
  403. void GenerateFastInlineMathFround(IR::Instr* instr);
  404. void GenerateFastInlineRegExpExec(IR::Instr * instr);
  405. bool GenerateFastPush(IR::Opnd *baseOpndParam, IR::Opnd *src, IR::Instr *callInstr, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel, IR::LabelInstr * bailOutLabelHelper, bool returnLength = false);
  406. bool GenerateFastReplace(IR::Opnd* strOpnd, IR::Opnd* src1, IR::Opnd* src2, IR::Instr *callInstr, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel);
  407. bool ShouldGenerateStringReplaceFastPath(IR::Instr * instr, IntConstType argCount);
  408. bool GenerateFastPop(IR::Opnd *baseOpndParam, IR::Instr *callInstr, IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel, IR::LabelInstr * bailOutLabelHelper);
  409. bool GenerateFastStringLdElem(IR::Instr * ldElem, IR::LabelInstr * labelHelper, IR::LabelInstr * labelFallThru);
  410. IR::Instr * LowerCallDirect(IR::Instr * instr);
  411. IR::Instr * GenerateDirectCall(IR::Instr* inlineInstr, IR::Opnd* funcObj, ushort callflags);
  412. IR::Instr * GenerateFastInlineBuiltInMathRandom(IR::Instr* instr);
  413. IR::Instr * GenerateHelperToArrayPushFastPath(IR::Instr * instr, IR::LabelInstr * bailOutLabelHelper);
  414. IR::Instr * GenerateHelperToArrayPopFastPath(IR::Instr * instr, IR::LabelInstr * doneLabel, IR::LabelInstr * bailOutLabelHelper);
  415. IR::Instr * LowerCondBranchCheckBailOut(IR::BranchInstr * instr, IR::Instr * helperCall, bool isHelper);
  416. IR::Instr * LowerBailOnEqualOrNotEqual(IR::Instr * instr, IR::BranchInstr * branchInstr = nullptr, IR::LabelInstr * labelBailOut = nullptr, IR::PropertySymOpnd * propSymOpnd = nullptr, bool isHelper = false);
  417. void LowerBailOnNegative(IR::Instr *const instr);
  418. void LowerBailoutCheckAndLabel(IR::Instr *instr, bool onEqual, bool isHelper);
  419. IR::Instr * LowerBailOnNotSpreadable(IR::Instr *instr);
  420. IR::Instr * LowerBailOnNotPolymorphicInlinee(IR::Instr * instr);
  421. IR::Instr * LowerBailOnNotStackArgs(IR::Instr * instr);
  422. IR::Instr * LowerBailOnNotObject(IR::Instr *instr, IR::BranchInstr *branchInstr = nullptr, IR::LabelInstr *labelBailOut = nullptr);
  423. IR::Instr * LowerBailOnTrue(IR::Instr *instr, IR::LabelInstr *labelBailOut = nullptr);
  424. IR::Instr * LowerBailOnNotBuiltIn(IR::Instr *instr, IR::BranchInstr *branchInstr = nullptr, IR::LabelInstr *labelBailOut = nullptr);
  425. IR::Instr * LowerBailOnNotInteger(IR::Instr *instr, IR::BranchInstr *branchInstr = nullptr, IR::LabelInstr *labelBailOut = nullptr);
  426. IR::Instr * LowerBailOnIntMin(IR::Instr *instr, IR::BranchInstr *branchInstr = nullptr, IR::LabelInstr *labelBailOut = nullptr);
  427. void LowerBailOnNotString(IR::Instr *instr);
  428. IR::Instr * LowerBailForDebugger(IR::Instr* instr, bool isInsideHelper = false);
  429. IR::Instr * LowerBailOnException(IR::Instr* instr);
  430. IR::Instr * LowerReinterpretPrimitive(IR::Instr* instr);
  431. void LowerOneBailOutKind(IR::Instr *const instr, const IR::BailOutKind bailOutKindToLower, const bool isInHelperBlock, const bool preserveBailOutKindInInstr = false);
  432. void SplitBailOnNotArray(IR::Instr *const instr, IR::Instr * *const bailOnNotArrayRef, IR::Instr * *const bailOnMissingValueRef);
  433. IR::RegOpnd * LowerBailOnNotArray(IR::Instr *const instr);
  434. void LowerBailOnMissingValue(IR::Instr *const instr, IR::RegOpnd *const arrayOpnd);
  435. void LowerBailOnInvalidatedArrayHeadSegment(IR::Instr *const instr, const bool isInHelperBlock);
  436. void LowerBailOnInvalidatedArrayLength(IR::Instr *const instr, const bool isInHelperBlock);
  437. void LowerBailOnCreatedMissingValue(IR::Instr *const instr, const bool isInHelperBlock);
  438. void LowerBoundCheck(IR::Instr *const instr);
  439. IR::Instr * LowerBailTarget(IR::Instr * instr);
  440. IR::Instr * SplitBailOnImplicitCall(IR::Instr *& instr);
  441. IR::Instr * SplitBailOnImplicitCall(IR::Instr * instr, IR::Instr * helperCall, IR::Instr * insertBeforeInstr);
  442. IR::Instr * SplitBailForDebugger(IR::Instr* instr);
  443. IR::Instr * SplitBailOnResultCondition(IR::Instr *const instr) const;
  444. void LowerBailOnResultCondition(IR::Instr *const instr, IR::LabelInstr * *const bailOutLabel, IR::LabelInstr * *const skipBailOutLabel);
  445. void PreserveSourcesForBailOnResultCondition(IR::Instr *const instr, IR::LabelInstr *const skipBailOutLabel) const;
  446. void LowerInstrWithBailOnResultCondition(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel) const;
  447. void GenerateObjectTestAndTypeLoad(IR::Instr *instrLdSt, IR::RegOpnd *opndBase, IR::RegOpnd *opndType, IR::LabelInstr *labelHelper);
  448. IR::LabelInstr *GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr = nullptr, IR::LabelInstr * labelBailOut = nullptr, IR::LabelInstr * collectRuntimeStatsLabel = nullptr);
  449. void GenerateJumpToEpilogForBailOut(BailOutInfo * bailOutInfo, IR::Instr *instrAfter);
  450. void GenerateThrow(IR::Opnd* errorCode, IR::Instr * instr) const;
  451. void LowerDivI4(IR::Instr * const instr);
  452. void LowerRemI4(IR::Instr * const instr);
  453. void LowerDivI4Common(IR::Instr * const instr);
  454. void LowerRemR8(IR::Instr * const instr);
  455. void LowerRemR4(IR::Instr * const instr);
  456. void LowerInlineeStart(IR::Instr * instr);
  457. void LowerInlineeEnd(IR::Instr * instr);
  458. static
  459. IR::SymOpnd* LoadCallInfo(IR::Instr * instrInsert);
  460. IR::Instr * LowerCallIDynamic(IR::Instr * callInstr, ushort callFlags);
  461. IR::Opnd* GenerateArgOutForInlineeStackArgs(IR::Instr* callInstr, IR::Instr* stackArgsInstr);
  462. IR::Opnd* GenerateArgOutForStackArgs(IR::Instr* callInstr, IR::Instr* stackArgsInstr);
  463. void GenerateLoadStackArgumentByIndex(IR::Opnd *dst, IR::RegOpnd *indexOpnd, IR::Instr *instr, int32 offset, Func *func);
  464. bool GenerateFastStackArgumentsLdElemI(IR::Instr* ldElem);
  465. IR::IndirOpnd* GetArgsIndirOpndForInlinee(IR::Instr* ldElem, IR::Opnd* valueOpnd);
  466. IR::IndirOpnd* GetArgsIndirOpndForTopFunction(IR::Instr* ldElem, IR::Opnd* valueOpnd);
  467. void GenerateCheckForArgumentsLength(IR::Instr* ldElem, IR::LabelInstr* labelCreateHeapArgs, IR::Opnd* actualParamOpnd, IR::Opnd* valueOpnd, Js::OpCode opcode);
  468. bool GenerateFastArgumentsLdElemI(IR::Instr* ldElem, IR::LabelInstr *labelFallThru);
  469. bool GenerateFastRealStackArgumentsLdLen(IR::Instr *ldLen);
  470. bool GenerateFastArgumentsLdLen(IR::Instr *ldLen, IR::LabelInstr* labelFallThru);
  471. static const uint16 GetFormalParamOffset() { /*formal start after frame pointer, return address, function object, callInfo*/ return 4;};
  472. IR::RegOpnd* GenerateFunctionTypeFromFixedFunctionObject(IR::Instr *callInstr, IR::Opnd* functionObjOpnd);
  473. bool GenerateFastLdFld(IR::Instr * const instrLdFld, IR::JnHelperMethod helperMethod, IR::JnHelperMethod polymorphicHelperMethod,
  474. IR::LabelInstr ** labelBailOut, IR::RegOpnd* typeOpnd, bool* pIsHelper, IR::LabelInstr** pLabelHelper);
  475. void GenerateAuxSlotAdjustmentRequiredCheck(IR::Instr * instrToInsertBefore, IR::RegOpnd * opndInlineCache, IR::LabelInstr * labelHelper);
  476. void GenerateSetObjectTypeFromInlineCache(IR::Instr * instrToInsertBefore, IR::RegOpnd * opndBase, IR::RegOpnd * opndInlineCache, bool isTypeTagged);
  477. bool GenerateFastStFld(IR::Instr * const instrStFld, IR::JnHelperMethod helperMethod, IR::JnHelperMethod polymorphicHelperMethod,
  478. IR::LabelInstr ** labelBailOut, IR::RegOpnd* typeOpnd, bool* pIsHelper, IR::LabelInstr** pLabelHelper, bool withPutFlags = false, Js::PropertyOperationFlags flags = Js::PropertyOperation_None);
  479. bool GenerateFastStFldForCustomProperty(IR::Instr *const instr, IR::LabelInstr * *const labelHelperRef);
  480. void RelocateCallDirectToHelperPath(IR::Instr* argoutInlineSpecialized, IR::LabelInstr* labelHelper);
  481. bool TryGenerateFastBrOrCmTypeOf(IR::Instr *instr, IR::Instr **prev, bool isNeqOp, bool *pfNoLower);
  482. void GenerateFastBrTypeOf(IR::Instr *branch, IR::RegOpnd *object, IR::IntConstOpnd *typeIdOpnd, IR::Instr *typeOf, bool *pfNoLower, bool isNeqOp);
  483. void GenerateFastCmTypeOf(IR::Instr *compare, IR::RegOpnd *object, IR::IntConstOpnd *typeIdOpnd, IR::Instr *typeOf, bool *pfNoLower, bool isNeqOp);
  484. void GenerateFalsyObjectTest(IR::Instr *insertInstr, IR::RegOpnd *typeOpnd, Js::TypeId typeIdToCheck, IR::LabelInstr* target, IR::LabelInstr* done, bool isNeqOp);
  485. void GenerateFalsyObjectTest(IR::Instr * insertInstr, IR::RegOpnd * typeOpnd, IR::LabelInstr * falsyLabel);
  486. void GenerateJavascriptOperatorsIsConstructorGotoElse(IR::Instr *instrInsert, IR::RegOpnd *instanceRegOpnd, IR::LabelInstr *labelTrue, IR::LabelInstr *labelFalse);
  487. void GenerateRecyclableObjectGetPrototypeNullptrGoto(IR::Instr *instrInsert, IR::RegOpnd *instanceRegOpnd, IR::LabelInstr *labelReturnNullptr);
  488. void GenerateRecyclableObjectIsElse(IR::Instr *instrInsert, IR::RegOpnd *instanceRegOpnd, IR::LabelInstr *labelFalse);
  489. void GenerateLdHomeObj(IR::Instr* instr);
  490. void GenerateLdHomeObjProto(IR::Instr* instr);
  491. void GenerateLdFuncObj(IR::Instr* instr);
  492. void GenerateLdFuncObjProto(IR::Instr* instr);
  493. void GenerateSetHomeObj(IR::Instr* instrInsert);
  494. void GenerateLoadNewTarget(IR::Instr* instrInsert);
  495. void GenerateCheckForCallFlagNew(IR::Instr* instrInsert);
  496. void GenerateGetCurrentFunctionObject(IR::Instr * instr);
  497. IR::Opnd * GetInlineCacheFromFuncObjectForRuntimeUse(IR::Instr * instr, IR::PropertySymOpnd * propSymOpnd, bool isHelper);
  498. IR::Instr * LowerInitClass(IR::Instr * instr);
  499. IR::RegOpnd * GenerateGetImmutableOrScriptUnreferencedString(IR::RegOpnd * strOpnd, IR::Instr * insertBeforeInstr, IR::JnHelperMethod helperMethod, bool reloadDst = true);
  500. void LowerNewConcatStrMulti(IR::Instr * instr);
  501. void LowerNewConcatStrMultiBE(IR::Instr * instr);
  502. void LowerSetConcatStrMultiItem(IR::Instr * instr);
  503. void LowerConvStr(IR::Instr * instr);
  504. void LowerCoerseStr(IR::Instr * instr);
  505. void LowerCoerseRegex(IR::Instr * instr);
  506. void LowerCoerseStrOrRegex(IR::Instr * instr);
  507. void LowerConvPrimStr(IR::Instr * instr);
  508. void LowerConvStrCommon(IR::JnHelperMethod helper, IR::Instr * instr);
  509. void GenerateRecyclerAlloc(IR::JnHelperMethod allocHelper, size_t allocSize, IR::RegOpnd* newObjDst, IR::Instr* insertionPointInstr, bool inOpHelper = false);
  510. template <typename ArrayType>
  511. IR::RegOpnd * GenerateArrayAllocHelper(IR::Instr *instr, uint32 * psize, Js::ArrayCallSiteInfo * arrayInfo, bool * pIsHeadSegmentZeroed, bool isArrayObjCtor, bool isNoArgs);
  512. template <typename ArrayType>
  513. IR::RegOpnd * GenerateArrayLiteralsAlloc(IR::Instr *instr, uint32 * psize, Js::ArrayCallSiteInfo * arrayInfo, bool * pIsHeadSegmentZeroed);
  514. template <typename ArrayType>
  515. IR::RegOpnd * GenerateArrayObjectsAlloc(IR::Instr *instr, uint32 * psize, Js::ArrayCallSiteInfo * arrayInfo, bool * pIsHeadSegmentZeroed, bool isNoArgs);
  516. template <typename ArrayType>
  517. IR::RegOpnd * GenerateArrayAlloc(IR::Instr *instr, IR::Opnd * sizeOpnd, Js::ArrayCallSiteInfo * arrayInfo);
  518. void GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length, IR::LabelInstr* labelDone, bool isNoArgs);
  519. template <typename ArrayType>
  520. void GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, IR::LabelInstr* helperLabel, IR::LabelInstr* labelDone, IR::Opnd* lengthOpnd, uint32 offsetOfCallSiteIndex, uint32 offsetOfWeakFuncRef);
  521. void GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length);
  522. void GenerateMemInit(IR::RegOpnd * opnd, int32 offset, int32 value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  523. void GenerateMemInit(IR::RegOpnd * opnd, int32 offset, uint32 value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  524. void GenerateMemInitNull(IR::RegOpnd * opnd, int32 offset, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  525. void GenerateMemInit(IR::RegOpnd * opnd, int32 offset, IR::Opnd * value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  526. void GenerateMemInit(IR::RegOpnd * opnd, IR::RegOpnd * offset, IR::Opnd * value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
  527. void GenerateRecyclerMemInit(IR::RegOpnd * opnd, int32 offset, int32 value, IR::Instr * insertBeforeInstr);
  528. void GenerateRecyclerMemInit(IR::RegOpnd * opnd, int32 offset, uint32 value, IR::Instr * insertBeforeInstr);
  529. void GenerateRecyclerMemInitNull(IR::RegOpnd * opnd, int32 offset, IR::Instr * insertBeforeInstr);
  530. void GenerateRecyclerMemInit(IR::RegOpnd * opnd, int32 offset, IR::Opnd * value, IR::Instr * insertBeforeInstr);
  531. void GenerateMemCopy(IR::Opnd * dst, IR::Opnd * src, uint32 size, IR::Instr * insertBeforeInstr);
  532. void GenerateDynamicObjectAlloc(IR::Instr * newObjInstr, uint inlineSlotCount, uint slotCount, IR::RegOpnd * newObjDst, IR::Opnd * typeSrc);
  533. bool GenerateSimplifiedInt4Rem(IR::Instr *const remInstr, IR::LabelInstr *const skipBailOutLabel = nullptr) const;
  534. IR::Instr* GenerateCallProfiling(Js::ProfileId profileId, Js::InlineCacheIndex inlineCacheIndex, IR::Opnd* retval, IR::Opnd*calleeFunctionObjOpnd, IR::Opnd* callInfo, bool returnTypeOnly, IR::Instr*callInstr, IR::Instr*insertAfter);
  535. IR::Opnd* GetImplicitCallFlagsOpnd();
  536. IR::Opnd* CreateClearImplicitCallFlagsOpnd();
  537. IR::Instr * LoadScriptContext(IR::Instr *instr);
  538. IR::Instr * LoadFunctionBody(IR::Instr * instr);
  539. IR::Opnd * LoadFunctionBodyOpnd(IR::Instr *instr);
  540. IR::Opnd * LoadFunctionInfoOpnd(IR::Instr *instr);
  541. IR::Opnd * LoadScriptContextOpnd(IR::Instr *instr);
  542. IR::Opnd * LoadScriptContextValueOpnd(IR::Instr * instr, ScriptContextValue valueType);
  543. IR::Opnd * LoadLibraryValueOpnd(IR::Instr * instr, LibraryValue valueType);
  544. IR::Opnd * LoadVTableValueOpnd(IR::Instr * instr, VTableValue vtableType);
  545. IR::Opnd * LoadOptimizationOverridesValueOpnd(IR::Instr *instr, OptimizationOverridesValue valueType);
  546. IR::Opnd * LoadNumberAllocatorValueOpnd(IR::Instr *instr, NumberAllocatorValue valueType);
  547. IR::Opnd * LoadIsInstInlineCacheOpnd(IR::Instr *instr, uint inlineCacheIndex);
  548. IR::Opnd * LoadRuntimeInlineCacheOpnd(IR::Instr * instr, IR::PropertySymOpnd * sym, bool isHelper = false);
  549. void LowerSpreadArrayLiteral(IR::Instr *instr);
  550. IR::Instr* LowerSpreadCall(IR::Instr *instr, Js::CallFlags callFlags, bool setupProfiledVersion = false);
  551. void LowerInlineSpreadArgOutLoopUsingRegisters(IR::Instr *callInstr, IR::RegOpnd *indexOpnd, IR::RegOpnd *arrayElementsStartOpnd);
  552. IR::Instr* LowerCallIDynamicSpread(IR::Instr * callInstr, ushort callFlags);
  553. void LowerNewScopeSlots(IR::Instr * instr, bool doStackSlots);
  554. void LowerLdFrameDisplay(IR::Instr * instr, bool doStackDisplay);
  555. void LowerLdInnerFrameDisplay(IR::Instr * instr);
  556. IR::AddrOpnd * CreateFunctionBodyOpnd(Func *const func) const;
  557. IR::AddrOpnd * CreateFunctionBodyOpnd(Js::FunctionBody *const functionBody) const;
  558. bool GenerateRecyclerOrMarkTempAlloc(IR::Instr * instr, IR::RegOpnd * dstOpnd, IR::JnHelperMethod allocHelper, size_t allocSize, IR::SymOpnd ** tempObjectSymOpnd);
  559. IR::SymOpnd * GenerateMarkTempAlloc(IR::RegOpnd *const dstOpnd, const size_t allocSize, IR::Instr *const insertBeforeInstr);
  560. void LowerBrFncCachedScopeEq(IR::Instr *instr);
  561. IR::Instr* InsertLoweredRegionStartMarker(IR::Instr* instrToInsertBefore);
  562. IR::Instr* RemoveLoweredRegionStartMarker(IR::Instr* startMarkerInstr);
  563. void ConvertArgOpndIfGeneratorFunction(IR::Instr *instrArgIn, IR::RegOpnd *generatorArgsPtrOpnd);
  564. static IR::RegOpnd * LoadGeneratorArgsPtr(IR::Instr *instrInsert);
  565. static IR::Instr * LoadGeneratorObject(IR::Instr *instrInsert);
  566. IR::Opnd * LoadSlotArrayWithCachedLocalType(IR::Instr * instrInsert, IR::PropertySymOpnd *propertySymOpnd);
  567. IR::Opnd * LoadSlotArrayWithCachedProtoType(IR::Instr * instrInsert, IR::PropertySymOpnd *propertySymOpnd);
  568. IR::Instr * LowerLdAsmJsEnv(IR::Instr *instr);
  569. IR::Instr * LowerLdEnv(IR::Instr *instr);
  570. IR::Instr * LowerLdNativeCodeData(IR::Instr *instr);
  571. IR::Instr * LowerFrameDisplayCheck(IR::Instr * instr);
  572. IR::Instr * LowerSlotArrayCheck(IR::Instr * instr);
  573. void InsertSlotArrayCheck(IR::Instr * instr, StackSym * dstSym, uint32 slotId);
  574. void InsertFrameDisplayCheck(IR::Instr * instr, StackSym * dstSym, FrameDisplayCheckRecord * record);
  575. IR::RegOpnd * LoadIndexFromLikelyFloat(IR::RegOpnd *indexOpnd, const bool skipNegativeCheck, IR::LabelInstr *const notTaggedIntLabel, IR::LabelInstr *const negativeLabel, IR::Instr *const insertBeforeInstr);
  576. void MarkConstantAddressRegOpndLiveOnBackEdge(IR::LabelInstr * loopTop);
  577. #if DBG
  578. static void LegalizeVerifyRange(IR::Instr * instrStart, IR::Instr * instrLast);
  579. #endif
  580. IR::Instr* LowerTry(IR::Instr* instr, bool tryCatch);
  581. void EnsureBailoutReturnValueSym();
  582. void EnsureHasBailedOutSym();
  583. void InsertReturnThunkForRegion(Region* region, IR::LabelInstr* restoreLabel);
  584. void SetHasBailedOut(IR::Instr * bailoutInstr);
  585. IR::Instr* EmitEHBailoutStackRestore(IR::Instr * bailoutInstr);
  586. void EmitSaveEHBailoutReturnValueAndJumpToRetThunk(IR::Instr * instr);
  587. void EmitRestoreReturnValueFromEHBailout(IR::LabelInstr * restoreLabel, IR::LabelInstr * epilogLabel);
  588. void LowerInitForInEnumerator(IR::Instr * instr);
  589. void AllocStackForInObjectEnumeratorArray();
  590. IR::RegOpnd * GenerateForInEnumeratorLoad(IR::Opnd * forInEnumeratorOpnd, IR::Instr * insertBeforeInstr);
  591. IR::Opnd * GetForInEnumeratorFieldOpnd(IR::Opnd * forInEnumeratorOpnd, uint fieldOffset, IRType type);
  592. void GenerateInitForInEnumeratorFastPath(IR::Instr * instr, Js::ForInCache * forInCache);
  593. void GenerateHasObjectArrayCheck(IR::RegOpnd * objectOpnd, IR::RegOpnd * typeOpnd, IR::LabelInstr * hasObjectArray, IR::Instr * insertBeforeInstr);
  594. IR::LabelInstr* InsertLoopTopLabel(IR::Instr * insertBeforeInstr);
  595. public:
  596. static IRType GetImplicitCallFlagsType()
  597. {
  598. static_assert(sizeof(Js::ImplicitCallFlags) == 1, "If this size changes, change TyUint8 in the line below to the right type.");
  599. return TyUint8;
  600. }
  601. static IRType GetFldInfoFlagsType()
  602. {
  603. static_assert(sizeof(Js::FldInfoFlags) == 1, "If this size changes, change TyUint8 in the line below to the right type.");
  604. return TyUint8;
  605. }
  606. static bool IsSpreadCall(IR::Instr *instr);
  607. static
  608. IR::Instr* GetLdSpreadIndicesInstr(IR::Instr *instr);
  609. static bool DoLazyBailout(Func* func) { return PHASE_ON(Js::LazyBailoutPhase, func) && !func->IsLoopBody(); }
  610. static bool DoLazyFixedTypeBailout(Func* func) { return DoLazyBailout(func) && !PHASE_OFF(Js::LazyFixedTypeBailoutPhase, func); }
  611. static bool DoLazyFixedDataBailout(Func* func) { return DoLazyBailout(func) && !PHASE_OFF(Js::LazyFixedDataBailoutPhase, func); }
  612. LowererMD * GetLowererMD() { return &m_lowererMD; }
  613. private:
  614. Func * m_func;
  615. LowererMD m_lowererMD;
  616. JitArenaAllocator *m_alloc;
  617. IR::Opnd * nextStackFunctionOpnd;
  618. IR::LabelInstr * outerMostLoopLabel;
  619. BVSparse<JitArenaAllocator> * initializedTempSym;
  620. BVSparse<JitArenaAllocator> * addToLiveOnBackEdgeSyms;
  621. Region * currentRegion;
  622. #ifndef _M_X64
  623. struct Int64SymPair { StackSym* high; StackSym* low; };
  624. typedef BaseDictionary<SymID, Int64SymPair, JitArenaAllocator> Int64RegPairMap;
  625. Int64RegPairMap* m_int64RegPairMap;
  626. #endif
  627. };