MetaAllocator.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright (C) 2011 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef WTF_MetaAllocator_h
  29. #define WTF_MetaAllocator_h
  30. #include <wtf/Assertions.h>
  31. #include <wtf/HashMap.h>
  32. #include <wtf/MetaAllocatorHandle.h>
  33. #include <wtf/Noncopyable.h>
  34. #include <wtf/PageBlock.h>
  35. #include <wtf/RedBlackTree.h>
  36. #include <wtf/RefCounted.h>
  37. #include <wtf/RefPtr.h>
  38. #include <wtf/TCSpinLock.h>
  39. namespace WTF {
  40. #define ENABLE_META_ALLOCATOR_PROFILE 0
  41. class MetaAllocatorTracker {
  42. WTF_MAKE_FAST_ALLOCATED;
  43. public:
  44. void notify(MetaAllocatorHandle*);
  45. void release(MetaAllocatorHandle*);
  46. MetaAllocatorHandle* find(void* address)
  47. {
  48. MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address);
  49. if (handle && address < handle->end())
  50. return handle;
  51. return 0;
  52. }
  53. RedBlackTree<MetaAllocatorHandle, void*> m_allocations;
  54. };
  55. class MetaAllocator {
  56. WTF_MAKE_NONCOPYABLE(MetaAllocator);
  57. public:
  58. #if ENABLE(DETACHED_JIT)
  59. typedef enum {
  60. e_MetaAllocatorBaseType,
  61. e_SuperRegionType,
  62. e_DemandAllocatorType,
  63. e_FixedAllocatorType
  64. } MetaAllocatorType;
  65. WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, MetaAllocatorType, size_t pageSize = WTF::pageSize());
  66. #else
  67. WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, size_t pageSize = WTF::pageSize());
  68. #endif
  69. WTF_EXPORT_PRIVATE DETACHED_JIT_VIRTUAL_DTOR ~MetaAllocator();
  70. public:
  71. WTF_EXPORT_PRIVATE PassRefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes, void* ownerUID);
  72. void trackAllocations(MetaAllocatorTracker* tracker)
  73. {
  74. m_tracker = tracker;
  75. }
  76. // Non-atomic methods for getting allocator statistics.
  77. size_t bytesAllocated() { return m_bytesAllocated; }
  78. size_t bytesReserved() { return m_bytesReserved; }
  79. size_t bytesCommitted() { return m_bytesCommitted; }
  80. // Atomic method for getting allocator statistics.
  81. struct Statistics {
  82. size_t bytesAllocated;
  83. size_t bytesReserved;
  84. size_t bytesCommitted;
  85. };
  86. Statistics currentStatistics();
  87. // Add more free space to the allocator. Call this directly from
  88. // the constructor if you wish to operate the allocator within a
  89. // fixed pool.
  90. WTF_EXPORT_PRIVATE void addFreshFreeSpace(void* start, size_t sizeInBytes);
  91. // This is meant only for implementing tests. Never call this in release
  92. // builds.
  93. WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize();
  94. #if ENABLE(META_ALLOCATOR_PROFILE)
  95. void dumpProfile();
  96. #else
  97. void dumpProfile() { }
  98. #endif
  99. protected:
  100. #if ENABLE(DETACHED_JIT)
  101. void* allocateNewSpace(size_t& numPages);
  102. void notifyNeedPage(void* page);
  103. void notifyPageIsFree(void* page);
  104. #else
  105. // Allocate new virtual space, but don't commit. This may return more
  106. // pages than we asked, in which case numPages is changed.
  107. virtual void* allocateNewSpace(size_t& numPages) = 0;
  108. // Commit a page.
  109. virtual void notifyNeedPage(void* page) = 0;
  110. // Uncommit a page.
  111. virtual void notifyPageIsFree(void* page) = 0;
  112. #endif
  113. // NOTE: none of the above methods are called during allocator
  114. // destruction, in part because a MetaAllocator cannot die so long
  115. // as there are Handles that refer to it.
  116. private:
  117. friend class MetaAllocatorHandle;
  118. class FreeSpaceNode : public RedBlackTree<FreeSpaceNode, size_t>::Node {
  119. public:
  120. FreeSpaceNode(void* start, size_t sizeInBytes)
  121. : m_start(start)
  122. , m_sizeInBytes(sizeInBytes)
  123. {
  124. }
  125. size_t key()
  126. {
  127. return m_sizeInBytes;
  128. }
  129. void* m_start;
  130. size_t m_sizeInBytes;
  131. };
  132. typedef RedBlackTree<FreeSpaceNode, size_t> Tree;
  133. // Release a MetaAllocatorHandle.
  134. void release(MetaAllocatorHandle*);
  135. // Remove free space from the allocator. This is effectively
  136. // the allocate() function, except that it does not mark the
  137. // returned space as being in-use.
  138. void* findAndRemoveFreeSpace(size_t sizeInBytes);
  139. // This is called when memory from an allocation is freed.
  140. void addFreeSpaceFromReleasedHandle(void* start, size_t sizeInBytes);
  141. // This is the low-level implementation of adding free space; it
  142. // is called from both addFreeSpaceFromReleasedHandle and from
  143. // addFreshFreeSpace.
  144. void addFreeSpace(void* start, size_t sizeInBytes);
  145. // Management of used space.
  146. void incrementPageOccupancy(void* address, size_t sizeInBytes);
  147. void decrementPageOccupancy(void* address, size_t sizeInBytes);
  148. // Utilities.
  149. size_t roundUp(size_t sizeInBytes);
  150. FreeSpaceNode* allocFreeSpaceNode();
  151. WTF_EXPORT_PRIVATE void freeFreeSpaceNode(FreeSpaceNode*);
  152. size_t m_allocationGranule;
  153. unsigned m_logAllocationGranule;
  154. size_t m_pageSize;
  155. unsigned m_logPageSize;
  156. Tree m_freeSpaceSizeMap;
  157. HashMap_shared<void*, FreeSpaceNode*> m_freeSpaceStartAddressMap;
  158. HashMap_shared<void*, FreeSpaceNode*> m_freeSpaceEndAddressMap;
  159. HashMap_shared<uintptr_t, size_t> m_pageOccupancyMap;
  160. size_t m_bytesAllocated;
  161. size_t m_bytesReserved;
  162. size_t m_bytesCommitted;
  163. SpinLock m_lock;
  164. MetaAllocatorTracker* m_tracker;
  165. #ifndef NDEBUG
  166. size_t m_mallocBalance;
  167. #endif
  168. #if ENABLE(META_ALLOCATOR_PROFILE)
  169. unsigned m_numAllocations;
  170. unsigned m_numFrees;
  171. #endif
  172. #if ENABLE(DETACHED_JIT)
  173. protected:
  174. MetaAllocatorType m_type;
  175. #endif
  176. };
  177. } // namespace WTF
  178. #endif // WTF_MetaAllocator_h