Commit 44d8954c authored by oliver@apple.com's avatar oliver@apple.com

Refactor Heap allocation logic into separate AllocationSpace class

https://bugs.webkit.org/show_bug.cgi?id=68409

Reviewed by Gavin Barraclough.

../../../../Volumes/Data/git/WebKit/OpenSource/Source/JavaScriptCore:

This patch hoists direct manipulation of the MarkedSpace and related
data out of Heap and into a separate class.  This will allow us to
have multiple allocation spaces in future, so easing the way towards
having GC'd backing stores for objects.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.exp:
* JavaScriptCore.gypi:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions):
* heap/AllocationSpace.cpp: Added.
(JSC::AllocationSpace::tryAllocate):
(JSC::AllocationSpace::allocateSlowCase):
(JSC::AllocationSpace::allocateBlock):
(JSC::AllocationSpace::freeBlocks):
(JSC::TakeIfEmpty::TakeIfEmpty):
(JSC::TakeIfEmpty::operator()):
(JSC::TakeIfEmpty::returnValue):
(JSC::AllocationSpace::shrink):
* heap/AllocationSpace.h: Added.
(JSC::AllocationSpace::AllocationSpace):
(JSC::AllocationSpace::blocks):
(JSC::AllocationSpace::sizeClassFor):
(JSC::AllocationSpace::setHighWaterMark):
(JSC::AllocationSpace::highWaterMark):
(JSC::AllocationSpace::canonicalizeBlocks):
(JSC::AllocationSpace::resetAllocator):
(JSC::AllocationSpace::forEachCell):
(JSC::AllocationSpace::forEachBlock):
(JSC::AllocationSpace::allocate):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::reportExtraMemoryCostSlowCase):
(JSC::Heap::getConservativeRegisterRoots):
(JSC::Heap::markRoots):
(JSC::Heap::clearMarks):
(JSC::Heap::sweep):
(JSC::Heap::objectCount):
(JSC::Heap::size):
(JSC::Heap::capacity):
(JSC::Heap::globalObjectCount):
(JSC::Heap::objectTypeCounts):
(JSC::Heap::collect):
(JSC::Heap::canonicalizeBlocks):
(JSC::Heap::resetAllocator):
(JSC::Heap::freeBlocks):
(JSC::Heap::shrink):
* heap/Heap.h:
(JSC::Heap::objectSpace):
(JSC::Heap::sizeClassForObject):
(JSC::Heap::allocate):
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateBasicJSObject):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::recompileAllJSFunctions):
(JSC::JSGlobalData::releaseExecutableMemory):

../../../../Volumes/Data/git/WebKit/OpenSource/Source/WebCore:

Adding a forwarding header.

