diff options
Diffstat (limited to 'JavaScriptCore/runtime/AlignedMemoryAllocator.h')
-rw-r--r-- | JavaScriptCore/runtime/AlignedMemoryAllocator.h | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/JavaScriptCore/runtime/AlignedMemoryAllocator.h b/JavaScriptCore/runtime/AlignedMemoryAllocator.h new file mode 100644 index 0000000..e682eb3 --- /dev/null +++ b/JavaScriptCore/runtime/AlignedMemoryAllocator.h @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef AlignedMemoryAllocator_h +#define AlignedMemoryAllocator_h + +#include <wtf/Bitmap.h> +#include <wtf/PageReservation.h> + +namespace JSC { + +struct AlignedMemoryAllocatorConstants { +// Set sane defaults if -D<flagname=value> wasn't provided via compiler args +#if defined(JSCCOLLECTOR_VIRTUALMEM_RESERVATION) + // Keep backwards compatibility with symbian build system + static const size_t virtualMemoryReservation = JSCCOLLECTOR_VIRTUALMEM_RESERVATION; +#elif defined(__WINS__) + // Emulator has limited virtual address space + static const size_t virtualMemoryReservation = 0x400000; +#else + // HW has plenty of virtual addresses + static const size_t virtualMemoryReservation = 0x8000000; +#endif +}; + +template<size_t blockSize> class AlignedMemory; +template<size_t blockSize> class AlignedMemoryAllocator; + +#if HAVE(PAGE_ALLOCATE_ALIGNED) + +template<size_t blockSize> +class AlignedMemoryAllocator; + +template<size_t blockSize> +class AlignedMemory { +public: + void deallocate(); + void* base(); + +private: + friend class AlignedMemoryAllocator<blockSize>; + + AlignedMemory(PageAllocation); + + PageAllocation m_allocation; +}; + +template<size_t blockSize> +class AlignedMemoryAllocator { +public: + void destroy(); + AlignedMemory<blockSize> allocate(); +}; + +template<size_t blockSize> +inline void AlignedMemoryAllocator<blockSize>::destroy() +{ +} + +template<size_t blockSize> +inline AlignedMemory<blockSize> AlignedMemoryAllocator<blockSize>::allocate() +{ + return AlignedMemory<blockSize>(PageAllocation::allocateAligned(blockSize, PageAllocation::JSGCHeapPages)); +} + +template<size_t blockSize> +inline void AlignedMemory<blockSize>::deallocate() +{ + m_allocation.deallocate(); +} + +template<size_t blockSize> +inline void* AlignedMemory<blockSize>::base() +{ + return m_allocation.base(); +} + +template<size_t blockSize> +inline AlignedMemory<blockSize>::AlignedMemory(PageAllocation allocation) + : m_allocation(allocation) +{ +} + +#else + +template<size_t blockSize> +class AlignedMemory { +public: + void deallocate(); + void* base(); + +private: + friend class AlignedMemoryAllocator<blockSize>; + + AlignedMemory(void* base, AlignedMemoryAllocator<blockSize>* allocator); + + void* m_base; + AlignedMemoryAllocator<blockSize>* m_allocator; +}; + +template<size_t blockSize> +class AlignedMemoryAllocator { +public: + AlignedMemoryAllocator(); + ~AlignedMemoryAllocator(); + + void destroy(); + AlignedMemory<blockSize> allocate(); + void free(AlignedMemory<blockSize>); + +private: + static const size_t reservationSize = AlignedMemoryAllocatorConstants::virtualMemoryReservation; + static const size_t bitmapSize = reservationSize / blockSize; + + PageReservation m_reservation; + size_t m_nextFree; + uintptr_t m_reservationBase; + WTF::Bitmap<bitmapSize> m_bitmap; +}; + +template<size_t blockSize> +AlignedMemoryAllocator<blockSize>::AlignedMemoryAllocator() + : m_reservation(PageReservation::reserve(reservationSize + blockSize, PageAllocation::JSGCHeapPages)) + , m_nextFree(0) +{ + // check that blockSize and reservationSize are powers of two + ASSERT(!(blockSize & (blockSize - 1))); + ASSERT(!(reservationSize & (reservationSize - 1))); + + // check that blockSize is a multiple of pageSize and that + // reservationSize is a multiple of blockSize + ASSERT(!(blockSize & (PageAllocation::pageSize() - 1))); + ASSERT(!(reservationSize & (blockSize - 1))); + + ASSERT(m_reservation); + + m_reservationBase = reinterpret_cast<uintptr_t>(m_reservation.base()); + m_reservationBase = (m_reservationBase + blockSize) & ~(blockSize - 1); +} + +template<size_t blockSize> +AlignedMemoryAllocator<blockSize>::~AlignedMemoryAllocator() +{ + destroy(); + m_reservation.deallocate(); +} + +template<size_t blockSize> +inline void AlignedMemoryAllocator<blockSize>::destroy() +{ + for (unsigned i = 0; i < bitmapSize; ++i) { + if (m_bitmap.get(i)) { + void* blockAddress = reinterpret_cast<void*>(m_reservationBase + m_nextFree * blockSize); + m_reservation.decommit(blockAddress, blockSize); + + m_bitmap.clear(i); + } + } +} + +template<size_t blockSize> +AlignedMemory<blockSize> AlignedMemoryAllocator<blockSize>::allocate() +{ + while (m_nextFree < bitmapSize) { + if (!m_bitmap.get(m_nextFree)) { + void* blockAddress = reinterpret_cast<void*>(m_reservationBase + m_nextFree * blockSize); + m_reservation.commit(blockAddress, blockSize); + + m_bitmap.set(m_nextFree); + ++m_nextFree; + + return AlignedMemory<blockSize>(blockAddress, this); + } + m_bitmap.advanceToNextFreeBit(m_nextFree); + } + + if (m_bitmap.isFull()) + return AlignedMemory<blockSize>(0, this); + + m_nextFree = 0; + + return allocate(); +} + +template<size_t blockSize> +void AlignedMemoryAllocator<blockSize>::free(AlignedMemory<blockSize> allocation) +{ + ASSERT(allocation.base()); + m_reservation.decommit(allocation.base(), blockSize); + + size_t diff = (reinterpret_cast<uintptr_t>(allocation.base()) - m_reservationBase); + ASSERT(!(diff & (blockSize - 1))); + + size_t i = diff / blockSize; + ASSERT(m_bitmap.get(i)); + + m_bitmap.clear(i); +} + +template<size_t blockSize> +inline void AlignedMemory<blockSize>::deallocate() +{ + m_allocator->free(*this); +} + +template<size_t blockSize> +inline void* AlignedMemory<blockSize>::base() +{ + return m_base; +} + +template<size_t blockSize> +AlignedMemory<blockSize>::AlignedMemory(void* base, AlignedMemoryAllocator<blockSize>* allocator) + : m_base(base) + , m_allocator(allocator) +{ +} + +#endif + +} + +#endif |