RecyclerSweep.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. #include "CommonMemoryPch.h"
  6. RecyclerSweepManager *
  7. RecyclerSweep::GetManager() const
  8. {
  9. return this->recyclerSweepManager;
  10. }
  11. bool
  12. RecyclerSweep::IsBackground() const
  13. {
  14. return GetManager()->IsBackground();
  15. }
  16. Recycler *
  17. RecyclerSweep::GetRecycler() const
  18. {
  19. return recycler;
  20. }
  21. void
  22. RecyclerSweep::BeginSweep(Recycler * recycler, RecyclerSweepManager * recyclerSweepManager, HeapInfo * heapInfo)
  23. {
  24. // RecyclerSweep may not be initialized till later in this function but
  25. // GCETW relies on the recycler pointer being correctly set up
  26. this->recycler = recycler;
  27. this->recyclerSweepManager = recyclerSweepManager;
  28. this->heapInfo = heapInfo;
  29. // We might still have block that has disposed but not put back into the allocable
  30. // heap block list yet, which happens if we finish disposing object during concurrent
  31. // reset mark and can't
  32. // modify the heap block lists
  33. // CONCURRENT-TODO: Consider doing it during FinishDisposeObjects to get these block
  34. // available sooner as well. We will still need it here as we only always get to
  35. // finish dispose before sweep.
  36. this->FlushPendingTransferDisposedObjects();
  37. #if ENABLE_CONCURRENT_GC
  38. // Take the small heap block new heap block list and store in RecyclerSweep temporary
  39. // We get merge later before we start sweeping the bucket.
  40. leafData.pendingMergeNewHeapBlockList = heapInfo->newLeafHeapBlockList;
  41. normalData.pendingMergeNewHeapBlockList = heapInfo->newNormalHeapBlockList;
  42. #ifdef RECYCLER_WRITE_BARRIER
  43. withBarrierData.pendingMergeNewHeapBlockList = heapInfo->newNormalWithBarrierHeapBlockList;
  44. finalizableWithBarrierData.pendingMergeNewHeapBlockList = heapInfo->newFinalizableWithBarrierHeapBlockList;
  45. #endif
  46. finalizableData.pendingMergeNewHeapBlockList = heapInfo->newFinalizableHeapBlockList;
  47. #ifdef RECYCLER_VISITED_HOST
  48. recyclerVisitedHostData.pendingMergeNewHeapBlockList = heapInfo->newRecyclerVisitedHostHeapBlockList;
  49. #endif
  50. mediumLeafData.pendingMergeNewHeapBlockList = heapInfo->newMediumLeafHeapBlockList;
  51. mediumNormalData.pendingMergeNewHeapBlockList = heapInfo->newMediumNormalHeapBlockList;
  52. #ifdef RECYCLER_WRITE_BARRIER
  53. mediumWithBarrierData.pendingMergeNewHeapBlockList = heapInfo->newMediumNormalWithBarrierHeapBlockList;
  54. mediumFinalizableWithBarrierData.pendingMergeNewHeapBlockList = heapInfo->newMediumFinalizableWithBarrierHeapBlockList;
  55. #endif
  56. mediumFinalizableData.pendingMergeNewHeapBlockList = heapInfo->newMediumFinalizableHeapBlockList;
  57. #ifdef RECYCLER_VISITED_HOST
  58. mediumRecyclerVisitedHostData.pendingMergeNewHeapBlockList = heapInfo->newMediumRecyclerVisitedHostHeapBlockList;
  59. #endif
  60. heapInfo->newLeafHeapBlockList = nullptr;
  61. heapInfo->newNormalHeapBlockList = nullptr;
  62. heapInfo->newFinalizableHeapBlockList = nullptr;
  63. #ifdef RECYCLER_VISITED_HOST
  64. heapInfo->newRecyclerVisitedHostHeapBlockList = nullptr;
  65. #endif
  66. #ifdef RECYCLER_WRITE_BARRIER
  67. heapInfo->newNormalWithBarrierHeapBlockList = nullptr;
  68. heapInfo->newFinalizableWithBarrierHeapBlockList = nullptr;
  69. #endif
  70. heapInfo->newMediumLeafHeapBlockList = nullptr;
  71. heapInfo->newMediumNormalHeapBlockList = nullptr;
  72. heapInfo->newMediumFinalizableHeapBlockList = nullptr;
  73. #ifdef RECYCLER_VISITED_HOST
  74. heapInfo->newMediumRecyclerVisitedHostHeapBlockList = nullptr;
  75. #endif
  76. #ifdef RECYCLER_WRITE_BARRIER
  77. heapInfo->newMediumNormalWithBarrierHeapBlockList = nullptr;
  78. heapInfo->newMediumFinalizableWithBarrierHeapBlockList = nullptr;
  79. #endif
  80. #endif
  81. }
  82. void
  83. RecyclerSweep::ShutdownCleanup()
  84. {
  85. // REVIEW: Does this need to be controlled more granularly, say with ENABLE_PARTIAL_GC?
  86. #if ENABLE_CONCURRENT_GC
  87. SmallLeafHeapBucketT<SmallAllocationBlockAttributes>::DeleteHeapBlockList(this->leafData.pendingMergeNewHeapBlockList, recycler);
  88. SmallNormalHeapBucket::DeleteHeapBlockList(this->normalData.pendingMergeNewHeapBlockList, recycler);
  89. #ifdef RECYCLER_WRITE_BARRIER
  90. SmallNormalWithBarrierHeapBucket::DeleteHeapBlockList(this->withBarrierData.pendingMergeNewHeapBlockList, recycler);
  91. SmallFinalizableWithBarrierHeapBucket::DeleteHeapBlockList(this->finalizableWithBarrierData.pendingMergeNewHeapBlockList, recycler);
  92. #endif
  93. SmallFinalizableHeapBucket::DeleteHeapBlockList(this->finalizableData.pendingMergeNewHeapBlockList, recycler);
  94. for (uint i = 0; i < HeapConstants::BucketCount; i++)
  95. {
  96. // For leaf, we can always reuse the page as we don't need to rescan them for partial GC
  97. // It should have been swept immediately during Sweep
  98. Assert(this->leafData.bucketData[i].pendingSweepList == nullptr);
  99. SmallNormalHeapBucket::DeleteHeapBlockList(this->normalData.bucketData[i].pendingSweepList, recycler);
  100. SmallFinalizableHeapBucket::DeleteHeapBlockList(this->finalizableData.bucketData[i].pendingSweepList, recycler);
  101. #ifdef RECYCLER_WRITE_BARRIER
  102. SmallFinalizableWithBarrierHeapBucket::DeleteHeapBlockList(this->finalizableWithBarrierData.bucketData[i].pendingSweepList, recycler);
  103. #endif
  104. SmallLeafHeapBucket::DeleteEmptyHeapBlockList(this->leafData.bucketData[i].pendingEmptyBlockList);
  105. SmallNormalHeapBucket::DeleteEmptyHeapBlockList(this->normalData.bucketData[i].pendingEmptyBlockList);
  106. #ifdef RECYCLER_WRITE_BARRIER
  107. SmallNormalWithBarrierHeapBucket::DeleteEmptyHeapBlockList(this->withBarrierData.bucketData[i].pendingEmptyBlockList);
  108. Assert(this->finalizableWithBarrierData.bucketData[i].pendingEmptyBlockList == nullptr);
  109. #endif
  110. Assert(this->finalizableData.bucketData[i].pendingEmptyBlockList == nullptr);
  111. }
  112. MediumLeafHeapBucket::DeleteHeapBlockList(this->mediumLeafData.pendingMergeNewHeapBlockList, recycler);
  113. MediumNormalHeapBucket::DeleteHeapBlockList(this->mediumNormalData.pendingMergeNewHeapBlockList, recycler);
  114. #ifdef RECYCLER_WRITE_BARRIER
  115. MediumNormalWithBarrierHeapBucket::DeleteHeapBlockList(this->mediumWithBarrierData.pendingMergeNewHeapBlockList, recycler);
  116. MediumFinalizableWithBarrierHeapBucket::DeleteHeapBlockList(this->mediumFinalizableWithBarrierData.pendingMergeNewHeapBlockList, recycler);
  117. #endif
  118. MediumFinalizableHeapBucket::DeleteHeapBlockList(this->mediumFinalizableData.pendingMergeNewHeapBlockList, recycler);
  119. for (uint i = 0; i < HeapConstants::MediumBucketCount; i++)
  120. {
  121. // For leaf, we can always reuse the page as we don't need to rescan them for partial GC
  122. // It should have been swept immediately during Sweep
  123. Assert(this->mediumLeafData.bucketData[i].pendingSweepList == nullptr);
  124. MediumNormalHeapBucket::DeleteHeapBlockList(this->mediumNormalData.bucketData[i].pendingSweepList, recycler);
  125. MediumFinalizableHeapBucket::DeleteHeapBlockList(this->mediumFinalizableData.bucketData[i].pendingSweepList, recycler);
  126. #ifdef RECYCLER_WRITE_BARRIER
  127. MediumFinalizableWithBarrierHeapBucket::DeleteHeapBlockList(this->mediumFinalizableWithBarrierData.bucketData[i].pendingSweepList, recycler);
  128. #endif
  129. MediumLeafHeapBucket::DeleteEmptyHeapBlockList(this->mediumLeafData.bucketData[i].pendingEmptyBlockList);
  130. MediumNormalHeapBucket::DeleteEmptyHeapBlockList(this->mediumNormalData.bucketData[i].pendingEmptyBlockList);
  131. #ifdef RECYCLER_WRITE_BARRIER
  132. MediumNormalWithBarrierHeapBucket::DeleteEmptyHeapBlockList(this->mediumWithBarrierData.bucketData[i].pendingEmptyBlockList);
  133. Assert(this->mediumFinalizableWithBarrierData.bucketData[i].pendingEmptyBlockList == nullptr);
  134. #endif
  135. Assert(this->mediumFinalizableData.bucketData[i].pendingEmptyBlockList == nullptr);
  136. }
  137. #endif
  138. }
  139. void
  140. RecyclerSweep::FlushPendingTransferDisposedObjects()
  141. {
  142. if (this->heapInfo->hasPendingTransferDisposedObjects)
  143. {
  144. Assert(!recycler->inDispose);
  145. Assert(!recycler->hasDisposableObject);
  146. heapInfo->TransferDisposedObjects();
  147. }
  148. }
  149. #if ENABLE_CONCURRENT_GC
  150. template <typename TBlockType>
  151. void
  152. RecyclerSweep::MergePendingNewHeapBlockList()
  153. {
  154. TBlockType *& blockList = this->GetData<TBlockType>().pendingMergeNewHeapBlockList;
  155. TBlockType * list = blockList;
  156. blockList = nullptr;
  157. HeapBlockList::ForEachEditing(list, [this](TBlockType * heapBlock)
  158. {
  159. auto& bucket = this->heapInfo->GetBucket<TBlockType::RequiredAttributes>(heapBlock->GetObjectSize());
  160. bucket.MergeNewHeapBlock(heapBlock);
  161. });
  162. }
  163. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallLeafHeapBlock>();
  164. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallNormalHeapBlock>();
  165. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallFinalizableHeapBlock>();
  166. #ifdef RECYCLER_VISITED_HOST
  167. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallRecyclerVisitedHostHeapBlock>();
  168. #endif
  169. #ifdef RECYCLER_WRITE_BARRIER
  170. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallNormalWithBarrierHeapBlock>();
  171. template void RecyclerSweep::MergePendingNewHeapBlockList<SmallFinalizableWithBarrierHeapBlock>();
  172. #endif
  173. template <typename TBlockType>
  174. void
  175. RecyclerSweep::MergePendingNewMediumHeapBlockList()
  176. {
  177. TBlockType *& blockList = this->GetData<TBlockType>().pendingMergeNewHeapBlockList;
  178. TBlockType * list = blockList;
  179. blockList = nullptr;
  180. HeapBlockList::ForEachEditing(list, [this](TBlockType * heapBlock)
  181. {
  182. auto& bucket = this->heapInfo->GetMediumBucket<TBlockType::RequiredAttributes>(heapBlock->GetObjectSize());
  183. bucket.MergeNewHeapBlock(heapBlock);
  184. });
  185. }
  186. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumLeafHeapBlock>();
  187. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumNormalHeapBlock>();
  188. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumFinalizableHeapBlock>();
  189. #ifdef RECYCLER_VISITED_HOST
  190. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumRecyclerVisitedHostHeapBlock>();
  191. #endif
  192. #ifdef RECYCLER_WRITE_BARRIER
  193. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumNormalWithBarrierHeapBlock>();
  194. template void RecyclerSweep::MergePendingNewMediumHeapBlockList<MediumFinalizableWithBarrierHeapBlock>();
  195. #endif
  196. bool
  197. RecyclerSweep::HasPendingEmptyBlocks() const
  198. {
  199. return this->hasPendingEmptyBlocks;
  200. }
  201. bool
  202. RecyclerSweep::HasPendingSweepSmallHeapBlocks() const
  203. {
  204. return this->hasPendingSweepSmallHeapBlocks;
  205. }
  206. void
  207. RecyclerSweep::SetHasPendingSweepSmallHeapBlocks()
  208. {
  209. this->hasPendingSweepSmallHeapBlocks = true;
  210. }
  211. #if DBG
  212. bool
  213. RecyclerSweep::HasPendingNewHeapBlocks() const
  214. {
  215. return leafData.pendingMergeNewHeapBlockList != nullptr
  216. || normalData.pendingMergeNewHeapBlockList != nullptr
  217. || finalizableData.pendingMergeNewHeapBlockList != nullptr
  218. #ifdef RECYCLER_WRITE_BARRIER
  219. || withBarrierData.pendingMergeNewHeapBlockList != nullptr
  220. || finalizableWithBarrierData.pendingMergeNewHeapBlockList != nullptr
  221. #endif
  222. || mediumLeafData.pendingMergeNewHeapBlockList != nullptr
  223. || mediumNormalData.pendingMergeNewHeapBlockList != nullptr
  224. || mediumFinalizableData.pendingMergeNewHeapBlockList != nullptr
  225. #ifdef RECYCLER_WRITE_BARRIER
  226. || mediumWithBarrierData.pendingMergeNewHeapBlockList != nullptr
  227. || mediumFinalizableWithBarrierData.pendingMergeNewHeapBlockList != nullptr
  228. #endif
  229. ;
  230. }
  231. #endif
  232. #if DBG || defined(RECYCLER_SLOW_CHECK_ENABLED)
  233. size_t
  234. RecyclerSweep::GetPendingMergeNewHeapBlockCount(HeapInfo const * heapInfo)
  235. {
  236. if (this->heapInfo != heapInfo)
  237. {
  238. return 0;
  239. }
  240. return HeapBlockList::Count(leafData.pendingMergeNewHeapBlockList)
  241. + HeapBlockList::Count(normalData.pendingMergeNewHeapBlockList)
  242. + HeapBlockList::Count(finalizableData.pendingMergeNewHeapBlockList)
  243. #ifdef RECYCLER_VISITED_HOST
  244. + HeapBlockList::Count(recyclerVisitedHostData.pendingMergeNewHeapBlockList)
  245. + HeapBlockList::Count(mediumRecyclerVisitedHostData.pendingMergeNewHeapBlockList)
  246. #endif
  247. #ifdef RECYCLER_WRITE_BARRIER
  248. + HeapBlockList::Count(withBarrierData.pendingMergeNewHeapBlockList)
  249. + HeapBlockList::Count(finalizableWithBarrierData.pendingMergeNewHeapBlockList)
  250. #endif
  251. + HeapBlockList::Count(mediumLeafData.pendingMergeNewHeapBlockList)
  252. + HeapBlockList::Count(mediumNormalData.pendingMergeNewHeapBlockList)
  253. + HeapBlockList::Count(mediumFinalizableData.pendingMergeNewHeapBlockList)
  254. #ifdef RECYCLER_WRITE_BARRIER
  255. + HeapBlockList::Count(mediumWithBarrierData.pendingMergeNewHeapBlockList)
  256. + HeapBlockList::Count(mediumFinalizableWithBarrierData.pendingMergeNewHeapBlockList)
  257. #endif
  258. ;
  259. }
  260. #endif
  261. #endif
  262. #if ENABLE_PARTIAL_GC
  263. bool
  264. RecyclerSweep::InPartialCollectMode() const
  265. {
  266. return GetRecycler()->inPartialCollectMode;
  267. }
  268. bool
  269. RecyclerSweep::InPartialCollect() const
  270. {
  271. return GetManager()->InPartialCollect();
  272. }
  273. #endif