PageRenderTime 105ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/MicroFrameworkPK_v4_1/CLR/Core/GarbageCollector_Compaction.cpp

https://bitbucket.org/pmfsampaio/netmf-lpc
C++ | 448 lines | 305 code | 108 blank | 35 comment | 47 complexity | 49f92928abbfa4def575d766b6b2253c MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4. #include "Core.h"
  5. ////////////////////////////////////////////////////////////////////////////////////////////////////
  6. CLR_UINT32 CLR_RT_GarbageCollector::ExecuteCompaction()
  7. {
  8. NATIVE_PROFILE_CLR_CORE();
  9. #if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS)
  10. g_CLR_PRF_Profiler.RecordHeapCompactionBegin();
  11. #endif
  12. ////////////////////////////////////////////////////////////////////////////////////////////////
  13. CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend();
  14. Heap_Compact();
  15. CLR_RT_ExecutionEngine::ExecutionConstraint_Resume();
  16. m_numberOfCompactions++;
  17. ////////////////////////////////////////////////////////////////////////////////////////////////
  18. #if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS)
  19. g_CLR_PRF_Profiler.RecordHeapCompactionEnd();
  20. #endif
  21. return 0;
  22. }
  23. ////////////////////////////////////////////////////////////////////////////////
  24. void CLR_RT_GarbageCollector::Heap_Compact()
  25. {
  26. NATIVE_PROFILE_CLR_CORE();
  27. ValidatePointers();
  28. //--//
  29. RelocationRegion relocHelper[ c_minimumSpaceForCompact ];
  30. const size_t relocMax = ARRAYSIZE(relocHelper);
  31. Heap_Relocate_Prepare( relocHelper, relocMax );
  32. RelocationRegion* relocBlocks = relocHelper;
  33. RelocationRegion* relocCurrent = relocBlocks;
  34. //--//
  35. TestPointers_PopulateOld();
  36. CLR_RT_HeapCluster* freeRegion_hc = NULL;;
  37. CLR_RT_HeapBlock_Node* freeRegion = NULL;
  38. CLR_RT_HeapCluster* currentSource_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode();
  39. while(currentSource_hc->Next())
  40. {
  41. CLR_RT_HeapBlock_Node* currentSource = currentSource_hc->m_payloadStart;
  42. CLR_RT_HeapBlock_Node* currentSource_end = currentSource_hc->m_payloadEnd;
  43. if(!freeRegion)
  44. {
  45. //
  46. // Move to the next first free region.
  47. //
  48. freeRegion_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode();
  49. while(true)
  50. {
  51. CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break;
  52. freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break;
  53. freeRegion = NULL;
  54. freeRegion_hc = freeRegion_hcNext;
  55. }
  56. if(!freeRegion) break;
  57. }
  58. while(true)
  59. {
  60. //
  61. // We can only move backward.
  62. //
  63. if(currentSource < freeRegion)
  64. {
  65. currentSource_hc = freeRegion_hc;
  66. currentSource = freeRegion;
  67. currentSource_end = freeRegion_hc->m_payloadEnd;
  68. }
  69. while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ))
  70. {
  71. currentSource += currentSource->DataSize();
  72. }
  73. if(currentSource == currentSource_end) break;
  74. //////////////////////////////////////////////////////
  75. //
  76. // At this point, we have at least ONE movable block.
  77. //
  78. //////////////////////////////////////////////////////
  79. #if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_4_CompactionPlus
  80. if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, freeRegion, true ) == false)
  81. {
  82. CLR_Debug::Printf( "'freeRegion' is not in a free list!! %08x\r\n", freeRegion );
  83. TINYCLR_DEBUG_STOP();
  84. }
  85. if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, currentSource, false ))
  86. {
  87. CLR_Debug::Printf( "'currentSource' is in a free list!! %08x\r\n", currentSource );
  88. TINYCLR_DEBUG_STOP();
  89. }
  90. #endif
  91. if(m_relocCount >= relocMax)
  92. {
  93. ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap );
  94. Heap_Relocate();
  95. ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap );
  96. relocBlocks = m_relocBlocks;
  97. relocCurrent = relocBlocks;
  98. TestPointers_PopulateOld();
  99. }
  100. {
  101. CLR_UINT32 move = 0;
  102. CLR_UINT32 freeRegion_Size = freeRegion->DataSize();
  103. bool fSlide;
  104. relocCurrent->m_destination = (CLR_UINT8*)freeRegion;
  105. relocCurrent->m_start = (CLR_UINT8*)currentSource;
  106. relocCurrent->m_offset = (CLR_UINT32)(relocCurrent->m_destination - relocCurrent->m_start);
  107. //
  108. // Are the free block and the last moved block adjacent?
  109. //
  110. if(currentSource == freeRegion + freeRegion_Size)
  111. {
  112. while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false)
  113. {
  114. CLR_UINT32 len = currentSource->DataSize();
  115. currentSource += len;
  116. move += len;
  117. }
  118. fSlide = true;
  119. }
  120. else
  121. {
  122. while(freeRegion_Size && currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false)
  123. {
  124. CLR_UINT32 len = currentSource->DataSize();
  125. if(freeRegion_Size < len)
  126. {
  127. break;
  128. }
  129. freeRegion_Size -= len;
  130. currentSource += len;
  131. move += len;
  132. }
  133. fSlide = false;
  134. }
  135. if(move)
  136. {
  137. //
  138. // Skip forward to the next movable block.
  139. //
  140. while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ))
  141. {
  142. currentSource += currentSource->DataSize();
  143. }
  144. CLR_UINT32 moveBytes = move * sizeof(*currentSource);
  145. relocCurrent->m_end = relocCurrent->m_start + moveBytes;
  146. //--//
  147. //
  148. // Remove the old free block, copy the data, recreate the new free block.
  149. // Merge with the following one if they are adjacent now.
  150. //
  151. CLR_RT_HeapBlock_Node* freeRegionNext = freeRegion->Next();
  152. freeRegion->Unlink();
  153. memmove( relocCurrent->m_destination, relocCurrent->m_start, moveBytes );
  154. if(freeRegion_Size)
  155. {
  156. freeRegion = freeRegion_hc->InsertInOrder( freeRegion + move, freeRegion_Size );
  157. }
  158. else
  159. {
  160. freeRegion = freeRegionNext;
  161. }
  162. if(fSlide == false)
  163. {
  164. CLR_RT_HeapBlock_Node* dst = currentSource_hc->InsertInOrder( (CLR_RT_HeapBlock_Node*)relocCurrent->m_start, move );
  165. if(dst < freeRegion && freeRegion < (dst + dst->DataSize()))
  166. {
  167. freeRegion = dst;
  168. }
  169. }
  170. CLR_RT_GarbageCollector::ValidateCluster( currentSource_hc );
  171. CLR_RT_GarbageCollector::ValidateCluster( freeRegion_hc );
  172. relocCurrent++;
  173. m_relocCount++;
  174. }
  175. else
  176. {
  177. freeRegion = freeRegion->Next();
  178. }
  179. if(freeRegion->Next() == NULL)
  180. {
  181. freeRegion = NULL;
  182. freeRegion_hc = (CLR_RT_HeapCluster*)freeRegion_hc->Next();
  183. while(true)
  184. {
  185. CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break;
  186. freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break;
  187. freeRegion = NULL;
  188. freeRegion_hc = freeRegion_hcNext;
  189. }
  190. if(!freeRegion) break;
  191. }
  192. }
  193. }
  194. currentSource_hc = (CLR_RT_HeapCluster*)currentSource_hc->Next();
  195. }
  196. if(m_relocCount)
  197. {
  198. ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap );
  199. Heap_Relocate();
  200. ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap );
  201. }
  202. }
  203. void CLR_RT_GarbageCollector::Heap_Relocate_Prepare( RelocationRegion* blocks, size_t total )
  204. {
  205. NATIVE_PROFILE_CLR_CORE();
  206. m_relocBlocks = blocks;
  207. m_relocTotal = total;
  208. m_relocCount = 0;
  209. }
  210. void CLR_RT_GarbageCollector::Heap_Relocate_AddBlock( CLR_UINT8* dst, CLR_UINT8* src, CLR_UINT32 length )
  211. {
  212. NATIVE_PROFILE_CLR_CORE();
  213. RelocationRegion* reloc = m_relocBlocks;
  214. size_t count = m_relocCount;
  215. while(count)
  216. {
  217. if(reloc->m_start > src)
  218. {
  219. //
  220. // Insert region, so they are sorted by start address.
  221. //
  222. memmove( &reloc[ 1 ], &reloc[ 0 ], count * sizeof(*reloc) );
  223. break;
  224. }
  225. reloc++;
  226. count--;
  227. }
  228. reloc->m_start = src;
  229. reloc->m_end = &src[ length ];
  230. reloc->m_destination = dst;
  231. reloc->m_offset = (CLR_UINT32)(dst - src);
  232. if(++m_relocCount == m_relocTotal)
  233. {
  234. Heap_Relocate();
  235. }
  236. }
  237. void CLR_RT_GarbageCollector::Heap_Relocate()
  238. {
  239. NATIVE_PROFILE_CLR_CORE();
  240. if(m_relocCount)
  241. {
  242. RelocationRegion* relocBlocks = m_relocBlocks;
  243. CLR_UINT8* relocMinimum = relocBlocks->m_start;
  244. CLR_UINT8* relocMaximum = relocBlocks->m_end;
  245. for(size_t i=0; i<m_relocCount; i++, relocBlocks++)
  246. {
  247. if(relocMinimum > relocBlocks->m_start) relocMinimum = relocBlocks->m_start;
  248. if(relocMaximum < relocBlocks->m_end ) relocMaximum = relocBlocks->m_end;
  249. }
  250. m_relocMinimum = relocMinimum;
  251. m_relocMaximum = relocMaximum;
  252. TestPointers_Remap();
  253. Heap_Relocate_Pass( NULL );
  254. #if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS)
  255. g_CLR_PRF_Profiler.TrackObjectRelocation();
  256. #endif
  257. ValidatePointers();
  258. TestPointers_PopulateNew();
  259. m_relocCount = 0;
  260. }
  261. }
  262. void CLR_RT_GarbageCollector::Heap_Relocate_Pass( RelocateFtn ftn )
  263. {
  264. NATIVE_PROFILE_CLR_CORE();
  265. #if TINYCLR_VALIDATE_HEAP > TINYCLR_VALIDATE_HEAP_0_None
  266. m_relocWorker = ftn;
  267. #endif
  268. TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap)
  269. {
  270. CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart;
  271. CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd;
  272. while(ptr < end)
  273. {
  274. CLR_RT_HEAPBLOCK_RELOCATE(ptr);
  275. ptr += ptr->DataSize();
  276. }
  277. }
  278. TINYCLR_FOREACH_NODE_END();
  279. g_CLR_RT_ExecutionEngine.Relocate();
  280. }
  281. //--//
  282. void CLR_RT_GarbageCollector::Heap_Relocate( CLR_RT_HeapBlock* lst, CLR_UINT32 len )
  283. {
  284. NATIVE_PROFILE_CLR_CORE();
  285. while(len--)
  286. {
  287. CLR_RT_HEAPBLOCK_RELOCATE(lst);
  288. lst++;
  289. }
  290. }
  291. void CLR_RT_GarbageCollector::Heap_Relocate( void** ref )
  292. {
  293. NATIVE_PROFILE_CLR_CORE();
  294. CLR_UINT8* dst = (CLR_UINT8*)*ref;
  295. #if TINYCLR_VALIDATE_HEAP > TINYCLR_VALIDATE_HEAP_0_None
  296. if(g_CLR_RT_GarbageCollector.m_relocWorker)
  297. {
  298. g_CLR_RT_GarbageCollector.m_relocWorker( ref );
  299. }
  300. else
  301. #endif
  302. {
  303. if(dst >= g_CLR_RT_GarbageCollector.m_relocMinimum && dst < g_CLR_RT_GarbageCollector.m_relocMaximum)
  304. {
  305. RelocationRegion* relocBlocks = g_CLR_RT_GarbageCollector.m_relocBlocks;
  306. size_t left = 0;
  307. size_t right = g_CLR_RT_GarbageCollector.m_relocCount;
  308. while(left < right)
  309. {
  310. size_t center = (left + right) / 2;
  311. RelocationRegion& relocCurrent = relocBlocks[ center ];
  312. if(dst < relocCurrent.m_start)
  313. {
  314. right = center;
  315. }
  316. else if(dst >= relocCurrent.m_end)
  317. {
  318. left = center+1;
  319. }
  320. else
  321. {
  322. *ref = (void*)(dst + relocCurrent.m_offset);
  323. return;
  324. }
  325. }
  326. }
  327. }
  328. }
  329. #if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_3_Compaction
  330. bool CLR_RT_GarbageCollector::Relocation_JustCheck( void** ref )
  331. {
  332. NATIVE_PROFILE_CLR_CORE();
  333. CLR_UINT8* dst = (CLR_UINT8*)*ref;
  334. if(dst)
  335. {
  336. ValidateBlockNotInFreeList( g_CLR_RT_ExecutionEngine.m_heap, (CLR_RT_HeapBlock_Node*)dst );
  337. }
  338. return true;
  339. }
  340. #endif