TempTracker.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. // Base class for TempTrackers. Contain the basic data and merge logic
  7. class TempTrackerBase
  8. {
  9. public:
  10. #if DBG
  11. bool HasTempTransferDependencies() const { return tempTransferDependencies != nullptr; }
  12. #endif
  13. protected:
  14. TempTrackerBase(JitArenaAllocator * alloc, bool inLoop);
  15. ~TempTrackerBase();
  16. void MergeData(TempTrackerBase * fromData, bool deleteData);
  17. void MergeDependencies(HashTable<BVSparse<JitArenaAllocator> *> * toData, HashTable<BVSparse<JitArenaAllocator> *> *& fromData, bool deleteData);
  18. void AddTransferDependencies(int sourceId, SymID dstSymId, HashTable<BVSparse<JitArenaAllocator> *> * dependencies);
  19. void AddTransferDependencies(BVSparse<JitArenaAllocator> * bv, SymID dstSymID);
  20. void OrHashTableOfBitVector(HashTable<BVSparse<JitArenaAllocator> *> * toData, HashTable<BVSparse<JitArenaAllocator> *> *& fromData, bool deleteData);
  21. JitArenaAllocator * GetAllocator() const;
  22. BVSparse<JitArenaAllocator> nonTempSyms;
  23. BVSparse<JitArenaAllocator> tempTransferredSyms;
  24. HashTable<BVSparse<JitArenaAllocator> *> * tempTransferDependencies;
  25. #if DBG
  26. void Dump(wchar_t const * traceName);
  27. #endif
  28. };
  29. // Actual temp tracker class, with a template plug-in model to determine what kind of temp we want to track
  30. // (Number or Object)
  31. template <typename T>
  32. class TempTracker : public T
  33. {
  34. #if DBG
  35. friend class ObjectTempVerify;
  36. #endif
  37. public:
  38. TempTracker(JitArenaAllocator * alloc, bool inLoop);
  39. void MergeData(TempTracker<T> * fromData, bool deleteData);
  40. // Actual mark temp algorithm that are shared, but have different condition based
  41. // on the type of tracker as the template parameter
  42. void ProcessUse(StackSym * sym, BackwardPass * backwardPass);
  43. void MarkTemp(StackSym * sym, BackwardPass * backwardPass);
  44. #if DBG
  45. void Dump() { __super::Dump(T::GetTraceName()); }
  46. #endif
  47. };
  48. class NumberTemp : public TempTrackerBase
  49. {
  50. public:
  51. void ProcessInstr(IR::Instr * instr, BackwardPass * backwardPass);
  52. void ProcessPropertySymUse(IR::SymOpnd * symOpnd, IR::Instr * instr, BackwardPass * backwardPass);
  53. void ProcessIndirUse(IR::IndirOpnd * indirOpnd, IR::Instr * instr, BackwardPass * backwardPass);
  54. protected:
  55. NumberTemp(JitArenaAllocator * alloc, bool inLoop);
  56. // Overrides of the base class for extra data merging
  57. void MergeData(NumberTemp * fromData, bool deleteData);
  58. // Function used by the TempTracker
  59. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  60. static bool IsTempTransfer(IR::Instr * instr);
  61. bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  62. static void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  63. static bool IsTempProducing(IR::Instr * instr);
  64. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass);
  65. // Support for property transfer, so we can stack allocate number if it is assigned to another stack allocated object
  66. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass);
  67. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass);
  68. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass);
  69. SymID GetRepresentativePropertySymId(PropertySym * propertySym, BackwardPass * backwardPass);
  70. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass);
  71. bool IsInLoop() const { return propertyIdsTempTransferDependencies != nullptr; }
  72. bool DoMarkTempNumbersOnTempObjects(BackwardPass * backwardPass) const;
  73. #if DBG_DUMP
  74. static bool DoTrace(BackwardPass * backwardPass);
  75. static wchar_t const * GetTraceName() { return L"MarkTempNumber"; }
  76. void Dump(wchar_t const * traceName);
  77. #endif
  78. // true if we have a LdElem_A from stack object that has non temp uses.
  79. bool nonTempElemLoad;
  80. // all the uses of values coming from LdElem_A, needed to detect dependencies on value set on stack objects
  81. BVSparse<JitArenaAllocator> elemLoadDependencies;
  82. // Per properties dependencies of Ld*Fld
  83. HashTable<BVSparse<JitArenaAllocator> *> * propertyIdsTempTransferDependencies;
  84. // Trace upward exposed mark temp object fields to answer
  85. // whether if there is any field value is still live on the next iteration
  86. HashTable<BVSparse<JitArenaAllocator> * > * upwardExposedMarkTempObjectSymsProperties;
  87. BVSparse<JitArenaAllocator> upwardExposedMarkTempObjectLiveFields;
  88. };
  89. typedef TempTracker<NumberTemp> TempNumberTracker;
  90. class ObjectTemp : public TempTrackerBase
  91. {
  92. public:
  93. static bool CanStoreTemp(IR::Instr * instr);
  94. static void ProcessInstr(IR::Instr * instr);
  95. void ProcessBailOnNoProfile(IR::Instr * instr);
  96. // Used internally and by Globopt::GenerateBailOutMarkTempObjectIfNeeded
  97. static StackSym * GetStackSym(IR::Opnd * opnd, IR::PropertySymOpnd ** pPropertySymOpnd);
  98. protected:
  99. // Place holder functions, only implemented for ObjectTempVerify
  100. ObjectTemp(JitArenaAllocator * alloc, bool inLoop) : TempTrackerBase(alloc, inLoop) { /* Do nothing */ }
  101. // Function used by the TempTracker
  102. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  103. static bool IsTempTransfer(IR::Instr * instr);
  104. static bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  105. static void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  106. // Object tracker doesn't support property transfer
  107. // (So we don't stack allocate object if it is assigned to another stack allocated object)
  108. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  109. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  110. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass) { Assert(false); }
  111. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  112. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass) { return false; }
  113. #if DBG_DUMP
  114. static bool DoTrace(BackwardPass * backwardPass);
  115. static wchar_t const * GetTraceName() { return L"MarkTempObject"; }
  116. #endif
  117. private:
  118. static bool IsTempProducing(IR::Instr * instr);
  119. static bool IsTempUseOpCodeSym(IR::Instr * instr, Js::OpCode opcode, Sym * sym);
  120. friend class NumberTemp;
  121. #if DBG
  122. friend class ObjectTempVerify;
  123. #endif
  124. };
  125. typedef TempTracker<ObjectTemp> TempObjectTracker;
  126. #if DBG
  127. class ObjectTempVerify : public TempTrackerBase
  128. {
  129. friend class GlobOpt;
  130. public:
  131. void ProcessInstr(IR::Instr * instr, BackwardPass * backwardPass);
  132. void NotifyBailOutRemoval(IR:: Instr * instr, BackwardPass * backwardPass);
  133. void NotifyDeadStore(IR::Instr * instr, BackwardPass * backwardPass);
  134. void NotifyDeadByteCodeUses(IR::Instr * instr);
  135. void NotifyReverseCopyProp(IR::Instr * instr);
  136. void MergeDeadData(BasicBlock * block);
  137. static bool DependencyCheck(IR::Instr *instr, BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass);
  138. protected:
  139. ObjectTempVerify(JitArenaAllocator * alloc, bool inLoop);
  140. void MergeData(ObjectTempVerify * fromData, bool deleteData);
  141. // Function used by the TempTracker
  142. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  143. static bool IsTempTransfer(IR::Instr * instr);
  144. static bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  145. void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  146. // Object tracker doesn't support property transfer
  147. // (So we don't stack allocate object if it is assigned to another stack allocated object)
  148. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  149. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  150. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass) { Assert(false); }
  151. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  152. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass) { return false; }
  153. static bool DoTrace(BackwardPass * backwardPass);
  154. static wchar_t const * GetTraceName() { return L"MarkTempObjectVerify"; }
  155. private:
  156. BVSparse<JitArenaAllocator> removedUpwardExposedUse;
  157. };
  158. template <typename T> bool IsObjectTempVerify() { return false; }
  159. template <> inline bool IsObjectTempVerify<ObjectTempVerify>() { return true; }
  160. typedef TempTracker<ObjectTempVerify> TempObjectVerifyTracker;
  161. #endif