123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef WTF_MetaAllocator_h
- #define WTF_MetaAllocator_h
- #include <wtf/Assertions.h>
- #include <wtf/HashMap.h>
- #include <wtf/MetaAllocatorHandle.h>
- #include <wtf/Noncopyable.h>
- #include <wtf/PageBlock.h>
- #include <wtf/RedBlackTree.h>
- #include <wtf/RefCounted.h>
- #include <wtf/RefPtr.h>
- #include <wtf/TCSpinLock.h>
- namespace WTF {
- #define ENABLE_META_ALLOCATOR_PROFILE 0
- class MetaAllocatorTracker {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- void notify(MetaAllocatorHandle*);
- void release(MetaAllocatorHandle*);
- MetaAllocatorHandle* find(void* address)
- {
- MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address);
- if (handle && address < handle->end())
- return handle;
- return 0;
- }
- RedBlackTree<MetaAllocatorHandle, void*> m_allocations;
- };
- class MetaAllocator {
- WTF_MAKE_NONCOPYABLE(MetaAllocator);
- public:
- #if ENABLE(DETACHED_JIT)
- typedef enum {
- e_MetaAllocatorBaseType,
- e_SuperRegionType,
- e_DemandAllocatorType,
- e_FixedAllocatorType
- } MetaAllocatorType;
- WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, MetaAllocatorType, size_t pageSize = WTF::pageSize());
- #else
- WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, size_t pageSize = WTF::pageSize());
- #endif
- WTF_EXPORT_PRIVATE DETACHED_JIT_VIRTUAL_DTOR ~MetaAllocator();
-
- public:
- WTF_EXPORT_PRIVATE PassRefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes, void* ownerUID);
- void trackAllocations(MetaAllocatorTracker* tracker)
- {
- m_tracker = tracker;
- }
-
- // Non-atomic methods for getting allocator statistics.
- size_t bytesAllocated() { return m_bytesAllocated; }
- size_t bytesReserved() { return m_bytesReserved; }
- size_t bytesCommitted() { return m_bytesCommitted; }
-
- // Atomic method for getting allocator statistics.
- struct Statistics {
- size_t bytesAllocated;
- size_t bytesReserved;
- size_t bytesCommitted;
- };
- Statistics currentStatistics();
- // Add more free space to the allocator. Call this directly from
- // the constructor if you wish to operate the allocator within a
- // fixed pool.
- WTF_EXPORT_PRIVATE void addFreshFreeSpace(void* start, size_t sizeInBytes);
- // This is meant only for implementing tests. Never call this in release
- // builds.
- WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize();
-
- #if ENABLE(META_ALLOCATOR_PROFILE)
- void dumpProfile();
- #else
- void dumpProfile() { }
- #endif
- protected:
-
- #if ENABLE(DETACHED_JIT)
- void* allocateNewSpace(size_t& numPages);
- void notifyNeedPage(void* page);
- void notifyPageIsFree(void* page);
- #else
- // Allocate new virtual space, but don't commit. This may return more
- // pages than we asked, in which case numPages is changed.
- virtual void* allocateNewSpace(size_t& numPages) = 0;
-
- // Commit a page.
- virtual void notifyNeedPage(void* page) = 0;
-
- // Uncommit a page.
- virtual void notifyPageIsFree(void* page) = 0;
- #endif
- // NOTE: none of the above methods are called during allocator
- // destruction, in part because a MetaAllocator cannot die so long
- // as there are Handles that refer to it.
- private:
-
- friend class MetaAllocatorHandle;
-
- class FreeSpaceNode : public RedBlackTree<FreeSpaceNode, size_t>::Node {
- public:
- FreeSpaceNode(void* start, size_t sizeInBytes)
- : m_start(start)
- , m_sizeInBytes(sizeInBytes)
- {
- }
- size_t key()
- {
- return m_sizeInBytes;
- }
- void* m_start;
- size_t m_sizeInBytes;
- };
- typedef RedBlackTree<FreeSpaceNode, size_t> Tree;
- // Release a MetaAllocatorHandle.
- void release(MetaAllocatorHandle*);
-
- // Remove free space from the allocator. This is effectively
- // the allocate() function, except that it does not mark the
- // returned space as being in-use.
- void* findAndRemoveFreeSpace(size_t sizeInBytes);
- // This is called when memory from an allocation is freed.
- void addFreeSpaceFromReleasedHandle(void* start, size_t sizeInBytes);
-
- // This is the low-level implementation of adding free space; it
- // is called from both addFreeSpaceFromReleasedHandle and from
- // addFreshFreeSpace.
- void addFreeSpace(void* start, size_t sizeInBytes);
-
- // Management of used space.
-
- void incrementPageOccupancy(void* address, size_t sizeInBytes);
- void decrementPageOccupancy(void* address, size_t sizeInBytes);
- // Utilities.
-
- size_t roundUp(size_t sizeInBytes);
-
- FreeSpaceNode* allocFreeSpaceNode();
- WTF_EXPORT_PRIVATE void freeFreeSpaceNode(FreeSpaceNode*);
-
- size_t m_allocationGranule;
- unsigned m_logAllocationGranule;
- size_t m_pageSize;
- unsigned m_logPageSize;
-
- Tree m_freeSpaceSizeMap;
- HashMap_shared<void*, FreeSpaceNode*> m_freeSpaceStartAddressMap;
- HashMap_shared<void*, FreeSpaceNode*> m_freeSpaceEndAddressMap;
- HashMap_shared<uintptr_t, size_t> m_pageOccupancyMap;
-
- size_t m_bytesAllocated;
- size_t m_bytesReserved;
- size_t m_bytesCommitted;
-
- SpinLock m_lock;
- MetaAllocatorTracker* m_tracker;
- #ifndef NDEBUG
- size_t m_mallocBalance;
- #endif
- #if ENABLE(META_ALLOCATOR_PROFILE)
- unsigned m_numAllocations;
- unsigned m_numFrees;
- #endif
- #if ENABLE(DETACHED_JIT)
- protected:
- MetaAllocatorType m_type;
- #endif
- };
- } // namespace WTF
- #endif // WTF_MetaAllocator_h
|