2011-06-08 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Jun 2011 19:44:37 +0000 (19:44 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Jun 2011 19:44:37 +0000 (19:44 +0000)
        Reviewed by Oliver Hunt.

        Factored a bunch of Heap functionality into stand-alone functors
        https://bugs.webkit.org/show_bug.cgi?id=62337

        This is in preparation for making these functors operate on arbitrary
        sets of MarkedBlocks.

        * JavaScriptCore.exp: This file is a small tragedy.

        * debugger/Debugger.cpp:
        (JSC::Debugger::recompileAllJSFunctions): Updated for type change and rename.

        * heap/HandleHeap.h:
        (JSC::HandleHeap::forEachStrongHandle): New function for iterating all
        strong handles, so we can play along in the functor game.

        * heap/Heap.cpp:
        (JSC::CountFunctor::CountFunctor::CountFunctor):
        (JSC::CountFunctor::CountFunctor::count):
        (JSC::CountFunctor::CountFunctor::returnValue):
        (JSC::CountFunctor::ClearMarks::operator()):
        (JSC::CountFunctor::ResetAllocator::operator()):
        (JSC::CountFunctor::Sweep::operator()):
        (JSC::CountFunctor::MarkCount::operator()):
        (JSC::CountFunctor::Size::operator()):
        (JSC::CountFunctor::Capacity::operator()):
        (JSC::CountFunctor::Count::operator()):
        (JSC::CountFunctor::CountIfGlobalObject::operator()):
        (JSC::CountFunctor::TakeIfEmpty::TakeIfEmpty):
        (JSC::CountFunctor::TakeIfEmpty::operator()):
        (JSC::CountFunctor::TakeIfEmpty::returnValue):
        (JSC::CountFunctor::RecordType::RecordType):
        (JSC::CountFunctor::RecordType::typeName):
        (JSC::CountFunctor::RecordType::operator()):
        (JSC::CountFunctor::RecordType::returnValue): These functors factor out
        behavior that used to be in the functions below.

        (JSC::Heap::clearMarks):
        (JSC::Heap::sweep):
        (JSC::Heap::objectCount):
        (JSC::Heap::size):
        (JSC::Heap::capacity):
        (JSC::Heap::protectedGlobalObjectCount):
        (JSC::Heap::protectedObjectCount):
        (JSC::Heap::protectedObjectTypeCounts):
        (JSC::Heap::objectTypeCounts):
        (JSC::Heap::resetAllocator):
        (JSC::Heap::freeBlocks):
        (JSC::Heap::shrink): Factored out behavior into the functors above.

        * heap/Heap.h:
        (JSC::Heap::forEachProtectedCell):
        (JSC::Heap::forEachCell):
        (JSC::Heap::forEachBlock): Added forEach* iteration templates. I chose
        functor-based templates instead of plain iterators because they're simpler
        to implement in this case and they require a lot less code at the call site.

        * heap/MarkedBlock.h:
        (JSC::MarkedBlock::VoidFunctor::returnValue): Default parent class for
        trivial functors.

        (JSC::MarkedBlock::forEachCell): Renamed forEach to forEachCell because
        we have a few different kind of "for each" now.

        * runtime/JSGlobalData.cpp:
        (WTF::Recompile::operator()):
        (JSC::JSGlobalData::JSGlobalData):
        (JSC::JSGlobalData::recompileAllJSFunctions): Updated for type change and rename.

        * runtime/JSGlobalData.h: Removed globalObjectCount because it was unused.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@88473 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/heap/HandleHeap.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/MarkedBlock.h
Source/JavaScriptCore/runtime/JSGlobalData.cpp
Source/JavaScriptCore/runtime/JSGlobalData.h

index 920ad21..8ca1f9f 100644 (file)
@@ -1,3 +1,77 @@
+2011-06-08  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Factored a bunch of Heap functionality into stand-alone functors
+        https://bugs.webkit.org/show_bug.cgi?id=62337
+        
+        This is in preparation for making these functors operate on arbitrary
+        sets of MarkedBlocks.
+
+        * JavaScriptCore.exp: This file is a small tragedy.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::recompileAllJSFunctions): Updated for type change and rename.
+
+        * heap/HandleHeap.h:
+        (JSC::HandleHeap::forEachStrongHandle): New function for iterating all
+        strong handles, so we can play along in the functor game.
+
+        * heap/Heap.cpp:
+        (JSC::CountFunctor::CountFunctor::CountFunctor):
+        (JSC::CountFunctor::CountFunctor::count):
+        (JSC::CountFunctor::CountFunctor::returnValue):
+        (JSC::CountFunctor::ClearMarks::operator()):
+        (JSC::CountFunctor::ResetAllocator::operator()):
+        (JSC::CountFunctor::Sweep::operator()):
+        (JSC::CountFunctor::MarkCount::operator()):
+        (JSC::CountFunctor::Size::operator()):
+        (JSC::CountFunctor::Capacity::operator()):
+        (JSC::CountFunctor::Count::operator()):
+        (JSC::CountFunctor::CountIfGlobalObject::operator()):
+        (JSC::CountFunctor::TakeIfEmpty::TakeIfEmpty):
+        (JSC::CountFunctor::TakeIfEmpty::operator()):
+        (JSC::CountFunctor::TakeIfEmpty::returnValue):
+        (JSC::CountFunctor::RecordType::RecordType):
+        (JSC::CountFunctor::RecordType::typeName):
+        (JSC::CountFunctor::RecordType::operator()):
+        (JSC::CountFunctor::RecordType::returnValue): These functors factor out
+        behavior that used to be in the functions below.
+
+        (JSC::Heap::clearMarks):
+        (JSC::Heap::sweep):
+        (JSC::Heap::objectCount):
+        (JSC::Heap::size):
+        (JSC::Heap::capacity):
+        (JSC::Heap::protectedGlobalObjectCount):
+        (JSC::Heap::protectedObjectCount):
+        (JSC::Heap::protectedObjectTypeCounts):
+        (JSC::Heap::objectTypeCounts):
+        (JSC::Heap::resetAllocator):
+        (JSC::Heap::freeBlocks):
+        (JSC::Heap::shrink): Factored out behavior into the functors above.
+
+        * heap/Heap.h:
+        (JSC::Heap::forEachProtectedCell):
+        (JSC::Heap::forEachCell):
+        (JSC::Heap::forEachBlock): Added forEach* iteration templates. I chose
+        functor-based templates instead of plain iterators because they're simpler
+        to implement in this case and they require a lot less code at the call site.
+
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::VoidFunctor::returnValue): Default parent class for
+        trivial functors.
+
+        (JSC::MarkedBlock::forEachCell): Renamed forEach to forEachCell because
+        we have a few different kind of "for each" now.
+
+        * runtime/JSGlobalData.cpp:
+        (WTF::Recompile::operator()):
+        (JSC::JSGlobalData::JSGlobalData):
+        (JSC::JSGlobalData::recompileAllJSFunctions): Updated for type change and rename.
+
+        * runtime/JSGlobalData.h: Removed globalObjectCount because it was unused.
+
 2011-06-08  Mikołaj Małecki  <m.malecki@samsung.com>
 
         Reviewed by Pavel Feldman.
