RecyclerFastAllocator.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. namespace Memory
  7. {
  8. template <typename T, ObjectInfoBits attributes>
  9. class RecyclerFastAllocator
  10. {
  11. typedef typename SmallHeapBlockType<(ObjectInfoBits)(attributes & GetBlockTypeBitMask), SmallAllocationBlockAttributes>::BlockType BlockType;
  12. public:
  13. #ifdef TRACK_ALLOC
  14. RecyclerFastAllocator * TrackAllocInfo(TrackAllocData const& data)
  15. {
  16. #ifdef PROFILE_RECYCLER_ALLOC
  17. recycler->TrackAllocInfo(data);
  18. #endif
  19. return this;
  20. }
  21. #endif
  22. void Initialize(Recycler * recycler)
  23. {
  24. this->recycler = recycler;
  25. size_t sizeCat = GetAlignedAllocSize();
  26. recycler->AddSmallAllocator(&allocator, sizeCat);
  27. }
  28. void Uninitialize()
  29. {
  30. size_t sizeCat = GetAlignedAllocSize();
  31. this->recycler->RemoveSmallAllocator(&allocator, sizeCat);
  32. this->recycler = nullptr;
  33. }
  34. Recycler * GetRecycler() { return recycler; }
  35. char * Alloc(DECLSPEC_GUARD_OVERFLOW size_t size)
  36. {
  37. Assert(recycler != nullptr);
  38. Assert(!recycler->IsHeapEnumInProgress() || recycler->AllowAllocationDuringHeapEnum());
  39. Assert(size == sizeof(T));
  40. #ifdef PROFILE_RECYCLER_ALLOC
  41. TrackAllocData trackAllocData;
  42. recycler->ClearTrackAllocInfo(&trackAllocData);
  43. #endif
  44. size_t sizeCat = GetAlignedAllocSize();
  45. Assert(HeapInfo::IsSmallObject(sizeCat));
  46. // TODO: SWB, currently RecyclerFastAllocator only used for number allocating, which is Leaf
  47. // need to add WithBarrierBit if we have other usage with NonLeaf
  48. char * memBlock = allocator.template InlinedAlloc<(ObjectInfoBits)(attributes & InternalObjectInfoBitMask)>(recycler, sizeCat);
  49. if (memBlock == nullptr)
  50. {
  51. memBlock = recycler->SmallAllocatorAlloc<attributes>(&allocator, sizeCat, size);
  52. Assert(memBlock != nullptr);
  53. }
  54. #ifdef PROFILE_RECYCLER_ALLOC
  55. recycler->TrackAlloc(memBlock, sizeof(T), trackAllocData);
  56. #endif
  57. RecyclerMemoryTracking::ReportAllocation(this->recycler, memBlock, sizeof(T));
  58. RECYCLER_PERF_COUNTER_INC(LiveObject);
  59. RECYCLER_PERF_COUNTER_ADD(LiveObjectSize, sizeCat);
  60. RECYCLER_PERF_COUNTER_SUB(FreeObjectSize, sizeCat);
  61. RECYCLER_PERF_COUNTER_INC(SmallHeapBlockLiveObject);
  62. RECYCLER_PERF_COUNTER_ADD(SmallHeapBlockLiveObjectSize, sizeCat);
  63. RECYCLER_PERF_COUNTER_SUB(SmallHeapBlockFreeObjectSize, sizeCat);
  64. #ifdef RECYCLER_MEMORY_VERIFY
  65. recycler->FillCheckPad(memBlock, sizeof(T), sizeCat);
  66. #endif
  67. #ifdef RECYCLER_PAGE_HEAP
  68. recycler->VerifyPageHeapFillAfterAlloc(memBlock, size, attributes);
  69. #endif
  70. return memBlock;
  71. };
  72. static uint32 GetEndAddressOffset()
  73. {
  74. return offsetof(RecyclerFastAllocator, allocator) + SmallHeapBlockAllocator<BlockType>::GetEndAddressOffset();
  75. }
  76. bool AllowNativeCodeBumpAllocation()
  77. {
  78. return recycler->AllowNativeCodeBumpAllocation();
  79. }
  80. char *GetEndAddress()
  81. {
  82. return allocator.GetEndAddress();
  83. }
  84. static uint32 GetFreeObjectListOffset()
  85. {
  86. return offsetof(RecyclerFastAllocator, allocator) + SmallHeapBlockAllocator<BlockType>::GetFreeObjectListOffset();
  87. }
  88. FreeObject *GetFreeObjectList()
  89. {
  90. return allocator.GetFreeObjectList();
  91. }
  92. void SetFreeObjectList(FreeObject *freeObject)
  93. {
  94. allocator.SetFreeObjectList(freeObject);
  95. }
  96. #if defined(PROFILE_RECYCLER_ALLOC) || defined(RECYCLER_MEMORY_VERIFY) || defined(MEMSPECT_TRACKING) || defined(ETW_MEMORY_TRACKING)
  97. RecyclerFastAllocator()
  98. {
  99. allocator.SetTrackNativeAllocatedObjectCallBack(&TrackNativeAllocatedObject);
  100. }
  101. static void TrackNativeAllocatedObject(Recycler * recycler, void * memBlock, size_t sizeCat)
  102. {
  103. #ifdef PROFILE_RECYCLER_ALLOC
  104. TrackAllocData trackAllocData = { &typeid(T), 0, (size_t)-1, NULL, 0 };
  105. recycler->TrackAlloc(memBlock, sizeof(T), trackAllocData);
  106. #endif
  107. RecyclerMemoryTracking::ReportAllocation(recycler, memBlock, sizeof(T));
  108. RECYCLER_PERF_COUNTER_INC(LiveObject);
  109. RECYCLER_PERF_COUNTER_ADD(LiveObjectSize, sizeCat);
  110. RECYCLER_PERF_COUNTER_SUB(FreeObjectSize, sizeCat);
  111. RECYCLER_PERF_COUNTER_INC(SmallHeapBlockLiveObject);
  112. RECYCLER_PERF_COUNTER_ADD(SmallHeapBlockLiveObjectSize, sizeCat);
  113. RECYCLER_PERF_COUNTER_SUB(SmallHeapBlockFreeObjectSize, sizeCat);
  114. #ifdef RECYCLER_MEMORY_VERIFY
  115. recycler->FillCheckPad(memBlock, sizeof(T), sizeCat, true);
  116. #endif
  117. }
  118. #endif
  119. size_t GetAlignedAllocSize() const
  120. {
  121. #ifdef RECYCLER_MEMORY_VERIFY
  122. return GetAlignedAllocSize(recycler->VerifyEnabled(), recycler->verifyPad);
  123. #else
  124. return GetAlignedAllocSize(FALSE, 0);
  125. #endif
  126. }
  127. static size_t GetAlignedAllocSize(BOOL verifyEnabled, uint verifyPad)
  128. {
  129. #ifdef RECYCLER_MEMORY_VERIFY
  130. if (verifyEnabled)
  131. {
  132. CompileAssert(sizeof(T) <= (size_t)-1 - sizeof(size_t));
  133. return HeapInfo::GetAlignedSize(AllocSizeMath::Add(sizeof(T) + sizeof(size_t), verifyPad));
  134. }
  135. #endif
  136. // We should have structures large enough that would cause this to overflow
  137. CompileAssert(((sizeof(T) + (HeapConstants::ObjectGranularity - 1)) & ~(HeapConstants::ObjectGranularity - 1)) != 0);
  138. return HeapInfo::GetAlignedSizeNoCheck(sizeof(T));
  139. }
  140. private:
  141. SmallHeapBlockAllocator<BlockType> allocator;
  142. Recycler * recycler;
  143. CompileAssert(sizeof(T) <= HeapConstants::MaxSmallObjectSize);
  144. };
  145. }