TempTracker.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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(char16 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 DisallowMarkTempAcrossYield(BVSparse<JitArenaAllocator>* bytecodeUpwardExposed);
  43. void ProcessUse(StackSym * sym, BackwardPass * backwardPass);
  44. void MarkTemp(StackSym * sym, BackwardPass * backwardPass);
  45. #if DBG
  46. void Dump() { __super::Dump(T::GetTraceName()); }
  47. #endif
  48. };
  49. class NumberTemp : public TempTrackerBase
  50. {
  51. public:
  52. void ProcessInstr(IR::Instr * instr, BackwardPass * backwardPass);
  53. void ProcessPropertySymUse(IR::SymOpnd * symOpnd, IR::Instr * instr, BackwardPass * backwardPass);
  54. void ProcessIndirUse(IR::IndirOpnd * indirOpnd, IR::Instr * instr, BackwardPass * backwardPass);
  55. protected:
  56. NumberTemp(JitArenaAllocator * alloc, bool inLoop);
  57. // Overrides of the base class for extra data merging
  58. void MergeData(NumberTemp * fromData, bool deleteData);
  59. // Function used by the TempTracker
  60. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  61. static bool IsTempTransfer(IR::Instr * instr);
  62. bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  63. static void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  64. static bool IsTempProducing(IR::Instr * instr);
  65. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass);
  66. // Support for property transfer, so we can stack allocate number if it is assigned to another stack allocated object
  67. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass);
  68. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass);
  69. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass);
  70. SymID GetRepresentativePropertySymId(PropertySym * propertySym, BackwardPass * backwardPass);
  71. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass);
  72. bool IsInLoop() const { return propertyIdsTempTransferDependencies != nullptr; }
  73. bool DoMarkTempNumbersOnTempObjects(BackwardPass * backwardPass) const;
  74. #if DBG_DUMP
  75. static bool DoTrace(BackwardPass * backwardPass);
  76. static char16 const * GetTraceName() { return _u("MarkTempNumber"); }
  77. void Dump(char16 const * traceName);
  78. #endif
  79. // true if we have a LdElem_A from stack object that has non temp uses.
  80. bool nonTempElemLoad;
  81. // all the uses of values coming from LdElem_A, needed to detect dependencies on value set on stack objects
  82. BVSparse<JitArenaAllocator> elemLoadDependencies;
  83. // Per properties dependencies of Ld*Fld
  84. HashTable<BVSparse<JitArenaAllocator> *> * propertyIdsTempTransferDependencies;
  85. // Trace upward exposed mark temp object fields to answer
  86. // whether if there is any field value is still live on the next iteration
  87. HashTable<BVSparse<JitArenaAllocator> * > * upwardExposedMarkTempObjectSymsProperties;
  88. BVSparse<JitArenaAllocator> upwardExposedMarkTempObjectLiveFields;
  89. };
  90. typedef TempTracker<NumberTemp> TempNumberTracker;
  91. class ObjectTemp : public TempTrackerBase
  92. {
  93. public:
  94. static bool CanStoreTemp(IR::Instr * instr);
  95. static void ProcessInstr(IR::Instr * instr);
  96. void ProcessBailOnNoProfile(IR::Instr * instr);
  97. // Used internally and by Globopt::GenerateBailOutMarkTempObjectIfNeeded
  98. static StackSym * GetStackSym(IR::Opnd * opnd, IR::PropertySymOpnd ** pPropertySymOpnd);
  99. protected:
  100. // Place holder functions, only implemented for ObjectTempVerify
  101. ObjectTemp(JitArenaAllocator * alloc, bool inLoop) : TempTrackerBase(alloc, inLoop) { /* Do nothing */ }
  102. // Function used by the TempTracker
  103. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  104. static bool IsTempTransfer(IR::Instr * instr);
  105. static bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  106. static void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  107. // Object tracker doesn't support property transfer
  108. // (So we don't stack allocate object if it is assigned to another stack allocated object)
  109. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  110. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  111. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass) { Assert(false); }
  112. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  113. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass) { return false; }
  114. #if DBG_DUMP
  115. static bool DoTrace(BackwardPass * backwardPass);
  116. static char16 const * GetTraceName() { return _u("MarkTempObject"); }
  117. #endif
  118. private:
  119. static bool IsTempProducing(IR::Instr * instr);
  120. static bool IsTempUseOpCodeSym(IR::Instr * instr, Js::OpCode opcode, Sym * sym);
  121. friend class NumberTemp;
  122. #if DBG
  123. friend class ObjectTempVerify;
  124. #endif
  125. };
  126. typedef TempTracker<ObjectTemp> TempObjectTracker;
  127. #if DBG
  128. class ObjectTempVerify : public TempTrackerBase
  129. {
  130. friend class GlobOpt;
  131. public:
  132. void ProcessInstr(IR::Instr * instr, BackwardPass * backwardPass);
  133. void NotifyBailOutRemoval(IR:: Instr * instr, BackwardPass * backwardPass);
  134. void NotifyDeadStore(IR::Instr * instr, BackwardPass * backwardPass);
  135. void NotifyDeadByteCodeUses(IR::Instr * instr);
  136. void NotifyReverseCopyProp(IR::Instr * instr);
  137. void MergeDeadData(BasicBlock * block);
  138. static bool DependencyCheck(IR::Instr *instr, BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass);
  139. protected:
  140. ObjectTempVerify(JitArenaAllocator * alloc, bool inLoop);
  141. void MergeData(ObjectTempVerify * fromData, bool deleteData);
  142. // Function used by the TempTracker
  143. static bool IsTempUse(IR::Instr * instr, Sym * sym, BackwardPass * backwardPass);
  144. static bool IsTempTransfer(IR::Instr * instr);
  145. static bool CanMarkTemp(IR::Instr * instr, BackwardPass * backwardPass);
  146. void SetDstIsTemp(bool dstIsTemp, bool dstIsTempTransferred, IR::Instr * instr, BackwardPass * backwardPass);
  147. // Object tracker doesn't support property transfer
  148. // (So we don't stack allocate object if it is assigned to another stack allocated object)
  149. bool IsTempPropertyTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  150. bool IsTempPropertyTransferStore(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  151. void PropagateTempPropertyTransferStoreDependencies(SymID usedSymID, PropertySym * propertySym, BackwardPass * backwardPass) { Assert(false); }
  152. bool IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPass) { return false; }
  153. bool HasExposedFieldDependencies(BVSparse<JitArenaAllocator> * bvTempTransferDependencies, BackwardPass * backwardPass) { return false; }
  154. static bool DoTrace(BackwardPass * backwardPass);
  155. static char16 const * GetTraceName() { return _u("MarkTempObjectVerify"); }
  156. private:
  157. BVSparse<JitArenaAllocator> removedUpwardExposedUse;
  158. };
  159. template <typename T> bool IsObjectTempVerify() { return false; }
  160. template <> inline bool IsObjectTempVerify<ObjectTempVerify>() { return true; }
  161. typedef TempTracker<ObjectTempVerify> TempObjectVerifyTracker;
  162. #endif