summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime/AlignedMemoryAllocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime/AlignedMemoryAllocator.h')
-rw-r--r--JavaScriptCore/runtime/AlignedMemoryAllocator.h239
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