index ff1f3e0..a8d82de 100644 (file)
@@ -221,6 +221,7 @@ __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObj
 __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC3NaNE
 __ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC4Heap11objectCountEv
 __ZN3JSC4Heap16activityCallbackEv
 __ZN3JSC4Heap16objectTypeCountsEv
 __ZN3JSC4Heap17collectAllGarbageEv
@@ -231,9 +232,11 @@ __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
 __ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
+__ZN3JSC4Heap4sizeEv
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC4Heap8allocateERNS_8NewSpace9SizeClassE
+__ZN3JSC4Heap8capacityEv
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 __ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
 __ZN3JSC4Yarr11byteCompileERNS0_11YarrPatternEPN3WTF20BumpPointerAllocatorE
@@ -535,9 +538,6 @@ __ZNK3JSC18PropertyDescriptor6getterEv
 __ZNK3JSC18PropertyDescriptor6setterEv
 __ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC19SourceProviderCache8byteSizeEv
-__ZNK3JSC4Heap11objectCountEv
-__ZNK3JSC4Heap4sizeEv
-__ZNK3JSC4Heap8capacityEv
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
index 6e2dd3c..88f5cef 100644 (file)
@@ -76,7 +76,7 @@ EXPORTS
     ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
     ?callOnMainThreadAndWait@WTF@@YAXP6AXPAX@Z0@Z
     ?cancelCallOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
