summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap/Region.h
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/heap/Region.h
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/heap/Region.h')
-rw-r--r--Source/JavaScriptCore/heap/Region.h319
1 files changed, 319 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/Region.h b/Source/JavaScriptCore/heap/Region.h
new file mode 100644
index 000000000..366f25643
--- /dev/null
+++ b/Source/JavaScriptCore/heap/Region.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 JSC_Region_h
+#define JSC_Region_h
+
+#include "HeapBlock.h"
+#include "SuperRegion.h"
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/MetaAllocatorHandle.h>
+#include <wtf/PageAllocationAligned.h>
+
+#define HEAP_MEMORY_ID reinterpret_cast<void*>(static_cast<intptr_t>(-3))
+
+#define ENABLE_SUPER_REGION 0
+
+#ifndef ENABLE_SUPER_REGION
+#if USE(JSVALUE64)
+#define ENABLE_SUPER_REGION 1
+#else
+#define ENABLE_SUPER_REGION 0
+#endif
+#endif
+
+namespace JSC {
+
+class DeadBlock : public HeapBlock<DeadBlock> {
+public:
+ DeadBlock(Region*);
+};
+
+inline DeadBlock::DeadBlock(Region* region)
+ : HeapBlock<DeadBlock>(region)
+{
+}
+
+class Region : public DoublyLinkedListNode<Region> {
+ friend CLASS_IF_GCC DoublyLinkedListNode<Region>;
+ friend class BlockAllocator;
+public:
+ ~Region();
+ static Region* create(SuperRegion*, size_t blockSize);
+ static Region* createCustomSize(SuperRegion*, size_t blockSize, size_t blockAlignment);
+ Region* reset(size_t blockSize);
+ void destroy();
+
+ size_t blockSize() const { return m_blockSize; }
+ bool isFull() const { return m_blocksInUse == m_totalBlocks; }
+ bool isEmpty() const { return !m_blocksInUse; }
+ bool isCustomSize() const { return m_isCustomSize; }
+
+ DeadBlock* allocate();
+ void deallocate(void*);
+
+ static const size_t s_regionSize = 64 * KB;
+ static const size_t s_regionMask = ~(s_regionSize - 1);
+
+protected:
+ Region(size_t blockSize, size_t totalBlocks, bool isExcess);
+ void initializeBlockList();
+
+ bool m_isExcess;
+
+private:
+ void* base();
+ size_t size();
+
+ size_t m_totalBlocks;
+ size_t m_blocksInUse;
+ size_t m_blockSize;
+ bool m_isCustomSize;
+ Region* m_prev;
+ Region* m_next;
+ DoublyLinkedList<DeadBlock> m_deadBlocks;
+};
+
+
+class NormalRegion : public Region {
+ friend class Region;
+private:
+ NormalRegion(PassRefPtr<WTF::MetaAllocatorHandle>, size_t blockSize, size_t totalBlocks);
+
+ static NormalRegion* tryCreate(SuperRegion*, size_t blockSize);
+ static NormalRegion* tryCreateCustomSize(SuperRegion*, size_t blockSize, size_t blockAlignment);
+
+ void* base() { return m_allocation->start(); }
+ size_t size() { return m_allocation->sizeInBytes(); }
+
+ NormalRegion* reset(size_t blockSize);
+
+ RefPtr<WTF::MetaAllocatorHandle> m_allocation;
+};
+
+class ExcessRegion : public Region {
+ friend class Region;
+private:
+ ExcessRegion(PageAllocationAligned&, size_t blockSize, size_t totalBlocks);
+
+ ~ExcessRegion();
+
+ static ExcessRegion* create(size_t blockSize);
+ static ExcessRegion* createCustomSize(size_t blockSize, size_t blockAlignment);
+
+ void* base() { return m_allocation.base(); }
+ size_t size() { return m_allocation.size(); }
+
+ ExcessRegion* reset(size_t blockSize);
+
+ PageAllocationAligned m_allocation;
+};
+
+inline NormalRegion::NormalRegion(PassRefPtr<WTF::MetaAllocatorHandle> allocation, size_t blockSize, size_t totalBlocks)
+ : Region(blockSize, totalBlocks, false)
+ , m_allocation(allocation)
+{
+ initializeBlockList();
+}
+
+inline NormalRegion* NormalRegion::tryCreate(SuperRegion* superRegion, size_t blockSize)
+{
+ RefPtr<WTF::MetaAllocatorHandle> allocation = superRegion->allocate(s_regionSize, HEAP_MEMORY_ID);
+ if (!allocation)
+ return 0;
+ return new NormalRegion(allocation, blockSize, s_regionSize / blockSize);
+}
+
+inline NormalRegion* NormalRegion::tryCreateCustomSize(SuperRegion* superRegion, size_t blockSize, size_t blockAlignment)
+{
+ ASSERT_UNUSED(blockAlignment, blockAlignment <= s_regionSize);
+ RefPtr<WTF::MetaAllocatorHandle> allocation = superRegion->allocate(blockSize, HEAP_MEMORY_ID);
+ if (!allocation)
+ return 0;
+ return new NormalRegion(allocation, blockSize, 1);
+}
+
+inline NormalRegion* NormalRegion::reset(size_t blockSize)
+{
+ ASSERT(!m_isExcess);
+ RefPtr<WTF::MetaAllocatorHandle> allocation = m_allocation.release();
+ return new (NotNull, this) NormalRegion(allocation.release(), blockSize, s_regionSize / blockSize);
+}
+
+inline ExcessRegion::ExcessRegion(PageAllocationAligned& allocation, size_t blockSize, size_t totalBlocks)
+ : Region(blockSize, totalBlocks, true)
+ , m_allocation(allocation)
+{
+ initializeBlockList();
+}
+
+inline ExcessRegion::~ExcessRegion()
+{
+ m_allocation.deallocate();
+}
+
+inline ExcessRegion* ExcessRegion::create(size_t blockSize)
+{
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(s_regionSize, s_regionSize, OSAllocator::JSGCHeapPages);
+ ASSERT(static_cast<bool>(allocation));
+ return new ExcessRegion(allocation, blockSize, s_regionSize / blockSize);
+}
+
+inline ExcessRegion* ExcessRegion::createCustomSize(size_t blockSize, size_t blockAlignment)
+{
+ PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockAlignment, OSAllocator::JSGCHeapPages);
+ ASSERT(static_cast<bool>(allocation));
+ return new ExcessRegion(allocation, blockSize, 1);
+}
+
+inline ExcessRegion* ExcessRegion::reset(size_t blockSize)
+{
+ ASSERT(m_isExcess);
+ PageAllocationAligned allocation = m_allocation;
+ return new (NotNull, this) ExcessRegion(allocation, blockSize, s_regionSize / blockSize);
+}
+
+inline Region::Region(size_t blockSize, size_t totalBlocks, bool isExcess)
+ : DoublyLinkedListNode<Region>()
+ , m_isExcess(isExcess)
+ , m_totalBlocks(totalBlocks)
+ , m_blocksInUse(0)
+ , m_blockSize(blockSize)
+ , m_isCustomSize(false)
+ , m_prev(0)
+ , m_next(0)
+{
+}
+
+inline void Region::initializeBlockList()
+{
+ char* start = static_cast<char*>(base());
+ char* current = start;
+ for (size_t i = 0; i < m_totalBlocks; i++) {
+ ASSERT(current < start + size());
+ m_deadBlocks.append(new (NotNull, current) DeadBlock(this));
+ current += m_blockSize;
+ }
+}
+
+inline Region* Region::create(SuperRegion* superRegion, size_t blockSize)
+{
+#if ENABLE(SUPER_REGION)
+ ASSERT(blockSize <= s_regionSize);
+ ASSERT(!(s_regionSize % blockSize));
+ Region* region = NormalRegion::tryCreate(superRegion, blockSize);
+ if (LIKELY(!!region))
+ return region;
+#else
+ UNUSED_PARAM(superRegion);
+#endif
+ return ExcessRegion::create(blockSize);
+}
+
+inline Region* Region::createCustomSize(SuperRegion* superRegion, size_t blockSize, size_t blockAlignment)
+{
+#if ENABLE(SUPER_REGION)
+ Region* region = NormalRegion::tryCreateCustomSize(superRegion, blockSize, blockAlignment);
+ if (UNLIKELY(!region))
+ region = ExcessRegion::createCustomSize(blockSize, blockAlignment);
+#else
+ UNUSED_PARAM(superRegion);
+ Region* region = ExcessRegion::createCustomSize(blockSize, blockAlignment);
+#endif
+ region->m_isCustomSize = true;
+ return region;
+}
+
+inline Region::~Region()
+{
+ ASSERT(isEmpty());
+}
+
+inline void Region::destroy()
+{
+#if ENABLE(SUPER_REGION)
+ if (UNLIKELY(m_isExcess))
+ delete static_cast<ExcessRegion*>(this);
+ else
+ delete static_cast<NormalRegion*>(this);
+#else
+ delete static_cast<ExcessRegion*>(this);
+#endif
+}
+
+inline Region* Region::reset(size_t blockSize)
+{
+#if ENABLE(SUPER_REGION)
+ ASSERT(isEmpty());
+ if (UNLIKELY(m_isExcess))
+ return static_cast<ExcessRegion*>(this)->reset(blockSize);
+ return static_cast<NormalRegion*>(this)->reset(blockSize);
+#else
+ return static_cast<ExcessRegion*>(this)->reset(blockSize);
+#endif
+}
+
+inline DeadBlock* Region::allocate()
+{
+ ASSERT(!isFull());
+ m_blocksInUse++;
+ return m_deadBlocks.removeHead();
+}
+
+inline void Region::deallocate(void* base)
+{
+ ASSERT(base);
+ ASSERT(m_blocksInUse);
+ ASSERT(base >= this->base() && base < static_cast<char*>(this->base()) + size());
+ DeadBlock* block = new (NotNull, base) DeadBlock(this);
+ m_deadBlocks.push(block);
+ m_blocksInUse--;
+}
+
+inline void* Region::base()
+{
+#if ENABLE(SUPER_REGION)
+ if (UNLIKELY(m_isExcess))
+ return static_cast<ExcessRegion*>(this)->ExcessRegion::base();
+ return static_cast<NormalRegion*>(this)->NormalRegion::base();
+#else
+ return static_cast<ExcessRegion*>(this)->ExcessRegion::base();
+#endif
+}
+
+inline size_t Region::size()
+{
+#if ENABLE(SUPER_REGION)
+ if (UNLIKELY(m_isExcess))
+ return static_cast<ExcessRegion*>(this)->ExcessRegion::size();
+ return static_cast<NormalRegion*>(this)->NormalRegion::size();
+#else
+ return static_cast<ExcessRegion*>(this)->ExcessRegion::size();
+#endif
+}
+
+} // namespace JSC
+
+#endif // JSC_Region_h