From: mhahnenberg@apple.com Date: Fri, 27 Jan 2012 02:30:38 +0000 (+0000) Subject: Merge AllocationSpace into MarkedSpace X-Git-Tag: 070512121124~14398 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=748f5594e66f25a582571c0a9a38ea704546d32b;p=profile%2Fivi%2Fwebkit-efl.git Merge AllocationSpace into MarkedSpace https://bugs.webkit.org/show_bug.cgi?id=77116 Reviewed by Geoffrey Garen. Merging AllocationSpace and MarkedSpace in preparation for future refactoring/enhancement to MarkedSpace allocation. * CMakeLists.txt: * GNUmakefile.list.am: * JavaScriptCore.exp: * JavaScriptCore.gypi: * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: * JavaScriptCore.xcodeproj/project.pbxproj: * Target.pri: * heap/AllocationSpace.cpp: Removed. * heap/AllocationSpace.h: Removed. * heap/BumpSpace.h: (BumpSpace): * heap/Heap.h: (JSC::Heap::objectSpace): (Heap): (): * heap/HeapBlock.h: (): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::tryAllocateHelper): (JSC): (JSC::MarkedSpace::tryAllocate): (JSC::MarkedSpace::allocateSlowCase): (JSC::MarkedSpace::allocateBlock): (JSC::MarkedSpace::freeBlocks): (TakeIfUnmarked): (JSC::TakeIfUnmarked::TakeIfUnmarked): (JSC::TakeIfUnmarked::operator()): (JSC::TakeIfUnmarked::returnValue): (JSC::MarkedSpace::shrink): (GatherDirtyCells): (JSC::GatherDirtyCells::returnValue): (JSC::GatherDirtyCells::GatherDirtyCells): (JSC::GatherDirtyCells::operator()): (JSC::MarkedSpace::gatherDirtyCells): * heap/MarkedSpace.h: (MarkedSpace): (JSC::MarkedSpace::blocks): (JSC::MarkedSpace::forEachCell): (JSC): (JSC::MarkedSpace::allocate): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106078 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 7186cb7..c7cf03a 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -73,7 +73,6 @@ SET(JavaScriptCore_SOURCES dfg/DFGSpeculativeJIT64.cpp dfg/DFGThunks.cpp - heap/AllocationSpace.cpp heap/BumpSpace.cpp heap/DFGCodeBlocks.cpp heap/Heap.cpp diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index abcb1ac..a03a3f4 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,55 @@ +2012-01-26 Mark Hahnenberg + + Merge AllocationSpace into MarkedSpace + https://bugs.webkit.org/show_bug.cgi?id=77116 + + Reviewed by Geoffrey Garen. + + Merging AllocationSpace and MarkedSpace in preparation for future refactoring/enhancement to + MarkedSpace allocation. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * heap/AllocationSpace.cpp: Removed. + * heap/AllocationSpace.h: Removed. + * heap/BumpSpace.h: + (BumpSpace): + * heap/Heap.h: + (JSC::Heap::objectSpace): + (Heap): + (): + * heap/HeapBlock.h: + (): + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::tryAllocateHelper): + (JSC): + (JSC::MarkedSpace::tryAllocate): + (JSC::MarkedSpace::allocateSlowCase): + (JSC::MarkedSpace::allocateBlock): + (JSC::MarkedSpace::freeBlocks): + (TakeIfUnmarked): + (JSC::TakeIfUnmarked::TakeIfUnmarked): + (JSC::TakeIfUnmarked::operator()): + (JSC::TakeIfUnmarked::returnValue): + (JSC::MarkedSpace::shrink): + (GatherDirtyCells): + (JSC::GatherDirtyCells::returnValue): + (JSC::GatherDirtyCells::GatherDirtyCells): + (JSC::GatherDirtyCells::operator()): + (JSC::MarkedSpace::gatherDirtyCells): + * heap/MarkedSpace.h: + (MarkedSpace): + (JSC::MarkedSpace::blocks): + (JSC::MarkedSpace::forEachCell): + (JSC): + (JSC::MarkedSpace::allocate): + 2012-01-26 Oliver Hunt MSVC bug fix. diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index 54b778d..1fc1338 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -178,8 +178,6 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGThunks.cpp \ Source/JavaScriptCore/dfg/DFGThunks.h \ Source/JavaScriptCore/dfg/DFGVariableAccessData.h \ - Source/JavaScriptCore/heap/AllocationSpace.cpp \ - Source/JavaScriptCore/heap/AllocationSpace.h \ Source/JavaScriptCore/heap/BumpBlock.h \ Source/JavaScriptCore/heap/BumpSpace.cpp \ Source/JavaScriptCore/heap/BumpSpace.h \ diff --git a/Source/JavaScriptCore/JavaScriptCore.exp b/Source/JavaScriptCore/JavaScriptCore.exp index 8a57df3..1d5bd04 100644 --- a/Source/JavaScriptCore/JavaScriptCore.exp +++ b/Source/JavaScriptCore/JavaScriptCore.exp @@ -127,6 +127,7 @@ __ZN3JSC11JSByteArray3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSVal __ZN3JSC11JSByteArray6s_infoE __ZN3JSC11JSByteArray7destroyEPNS_6JSCellE __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE +__ZN3JSC11MarkedSpace16allocateSlowCaseERNS0_9SizeClassE __ZN3JSC11ParserArena5resetEv __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE __ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE @@ -190,7 +191,6 @@ __ZN3JSC14TimeoutChecker5resetEv __ZN3JSC14VTableSpectrum5countEPNS_6JSCellE __ZN3JSC14throwTypeErrorEPNS_9ExecStateE __ZN3JSC14throwTypeErrorEPNS_9ExecStateERKNS_7UStringE -__ZN3JSC15AllocationSpace16allocateSlowCaseERNS_11MarkedSpace9SizeClassE __ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_11SlotVisitorE __ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv __ZN3JSC15WeakHandleOwnerD2Ev diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi index 9a876c2..b59be38 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gypi +++ b/Source/JavaScriptCore/JavaScriptCore.gypi @@ -27,7 +27,6 @@ 'API/OpaqueJSString.h', 'assembler/MacroAssemblerCodeRef.h', 'bytecode/Opcode.h', - 'heap/AllocationSpace.h', 'heap/BumpBlock.h', 'heap/BumpSpace.h', 'heap/BumpSpaceInlineMethods.h', @@ -333,7 +332,6 @@ 'bytecompiler/LabelScope.h', 'bytecompiler/NodesCodegen.cpp', 'bytecompiler/RegisterID.h', - 'heap/AllocationSpace.cpp', 'heap/ConservativeRoots.cpp', 'heap/HandleHeap.cpp', 'heap/HandleStack.cpp', diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 7296cdd..433135f 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -64,7 +64,7 @@ EXPORTS ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVJSGlobalData@2@PAVStringImpl@4@@Z ?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z - ?allocateSlowCase@AllocationSpace@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z + ?allocateSlowCase@MarkedSpace@JSC@@AAEPAXAAUSizeClass@12@@Z ?append@StringBuilder@WTF@@QAEXPBEI@Z ?append@StringBuilder@WTF@@QAEXPB_WI@Z ?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 4f5768a..cfb1da6 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -2006,14 +2006,6 @@ Name="heap" > - - - - diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index d4bea5d..174dbf5 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -476,8 +476,6 @@ A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1D764521354448B00C5C7C0 /* Alignment.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D764511354448B00C5C7C0 /* Alignment.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = A70456AF1427FB150037DA68 /* AllocationSpace.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A70456AE1427FB030037DA68 /* AllocationSpace.cpp */; }; A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */; }; A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; }; A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; @@ -1309,8 +1307,6 @@ A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = ""; }; A1712B4011C7B235007A5315 /* RegExpKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpKey.h; sourceTree = ""; }; A1D764511354448B00C5C7C0 /* Alignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alignment.h; sourceTree = ""; }; - A70456AE1427FB030037DA68 /* AllocationSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocationSpace.cpp; sourceTree = ""; }; - A70456AF1427FB150037DA68 /* AllocationSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocationSpace.h; sourceTree = ""; }; A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; sourceTree = ""; }; A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = ""; }; A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = ""; }; @@ -1777,8 +1773,6 @@ 142E312A134FF0A600AFADB5 /* heap */ = { isa = PBXGroup; children = ( - A70456AE1427FB030037DA68 /* AllocationSpace.cpp */, - A70456AF1427FB150037DA68 /* AllocationSpace.h */, C2C8D02E14A3CEFC00578E65 /* BumpBlock.h */, C240305314B404C90079EB64 /* BumpSpace.cpp */, C2EAA3F8149A830800FCE112 /* BumpSpace.h */, @@ -2652,7 +2646,6 @@ files = ( 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */, A1D764521354448B00C5C7C0 /* Alignment.h in Headers */, - A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */, BC18C3E40E16F5CD00B34460 /* AlwaysInline.h in Headers */, BC18C3E50E16F5CD00B34460 /* APICast.h in Headers */, 865F408810E7D56300947361 /* APIShims.h in Headers */, @@ -3413,7 +3406,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */, 147F39BD107EC37600427A48 /* ArgList.cpp in Sources */, 147F39BE107EC37600427A48 /* Arguments.cpp in Sources */, 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */, diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri index 6f44796..f2b2d74 100644 --- a/Source/JavaScriptCore/Target.pri +++ b/Source/JavaScriptCore/Target.pri @@ -65,7 +65,6 @@ SOURCES += \ bytecode/ValueProfile.cpp \ bytecompiler/BytecodeGenerator.cpp \ bytecompiler/NodesCodegen.cpp \ - heap/AllocationSpace.cpp \ heap/BumpSpace.cpp \ heap/ConservativeRoots.cpp \ heap/DFGCodeBlocks.cpp \ diff --git a/Source/JavaScriptCore/heap/AllocationSpace.cpp b/Source/JavaScriptCore/heap/AllocationSpace.cpp deleted file mode 100644 index 290f2a2..0000000 --- a/Source/JavaScriptCore/heap/AllocationSpace.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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. - * - * 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. - */ - -#include "config.h" - -#include "AllocationSpace.h" - -#include "Heap.h" - -namespace JSC { - -inline void* AllocationSpace::tryAllocate(MarkedSpace::SizeClass& sizeClass) -{ - m_heap->m_operationInProgress = Allocation; - void* result = m_markedSpace.allocate(sizeClass); - m_heap->m_operationInProgress = NoOperation; - return result; -} - -void* AllocationSpace::allocateSlowCase(MarkedSpace::SizeClass& sizeClass) -{ -#if COLLECT_ON_EVERY_ALLOCATION - m_heap->collectAllGarbage(); - ASSERT(m_heap->m_operationInProgress == NoOperation); -#endif - - void* result = tryAllocate(sizeClass); - - if (LIKELY(result != 0)) - return result; - - AllocationEffort allocationEffort; - - if (( -#if ENABLE(GGC) - m_markedSpace.nurseryWaterMark() < m_heap->m_minBytesPerCycle -#else - m_heap->waterMark() < m_heap->highWaterMark() -#endif - ) || !m_heap->m_isSafeToCollect) - allocationEffort = AllocationMustSucceed; - else - allocationEffort = AllocationCanFail; - - MarkedBlock* block = allocateBlock(sizeClass.cellSize, allocationEffort); - if (block) { - m_markedSpace.addBlock(sizeClass, block); - void* result = tryAllocate(sizeClass); - ASSERT(result); - return result; - } - - m_heap->collect(Heap::DoNotSweep); - - result = tryAllocate(sizeClass); - - if (result) - return result; - - ASSERT(m_heap->waterMark() < m_heap->highWaterMark()); - - m_markedSpace.addBlock(sizeClass, allocateBlock(sizeClass.cellSize, AllocationMustSucceed)); - - result = tryAllocate(sizeClass); - ASSERT(result); - return result; -} - -MarkedBlock* AllocationSpace::allocateBlock(size_t cellSize, AllocationEffort allocationEffort) -{ - MarkedBlock* block; - - { - MutexLocker locker(m_heap->m_freeBlockLock); - if (m_heap->m_numberOfFreeBlocks) { - block = static_cast(m_heap->m_freeBlocks.removeHead()); - ASSERT(block); - m_heap->m_numberOfFreeBlocks--; - } else - block = 0; - } - if (block) - block = MarkedBlock::recycle(block, m_heap, cellSize); - else if (allocationEffort == AllocationCanFail) - return 0; - else - block = MarkedBlock::create(m_heap, cellSize); - - m_blocks.add(block); - - return block; -} - -void AllocationSpace::freeBlocks(MarkedBlock* head) -{ - MarkedBlock* next; - for (MarkedBlock* block = head; block; block = next) { - next = static_cast(block->next()); - - m_blocks.remove(block); - block->sweep(); - MutexLocker locker(m_heap->m_freeBlockLock); - m_heap->m_freeBlocks.append(block); - m_heap->m_numberOfFreeBlocks++; - } -} - -class TakeIfUnmarked { -public: - typedef MarkedBlock* ReturnType; - - TakeIfUnmarked(MarkedSpace*); - void operator()(MarkedBlock*); - ReturnType returnValue(); - -private: - MarkedSpace* m_markedSpace; - DoublyLinkedList m_empties; -}; - -inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace) - : m_markedSpace(newSpace) -{ -} - -inline void TakeIfUnmarked::operator()(MarkedBlock* block) -{ - if (!block->markCountIsZero()) - return; - - m_markedSpace->removeBlock(block); - m_empties.append(block); -} - -inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue() -{ - return m_empties.head(); -} - -void AllocationSpace::shrink() -{ - // We record a temporary list of empties to avoid modifying m_blocks while iterating it. - TakeIfUnmarked takeIfUnmarked(&m_markedSpace); - freeBlocks(forEachBlock(takeIfUnmarked)); -} - -#if ENABLE(GGC) -class GatherDirtyCells { - WTF_MAKE_NONCOPYABLE(GatherDirtyCells); -public: - typedef void* ReturnType; - - explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*); - void operator()(MarkedBlock*); - ReturnType returnValue() { return 0; } - -private: - MarkedBlock::DirtyCellVector* m_dirtyCells; -}; - -inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells) - : m_dirtyCells(dirtyCells) -{ -} - -inline void GatherDirtyCells::operator()(MarkedBlock* block) -{ - block->gatherDirtyCells(*m_dirtyCells); -} - -void AllocationSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells) -{ - GatherDirtyCells gatherDirtyCells(&dirtyCells); - forEachBlock(gatherDirtyCells); -} -#endif - -} diff --git a/Source/JavaScriptCore/heap/AllocationSpace.h b/Source/JavaScriptCore/heap/AllocationSpace.h deleted file mode 100644 index 45a6b5a..0000000 --- a/Source/JavaScriptCore/heap/AllocationSpace.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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. - * - * 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 AllocationSpace_h -#define AllocationSpace_h - -#include "MarkedBlockSet.h" -#include "MarkedSpace.h" - -#include - -namespace JSC { - -class Heap; -class MarkedBlock; - -class AllocationSpace { -public: - AllocationSpace(Heap* heap) - : m_heap(heap) - , m_markedSpace(heap) - { - } - - typedef HashSet::iterator BlockIterator; - - MarkedBlockSet& blocks() { return m_blocks; } - MarkedSpace::SizeClass& sizeClassFor(size_t bytes) { return m_markedSpace.sizeClassFor(bytes); } - size_t waterMark() { return m_markedSpace.waterMark(); } - -#if ENABLE(GGC) - void gatherDirtyCells(MarkedBlock::DirtyCellVector&); -#endif - - template typename Functor::ReturnType forEachCell(Functor&); - template typename Functor::ReturnType forEachCell(); - template typename Functor::ReturnType forEachBlock(Functor&); - template typename Functor::ReturnType forEachBlock(); - - void canonicalizeCellLivenessData() { m_markedSpace.canonicalizeCellLivenessData(); } - void resetAllocator() { m_markedSpace.resetAllocator(); } - - void* allocate(size_t); - void freeBlocks(MarkedBlock*); - void shrink(); - -private: - enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; - - void* allocate(MarkedSpace::SizeClass&); - void* tryAllocate(MarkedSpace::SizeClass&); - JS_EXPORT_PRIVATE void* allocateSlowCase(MarkedSpace::SizeClass&); - MarkedBlock* allocateBlock(size_t cellSize, AllocationEffort); - - Heap* m_heap; - MarkedSpace m_markedSpace; - MarkedBlockSet m_blocks; -}; - -template inline typename Functor::ReturnType AllocationSpace::forEachCell(Functor& functor) -{ - canonicalizeCellLivenessData(); - - BlockIterator end = m_blocks.set().end(); - for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) - (*it)->forEachCell(functor); - return functor.returnValue(); -} - -template inline typename Functor::ReturnType AllocationSpace::forEachCell() -{ - Functor functor; - return forEachCell(functor); -} - -template inline typename Functor::ReturnType AllocationSpace::forEachBlock(Functor& functor) -{ - BlockIterator end = m_blocks.set().end(); - for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) - functor(*it); - return functor.returnValue(); -} - -template inline typename Functor::ReturnType AllocationSpace::forEachBlock() -{ - Functor functor; - return forEachBlock(functor); -} - -inline void* AllocationSpace::allocate(MarkedSpace::SizeClass& sizeClass) -{ - // This is a light-weight fast path to cover the most common case. - MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell; - if (UNLIKELY(!firstFreeCell)) - return allocateSlowCase(sizeClass); - - sizeClass.firstFreeCell = firstFreeCell->next; - return firstFreeCell; -} - -inline void* AllocationSpace::allocate(size_t bytes) -{ - MarkedSpace::SizeClass& sizeClass = sizeClassFor(bytes); - return allocate(sizeClass); -} - -} - -#endif diff --git a/Source/JavaScriptCore/heap/BumpSpace.h b/Source/JavaScriptCore/heap/BumpSpace.h index 1ffcb46..30e6b74 100644 --- a/Source/JavaScriptCore/heap/BumpSpace.h +++ b/Source/JavaScriptCore/heap/BumpSpace.h @@ -26,6 +26,7 @@ #ifndef BumpSpace_h #define BumpSpace_h +#include "HeapBlock.h" #include "TinyBloomFilter.h" #include #include @@ -66,8 +67,6 @@ public: static BumpBlock* blockFor(void*); private: - enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; - CheckedBoolean tryAllocateSlowCase(size_t, void**); CheckedBoolean addNewBlock(); CheckedBoolean allocateNewBlock(BumpBlock**); diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index 44a6f86..40a8376 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -22,7 +22,6 @@ #ifndef Heap_h #define Heap_h -#include "AllocationSpace.h" #include "DFGCodeBlocks.h" #include "HandleHeap.h" #include "HandleStack.h" @@ -86,7 +85,7 @@ namespace JSC { JS_EXPORT_PRIVATE void destroy(); // JSGlobalData must call destroy() before ~Heap(). JSGlobalData* globalData() const { return m_globalData; } - AllocationSpace& objectSpace() { return m_objectSpace; } + MarkedSpace& objectSpace() { return m_objectSpace; } MachineThreads& machineThreads() { return m_machineThreads; } JS_EXPORT_PRIVATE GCActivityCallback* activityCallback(); @@ -136,8 +135,8 @@ namespace JSC { void getConservativeRegisterRoots(HashSet& roots); private: + friend class MarkedSpace; friend class MarkedBlock; - friend class AllocationSpace; friend class BumpSpace; friend class SlotVisitor; friend class CodeBlock; @@ -191,7 +190,7 @@ namespace JSC { size_t m_highWaterMark; OperationInProgress m_operationInProgress; - AllocationSpace m_objectSpace; + MarkedSpace m_objectSpace; BumpSpace m_storageSpace; DoublyLinkedList m_freeBlocks; diff --git a/Source/JavaScriptCore/heap/HeapBlock.h b/Source/JavaScriptCore/heap/HeapBlock.h index 1d66aad..b0ecb20 100644 --- a/Source/JavaScriptCore/heap/HeapBlock.h +++ b/Source/JavaScriptCore/heap/HeapBlock.h @@ -31,6 +31,8 @@ namespace JSC { +enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; + class HeapBlock : public DoublyLinkedListNode { public: HeapBlock(PageAllocationAligned& allocation) diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp index c12e9ba..fcca188 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.cpp +++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp @@ -81,4 +81,192 @@ void MarkedSpace::canonicalizeCellLivenessData() sizeClassFor(cellSize).zapFreeList(); } +inline void* MarkedSpace::tryAllocateHelper(MarkedSpace::SizeClass& sizeClass) +{ + MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell; + if (!firstFreeCell) { + for (MarkedBlock*& block = sizeClass.currentBlock; block; block = static_cast(block->next())) { + firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); + if (firstFreeCell) + break; + m_nurseryWaterMark += block->capacity() - block->size(); + m_waterMark += block->capacity(); + block->didConsumeFreeList(); + } + + if (!firstFreeCell) + return 0; + } + + ASSERT(firstFreeCell); + sizeClass.firstFreeCell = firstFreeCell->next; + return firstFreeCell; +} + +inline void* MarkedSpace::tryAllocate(MarkedSpace::SizeClass& sizeClass) +{ + m_heap->m_operationInProgress = Allocation; + void* result = tryAllocateHelper(sizeClass); + m_heap->m_operationInProgress = NoOperation; + return result; +} + +void* MarkedSpace::allocateSlowCase(MarkedSpace::SizeClass& sizeClass) +{ +#if COLLECT_ON_EVERY_ALLOCATION + m_heap->collectAllGarbage(); + ASSERT(m_heap->m_operationInProgress == NoOperation); +#endif + + void* result = tryAllocate(sizeClass); + + if (LIKELY(result != 0)) + return result; + + AllocationEffort allocationEffort; + + if (( +#if ENABLE(GGC) + nurseryWaterMark() < m_heap->m_minBytesPerCycle +#else + m_heap->waterMark() < m_heap->highWaterMark() +#endif + ) || !m_heap->m_isSafeToCollect) + allocationEffort = AllocationMustSucceed; + else + allocationEffort = AllocationCanFail; + + MarkedBlock* block = allocateBlock(sizeClass.cellSize, allocationEffort); + if (block) { + addBlock(sizeClass, block); + void* result = tryAllocate(sizeClass); + ASSERT(result); + return result; + } + + m_heap->collect(Heap::DoNotSweep); + + result = tryAllocate(sizeClass); + + if (result) + return result; + + ASSERT(m_heap->waterMark() < m_heap->highWaterMark()); + + addBlock(sizeClass, allocateBlock(sizeClass.cellSize, AllocationMustSucceed)); + + result = tryAllocate(sizeClass); + ASSERT(result); + return result; +} + +MarkedBlock* MarkedSpace::allocateBlock(size_t cellSize, AllocationEffort allocationEffort) +{ + MarkedBlock* block; + + { + MutexLocker locker(m_heap->m_freeBlockLock); + if (m_heap->m_numberOfFreeBlocks) { + block = static_cast(m_heap->m_freeBlocks.removeHead()); + ASSERT(block); + m_heap->m_numberOfFreeBlocks--; + } else + block = 0; + } + if (block) + block = MarkedBlock::recycle(block, m_heap, cellSize); + else if (allocationEffort == AllocationCanFail) + return 0; + else + block = MarkedBlock::create(m_heap, cellSize); + + m_blocks.add(block); + + return block; +} + +void MarkedSpace::freeBlocks(MarkedBlock* head) +{ + MarkedBlock* next; + for (MarkedBlock* block = head; block; block = next) { + next = static_cast(block->next()); + + m_blocks.remove(block); + block->sweep(); + MutexLocker locker(m_heap->m_freeBlockLock); + m_heap->m_freeBlocks.append(block); + m_heap->m_numberOfFreeBlocks++; + } +} + +class TakeIfUnmarked { +public: + typedef MarkedBlock* ReturnType; + + TakeIfUnmarked(MarkedSpace*); + void operator()(MarkedBlock*); + ReturnType returnValue(); + +private: + MarkedSpace* m_markedSpace; + DoublyLinkedList m_empties; +}; + +inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace) + : m_markedSpace(newSpace) +{ +} + +inline void TakeIfUnmarked::operator()(MarkedBlock* block) +{ + if (!block->markCountIsZero()) + return; + + m_markedSpace->removeBlock(block); + m_empties.append(block); +} + +inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue() +{ + return m_empties.head(); +} + +void MarkedSpace::shrink() +{ + // We record a temporary list of empties to avoid modifying m_blocks while iterating it. + TakeIfUnmarked takeIfUnmarked(this); + freeBlocks(forEachBlock(takeIfUnmarked)); +} + +#if ENABLE(GGC) +class GatherDirtyCells { + WTF_MAKE_NONCOPYABLE(GatherDirtyCells); +public: + typedef void* ReturnType; + + explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*); + void operator()(MarkedBlock*); + ReturnType returnValue() { return 0; } + +private: + MarkedBlock::DirtyCellVector* m_dirtyCells; +}; + +inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells) + : m_dirtyCells(dirtyCells) +{ +} + +inline void GatherDirtyCells::operator()(MarkedBlock* block) +{ + block->gatherDirtyCells(*m_dirtyCells); +} + +void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells) +{ + GatherDirtyCells gatherDirtyCells(&dirtyCells); + forEachBlock(gatherDirtyCells); +} +#endif + } // namespace JSC diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index 3b2c828..0854efc 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -24,6 +24,7 @@ #include "MachineStackMarker.h" #include "MarkedBlock.h" +#include "MarkedBlockSet.h" #include "PageAllocationAligned.h" #include #include @@ -61,22 +62,36 @@ public: MarkedSpace(Heap*); SizeClass& sizeClassFor(size_t); + void* allocate(size_t); void* allocate(SizeClass&); void resetAllocator(); void addBlock(SizeClass&, MarkedBlock*); void removeBlock(MarkedBlock*); + MarkedBlockSet& blocks() { return m_blocks; } void canonicalizeCellLivenessData(); size_t waterMark(); size_t nurseryWaterMark(); - template typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating. + typedef HashSet::iterator BlockIterator; + + template typename Functor::ReturnType forEachCell(Functor&); + template typename Functor::ReturnType forEachCell(); + template typename Functor::ReturnType forEachBlock(Functor&); template typename Functor::ReturnType forEachBlock(); + + void shrink(); + void freeBlocks(MarkedBlock* head); private: + void* allocateSlowCase(SizeClass&); + void* tryAllocateHelper(MarkedSpace::SizeClass&); + void* tryAllocate(MarkedSpace::SizeClass&); + MarkedBlock* allocateBlock(size_t, AllocationEffort); + // [ 32... 256 ] static const size_t preciseStep = MarkedBlock::atomSize; static const size_t preciseCutoff = 256; @@ -92,6 +107,7 @@ private: size_t m_waterMark; size_t m_nurseryWaterMark; Heap* m_heap; + MarkedBlockSet m_blocks; }; inline size_t MarkedSpace::waterMark() @@ -104,6 +120,22 @@ inline size_t MarkedSpace::nurseryWaterMark() return m_nurseryWaterMark; } +template inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor) +{ + canonicalizeCellLivenessData(); + + BlockIterator end = m_blocks.set().end(); + for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) + (*it)->forEachCell(functor); + return functor.returnValue(); +} + +template inline typename Functor::ReturnType MarkedSpace::forEachCell() +{ + Functor functor; + return forEachCell(functor); +} + inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes) { ASSERT(bytes && bytes <= maxCellSize); @@ -112,25 +144,19 @@ inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes) return m_impreciseSizeClasses[(bytes - 1) / impreciseStep]; } +inline void* MarkedSpace::allocate(size_t bytes) +{ + SizeClass& sizeClass = sizeClassFor(bytes); + return allocate(sizeClass); +} + inline void* MarkedSpace::allocate(SizeClass& sizeClass) { + // This is a light-weight fast path to cover the most common case. MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell; - if (!firstFreeCell) { - for (MarkedBlock*& block = sizeClass.currentBlock; block; block = static_cast(block->next())) { - firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); - if (firstFreeCell) - break; - m_nurseryWaterMark += block->capacity() - block->size(); - m_waterMark += block->capacity(); - block->didConsumeFreeList(); - } - - if (!firstFreeCell) - return 0; - } - - ASSERT(firstFreeCell); - + if (UNLIKELY(!firstFreeCell)) + return allocateSlowCase(sizeClass); + sizeClass.firstFreeCell = firstFreeCell->next; return firstFreeCell; }