-    ?capacity@Heap@JSC@@QBEIXZ
+    ?capacity@Heap@JSC@@QAEIXZ
     ?changePrototypeTransition@Structure@JSC@@SAPAV12@AAVJSGlobalData@2@PAV12@VJSValue@2@@Z
     ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVExecState@2@@Z
     ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVJSGlobalData@2@@Z
@@ -253,7 +253,7 @@ EXPORTS
     ?number@UString@JSC@@SA?AV12@I@Z
     ?number@UString@JSC@@SA?AV12@N@Z
     ?numberToString@WTF@@YAINQA_W@Z
-    ?objectCount@Heap@JSC@@QBEIXZ
+    ?objectCount@Heap@JSC@@QAEIXZ
     ?objectProtoFuncToString@JSC@@YI_JPAVExecState@1@@Z
     ?parseDateFromNullTerminatedCharacters@WTF@@YANPBD@Z
     ?preventExtensions@JSObject@JSC@@UAEXAAVJSGlobalData@2@@Z
@@ -312,7 +312,7 @@ EXPORTS
     ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ
     ?shrinkToFit@StringBuilder@WTF@@QAEXXZ
     ?signal@ThreadCondition@WTF@@QAEXXZ
-    ?size@Heap@JSC@@QBEIXZ
+    ?size@Heap@JSC@@QAEIXZ
     ?slowAppend@MarkedArgumentBuffer@JSC@@AAEXVJSValue@2@@Z
     ?slowValidateCell@JSC@@YAXPAVJSCell@1@@Z
     ?slowValidateCell@JSC@@YAXPAVJSGlobalObject@1@@Z
index 64f6002..61044a8 100644 (file)
@@ -33,7 +33,7 @@ namespace {
 
 using namespace JSC;
 
-class Recompiler {
+class Recompiler : public MarkedBlock::VoidFunctor {
 public:
     Recompiler(Debugger*);
     ~Recompiler();
@@ -118,7 +118,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
         return;
 
     Recompiler recompiler(this);
-    globalData->heap.forEach(recompiler);
+    globalData->heap.forEachCell(recompiler);
 }
 
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
index 26c64d1..ed68b45 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "BlockStack.h"
 #include "Handle.h"
+#include "HashCountedSet.h"
 #include "SentinelLinkedList.h"
 #include "SinglyLinkedList.h"
 
@@ -38,7 +39,6 @@ class HeapRootVisitor;
 class JSGlobalData;
 class JSValue;
 class MarkStack;
-class TypeCounter;
 typedef MarkStack SlotVisitor;
 
 class WeakHandleOwner {
@@ -74,7 +74,8 @@ public:
 #endif
 
     unsigned protectedGlobalObjectCount();
-    void protectedObjectTypeCounts(TypeCounter&);
+
+    template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet);
 
 private:
     class Node {
@@ -278,6 +279,19 @@ inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
     return reinterpret_cast<WeakHandleOwner*>(-1);
 }
 
+template<typename Functor> void HandleHeap::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
+{
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+        JSValue value = *node->slot();
+        if (!value || !value.isCell())
+            continue;
+        if (skipSet.contains(value.asCell()))
+            continue;
+        functor(value.asCell());
+    }
+}
+
 }
 
 #endif
index f76a188..1546c75 100644 (file)
 #define COLLECT_ON_EVERY_ALLOCATION 0
 
 using namespace std;
