GCStress.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. // TODO, this should be elsewhere
  7. #define RecyclerNewImplicitRoot(recycler,T,...) AllocatorNewBase(Recycler, recycler, NoThrowAllocImplicitRoot, T, __VA_ARGS__)
  8. // Forward reference
  9. class RecyclerTestObject;
  10. // A "Location" represents a location in memory where object references (ReccylerTestObject *s) are stored.
  11. // It includes a "type" that defines how the reference should be read or written.
  12. // This allows us to specify special handling for certain location types,
  13. // such as pinned roots, software write barrier locations, tagged locations for tracked objects, etc.
  14. class Location
  15. {
  16. private:
  17. enum class Type
  18. {
  19. Scanned, // For regular locations in scanned objects (or stack locations)
  20. Rooted, // This is a non-heap location that's explicitly rooted.
  21. Barrier, // Write barrier location
  22. Tagged, // Tagged location (used in tracked objects)
  23. ImplicitRoot, // Uses ImplicitRootBit to hold reference
  24. };
  25. class ImplicitRootHolder
  26. {
  27. private:
  28. Field(RecyclerTestObject *) reference;
  29. public:
  30. ImplicitRootHolder(RecyclerTestObject * reference)
  31. : reference(reference)
  32. {
  33. VerifyCondition(reference != nullptr);
  34. }
  35. RecyclerTestObject * GetReference() const
  36. {
  37. VerifyCondition(this->reference != nullptr);
  38. return this->reference;
  39. }
  40. };
  41. Location(RecyclerTestObject ** location, Type type) :
  42. location(location), type(type)
  43. {
  44. VerifyCondition(location != nullptr);
  45. }
  46. public:
  47. static Location Scanned(RecyclerTestObject ** location)
  48. {
  49. return Location(location, Type::Scanned);
  50. }
  51. static Location Rooted(RecyclerTestObject ** location)
  52. {
  53. return Location(location, Type::Rooted);
  54. }
  55. static Location Barrier(RecyclerTestObject ** location)
  56. {
  57. return Location(location, Type::Barrier);
  58. }
  59. static Location Tagged(RecyclerTestObject ** location)
  60. {
  61. return Location(location, Type::Tagged);
  62. }
  63. static Location ImplicitRoot(RecyclerTestObject ** location)
  64. {
  65. return Location(location, Type::ImplicitRoot);
  66. }
  67. RecyclerTestObject * Get()
  68. {
  69. switch (type)
  70. {
  71. case Type::Scanned:
  72. return *location;
  73. case Type::Rooted:
  74. return *location;
  75. case Type::Barrier:
  76. return *location;
  77. case Type::Tagged:
  78. return Untag(*location);
  79. case Type::ImplicitRoot:
  80. // The stored location actually contains a pointer to the ImplicitRootHolder
  81. ImplicitRootHolder * holder = (ImplicitRootHolder *)(*location);
  82. if (holder == nullptr)
  83. {
  84. return nullptr;
  85. }
  86. return holder->GetReference();
  87. }
  88. // Shouldn't get here
  89. VerifyCondition(false);
  90. return nullptr;
  91. }
  92. void Set(RecyclerTestObject * value)
  93. {
  94. switch (type)
  95. {
  96. case Type::Scanned:
  97. *location = value;
  98. return;
  99. case Type::Rooted:
  100. Unroot();
  101. *location = value;
  102. Root();
  103. return;
  104. case Type::Barrier:
  105. *location = value;
  106. if (value != nullptr)
  107. {
  108. RecyclerWriteBarrierManager::WriteBarrier(location);
  109. }
  110. return;
  111. case Type::Tagged:
  112. *location = Tag(value);
  113. return;
  114. case Type::ImplicitRoot:
  115. // The stored location actually contains a pointer to the ImplicitRootHolder
  116. ImplicitRootHolder * holder = (ImplicitRootHolder *)(*location);
  117. if (holder != nullptr)
  118. {
  119. // Free the implicit root
  120. // TODO: This should be better encapsulated
  121. RecyclerHeapObjectInfo heapObject;
  122. bool found = recyclerInstance->FindHeapObject(holder, FindHeapObjectFlags_VerifyFreeBitForAttribute, heapObject);
  123. VerifyCondition(found);
  124. // Zero pointers in order to eliminate false-positives
  125. memset(holder, 0, heapObject.GetSize());
  126. bool success = heapObject.ClearImplicitRootBit();
  127. VerifyCondition(success);
  128. *location = nullptr;
  129. }
  130. if (value != nullptr)
  131. {
  132. // Create new holder object
  133. holder = RecyclerNewImplicitRoot(recyclerInstance, ImplicitRootHolder, value);
  134. VerifyCondition(holder != nullptr);
  135. // Store holder back to the location
  136. *location = (RecyclerTestObject *)holder;
  137. }
  138. return;
  139. }
  140. // Shouldn't get here
  141. VerifyCondition(false);
  142. }
  143. static RecyclerTestObject * Tag(RecyclerTestObject * untagged)
  144. {
  145. if (untagged == nullptr)
  146. {
  147. return nullptr;
  148. }
  149. else
  150. {
  151. size_t value = (size_t)untagged;
  152. VerifyCondition((value & 0x1) == 0);
  153. value |= 0x1;
  154. return (RecyclerTestObject *)value;
  155. }
  156. }
  157. static RecyclerTestObject * Untag(RecyclerTestObject * tagged)
  158. {
  159. if (tagged == nullptr)
  160. {
  161. return nullptr;
  162. }
  163. else
  164. {
  165. size_t value = (size_t)tagged;
  166. VerifyCondition((value & 0x1) == 0x1);
  167. value &= ~(0x1);
  168. return (RecyclerTestObject *)value;
  169. }
  170. }
  171. private:
  172. void Unroot()
  173. {
  174. if (*location != nullptr)
  175. {
  176. recyclerInstance->RootRelease(*location);
  177. }
  178. }
  179. void Root()
  180. {
  181. if (*location != nullptr)
  182. {
  183. recyclerInstance->RootAddRef(*location);
  184. }
  185. }
  186. private:
  187. RecyclerTestObject ** location;
  188. Type type;
  189. };