dfg/DFGSpeculativeJIT64.cpp
dfg/DFGThunks.cpp
- heap/AllocationSpace.cpp
heap/BumpSpace.cpp
heap/DFGCodeBlocks.cpp
heap/Heap.cpp
+2012-01-26 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ 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 <oliver@apple.com>
MSVC bug fix.
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 \
__ZN3JSC11JSByteArray6s_infoE
__ZN3JSC11JSByteArray7destroyEPNS_6JSCellE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
+__ZN3JSC11MarkedSpace16allocateSlowCaseERNS0_9SizeClassE
__ZN3JSC11ParserArena5resetEv
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE
__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC14VTableSpectrum5countEPNS_6JSCellE
__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
__ZN3JSC14throwTypeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC15AllocationSpace16allocateSlowCaseERNS_11MarkedSpace9SizeClassE
__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_11SlotVisitorE
__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
__ZN3JSC15WeakHandleOwnerD2Ev
'API/OpaqueJSString.h',
'assembler/MacroAssemblerCodeRef.h',
'bytecode/Opcode.h',
- 'heap/AllocationSpace.h',
'heap/BumpBlock.h',
'heap/BumpSpace.h',
'heap/BumpSpaceInlineMethods.h',
'bytecompiler/LabelScope.h',
'bytecompiler/NodesCodegen.cpp',
'bytecompiler/RegisterID.h',
- 'heap/AllocationSpace.cpp',
'heap/ConservativeRoots.cpp',
'heap/HandleHeap.cpp',
'heap/HandleStack.cpp',
?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
Name="heap"
>
<File
- RelativePath="..\..\heap\AllocationSpace.cpp"
- >
- </File>
- <File
- RelativePath="..\..\heap\AllocationSpace.h"
- >
- </File>
- <File
RelativePath="..\..\heap\BumpBlock.h"
>
</File>
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 */; };
A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; };
A1712B4011C7B235007A5315 /* RegExpKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpKey.h; sourceTree = "<group>"; };
A1D764511354448B00C5C7C0 /* Alignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alignment.h; sourceTree = "<group>"; };
- A70456AE1427FB030037DA68 /* AllocationSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllocationSpace.cpp; sourceTree = "<group>"; };
- A70456AF1427FB150037DA68 /* AllocationSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocationSpace.h; sourceTree = "<group>"; };
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; sourceTree = "<group>"; };
A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = "<group>"; };
A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = "<group>"; };
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
- A70456AE1427FB030037DA68 /* AllocationSpace.cpp */,
- A70456AF1427FB150037DA68 /* AllocationSpace.h */,
C2C8D02E14A3CEFC00578E65 /* BumpBlock.h */,
C240305314B404C90079EB64 /* BumpSpace.cpp */,
C2EAA3F8149A830800FCE112 /* BumpSpace.h */,
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 */,
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 */,
bytecode/ValueProfile.cpp \
bytecompiler/BytecodeGenerator.cpp \
bytecompiler/NodesCodegen.cpp \
- heap/AllocationSpace.cpp \
heap/BumpSpace.cpp \
heap/ConservativeRoots.cpp \
heap/DFGCodeBlocks.cpp \
+++ /dev/null
-/*
- * 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<MarkedBlock*>(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<MarkedBlock*>(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<MarkedBlock> 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
-
-}
+++ /dev/null
-/*
- * 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 <wtf/HashSet.h>
-
-namespace JSC {
-
-class Heap;
-class MarkedBlock;
-
-class AllocationSpace {
-public:
- AllocationSpace(Heap* heap)
- : m_heap(heap)
- , m_markedSpace(heap)
- {
- }
-
- typedef HashSet<MarkedBlock*>::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> typename Functor::ReturnType forEachCell(Functor&);
- template<typename Functor> typename Functor::ReturnType forEachCell();
- template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
- template<typename Functor> 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<typename Functor> 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<typename Functor> inline typename Functor::ReturnType AllocationSpace::forEachCell()
-{
- Functor functor;
- return forEachCell(functor);
-}
-
-template<typename Functor> 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<typename Functor> 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
#ifndef BumpSpace_h
#define BumpSpace_h
+#include "HeapBlock.h"
#include "TinyBloomFilter.h"
#include <wtf/Assertions.h>
#include <wtf/CheckedBoolean.h>
static BumpBlock* blockFor(void*);
private:
- enum AllocationEffort { AllocationCanFail, AllocationMustSucceed };
-
CheckedBoolean tryAllocateSlowCase(size_t, void**);
CheckedBoolean addNewBlock();
CheckedBoolean allocateNewBlock(BumpBlock**);
#ifndef Heap_h
#define Heap_h
-#include "AllocationSpace.h"
#include "DFGCodeBlocks.h"
#include "HandleHeap.h"
#include "HandleStack.h"
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();
void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
private:
+ friend class MarkedSpace;
friend class MarkedBlock;
- friend class AllocationSpace;
friend class BumpSpace;
friend class SlotVisitor;
friend class CodeBlock;
size_t m_highWaterMark;
OperationInProgress m_operationInProgress;
- AllocationSpace m_objectSpace;
+ MarkedSpace m_objectSpace;
BumpSpace m_storageSpace;
DoublyLinkedList<HeapBlock> m_freeBlocks;
namespace JSC {
+enum AllocationEffort { AllocationCanFail, AllocationMustSucceed };
+
class HeapBlock : public DoublyLinkedListNode<HeapBlock> {
public:
HeapBlock(PageAllocationAligned& allocation)
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<MarkedBlock*>(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<MarkedBlock*>(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<MarkedBlock*>(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<MarkedBlock> 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
#include "MachineStackMarker.h"
#include "MarkedBlock.h"
+#include "MarkedBlockSet.h"
#include "PageAllocationAligned.h"
#include <wtf/Bitmap.h>
#include <wtf/DoublyLinkedList.h>
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> typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating.
+ typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+
+ template<typename Functor> typename Functor::ReturnType forEachCell(Functor&);
+ template<typename Functor> typename Functor::ReturnType forEachCell();
+ template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
template<typename Functor> 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;
size_t m_waterMark;
size_t m_nurseryWaterMark;
Heap* m_heap;
+ MarkedBlockSet m_blocks;
};
inline size_t MarkedSpace::waterMark()
return m_nurseryWaterMark;
}
+template<typename Functor> 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<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell()
+{
+ Functor functor;
+ return forEachCell(functor);
+}
+
inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
{
ASSERT(bytes && bytes <= maxCellSize);
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<MarkedBlock*>(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;
}