+using namespace JSC;
 
 namespace JSC {
 
+namespace { 
+
 const size_t minBytesPerCycle = 512 * 1024;
 
 static inline bool isValidSharedInstanceThreadState()
@@ -63,6 +66,179 @@ static inline bool isValidThreadState(JSGlobalData* globalData)
     return true;
 }
 
+class CountFunctor {
+public:
+    typedef size_t ReturnType;
+
+    CountFunctor();
+    void count(size_t);
+    ReturnType returnValue();
+
+private:
+    ReturnType m_count;
+};
+
+inline CountFunctor::CountFunctor()
+    : m_count(0)
+{
+}
+
+inline void CountFunctor::count(size_t count)
+{
+    m_count += count;
+}
+
+inline CountFunctor::ReturnType CountFunctor::returnValue()
+{
+    return m_count;
+}
+
+struct ClearMarks : MarkedBlock::VoidFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void ClearMarks::operator()(MarkedBlock* block)
+{
+    block->clearMarks();
+}
+
+struct ResetAllocator : MarkedBlock::VoidFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void ResetAllocator::operator()(MarkedBlock* block)
+{
+    block->resetAllocator();
+}
+
+struct Sweep : MarkedBlock::VoidFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Sweep::operator()(MarkedBlock* block)
+{
+    block->sweep();
+}
+
+struct MarkCount : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void MarkCount::operator()(MarkedBlock* block)
+{
+    count(block->markCount());
+}
+
+struct Size : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Size::operator()(MarkedBlock* block)
+{
+    count(block->markCount() * block->cellSize());
+}
+
+struct Capacity : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Capacity::operator()(MarkedBlock* block)
+{
+    count(block->capacity());
+}
+
+struct Count : public CountFunctor {
+    void operator()(JSCell*);
+};
+
+inline void Count::operator()(JSCell*)
+{
+    count(1);
+}
+
+struct CountIfGlobalObject : CountFunctor {
+    void operator()(JSCell*);
+};
+
+inline void CountIfGlobalObject::operator()(JSCell* cell)
+{
+    if (!cell->isObject())
+        return;
+    if (!asObject(cell)->isGlobalObject())
+        return;
+    count(1);
+}
+
+class TakeIfEmpty {
+public:
+    typedef MarkedBlock* ReturnType;
+
+    TakeIfEmpty(NewSpace*);
+    void operator()(MarkedBlock*);
+    ReturnType returnValue();
+
+private:
+    NewSpace* m_newSpace;
+    DoublyLinkedList<MarkedBlock> m_empties;
+};
+
+inline TakeIfEmpty::TakeIfEmpty(NewSpace* newSpace)
+    : m_newSpace(newSpace)
+{
+}
+
+inline void TakeIfEmpty::operator()(MarkedBlock* block)
+{
+    if (!block->isEmpty())
+        return;
+
+    m_newSpace->removeBlock(block);
+    m_empties.append(block);
+}
+
+inline TakeIfEmpty::ReturnType TakeIfEmpty::returnValue()
+{
+    return m_empties.head();
+}
+
+class RecordType {
+public:
+    typedef PassOwnPtr<TypeCountSet> ReturnType;
+
+    RecordType();
+    void operator()(JSCell*);
+    ReturnType returnValue();
+
+private:
+    const char* typeName(JSCell*);
+    OwnPtr<TypeCountSet> m_typeCountSet;
+};
+
+inline RecordType::RecordType()
+    : m_typeCountSet(adoptPtr(new TypeCountSet))
+{
+}
+
+inline const char* RecordType::typeName(JSCell* cell)
+{
+    const ClassInfo* info = cell->classInfo();
+    if (!info || !info->className)
+        return "[unknown]";
+    return info->className;
+}
+
+inline void RecordType::operator()(JSCell* cell)
+{
+    m_typeCountSet->add(typeName(cell));
+}
+
+inline PassOwnPtr<TypeCountSet> RecordType::returnValue()
+{
+    return m_typeCountSet.release();
+}
+
+} // anonymous namespace
+
 Heap::Heap(JSGlobalData* globalData)
     : m_operationInProgress(NoOperation)
     , m_newSpace(this)
@@ -282,141 +458,52 @@ void Heap::markRoots()
 
 void Heap::clearMarks()
 {
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        (*it)->clearMarks();
+    forEachBlock<ClearMarks>();
 }
 
 void Heap::sweep()
 {
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        (*it)->sweep();
+    forEachBlock<Sweep>();
 }
 
-size_t Heap::objectCount() const
+size_t Heap::objectCount()
 {
-    size_t result = 0;
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        result += (*it)->markCount();
-    return result;
+    return forEachBlock<MarkCount>();
 }
 
-size_t Heap::size() const
+size_t Heap::size()
 {
-    size_t result = 0;
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        result += (*it)->size();
-    return result;
+    return forEachBlock<Size>();
 }
 