* ForwardingHeaders/heap/AllocationSpace.h: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95559 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1afa292f
......@@ -45,6 +45,7 @@ SET(JavaScriptCore_SOURCES
bytecompiler/BytecodeGenerator.cpp
bytecompiler/NodesCodegen.cpp
heap/AllocationSpace.cpp
heap/Heap.cpp
heap/HandleHeap.cpp
heap/HandleStack.cpp
......
2011-09-19 Oliver Hunt <oliver@apple.com>
Refactor Heap allocation logic into separate AllocationSpace class
https://bugs.webkit.org/show_bug.cgi?id=68409
Reviewed by Gavin Barraclough.
This patch hoists direct manipulation of the MarkedSpace and related
data out of Heap and into a separate class. This will allow us to
have multiple allocation spaces in future, so easing the way towards
having GC'd backing stores for objects.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.exp:
* JavaScriptCore.gypi:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* debugger/Debugger.cpp:
(JSC::Debugger::recompileAllJSFunctions):
* heap/AllocationSpace.cpp: Added.
(JSC::AllocationSpace::tryAllocate):
(JSC::AllocationSpace::allocateSlowCase):
(JSC::AllocationSpace::allocateBlock):
(JSC::AllocationSpace::freeBlocks):
(JSC::TakeIfEmpty::TakeIfEmpty):
(JSC::TakeIfEmpty::operator()):
(JSC::TakeIfEmpty::returnValue):
(JSC::AllocationSpace::shrink):
* heap/AllocationSpace.h: Added.
(JSC::AllocationSpace::AllocationSpace):
(JSC::AllocationSpace::blocks):
(JSC::AllocationSpace::sizeClassFor):
(JSC::AllocationSpace::setHighWaterMark):
(JSC::AllocationSpace::highWaterMark):
(JSC::AllocationSpace::canonicalizeBlocks):
(JSC::AllocationSpace::resetAllocator):
(JSC::AllocationSpace::forEachCell):
(JSC::AllocationSpace::forEachBlock):
(JSC::AllocationSpace::allocate):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::reportExtraMemoryCostSlowCase):
(JSC::Heap::getConservativeRegisterRoots):
(JSC::Heap::markRoots):
(JSC::Heap::clearMarks):
(JSC::Heap::sweep):
(JSC::Heap::objectCount):
(JSC::Heap::size):
(JSC::Heap::capacity):
(JSC::Heap::globalObjectCount):
(JSC::Heap::objectTypeCounts):
(JSC::Heap::collect):
(JSC::Heap::canonicalizeBlocks):
(JSC::Heap::resetAllocator):
(JSC::Heap::freeBlocks):
(JSC::Heap::shrink):
* heap/Heap.h:
(JSC::Heap::objectSpace):
(JSC::Heap::sizeClassForObject):
(JSC::Heap::allocate):
* jit/JITInlineMethods.h:
(JSC::JIT::emitAllocateBasicJSObject):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::recompileAllJSFunctions):
(JSC::JSGlobalData::releaseExecutableMemory):
2011-09-19 Geoffrey Garen <ggaren@apple.com>
Removed BREWMP* platform #ifdefs
......@@ -133,6 +133,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGScoreBoard.h \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
Source/JavaScriptCore/heap/AllocationSpace.cpp \
Source/JavaScriptCore/heap/AllocationSpace.h \
Source/JavaScriptCore/heap/ConservativeRoots.cpp \
Source/JavaScriptCore/heap/ConservativeRoots.h \
Source/JavaScriptCore/heap/Handle.h \
......
......@@ -118,6 +118,7 @@ __ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
__ZN3JSC11JSByteArray13s_defaultInfoE
__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataEPNS_14JSGlobalObjectENS_7JSValueEPKNS_9ClassInfoE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
__ZN3JSC15AllocationSpace16allocateSlowCaseERNS_11MarkedSpace9SizeClassE
__ZN3JSC11ParserArena5resetEv
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE
__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
......@@ -233,7 +234,6 @@ __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
__ZN3JSC4Heap11objectCountEv
__ZN3JSC4Heap16activityCallbackEv
__ZN3JSC4Heap16allocateSlowCaseERNS_11MarkedSpace9SizeClassE
__ZN3JSC4Heap16objectTypeCountsEv
__ZN3JSC4Heap17collectAllGarbageEv
__ZN3JSC4Heap17globalObjectCountEv
......
......@@ -27,6 +27,7 @@
'API/OpaqueJSString.h',
'assembler/MacroAssemblerCodeRef.h',
'bytecode/Opcode.h',
'heap/AllocationSpace.h',
'heap/ConservativeRoots.h',
'heap/Handle.h',
'heap/HandleHeap.h',
......@@ -324,6 +325,7 @@
'bytecompiler/LabelScope.h',
'bytecompiler/NodesCodegen.cpp',
'bytecompiler/RegisterID.h',
'heap/AllocationSpace.cpp',
'heap/ConservativeRoots.cpp',
'heap/HandleHeap.cpp',
'heap/HandleStack.cpp',
......
......@@ -72,6 +72,7 @@ SOURCES += \
bytecode/ValueProfile.cpp \
bytecompiler/BytecodeGenerator.cpp \
bytecompiler/NodesCodegen.cpp \
heap/AllocationSpace.cpp \
heap/ConservativeRoots.cpp \
heap/HandleHeap.cpp \
heap/HandleStack.cpp \
......
......@@ -59,9 +59,8 @@ EXPORTS
?addPropertyWithoutTransition@Structure@JSC@@QAEIAAVJSGlobalData@2@ABVIdentifier@2@IPAVJSCell@2@@Z
?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PAVStringImpl@4@@Z
?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z
?allocate@Heap@JSC@@QAEPAXAAUSizeClass@MarkedSpace@2@@Z
?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
?allocateSlowCase@Heap@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z
?allocateSlowCase@AllocationSpace@JSC@@AAEPAXAAUSizeClass@MarkedSpace@2@@Z
?append@StringBuilder@WTF@@QAEXPBDI@Z
?append@StringBuilder@WTF@@QAEXPB_WI@Z
?ascii@UString@JSC@@QBE?AVCString@WTF@@XZ
......
......@@ -1889,6 +1889,14 @@
<Filter
Name="heap"
>
<File
RelativePath="..\..\heap\AllocationSpace.cpp"
>
</File>
<File
RelativePath="..\..\heap\AllocationSpace.h"
>
</File>
<File
RelativePath="..\..\heap\ConservativeRoots.cpp"
>
......
......@@ -406,6 +406,8 @@
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 */; };
......@@ -1182,6 +1184,8 @@
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>"; };
......@@ -1617,6 +1621,8 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
A70456AF1427FB150037DA68 /* AllocationSpace.h */,
A70456AE1427FB030037DA68 /* AllocationSpace.cpp */,
0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */,
0FC815141405118D00CFA603 /* VTableSpectrum.h */,
0FC815121405118600CFA603 /* VTableSpectrum.cpp */,
......@@ -2793,6 +2799,7 @@
A7BC0C82140608B000B1BB71 /* CheckedArithmetic.h in Headers */,
A781E359141970C700094D90 /* StorageBarrier.h in Headers */,
1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */,
A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -3298,6 +3305,7 @@
C22C52FE13FAF6EF00B7DC0D /* fixed-dtoa.cc in Sources */,
C22C531313FAF6EF00B7DC0D /* strtod.cc in Sources */,
1A082779142168D70090CCAC /* BinarySemaphore.cpp in Sources */,
A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -118,7 +118,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
return;
Recompiler recompiler(this);
globalData->heap.forEachCell(recompiler);
globalData->heap.objectSpace().forEachCell(recompiler);
}
JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
......
/*
* 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"
#define COLLECT_ON_EVERY_ALLOCATION 0
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
collectAllGarbage();
ASSERT(m_heap->m_operationInProgress == NoOperation);
#endif
void* result = tryAllocate(sizeClass);
if (LIKELY(result != 0))
return result;
AllocationEffort allocationEffort;
if (m_markedSpace.waterMark() < m_markedSpace.highWaterMark() || !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_markedSpace.waterMark() < m_markedSpace.highWaterMark());
m_markedSpace.addBlock(sizeClass, allocateBlock(sizeClass.cellSize, AllocationMustSucceed));
result = tryAllocate(sizeClass);
ASSERT(result);
return result;
}
MarkedBlock* AllocationSpace::allocateBlock(size_t cellSize, AllocationSpace::AllocationEffort allocationEffort)
{
MarkedBlock* block;
{
MutexLocker locker(m_heap->m_freeBlockLock);
if (m_heap->m_numberOfFreeBlocks) {
block = m_heap->m_freeBlocks.removeHead();
ASSERT(block);
m_heap->m_numberOfFreeBlocks--;
} else
block = 0;
}
if (block)
block->initForCellSize(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 = block->next();
m_blocks.remove(block);
block->reset();
MutexLocker locker(m_heap->m_freeBlockLock);
m_heap->m_freeBlocks.append(block);
m_heap->m_numberOfFreeBlocks++;
}
}
class TakeIfEmpty {
public:
typedef MarkedBlock* ReturnType;
TakeIfEmpty(MarkedSpace*);
void operator()(MarkedBlock*);
ReturnType returnValue();
private:
MarkedSpace* m_markedSpace;
DoublyLinkedList<MarkedBlock> m_empties;
};
inline TakeIfEmpty::TakeIfEmpty(MarkedSpace* newSpace)
: m_markedSpace(newSpace)
{
}
inline void TakeIfEmpty::operator()(MarkedBlock* block)
{
if (!block->isEmpty())
return;
m_markedSpace->removeBlock(block);
m_empties.append(block);
}
inline TakeIfEmpty::ReturnType TakeIfEmpty::returnValue()
{
return m_empties.head();
}
void AllocationSpace::shrink()
{
// We record a temporary list of empties to avoid modifying m_blocks while iterating it.
TakeIfEmpty takeIfEmpty(&m_markedSpace);
freeBlocks(forEachBlock(takeIfEmpty));
}
}
/*
* 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); }
void setHighWaterMark(size_t bytes) { m_markedSpace.setHighWaterMark(bytes); }
size_t highWaterMark() { return m_markedSpace.highWaterMark(); }
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 canonicalizeBlocks() { m_markedSpace.canonicalizeBlocks(); }
void resetAllocator() { m_markedSpace.resetAllocator(); }
void* allocate(size_t);
void freeBlocks(MarkedBlock*);
void shrink();
private:
enum AllocationEffort { AllocationMustSucceed, AllocationCanFail };
void* allocate(MarkedSpace::SizeClass&);
void* tryAllocate(MarkedSpace::SizeClass&);
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)
{
canonicalizeBlocks();
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)
{
canonicalizeBlocks();
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
......@@ -33,7 +33,6 @@
#include "Tracing.h"
#include <algorithm>
#define COLLECT_ON_EVERY_ALLOCATION 0
using namespace std;
using namespace JSC;
......@@ -175,38 +174,6 @@ inline void CountIfGlobalObject::operator()(JSCell* cell)
count(1);
}
class TakeIfEmpty {
public:
typedef MarkedBlock* ReturnType;
TakeIfEmpty(MarkedSpace*);
void operator()(MarkedBlock*);
ReturnType returnValue();
private:
MarkedSpace* m_markedSpace;
DoublyLinkedList<MarkedBlock> m_empties;
};
inline TakeIfEmpty::TakeIfEmpty(MarkedSpace* newSpace)
: m_markedSpace(newSpace)
{
}
inline void TakeIfEmpty::operator()(MarkedBlock* block)
{
if (!block->isEmpty())
return;
m_markedSpace->removeBlock(block);
m_empties.append(block);
}
inline TakeIfEmpty::ReturnType TakeIfEmpty::returnValue()
{
return m_empties.head();
}
class RecordType {
public:
typedef PassOwnPtr<TypeCountSet> ReturnType;
......@@ -249,7 +216,7 @@ Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
: m_heapSize(heapSize)
, m_minBytesPerCycle(heapSizeForHint(heapSize))
, m_operationInProgress(NoOperation)
, m_markedSpace(this)
, m_objectSpace(this)
, m_extraCost(0)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
......@@ -259,7 +226,7 @@ Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
, m_isSafeToCollect(false)
, m_globalData(globalData)
{
m_markedSpace.setHighWaterMark(m_minBytesPerCycle);
m_objectSpace.setHighWaterMark(m_minBytesPerCycle);
(*m_activityCallback)();
m_numberOfFreeBlocks = 0;
m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree");
......@@ -393,62 +360,11 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost)
// if a large value survives one garbage collection, there is not much point to
// collecting more frequently as long as it stays alive.
if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.highWaterMark() / 2)
if (m_extraCost > maxExtraCost && m_extraCost > m_objectSpace.highWaterMark() / 2)
collectAllGarbage();
m_extraCost += cost;
}
inline void* Heap::tryAllocate(MarkedSpace::SizeClass& sizeClass)
{
m_operationInProgress = Allocation;
void* result = m_markedSpace.allocate(sizeClass);
m_operationInProgress = NoOperation;
return result;
}
void* Heap::allocateSlowCase(MarkedSpace::SizeClass& sizeClass)
{
#if COLLECT_ON_EVERY_ALLOCATION
collectAllGarbage();
ASSERT(m_operationInProgress == NoOperation);
#endif
void* result = tryAllocate(sizeClass);
if (LIKELY(result != 0))
return result;
AllocationEffort allocationEffort;
if (m_markedSpace.waterMark() < m_markedSpace.highWaterMark() || !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;
}
collect(DoNotSweep);
result = tryAllocate(sizeClass);
if (result)
return result;