Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (115589 => 115590)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2012-04-29 01:44:37 UTC (rev 115590)
@@ -85,6 +85,7 @@
dfg/DFGThunks.cpp
dfg/DFGVirtualRegisterAllocationPhase.cpp
+ heap/BlockAllocator.cpp
heap/CopiedSpace.cpp
heap/ConservativeRoots.cpp
heap/DFGCodeBlocks.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (115589 => 115590)
--- trunk/Source/_javascript_Core/ChangeLog 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-04-29 01:44:37 UTC (rev 115590)
@@ -1,3 +1,22 @@
+2012-04-28 Geoffrey Garen <[email protected]>
+
+ Factored threaded block allocation into a separate object
+ https://bugs.webkit.org/show_bug.cgi?id=85148
+
+ Reviewed by Sam Weinig.
+
+ 99% of this patch just moves duplicated block allocation and
+ deallocation code into a new object named BlockAllocator, with these
+ exceptions:
+
+ * heap/BlockAllocator.h: Added.
+ (BlockAllocator::BlockAllocator): The order of declarations here now
+ guards us against an unlikely race condition during startup.
+
+ * heap/BlockAllocator.cpp:
+ JSC::BlockAllocator::blockFreeingThreadMain): Added a FIXME to
+ highlight a lack of clarity we have in our block deallocation routines.
+
2012-04-28 Sam Weinig <[email protected]>
Try to fix the Qt build.
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (115589 => 115590)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2012-04-29 01:44:37 UTC (rev 115590)
@@ -226,6 +226,7 @@
Source/_javascript_Core/heap/HandleStack.cpp \
Source/_javascript_Core/heap/HandleStack.h \
Source/_javascript_Core/heap/HandleTypes.h \
+ Source/_javascript_Core/heap/BlockAllocator.cpp \
Source/_javascript_Core/heap/Heap.cpp \
Source/_javascript_Core/heap/Heap.h \
Source/_javascript_Core/heap/ListableHandler.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.gypi (115589 => 115590)
--- trunk/Source/_javascript_Core/_javascript_Core.gypi 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/_javascript_Core.gypi 2012-04-29 01:44:37 UTC (rev 115590)
@@ -401,6 +401,7 @@
'heap/DFGCodeBlocks.cpp',
'heap/HandleSet.cpp',
'heap/HandleStack.cpp',
+ 'heap/BlockAllocator.cpp',
'heap/Heap.cpp',
'heap/MachineStackMarker.cpp',
'heap/MarkedAllocator.cpp',
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj (115589 => 115590)
--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj 2012-04-29 01:44:37 UTC (rev 115590)
@@ -2170,6 +2170,14 @@
>
</File>
<File
+ RelativePath="..\..\heap\BlockAllocator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\heap\BlockAllocator.h"
+ >
+ </File>
+ <File
RelativePath="..\..\heap\Heap.cpp"
>
</File>
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (115589 => 115590)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2012-04-29 01:44:37 UTC (rev 115590)
@@ -298,6 +298,8 @@
147F39D5107EC37600427A48 /* JSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9B60E1842FA000F9297 /* JSString.cpp */; };
147F39D6107EC37600427A48 /* JSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8870255597D01FF60F7 /* JSValue.cpp */; };
147F39D7107EC37600427A48 /* JSVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC22A39A0E16E14800AF21C8 /* JSVariableObject.cpp */; };
+ 14816E1B154CC56C00B8054C /* BlockAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14816E19154CC56C00B8054C /* BlockAllocator.cpp */; };
+ 14816E1C154CC56C00B8054C /* BlockAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14816E1A154CC56C00B8054C /* BlockAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1482B74C0A43032800517CFC /* JSStringRef.cpp */; };
1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1482B7E20A43076000517CFC /* JSObjectRef.cpp */; };
148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 148CD1D7108CF902008163C6 /* JSContextRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -915,6 +917,8 @@
147B83AA0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BatchedTransitionOptimizer.h; sourceTree = "<group>"; };
147B84620E6DE6B1004775A4 /* PutPropertySlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutPropertySlot.h; sourceTree = "<group>"; };
1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerCallFrame.h; sourceTree = "<group>"; };
+ 14816E19154CC56C00B8054C /* BlockAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockAllocator.cpp; sourceTree = "<group>"; };
+ 14816E1A154CC56C00B8054C /* BlockAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockAllocator.h; sourceTree = "<group>"; };
1482B6EA0A4300B300517CFC /* JSValueRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSValueRef.h; sourceTree = "<group>"; };
1482B74B0A43032800517CFC /* JSStringRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringRef.h; sourceTree = "<group>"; };
1482B74C0A43032800517CFC /* JSStringRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringRef.cpp; sourceTree = "<group>"; };
@@ -1560,6 +1564,8 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
+ 14816E19154CC56C00B8054C /* BlockAllocator.cpp */,
+ 14816E1A154CC56C00B8054C /* BlockAllocator.h */,
A7521E121429169A003C8D0C /* CardSet.h */,
146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
@@ -2567,6 +2573,7 @@
0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */,
0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */,
14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */,
+ 14816E1C154CC56C00B8054C /* BlockAllocator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3129,6 +3136,7 @@
8642C510151C06A90046D4EF /* RegExpCachedResult.cpp in Sources */,
8642C512151C083D0046D4EF /* RegExpMatchesArray.cpp in Sources */,
863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */,
+ 14816E1B154CC56C00B8054C /* BlockAllocator.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: trunk/Source/_javascript_Core/Target.pri (115589 => 115590)
--- trunk/Source/_javascript_Core/Target.pri 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/Target.pri 2012-04-29 01:44:37 UTC (rev 115590)
@@ -76,6 +76,7 @@
heap/WeakBlock.cpp \
heap/HandleSet.cpp \
heap/HandleStack.cpp \
+ heap/BlockAllocator.cpp \
heap/Heap.cpp \
heap/MachineStackMarker.cpp \
heap/MarkStack.cpp \
Added: trunk/Source/_javascript_Core/heap/BlockAllocator.cpp (0 => 115590)
--- trunk/Source/_javascript_Core/heap/BlockAllocator.cpp (rev 0)
+++ trunk/Source/_javascript_Core/heap/BlockAllocator.cpp 2012-04-29 01:44:37 UTC (rev 115590)
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 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 "BlockAllocator.h"
+
+#include "MarkedBlock.h"
+#include <wtf/CurrentTime.h>
+
+namespace JSC {
+
+BlockAllocator::BlockAllocator()
+ : m_numberOfFreeBlocks(0)
+ , m_blockFreeingThreadShouldQuit(false)
+ , m_blockFreeingThread(createThread(blockFreeingThreadStartFunc, this, "_javascript_Core::BlockFree"))
+{
+ ASSERT(m_blockFreeingThread);
+}
+
+BlockAllocator::~BlockAllocator()
+{
+ releaseFreeBlocks();
+ {
+ MutexLocker locker(m_freeBlockLock);
+ m_blockFreeingThreadShouldQuit = true;
+ m_freeBlockCondition.broadcast();
+ }
+ waitForThreadCompletion(m_blockFreeingThread);
+}
+
+void BlockAllocator::releaseFreeBlocks()
+{
+ while (true) {
+ MarkedBlock* block;
+ {
+ MutexLocker locker(m_freeBlockLock);
+ if (!m_numberOfFreeBlocks)
+ block = 0;
+ else {
+ // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock.
+ block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
+ ASSERT(block);
+ m_numberOfFreeBlocks--;
+ }
+ }
+
+ if (!block)
+ break;
+
+ MarkedBlock::destroy(block);
+ }
+}
+
+void BlockAllocator::waitForRelativeTimeWhileHoldingLock(double relative)
+{
+ if (m_blockFreeingThreadShouldQuit)
+ return;
+ m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative);
+}
+
+void BlockAllocator::waitForRelativeTime(double relative)
+{
+ // If this returns early, that's fine, so long as it doesn't do it too
+ // frequently. It would only be a bug if this function failed to return
+ // when it was asked to do so.
+
+ MutexLocker locker(m_freeBlockLock);
+ waitForRelativeTimeWhileHoldingLock(relative);
+}
+
+void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator)
+{
+ static_cast<BlockAllocator*>(blockAllocator)->blockFreeingThreadMain();
+}
+
+void BlockAllocator::blockFreeingThreadMain()
+{
+ while (!m_blockFreeingThreadShouldQuit) {
+ // Generally wait for one second before scavenging free blocks. This
+ // may return early, particularly when we're being asked to quit.
+ waitForRelativeTime(1.0);
+ if (m_blockFreeingThreadShouldQuit)
+ break;
+
+ // Now process the list of free blocks. Keep freeing until half of the
+ // blocks that are currently on the list are gone. Assume that a size_t
+ // field can be accessed atomically.
+ size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks;
+ if (!currentNumberOfFreeBlocks)
+ continue;
+
+ size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2;
+
+ while (!m_blockFreeingThreadShouldQuit) {
+ MarkedBlock* block;
+ {
+ MutexLocker locker(m_freeBlockLock);
+ if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
+ block = 0;
+ else {
+ // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock.
+ block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
+ ASSERT(block);
+ m_numberOfFreeBlocks--;
+ }
+ }
+
+ if (!block)
+ break;
+
+ MarkedBlock::destroy(block);
+ }
+ }
+}
+
+} // namespace JSC
Added: trunk/Source/_javascript_Core/heap/BlockAllocator.h (0 => 115590)
--- trunk/Source/_javascript_Core/heap/BlockAllocator.h (rev 0)
+++ trunk/Source/_javascript_Core/heap/BlockAllocator.h 2012-04-29 01:44:37 UTC (rev 115590)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 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 BlockAllocator_h
+#define BlockAllocator_h
+
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/Forward.h>
+#include <wtf/Threading.h>
+
+namespace JSC {
+
+class HeapBlock;
+
+// Simple allocator to reduce VM cost by holding onto blocks of memory for
+// short periods of time and then freeing them on a secondary thread.
+
+class BlockAllocator {
+public:
+ BlockAllocator();
+ ~BlockAllocator();
+
+ HeapBlock* allocate();
+ void deallocate(HeapBlock*);
+
+private:
+ void waitForRelativeTimeWhileHoldingLock(double relative);
+ void waitForRelativeTime(double relative);
+
+ void blockFreeingThreadMain();
+ static void blockFreeingThreadStartFunc(void* heap);
+
+ void releaseFreeBlocks();
+
+ DoublyLinkedList<HeapBlock> m_freeBlocks;
+ size_t m_numberOfFreeBlocks;
+ bool m_blockFreeingThreadShouldQuit;
+ Mutex m_freeBlockLock;
+ ThreadCondition m_freeBlockCondition;
+ ThreadIdentifier m_blockFreeingThread;
+};
+
+inline HeapBlock* BlockAllocator::allocate()
+{
+ MutexLocker locker(m_freeBlockLock);
+ if (!m_numberOfFreeBlocks) {
+ ASSERT(m_freeBlocks.isEmpty());
+ return 0;
+ }
+
+ ASSERT(!m_freeBlocks.isEmpty());
+ m_numberOfFreeBlocks--;
+ return m_freeBlocks.removeHead();
+}
+
+inline void BlockAllocator::deallocate(HeapBlock* block)
+{
+ MutexLocker locker(m_freeBlockLock);
+ m_freeBlocks.push(block);
+ m_numberOfFreeBlocks++;
+}
+
+} // namespace JSC
+
+#endif // BlockAllocator_h
Modified: trunk/Source/_javascript_Core/heap/CopiedSpace.cpp (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/CopiedSpace.cpp 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/CopiedSpace.cpp 2012-04-29 01:44:37 UTC (rev 115590)
@@ -188,11 +188,7 @@
}
m_toSpaceSet.remove(block);
- {
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.push(block);
- m_heap->m_numberOfFreeBlocks++;
- }
+ m_heap->blockAllocator().deallocate(block);
}
CopiedBlock* curr = static_cast<CopiedBlock*>(m_oversizeBlocks.head());
@@ -215,16 +211,8 @@
CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, CopiedBlock** outBlock)
{
- HeapBlock* heapBlock = 0;
CopiedBlock* block = 0;
- {
- MutexLocker locker(m_heap->m_freeBlockLock);
- if (!m_heap->m_freeBlocks.isEmpty()) {
- heapBlock = m_heap->m_freeBlocks.removeHead();
- m_heap->m_numberOfFreeBlocks--;
- }
- }
- if (heapBlock)
+ if (HeapBlock* heapBlock = m_heap->blockAllocator().allocate())
block = new (NotNull, heapBlock) CopiedBlock(heapBlock->m_allocation);
else if (allocationEffort == AllocationMustSucceed) {
if (!allocateNewBlock(&block)) {
@@ -251,24 +239,14 @@
void CopiedSpace::freeAllBlocks()
{
- while (!m_toSpace->isEmpty()) {
- CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->removeHead());
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.append(block);
- m_heap->m_numberOfFreeBlocks++;
- }
+ while (!m_toSpace->isEmpty())
+ m_heap->blockAllocator().deallocate(m_toSpace->removeHead());
- while (!m_fromSpace->isEmpty()) {
- CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->removeHead());
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.append(block);
- m_heap->m_numberOfFreeBlocks++;
- }
+ while (!m_fromSpace->isEmpty())
+ m_heap->blockAllocator().deallocate(m_fromSpace->removeHead());
- while (!m_oversizeBlocks.isEmpty()) {
- CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.removeHead());
- block->m_allocation.deallocate();
- }
+ while (!m_oversizeBlocks.isEmpty())
+ m_oversizeBlocks.removeHead()->m_allocation.deallocate();
}
size_t CopiedSpace::size()
Modified: trunk/Source/_javascript_Core/heap/CopiedSpaceInlineMethods.h (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/CopiedSpaceInlineMethods.h 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/CopiedSpaceInlineMethods.h 2012-04-29 01:44:37 UTC (rev 115590)
@@ -63,11 +63,7 @@
inline void CopiedSpace::recycleBlock(CopiedBlock* block)
{
- {
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.push(block);
- m_heap->m_numberOfFreeBlocks++;
- }
+ m_heap->blockAllocator().deallocate(block);
{
MutexLocker locker(m_loanedBlocksLock);
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2012-04-29 01:44:37 UTC (rev 115590)
@@ -319,7 +319,6 @@
, m_operationInProgress(NoOperation)
, m_objectSpace(this)
, m_storageSpace(this)
- , m_blockFreeingThreadShouldQuit(false)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
, m_machineThreads(this)
@@ -332,10 +331,6 @@
, m_lastGCLength(0)
, m_lastCodeDiscardTime(WTF::currentTime())
{
- m_numberOfFreeBlocks = 0;
- m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "_javascript_Core::BlockFree");
-
- ASSERT(m_blockFreeingThread);
m_storageSpace.init();
}
@@ -345,13 +340,6 @@
m_objectSpace.shrink();
m_storageSpace.freeAllBlocks();
- releaseFreeBlocks();
- {
- MutexLocker locker(m_freeBlockLock);
- m_blockFreeingThreadShouldQuit = true;
- m_freeBlockCondition.broadcast();
- }
- waitForThreadCompletion(m_blockFreeingThread);
ASSERT(!size());
ASSERT(!capacity());
@@ -380,67 +368,6 @@
#endif
}
-void Heap::waitForRelativeTimeWhileHoldingLock(double relative)
-{
- if (m_blockFreeingThreadShouldQuit)
- return;
- m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative);
-}
-
-void Heap::waitForRelativeTime(double relative)
-{
- // If this returns early, that's fine, so long as it doesn't do it too
- // frequently. It would only be a bug if this function failed to return
- // when it was asked to do so.
-
- MutexLocker locker(m_freeBlockLock);
- waitForRelativeTimeWhileHoldingLock(relative);
-}
-
-void Heap::blockFreeingThreadStartFunc(void* heap)
-{
- static_cast<Heap*>(heap)->blockFreeingThreadMain();
-}
-
-void Heap::blockFreeingThreadMain()
-{
- while (!m_blockFreeingThreadShouldQuit) {
- // Generally wait for one second before scavenging free blocks. This
- // may return early, particularly when we're being asked to quit.
- waitForRelativeTime(1.0);
- if (m_blockFreeingThreadShouldQuit)
- break;
-
- // Now process the list of free blocks. Keep freeing until half of the
- // blocks that are currently on the list are gone. Assume that a size_t
- // field can be accessed atomically.
- size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks;
- if (!currentNumberOfFreeBlocks)
- continue;
-
- size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2;
-
- while (!m_blockFreeingThreadShouldQuit) {
- MarkedBlock* block;
- {
- MutexLocker locker(m_freeBlockLock);
- if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
- block = 0;
- else {
- block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
- ASSERT(block);
- m_numberOfFreeBlocks--;
- }
- }
-
- if (!block)
- break;
-
- MarkedBlock::destroy(block);
- }
- }
-}
-
void Heap::reportExtraMemoryCostSlowCase(size_t cost)
{
// Our frequency of garbage collection tries to balance memory use against speed
@@ -912,33 +839,6 @@
return true;
}
-void Heap::freeBlocks(MarkedBlock* head)
-{
- m_objectSpace.freeBlocks(head);
-}
-
-void Heap::releaseFreeBlocks()
-{
- while (true) {
- MarkedBlock* block;
- {
- MutexLocker locker(m_freeBlockLock);
- if (!m_numberOfFreeBlocks)
- block = 0;
- else {
- block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
- ASSERT(block);
- m_numberOfFreeBlocks--;
- }
- }
-
- if (!block)
- break;
-
- MarkedBlock::destroy(block);
- }
-}
-
void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
{
WeakSet::allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize().
Modified: trunk/Source/_javascript_Core/heap/Heap.h (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/Heap.h 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2012-04-29 01:44:37 UTC (rev 115590)
@@ -22,6 +22,7 @@
#ifndef Heap_h
#define Heap_h
+#include "BlockAllocator.h"
#include "DFGCodeBlocks.h"
#include "HandleSet.h"
#include "HandleStack.h"
@@ -33,8 +34,6 @@
#include "WeakHandleOwner.h"
#include "WeakSet.h"
#include "WriteBarrierSupport.h"
-#include <wtf/DoublyLinkedList.h>
-#include <wtf/Forward.h>
#include <wtf/HashCountedSet.h>
#include <wtf/HashSet.h>
@@ -184,7 +183,6 @@
void canonicalizeCellLivenessData();
void resetAllocators();
- void freeBlocks(MarkedBlock*);
void clearMarks();
void markRoots(bool fullGC);
@@ -193,16 +191,11 @@
void harvestWeakReferences();
void finalizeUnconditionalFinalizers();
- void releaseFreeBlocks();
void sweep();
RegisterFile& registerFile();
+ BlockAllocator& blockAllocator();
- void waitForRelativeTimeWhileHoldingLock(double relative);
- void waitForRelativeTime(double relative);
- void blockFreeingThreadMain();
- static void blockFreeingThreadStartFunc(void* heap);
-
const HeapSize m_heapSize;
const size_t m_minBytesPerCycle;
size_t m_sizeAfterLastCollect;
@@ -214,13 +207,7 @@
MarkedSpace m_objectSpace;
CopiedSpace m_storageSpace;
- DoublyLinkedList<HeapBlock> m_freeBlocks;
- size_t m_numberOfFreeBlocks;
-
- ThreadIdentifier m_blockFreeingThread;
- Mutex m_freeBlockLock;
- ThreadCondition m_freeBlockCondition;
- bool m_blockFreeingThreadShouldQuit;
+ BlockAllocator m_blockAllocator;
#if ENABLE(SIMPLE_HEAP_PROFILING)
VTableSpectrum m_destroyedTypeCounts;
@@ -372,6 +359,11 @@
return m_storageSpace.tryReallocate(ptr, oldSize, newSize);
}
+ inline BlockAllocator& Heap::blockAllocator()
+ {
+ return m_blockAllocator;
+ }
+
} // namespace JSC
#endif // Heap_h
Modified: trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp 2012-04-29 01:44:37 UTC (rev 115590)
@@ -82,17 +82,7 @@
MarkedBlock* MarkedAllocator::allocateBlock(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;
- }
+ MarkedBlock* block = static_cast<MarkedBlock*>(m_heap->blockAllocator().allocate());
if (block)
block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction);
else if (allocationEffort == AllocationCanFail)
Modified: trunk/Source/_javascript_Core/heap/MarkedSpace.cpp (115589 => 115590)
--- trunk/Source/_javascript_Core/heap/MarkedSpace.cpp 2012-04-29 01:32:16 UTC (rev 115589)
+++ trunk/Source/_javascript_Core/heap/MarkedSpace.cpp 2012-04-29 01:44:37 UTC (rev 115590)
@@ -79,9 +79,8 @@
m_blocks.remove(block);
block->sweep();
- MutexLocker locker(m_heap->m_freeBlockLock);
- m_heap->m_freeBlocks.append(block);
- m_heap->m_numberOfFreeBlocks++;
+
+ m_heap->blockAllocator().deallocate(block);
}
}