-size_t Heap::capacity() const
+size_t Heap::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()
-{
-    return m_globalData->globalObjectCount;
+    return forEachBlock<Capacity>();
 }
 
 size_t Heap::protectedGlobalObjectCount()
 {
-    size_t count = m_handleHeap.protectedGlobalObjectCount();
-
-    ProtectCountSet::iterator end = m_protectedValues.end();
-    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
-        if (it->first->isObject() && asObject(it->first)->isGlobalObject())
-            count++;
-    }
-
-    return count;
-}
-
-size_t Heap::protectedObjectCount()
-{
-    return m_protectedValues.size();
+    return forEachProtectedCell<CountIfGlobalObject>();
 }
 
-class TypeCounter {
-public:
-    TypeCounter();
-    void operator()(JSCell*);
-    PassOwnPtr<TypeCountSet> take();
-    
-private:
-    const char* typeName(JSCell*);
-    OwnPtr<TypeCountSet> m_typeCountSet;
-    HashSet<JSCell*> m_cells;
-};
-
-inline TypeCounter::TypeCounter()
-    : m_typeCountSet(adoptPtr(new TypeCountSet))
-{
-}
-
-inline const char* TypeCounter::typeName(JSCell* cell)
-{
-    if (cell->isString())
-        return "string";
-    if (cell->isGetterSetter())
-        return "Getter-Setter";
-    if (cell->isAPIValueWrapper())
-        return "API wrapper";
-    if (cell->isPropertyNameIterator())
-        return "For-in iterator";
-    if (const ClassInfo* info = cell->classInfo())
-        return info->className;
-    if (!cell->isObject())
-        return "[empty cell]";
-    return "Object";
-}
-
-inline void TypeCounter::operator()(JSCell* cell)
+size_t Heap::globalObjectCount()
 {
-    if (!m_cells.add(cell).second)
-        return;
-    m_typeCountSet->add(typeName(cell));
+    return forEachCell<CountIfGlobalObject>();
 }
 
-inline PassOwnPtr<TypeCountSet> TypeCounter::take()
+size_t Heap::protectedObjectCount()
 {
-    return m_typeCountSet.release();
+    return forEachProtectedCell<Count>();
 }
 
 PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
 {
-    TypeCounter typeCounter;
-
-    ProtectCountSet::iterator end = m_protectedValues.end();
-    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
-        typeCounter(it->first);
-    m_handleHeap.protectedObjectTypeCounts(typeCounter);
-
-    return typeCounter.take();
-}
-
-void HandleHeap::protectedObjectTypeCounts(TypeCounter& typeCounter)
-{
-    Node* end = m_strongList.end();
-    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
-        JSValue value = *node->slot();
-        if (value && value.isCell())
-            typeCounter(value.asCell());
-    }
+    return forEachProtectedCell<RecordType>();
 }
 
 PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
 {
-    TypeCounter typeCounter;
-    forEach(typeCounter);
-    return typeCounter.take();
+    return forEachCell<RecordType>();
 }
 
 void Heap::collectAllGarbage()
@@ -463,13 +550,9 @@ void Heap::collect(SweepToggle sweepToggle)
 
 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;
+    m_newSpace.resetAllocator();
+    forEachBlock<ResetAllocator>();
 }
 
 void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
@@ -504,10 +587,10 @@ MarkedBlock* Heap::allocateBlock(size_t cellSize)
     return block;
 }
 
-void Heap::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+void Heap::freeBlocks(MarkedBlock* head)
 {
     MarkedBlock* next;
-    for (MarkedBlock* block = blocks.head(); block; block = next) {
+    for (MarkedBlock* block = head; block; block = next) {
         next = block->next();
 
         m_blocks.remove(block);
@@ -518,19 +601,8 @@ void Heap::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
 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);
+    TakeIfEmpty takeIfEmpty(&m_newSpace);
+    freeBlocks(forEachBlock(takeIfEmpty));
 }
 
 } // namespace JSC
