diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/heap/Region.h | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-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.h | 319 |
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 |