RecyclerTestObject.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 "stdafx.h"
  6. class RecyclerTestObject : public FinalizableObject
  7. {
  8. protected:
  9. RecyclerTestObject()
  10. {
  11. generation = currentGeneration;
  12. }
  13. public:
  14. // FinalizableObject implementation
  15. virtual void Finalize(bool isShutdown) override { VerifyCondition(false); };
  16. virtual void Dispose(bool isShutdown) override { VerifyCondition(false); };
  17. virtual void Mark(Recycler * recycler) override { VerifyCondition(false); };
  18. public:
  19. static void BeginWalk()
  20. {
  21. currentGeneration++;
  22. walkObjectCount = 0;
  23. walkScannedByteCount = 0;
  24. walkBarrierByteCount = 0;
  25. walkTrackedByteCount = 0;
  26. walkLeafByteCount = 0;
  27. maxWalkDepth = 0;
  28. currentWalkDepth = 0;
  29. wprintf(_u("-------------------------------------------\n"));
  30. wprintf(_u("Full heap walk starting\n"));
  31. }
  32. static void WalkReference(RecyclerTestObject * object)
  33. {
  34. if (object != nullptr)
  35. {
  36. // See if we've already seen the location in this traversal.
  37. if (object->generation != currentGeneration)
  38. {
  39. // Haven't see it yet. Must be from the previous generation; increment generation and validate that.
  40. // Update to current generation to indicate we've seen it
  41. object->generation++;
  42. VerifyCondition(object->generation == currentGeneration);
  43. walkObjectCount++;
  44. currentWalkDepth++;
  45. maxWalkDepth = max(currentWalkDepth, maxWalkDepth);
  46. // Call virtual for object-specific behavior
  47. object->DoWalkObject();
  48. currentWalkDepth--;
  49. }
  50. }
  51. }
  52. static void EndWalk()
  53. {
  54. VerifyCondition(currentWalkDepth == 0);
  55. wprintf(_u("Full heap walk finished\n"));
  56. wprintf(_u("Object Count: %12llu\n"), (unsigned long long) walkObjectCount);
  57. wprintf(_u("Scanned Bytes: %12llu\n"), (unsigned long long) walkScannedByteCount);
  58. wprintf(_u("Barrier Bytes: %12llu\n"), (unsigned long long) walkBarrierByteCount);
  59. wprintf(_u("Tracked Bytes: %12llu\n"), (unsigned long long) walkTrackedByteCount);
  60. wprintf(_u("Leaf Bytes: %12llu\n"), (unsigned long long) walkLeafByteCount);
  61. wprintf(_u("Total Bytes: %12llu\n"), (unsigned long long) (walkScannedByteCount + walkBarrierByteCount + walkTrackedByteCount + walkLeafByteCount));
  62. wprintf(_u("Max Depth: %12llu\n"), (unsigned long long) maxWalkDepth);
  63. }
  64. // Virtual methods
  65. virtual bool TryGetRandomLocation(Location * location)
  66. {
  67. // Return false to indicate no internal locations
  68. // Subclasses can override this to handle their internal locations as appropriate
  69. return false;
  70. }
  71. virtual void DoWalkObject() = 0;
  72. protected:
  73. // Global variables
  74. // This global variable contains the "generation" of GC objects
  75. // It is used to validate the correctness of GC objects
  76. // It is assigned initially during object creation, and
  77. // updated when we walk the entire object graph in TraverseAllObjects
  78. static size_t currentGeneration;
  79. // These globals contain statistical data generated by WalkAllReferences
  80. static size_t walkObjectCount;
  81. static size_t walkScannedByteCount;
  82. static size_t walkLeafByteCount;
  83. static size_t walkBarrierByteCount;
  84. static size_t walkTrackedByteCount;
  85. static size_t currentWalkDepth;
  86. static size_t maxWalkDepth;
  87. private:
  88. // Instance variables
  89. // See comments above re currentGeneration
  90. size_t generation;
  91. };
  92. template <unsigned int minCount, unsigned int maxCount>
  93. class LeafObject : public RecyclerTestObject
  94. {
  95. private:
  96. LeafObject(unsigned int count) :
  97. count(count)
  98. {
  99. for (unsigned int i = 0; i < count; i++)
  100. {
  101. data[i] = i;
  102. }
  103. }
  104. public:
  105. static RecyclerTestObject * New()
  106. {
  107. unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
  108. return RecyclerNewPlusLeaf(recyclerInstance, sizeof(size_t) * count, LeafObject, count);
  109. }
  110. protected:
  111. virtual void DoWalkObject() override
  112. {
  113. walkLeafByteCount += sizeof(LeafObject) + count * sizeof(size_t);
  114. }
  115. private:
  116. unsigned int count;
  117. size_t data[0];
  118. };
  119. template <unsigned int minCount, unsigned int maxCount>
  120. class ScannedObject : public RecyclerTestObject
  121. {
  122. private:
  123. ScannedObject(unsigned int count) :
  124. count(count)
  125. {
  126. for (unsigned int i = 0; i < count; i++)
  127. {
  128. references[i] = nullptr;
  129. }
  130. }
  131. public:
  132. static RecyclerTestObject * New()
  133. {
  134. unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
  135. return RecyclerNewPlus(recyclerInstance, sizeof(RecyclerTestObject *) * count, ScannedObject, count);
  136. }
  137. virtual bool TryGetRandomLocation(Location * location) override
  138. {
  139. // Get a random slot and construct a Location for it
  140. *location = Location::Scanned(&references[GetRandomInteger(count)]);
  141. return true;
  142. }
  143. protected:
  144. virtual void DoWalkObject() override
  145. {
  146. walkScannedByteCount += sizeof(ScannedObject) + count * sizeof(RecyclerTestObject *);
  147. for (unsigned int i = 0; i < count; i++)
  148. {
  149. RecyclerTestObject::WalkReference(references[i]);
  150. }
  151. }
  152. private:
  153. unsigned int count;
  154. RecyclerTestObject * references[0];
  155. };
  156. template <unsigned int minCount, unsigned int maxCount>
  157. class BarrierObject : public RecyclerTestObject
  158. {
  159. private:
  160. BarrierObject(unsigned int count) :
  161. count(count)
  162. {
  163. for (unsigned int i = 0; i < count; i++)
  164. {
  165. references[i] = nullptr;
  166. }
  167. }
  168. public:
  169. static RecyclerTestObject * New()
  170. {
  171. unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
  172. return RecyclerNewWithBarrierPlus(recyclerInstance, sizeof(RecyclerTestObject *) * count, BarrierObject, count);
  173. }
  174. virtual bool TryGetRandomLocation(Location * location) override
  175. {
  176. // Get a random slot and construct a Location for it
  177. *location = Location::Barrier(&references[GetRandomInteger(count)]);
  178. return true;
  179. }
  180. protected:
  181. virtual void DoWalkObject() override
  182. {
  183. walkBarrierByteCount += sizeof(BarrierObject) + count * sizeof(RecyclerTestObject *);
  184. for (unsigned int i = 0; i < count; i++)
  185. {
  186. RecyclerTestObject::WalkReference(references[i]);
  187. }
  188. }
  189. private:
  190. unsigned int count;
  191. RecyclerTestObject * references[0];
  192. };
  193. template <unsigned int minCount, unsigned int maxCount>
  194. class TrackedObject : public RecyclerTestObject
  195. {
  196. private:
  197. TrackedObject(unsigned int count) :
  198. count(count)
  199. {
  200. for (unsigned int i = 0; i < count; i++)
  201. {
  202. references[i] = nullptr;
  203. }
  204. }
  205. public:
  206. static RecyclerTestObject * New()
  207. {
  208. unsigned int count = minCount + GetRandomInteger(maxCount - minCount + 1);
  209. return RecyclerNewTrackedLeafPlusZ(recyclerInstance, sizeof(RecyclerTestObject *) * count, TrackedObject, count);
  210. }
  211. virtual bool TryGetRandomLocation(Location * location) override
  212. {
  213. // Get a random slot and construct a Location for it
  214. *location = Location::Tagged(&references[GetRandomInteger(count)]);
  215. return true;
  216. }
  217. // Tracked object implementation
  218. virtual void Mark(Recycler * recycler) override
  219. {
  220. for (unsigned int i = 0; i < count; i++)
  221. {
  222. RecyclerTestObject * object = Location::Untag(references[i]);
  223. if (object != nullptr)
  224. {
  225. recycler->TryMarkNonInterior(object);
  226. }
  227. }
  228. };
  229. // Tracked objects are always finalize as well. Just do nothing.
  230. virtual void Finalize(bool isShutdown) override { }
  231. virtual void Dispose(bool isShutdown) override { };
  232. protected:
  233. virtual void DoWalkObject() override
  234. {
  235. walkTrackedByteCount += sizeof(TrackedObject) + count * sizeof(RecyclerTestObject *);
  236. for (unsigned int i = 0; i < count; i++)
  237. {
  238. RecyclerTestObject::WalkReference(Location::Untag(references[i]));
  239. }
  240. }
  241. private:
  242. unsigned int count;
  243. RecyclerTestObject * references[0];
  244. };