index ffa2a00..ed9715d 100644 (file)
@@ -91,9 +91,9 @@ namespace JSC {
 
         bool contains(const void*);
 
-        size_t size() const;
-        size_t capacity() const;
-        size_t objectCount() const;
+        size_t size();
+        size_t capacity();
+        size_t objectCount();
         size_t globalObjectCount();
         size_t protectedObjectCount();
         size_t protectedGlobalObjectCount();
@@ -105,7 +105,12 @@ namespace JSC {
     
         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
         
-        template <typename Functor> void forEach(Functor&);
+        template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
+        template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
+        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();
         
         HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); }
         HandleSlot allocateLocalHandle() { return m_handleStack.push(); }
@@ -124,7 +129,7 @@ namespace JSC {
         void resetAllocator();
 
         MarkedBlock* allocateBlock(size_t cellSize);
-        void freeBlocks(DoublyLinkedList<MarkedBlock>&);
+        void freeBlocks(MarkedBlock*);
 
         void clearMarks();
         void markRoots();
@@ -221,11 +226,48 @@ namespace JSC {
             reportExtraMemoryCostSlowCase(cost);
     }
 
-    template <typename Functor> inline void Heap::forEach(Functor& functor)
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
+    {
+        ProtectCountSet::iterator end = m_protectedValues.end();
+        for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+            functor(it->first);
+        m_handleHeap.forEachStrongHandle(functor, m_protectedValues);
+
+        return functor.returnValue();
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
+    {
+        Functor functor;
+        return forEachProtectedCell(functor);
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachCell(Functor& functor)
+    {
+        BlockIterator end = m_blocks.end();
+        for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+            (*it)->forEachCell(functor);
+        return functor.returnValue();
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachCell()
+    {
+        Functor functor;
+        return forEachCell(functor);
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachBlock(Functor& functor)
     {
         BlockIterator end = m_blocks.end();
         for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-            (*it)->forEach(functor);
+            functor(*it);
+        return functor.returnValue();
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachBlock()
+    {
+        Functor functor;
+        return forEachBlock(functor);
     }
 
     inline void* Heap::allocate(size_t bytes)
index 9dee0d8..e104002 100644 (file)
@@ -41,6 +41,11 @@ namespace JSC {
     class MarkedBlock : public DoublyLinkedListNode<MarkedBlock> {
         friend class WTF::DoublyLinkedListNode<MarkedBlock>;
     public:
+        struct VoidFunctor {
+            typedef void ReturnType;
+            void returnValue() { }
+        };
+
         static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
 
         static MarkedBlock* create(Heap*, size_t cellSize);
@@ -72,7 +77,7 @@ namespace JSC {
         bool testAndClearMarked(const void*);
         void setMarked(const void*);
         
-        template <typename Functor> void forEach(Functor&);
+        template <typename Functor> void forEachCell(Functor&);
 
     private:
         static const size_t blockSize = 16 * KB;
@@ -184,7 +189,7 @@ namespace JSC {
         m_marks.set(atomNumber(p));
     }
 
-    template <typename Functor> inline void MarkedBlock::forEach(Functor& functor)
+    template <typename Functor> inline void MarkedBlock::forEachCell(Functor& functor)
     {
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
             if (!m_marks.get(i))
index 653462e..6ef7542 100644 (file)
@@ -75,7 +75,7 @@ namespace {
 
 using namespace JSC;
 
-class Recompiler {
+class Recompiler : public MarkedBlock::VoidFunctor {
 public:
     void operator()(JSCell*);
 };
@@ -186,7 +186,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     , parser(new Parser)
     , interpreter(0)
     , heap(this)
-    , globalObjectCount(0)
     , dynamicGlobalObject(0)
     , cachedUTCOffset(NaN)
     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
@@ -448,8 +447,7 @@ void JSGlobalData::recompileAllJSFunctions()
     // up throwing away code that is live on the stack.
     ASSERT(!dynamicGlobalObject);
     
-    Recompiler recompiler;
-    heap.forEach(recompiler);
+    heap.forEachCell<Recompiler>();
 }
 
 void JSGlobalData::releaseExecutableMemory()
index 5c5a909..783c9b9 100644 (file)
@@ -238,7 +238,6 @@ namespace JSC {
 
         HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
 
-        unsigned globalObjectCount;
         JSGlobalObject* dynamicGlobalObject;
 
         HashSet<JSObject*> stringRecursionCheckVisitedObjects;