- Revision
- 88389
- Author
- gga...@apple.com
- Date
- 2011-06-08 14:39:27 -0700 (Wed, 08 Jun 2011)
Log Message
2011-06-08 Geoffrey Garen <gga...@apple.com>
Reviewed by Oliver Hunt.
Took some responsibilities away from NewSpace
https://bugs.webkit.org/show_bug.cgi?id=62325
NewSpace is basically just an allocator now.
Heap acts as a controller, responsible for managing the set of all
MarkedBlocks.
This is in preparation for moving parts of the controller logic into
separate helper classes that can act on arbitrary sets of MarkedBlocks
that may or may not be in NewSpace.
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::destroy):
(JSC::Heap::allocate):
(JSC::Heap::markRoots):
(JSC::Heap::clearMarks):
(JSC::Heap::sweep):
(JSC::Heap::objectCount):
(JSC::Heap::size):
(JSC::Heap::capacity):
(JSC::Heap::collect):
(JSC::Heap::resetAllocator):
(JSC::Heap::allocateBlock):
(JSC::Heap::freeBlocks):
(JSC::Heap::shrink): Moved the set of MarkedBlocks from NewSpace to Heap,
along with all functions that operate on the set of MarkedBlocks. Also
moved responsibility for deciding whether to allocate a new MarkedBlock,
and for allocating it.
* heap/Heap.h:
(JSC::Heap::contains):
(JSC::Heap::forEach): Ditto.
* heap/NewSpace.cpp:
(JSC::NewSpace::addBlock):
(JSC::NewSpace::removeBlock):
(JSC::NewSpace::resetAllocator):
* heap/NewSpace.h:
(JSC::NewSpace::waterMark):
(JSC::NewSpace::allocate): Ditto.
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (88388 => 88389)
--- trunk/Source/_javascript_Core/ChangeLog 2011-06-08 21:38:24 UTC (rev 88388)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-06-08 21:39:27 UTC (rev 88389)
@@ -2,6 +2,53 @@
Reviewed by Oliver Hunt.
+ Took some responsibilities away from NewSpace
+ https://bugs.webkit.org/show_bug.cgi?id=62325
+
+ NewSpace is basically just an allocator now.
+
+ Heap acts as a controller, responsible for managing the set of all
+ MarkedBlocks.
+
+ This is in preparation for moving parts of the controller logic into
+ separate helper classes that can act on arbitrary sets of MarkedBlocks
+ that may or may not be in NewSpace.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::Heap):
+ (JSC::Heap::destroy):
+ (JSC::Heap::allocate):
+ (JSC::Heap::markRoots):
+ (JSC::Heap::clearMarks):
+ (JSC::Heap::sweep):
+ (JSC::Heap::objectCount):
+ (JSC::Heap::size):
+ (JSC::Heap::capacity):
+ (JSC::Heap::collect):
+ (JSC::Heap::resetAllocator):
+ (JSC::Heap::allocateBlock):
+ (JSC::Heap::freeBlocks):
+ (JSC::Heap::shrink): Moved the set of MarkedBlocks from NewSpace to Heap,
+ along with all functions that operate on the set of MarkedBlocks. Also
+ moved responsibility for deciding whether to allocate a new MarkedBlock,
+ and for allocating it.
+
+ * heap/Heap.h:
+ (JSC::Heap::contains):
+ (JSC::Heap::forEach): Ditto.
+
+ * heap/NewSpace.cpp:
+ (JSC::NewSpace::addBlock):
+ (JSC::NewSpace::removeBlock):
+ (JSC::NewSpace::resetAllocator):
+ * heap/NewSpace.h:
+ (JSC::NewSpace::waterMark):
+ (JSC::NewSpace::allocate): Ditto.
+
+2011-06-08 Geoffrey Garen <gga...@apple.com>
+
+ Reviewed by Oliver Hunt.
+
Some more MarkedSpace => NewSpace renaming
https://bugs.webkit.org/show_bug.cgi?id=62305
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (88388 => 88389)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2011-06-08 21:38:24 UTC (rev 88388)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2011-06-08 21:39:27 UTC (rev 88389)
@@ -66,13 +66,13 @@
Heap::Heap(JSGlobalData* globalData)
: m_operationInProgress(NoOperation)
, m_newSpace(this)
+ , m_extraCost(0)
, m_markListSet(0)
, m_activityCallback(DefaultGCActivityCallback::create(this))
- , m_globalData(globalData)
, m_machineThreads(this)
, m_markStack(globalData->jsArrayVPtr)
, m_handleHeap(globalData)
- , m_extraCost(0)
+ , m_globalData(globalData)
{
m_newSpace.setHighWaterMark(minBytesPerCycle);
(*m_activityCallback)();
@@ -104,11 +104,16 @@
delete m_markListSet;
m_markListSet = 0;
- m_newSpace.clearMarks();
+
+ clearMarks();
m_handleHeap.finalizeWeakHandles();
m_globalData->smallStrings.finalizeSmallStrings();
- m_newSpace.destroy();
+#if !ENABLE(JSC_ZOMBIES)
+ shrink();
+ ASSERT(!size());
+#endif
+
m_globalData = 0;
}
@@ -137,18 +142,20 @@
ASSERT(m_operationInProgress == NoOperation);
#endif
+ m_operationInProgress = Allocation;
void* result = m_newSpace.allocate(sizeClass);
+ m_operationInProgress = NoOperation;
+
if (result)
return result;
+ if (m_newSpace.waterMark() < m_newSpace.highWaterMark()) {
+ m_newSpace.addBlock(sizeClass, allocateBlock(sizeClass.cellSize));
+ return allocate(sizeClass);
+ }
+
collect(DoNotSweep);
-
- m_operationInProgress = Allocation;
- result = m_newSpace.allocate(sizeClass);
- m_operationInProgress = NoOperation;
-
- ASSERT(result);
- return result;
+ return allocate(sizeClass);
}
void Heap::protect(JSValue k)
@@ -232,7 +239,7 @@
ConservativeRoots registerFileRoots(this);
registerFile().gatherConservativeRoots(registerFileRoots);
- m_newSpace.clearMarks();
+ clearMarks();
visitor.append(machineThreadRoots);
visitor.drain();
@@ -273,19 +280,45 @@
m_operationInProgress = NoOperation;
}
+void Heap::clearMarks()
+{
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->clearMarks();
+}
+
+void Heap::sweep()
+{
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->sweep();
+}
+
size_t Heap::objectCount() const
{
- return m_newSpace.objectCount();
+ size_t result = 0;
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->markCount();
+ return result;
}
size_t Heap::size() const
{
- return m_newSpace.size();
+ size_t result = 0;
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->size();
+ return result;
}
size_t Heap::capacity() const
{
- return m_newSpace.capacity();
+ size_t result = 0;
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ result += (*it)->capacity();
+ return result;
}
size_t Heap::globalObjectCount()
@@ -404,24 +437,23 @@
m_globalData->smallStrings.finalizeSmallStrings();
_javascript_CORE_GC_MARKED();
+
+ resetAllocator();
- m_newSpace.resetAllocator();
- m_extraCost = 0;
-
#if ENABLE(JSC_ZOMBIES)
sweepToggle = DoSweep;
#endif
if (sweepToggle == DoSweep) {
- m_newSpace.sweep();
- m_newSpace.shrink();
+ sweep();
+ shrink();
}
// To avoid pathological GC churn in large heaps, we set the allocation high
// water mark to be proportional to the current size of the heap. The exact
// proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
// new bytes allocated) proportion, and seems to work well in benchmarks.
- size_t proportionalBytes = 2 * m_newSpace.size();
+ size_t proportionalBytes = 2 * size();
m_newSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));
_javascript_CORE_GC_END();
@@ -429,6 +461,17 @@
(*m_activityCallback)();
}
+void Heap::resetAllocator()
+{
+ m_newSpace.resetAllocator();
+
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->resetAllocator();
+
+ m_extraCost = 0;
+}
+
void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
{
m_activityCallback = activityCallback;
@@ -453,4 +496,41 @@
return true;
}
+MarkedBlock* Heap::allocateBlock(size_t cellSize)
+{
+ MarkedBlock* block = MarkedBlock::create(this, cellSize);
+ m_blocks.add(block);
+
+ return block;
+}
+
+void Heap::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+{
+ MarkedBlock* next;
+ for (MarkedBlock* block = blocks.head(); block; block = next) {
+ next = block->next();
+
+ m_blocks.remove(block);
+ MarkedBlock::destroy(block);
+ }
+}
+
+void Heap::shrink()
+{
+ // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+ DoublyLinkedList<MarkedBlock> empties;
+
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
+ MarkedBlock* block = *it;
+ if (!block->isEmpty())
+ continue;
+
+ m_newSpace.removeBlock(block);
+ empties.append(block);
+ }
+
+ freeBlocks(empties);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/heap/Heap.h (88388 => 88389)
--- trunk/Source/_javascript_Core/heap/Heap.h 2011-06-08 21:38:24 UTC (rev 88388)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2011-06-08 21:39:27 UTC (rev 88389)
@@ -89,7 +89,7 @@
void protect(JSValue);
bool unprotect(JSValue); // True when the protect count drops to 0.
- bool contains(void*);
+ bool contains(const void*);
size_t size() const;
size_t capacity() const;
@@ -113,40 +113,49 @@
HandleStack* handleStack() { return &m_handleStack; }
private:
+ typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+
static const size_t minExtraCost = 256;
static const size_t maxExtraCost = 1024 * 1024;
bool isValidAllocation(size_t);
void* allocateSlowCase(size_t);
void reportExtraMemoryCostSlowCase(size_t);
+ void resetAllocator();
+ MarkedBlock* allocateBlock(size_t cellSize);
+ void freeBlocks(DoublyLinkedList<MarkedBlock>&);
+
+ void clearMarks();
void markRoots();
void markProtectedObjects(HeapRootVisitor&);
void markTempSortVectors(HeapRootVisitor&);
enum SweepToggle { DoNotSweep, DoSweep };
void collect(SweepToggle);
+ void shrink();
+ void sweep();
RegisterFile& registerFile();
OperationInProgress m_operationInProgress;
NewSpace m_newSpace;
+ HashSet<MarkedBlock*> m_blocks;
+ size_t m_extraCost;
+
ProtectCountSet m_protectedValues;
Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
-
HashSet<MarkedArgumentBuffer*>* m_markListSet;
OwnPtr<GCActivityCallback> m_activityCallback;
-
- JSGlobalData* m_globalData;
MachineThreads m_machineThreads;
MarkStack m_markStack;
HandleHeap m_handleHeap;
HandleStack m_handleStack;
- size_t m_extraCost;
+ JSGlobalData* m_globalData;
};
bool Heap::isBusy()
@@ -194,9 +203,16 @@
{
}
- inline bool Heap::contains(void* p)
+ inline bool Heap::contains(const void* x)
{
- return m_newSpace.contains(p);
+ if (!MarkedBlock::isAtomAligned(x))
+ return false;
+
+ MarkedBlock* block = MarkedBlock::blockFor(x);
+ if (!block || !m_blocks.contains(block))
+ return false;
+
+ return true;
}
inline void Heap::reportExtraMemoryCost(size_t cost)
@@ -207,7 +223,9 @@
template <typename Functor> inline void Heap::forEach(Functor& functor)
{
- m_newSpace.forEach(functor);
+ BlockIterator end = m_blocks.end();
+ for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+ (*it)->forEach(functor);
}
inline void* Heap::allocate(size_t bytes)
Modified: trunk/Source/_javascript_Core/heap/NewSpace.cpp (88388 => 88389)
--- trunk/Source/_javascript_Core/heap/NewSpace.cpp 2011-06-08 21:38:24 UTC (rev 88388)
+++ trunk/Source/_javascript_Core/heap/NewSpace.cpp 2011-06-08 21:39:27 UTC (rev 88389)
@@ -43,99 +43,19 @@
sizeClassFor(cellSize).cellSize = cellSize;
}
-void NewSpace::destroy()
+void NewSpace::addBlock(SizeClass& sizeClass, MarkedBlock* block)
{
- /* Keep our precious zombies! */
-#if !ENABLE(JSC_ZOMBIES)
- clearMarks();
- shrink();
- ASSERT(!size());
-#endif
-}
-
-MarkedBlock* NewSpace::allocateBlock(SizeClass& sizeClass)
-{
- MarkedBlock* block = MarkedBlock::create(m_heap, sizeClass.cellSize);
- sizeClass.blockList.append(block);
sizeClass.nextBlock = block;
- m_blocks.add(block);
-
- return block;
+ sizeClass.blockList.append(block);
}
-void NewSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+void NewSpace::removeBlock(MarkedBlock* block)
{
- MarkedBlock* next;
- for (MarkedBlock* block = blocks.head(); block; block = next) {
- next = block->next();
-
- blocks.remove(block);
- m_blocks.remove(block);
- MarkedBlock::destroy(block);
- }
+ SizeClass& sizeClass = sizeClassFor(block->cellSize());
+ sizeClass.nextBlock = block->next();
+ sizeClass.blockList.remove(block);
}
-void NewSpace::shrink()
-{
- // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
- DoublyLinkedList<MarkedBlock> empties;
-
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
- MarkedBlock* block = *it;
- if (block->isEmpty()) {
- SizeClass& sizeClass = sizeClassFor(block->cellSize());
- sizeClass.blockList.remove(block);
- sizeClass.nextBlock = sizeClass.blockList.head();
- empties.append(block);
- }
- }
-
- freeBlocks(empties);
- ASSERT(empties.isEmpty());
-}
-
-void NewSpace::clearMarks()
-{
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->clearMarks();
-}
-
-void NewSpace::sweep()
-{
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->sweep();
-}
-
-size_t NewSpace::objectCount() const
-{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->markCount();
- return result;
-}
-
-size_t NewSpace::size() const
-{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->size();
- return result;
-}
-
-size_t NewSpace::capacity() const
-{
- size_t result = 0;
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- result += (*it)->capacity();
- return result;
-}
-
void NewSpace::resetAllocator()
{
m_waterMark = 0;
@@ -145,10 +65,6 @@
for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
sizeClassFor(cellSize).resetAllocator();
-
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->resetAllocator();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/heap/NewSpace.h (88388 => 88389)
--- trunk/Source/_javascript_Core/heap/NewSpace.h 2011-06-08 21:38:24 UTC (rev 88388)
+++ trunk/Source/_javascript_Core/heap/NewSpace.h 2011-06-08 21:39:27 UTC (rev 88389)
@@ -58,28 +58,19 @@
};
NewSpace(Heap*);
- void destroy();
- size_t highWaterMark();
- void setHighWaterMark(size_t);
-
SizeClass& sizeClassFor(size_t);
void* allocate(SizeClass&);
- void clearMarks();
- void markRoots();
- void resetAllocator();
- void sweep();
- void shrink();
+ void addBlock(SizeClass&, MarkedBlock*);
+ void removeBlock(MarkedBlock*);
- size_t size() const;
- size_t capacity() const;
- size_t objectCount() const;
+ size_t waterMark();
+ size_t highWaterMark();
+ void setHighWaterMark(size_t);
- bool contains(const void*);
+ void resetAllocator();
- template<typename Functor> void forEach(Functor&);
-
private:
// [ 8, 16... 128 )
static const size_t preciseStep = MarkedBlock::atomSize;
@@ -91,40 +82,18 @@
static const size_t impreciseCutoff = maxCellSize;
static const size_t impreciseCount = impreciseCutoff / impreciseStep - 1;
- typedef HashSet<MarkedBlock*>::iterator BlockIterator;
-
- MarkedBlock* allocateBlock(SizeClass&);
- void freeBlocks(DoublyLinkedList<MarkedBlock>&);
-
- void clearMarks(MarkedBlock*);
-
SizeClass m_preciseSizeClasses[preciseCount];
SizeClass m_impreciseSizeClasses[impreciseCount];
- HashSet<MarkedBlock*> m_blocks;
size_t m_waterMark;
size_t m_highWaterMark;
Heap* m_heap;
};
- inline bool NewSpace::contains(const void* x)
+ inline size_t NewSpace::waterMark()
{
- if (!MarkedBlock::isAtomAligned(x))
- return false;
-
- MarkedBlock* block = MarkedBlock::blockFor(x);
- if (!block || !m_blocks.contains(block))
- return false;
-
- return true;
+ return m_waterMark;
}
- template <typename Functor> inline void NewSpace::forEach(Functor& functor)
- {
- BlockIterator end = m_blocks.end();
- for (BlockIterator it = m_blocks.begin(); it != end; ++it)
- (*it)->forEach(functor);
- }
-
inline size_t NewSpace::highWaterMark()
{
return m_highWaterMark;
@@ -152,9 +121,6 @@
m_waterMark += block->capacity();
}
- if (m_waterMark < m_highWaterMark)
- return allocateBlock(sizeClass)->allocate();
-
return 0;
}