Sym.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. 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. class Lifetime;
  7. namespace IR
  8. {
  9. class Instr;
  10. class Opnd;
  11. }
  12. class StackSym;
  13. class PropertySym;
  14. typedef JsUtil::BaseDictionary<StackSym*, StackSym*, JitArenaAllocator, PrimeSizePolicy> StackSymMap;
  15. typedef JsUtil::BaseDictionary<StackSym*, IR::Instr*, JitArenaAllocator, PrimeSizePolicy> SymInstrMap;
  16. enum SymKind : BYTE
  17. {
  18. SymKindInvalid,
  19. SymKindStack,
  20. SymKindProperty
  21. };
  22. typedef uint32 SymID;
  23. constexpr SymID SymID_Invalid = (SymID)-1;
  24. ///---------------------------------------------------------------------------
  25. ///
  26. /// class Sym
  27. /// StackSym
  28. /// PropertySym
  29. ///
  30. ///---------------------------------------------------------------------------
  31. class Sym
  32. {
  33. public:
  34. bool IsStackSym() const;
  35. StackSym * AsStackSym();
  36. StackSym const * AsStackSym() const;
  37. bool IsPropertySym() const;
  38. PropertySym * AsPropertySym();
  39. PropertySym const * AsPropertySym() const;
  40. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  41. void Dump(IRDumpFlags flags, const ValueType valueType = ValueType::Uninitialized) const;
  42. void Dump(const ValueType valueType = ValueType::Uninitialized) const;
  43. void DumpSimple() const;
  44. #endif
  45. #if DBG_DUMP
  46. // Having a VTable helps the VS debugger determine which derived class we have
  47. void virtual DummyVirtualFunc() {};
  48. #endif
  49. public:
  50. Sym * m_next;
  51. SymID m_id;
  52. SymKind m_kind;
  53. };
  54. class ObjectSymInfo
  55. {
  56. public:
  57. static ObjectSymInfo * New(Func * func);
  58. static ObjectSymInfo * New(StackSym * typeSym, Func * func);
  59. ObjectSymInfo(): m_typeSym(nullptr), m_auxSlotPtrSym(nullptr), m_propertySymList(nullptr) {};
  60. public:
  61. StackSym * m_typeSym;
  62. StackSym * m_auxSlotPtrSym;
  63. PropertySym * m_propertySymList;
  64. };
  65. ///---------------------------------------------------------------------------
  66. ///
  67. /// class StackSym
  68. ///
  69. /// Used for stack symbols. These are the register candidates.
  70. ///
  71. ///---------------------------------------------------------------------------
  72. class StackSym: public Sym
  73. {
  74. private:
  75. static StackSym * New(SymID id, IRType type, Js::RegSlot byteCodeRegSlot, Func *func);
  76. public:
  77. static StackSym * NewArgSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType = TyVar);
  78. static StackSym * NewArgSlotRegSym(Js::ArgSlot argSlotNum, Func * func, IRType = TyVar);
  79. static StackSym * NewParamSlotSym(Js::ArgSlot argSlotNum, Func * func);
  80. static StackSym * NewParamSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType type);
  81. static StackSym *NewImplicitParamSym(Js::ArgSlot paramSlotNum, Func * func);
  82. static StackSym * New(IRType type, Func *func);
  83. static StackSym * New(Func *func);
  84. static StackSym * FindOrCreate(SymID id, Js::RegSlot byteCodeRegSlot, Func *func, IRType type = TyVar);
  85. IRType GetType() const { return this->m_type; }
  86. bool IsArgSlotSym() const;
  87. bool IsParamSlotSym() const;
  88. bool IsImplicitParamSym() const { return this->m_isImplicitParamSym; }
  89. bool IsAllocated() const;
  90. int32 GetIntConstValue() const;
  91. Js::Var GetFloatConstValueAsVar_PostGlobOpt() const;
  92. void * GetConstAddress(bool useLocal = false) const;
  93. StackSym * CloneDef(Func *func);
  94. StackSym * CloneUse(Func *func);
  95. void CopySymAttrs(StackSym *symSrc);
  96. bool IsSingleDef() const { return this->m_isSingleDef && this->m_instrDef; }
  97. bool IsConst() const;
  98. bool IsIntConst() const;
  99. bool IsInt64Const() const;
  100. bool IsTaggableIntConst() const;
  101. bool IsFloatConst() const;
  102. bool IsSimd128Const() const;
  103. void SetIsConst();
  104. void SetIsIntConst(IntConstType value);
  105. void SetIsInt64Const();
  106. void SetIsFloatConst();
  107. void SetIsSimd128Const();
  108. void SetIsStrConst();
  109. bool GetIsStrConst();
  110. intptr_t GetLiteralConstValue_PostGlobOpt() const;
  111. IR::Opnd * GetConstOpnd() const;
  112. BailoutConstantValue GetConstValueForBailout() const;
  113. bool IsSimd128() const { return IRType_IsSimd128(this->GetType()); }
  114. bool IsSimd128F4() const { return this->GetType() == TySimd128F4; }
  115. bool IsSimd128I4() const { return this->GetType() == TySimd128I4; }
  116. bool IsSimd128I8() const { return this->GetType() == TySimd128I8; }
  117. bool IsSimd128I16() const { return this->GetType() == TySimd128I16; }
  118. bool IsSimd128U4() const { return this->GetType() == TySimd128U4; }
  119. bool IsSimd128U8() const { return this->GetType() == TySimd128U8; }
  120. bool IsSimd128U16() const { return this->GetType() == TySimd128U16; }
  121. bool IsSimd128B4() const { return this->GetType() == TySimd128B4; }
  122. bool IsSimd128B8() const { return this->GetType() == TySimd128B8; }
  123. bool IsSimd128B16() const { return this->GetType() == TySimd128B16; }
  124. bool IsSimd128D2() const { return this->GetType() == TySimd128D2; }
  125. bool IsSimd128I2() const { return this->GetType() == TySimd128I2; }
  126. StackSym * GetFloat64EquivSym(Func *func);
  127. bool IsFloat64() const { return this->GetType() == TyFloat64; }
  128. bool IsFloat32() const { return this->GetType() == TyFloat32; }
  129. StackSym * GetInt32EquivSym(Func *func);
  130. bool IsInt32() const { return this->GetType() == TyInt32; }
  131. bool IsUInt32() const { return this->GetType() == TyUint32; }
  132. bool IsInt64() const { return this->GetType() == TyInt64; }
  133. bool IsUint64() const { return this->GetType() == TyUint64; }
  134. StackSym * GetVarEquivSym(Func *func);
  135. StackSym * GetVarEquivSym_NoCreate();
  136. StackSym const * GetVarEquivSym_NoCreate() const;
  137. bool IsVar() const { return this->GetType() == TyVar; }
  138. bool IsTypeSpec() const { return this->m_isTypeSpec; }
  139. static StackSym *GetVarEquivStackSym_NoCreate(Sym * sym);
  140. static StackSym const *GetVarEquivStackSym_NoCreate(Sym const * const sym);
  141. bool HasByteCodeRegSlot() const { return m_hasByteCodeRegSlot; }
  142. Func * GetByteCodeFunc() const;
  143. Js::RegSlot GetByteCodeRegSlot() const;
  144. bool IsTempReg(Func *const func) const;
  145. bool IsFromByteCodeConstantTable() const { return m_isFromByteCodeConstantTable; }
  146. void SetIsFromByteCodeConstantTable() { this->m_isFromByteCodeConstantTable = true; }
  147. Js::ArgSlot GetArgSlotNum() const { Assert(HasArgSlotNum()); return m_slotNum; }
  148. bool HasArgSlotNum() const { return !!(m_isArgSlotSym | m_isArgSlotRegSym); }
  149. void IncrementArgSlotNum();
  150. void DecrementArgSlotNum();
  151. Js::ArgSlot GetParamSlotNum() const { Assert(IsParamSlotSym()); return m_slotNum; }
  152. IR::Instr * GetInstrDef() const { return this->IsSingleDef() ? this->m_instrDef : nullptr; }
  153. bool HasObjectInfo() const { Assert(!IsTypeSpec()); return this->m_objectInfo != nullptr; };
  154. ObjectSymInfo * GetObjectInfo() const { Assert(this->m_objectInfo); return this->m_objectInfo; }
  155. void SetObjectInfo(ObjectSymInfo * value) { this->m_objectInfo = value; }
  156. ObjectSymInfo * EnsureObjectInfo(Func * func);
  157. bool HasObjectTypeSym() const { return HasObjectInfo() && GetObjectInfo()->m_typeSym; }
  158. StackSym * GetObjectTypeSym() const { Assert(HasObjectTypeSym()); return GetObjectInfo()->m_typeSym; }
  159. int GetSymSize(){ return TySize[m_type]; }
  160. void FixupStackOffset(Func * currentFunc);
  161. StackSym * EnsureAuxSlotPtrSym(Func * func);
  162. StackSym * GetAuxSlotPtrSym() const { return HasObjectInfo() ? GetObjectInfo()->m_auxSlotPtrSym : nullptr; }
  163. private:
  164. StackSym * GetTypeEquivSym(IRType type, Func *func);
  165. StackSym * GetTypeEquivSym_NoCreate(IRType type);
  166. StackSym const * GetTypeEquivSym_NoCreate(IRType type) const;
  167. #if DBG
  168. void VerifyConstFlags() const;
  169. #endif
  170. private:
  171. Js::ArgSlot m_slotNum;
  172. public:
  173. uint8 m_isSingleDef:1; // the symbol only has a single definition in the IR
  174. uint8 m_isNotNumber:1;
  175. uint8 m_isSafeThis : 1;
  176. uint8 m_isConst : 1; // single def and it is a constant
  177. uint8 m_isIntConst : 1; // a constant and it's value is an Int32
  178. uint8 m_isTaggableIntConst : 1; // a constant and it's value is taggable (Int31 in 32-bit, Int32 in x64)
  179. uint8 m_isEncodedConstant : 1; // the constant has
  180. uint8 m_isInt64Const: 1;
  181. uint8 m_isFltConst: 1;
  182. uint8 m_isSimd128Const : 1;
  183. uint8 m_isStrConst:1;
  184. uint8 m_isStrEmpty:1;
  185. uint8 m_allocated:1;
  186. uint8 m_hasByteCodeRegSlot:1;
  187. uint8 m_isInlinedArgSlot:1;
  188. uint8 m_isOrphanedArg :1;
  189. uint8 m_isTypeSpec:1;
  190. uint8 m_requiresBailOnNotNumber:1;
  191. uint8 m_isFromByteCodeConstantTable:1;
  192. uint8 m_mayNotBeTempLastUse:1;
  193. uint8 m_isArgSlotSym: 1; // When set this implies an argument stack slot with no lifetime for register allocation
  194. uint8 m_isArgSlotRegSym : 1;
  195. uint8 m_isParamSym : 1;
  196. uint8 m_isImplicitParamSym : 1;
  197. uint8 m_isBailOutReferenced: 1; // argument sym referenced by bailout
  198. uint8 m_isArgCaptured: 1; // True if there is a ByteCodeArgOutCapture for this symbol
  199. uint8 m_nonEscapingArgObjAlias : 1;
  200. uint8 m_isCatchObjectSym : 1; // a catch object sym (used while jitting loop bodies)
  201. uint8 m_isClosureSym : 1;
  202. IRType m_type;
  203. Js::BuiltinFunction m_builtInIndex;
  204. int32 m_offset;
  205. #ifdef _M_AMD64
  206. // Only for AsmJs on x64. Argument position for ArgSyms.
  207. int32 m_argPosition;
  208. #endif
  209. union
  210. {
  211. IR::Instr * m_instrDef; // m_isSingleDef
  212. size_t constantValue; // !m_isSingleDef && m_isEncodedConstant
  213. };
  214. StackSym * m_tempNumberSym;
  215. StackSym * m_equivNext;
  216. ObjectSymInfo * m_objectInfo;
  217. union {
  218. struct GlobOpt
  219. {
  220. int numCompoundedAddSubUses;
  221. } globOpt;
  222. struct LinearScan
  223. {
  224. Lifetime * lifetime;
  225. } linearScan;
  226. struct Peeps
  227. {
  228. RegNum reg;
  229. } peeps;
  230. }scratch;
  231. static const Js::ArgSlot InvalidSlot;
  232. };
  233. class ByteCodeStackSym : public StackSym
  234. {
  235. private:
  236. ByteCodeStackSym(Js::RegSlot byteCodeRegSlot, Func * byteCodeFunc)
  237. : byteCodeRegSlot(byteCodeRegSlot), byteCodeFunc(byteCodeFunc) {}
  238. Js::RegSlot byteCodeRegSlot;
  239. Func * byteCodeFunc;
  240. friend class StackSym;
  241. };
  242. ///---------------------------------------------------------------------------
  243. ///
  244. /// class PropertySym
  245. ///
  246. /// Used for field symbols. Property syms for a given objects are linked
  247. /// together.
  248. ///
  249. ///---------------------------------------------------------------------------
  250. enum PropertyKind : BYTE
  251. {
  252. PropertyKindData,
  253. PropertyKindSlots,
  254. PropertyKindLocalSlots,
  255. PropertyKindSlotArray,
  256. PropertyKindWriteGuard
  257. };
  258. class PropertySym: public Sym
  259. {
  260. friend class Sym;
  261. public:
  262. static PropertySym * New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
  263. static PropertySym * New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
  264. static PropertySym * Find(SymID stackSymID, int32 propertyId, Func *func);
  265. static PropertySym * FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func);
  266. Func *GetFunc() { return m_func; }
  267. bool HasPropertyIdIndex() { return m_propertyIdIndex != -1; }
  268. int32 GetPropertyIdIndex() { return m_propertyIdIndex; }
  269. bool HasInlineCacheIndex() { return m_inlineCacheIndex != -1; }
  270. int32 GetInlineCacheIndex() { return m_inlineCacheIndex; }
  271. bool HasObjectTypeSym() const { return this->m_stackSym->HasObjectTypeSym(); }
  272. bool HasWriteGuardSym() const { return this->m_writeGuardSym != nullptr; }
  273. StackSym * GetObjectTypeSym() const { return this->m_stackSym->GetObjectTypeSym(); }
  274. StackSym * GetAuxSlotPtrSym() const { return this->m_stackSym->GetAuxSlotPtrSym(); }
  275. StackSym * EnsureAuxSlotPtrSym(Func * func) { return this->m_stackSym->EnsureAuxSlotPtrSym(func); }
  276. public:
  277. PropertyKind m_fieldKind;
  278. int32 m_propertyId;
  279. StackSym * m_stackSym;
  280. BVSparse<JitArenaAllocator> *m_propertyEquivSet; // Bit vector of all propertySyms with same propertyId
  281. PropertySym * m_nextInStackSymList;
  282. PropertySym * m_writeGuardSym;
  283. Func * m_func;
  284. Func * m_loadInlineCacheFunc;
  285. uint m_loadInlineCacheIndex;
  286. private:
  287. uint32 m_propertyIdIndex;
  288. uint m_inlineCacheIndex;
  289. };