MarkedBlocks should know that they can be used for more than JSCells
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Jul 2016 21:33:45 +0000 (21:33 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Jul 2016 21:33:45 +0000 (21:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=159643

Reviewed by Geoffrey Garen.

This teaches the Heap that a MarkedBlock may hold either JSCells, or Auxiliary, which is
not a JSCell. It teaches the heap and all of the things that walk the heap to ignore
non-JSCells whenever they are looking for global objects, JSObjects, and things to trace
for debugging or profiling. The idea is that we will be able to allocate butterflies and
typed array backing stores as Auxiliary in MarkedSpace rather than allocating those things
in CopiedSpace. That's what bug 159658 is all about.

This gives us a new type, called HeapCell, which is just meant to be a class distinct from
JSCell or any type we would use for Auxiliary. For convenience, JSCell is a subclass of
HeapCell. HeapCell has an enum called HeapCell::Kind, which is either HeapCell::JSCell or
HeapCell::Auxiliary. MarkedSpace no longer speaks of JSCells directly except when dealing
with destruction.

This change required doing a lot of stuff to all of those functor callbacks, since they
now take HeapCell* instead of JSCell* and they take an extra HeapCell::Kind argument to
tell them if they are dealing with JSCells or Auxiliary. I figured that this would be as
good a time as any to convert those functors to being lambda-compatible. This means that
operator() must be const. In some cases, converting the operator() to be const would have
taken more work than just turning the whole thing into a lambda. Whenever this was the
case, I converted the code to use lambdas. I left a lot of functors alone. In cases where
the functor would benefit from being a lambda, for example because it would get rid of
const_casts or mutables, I put in a FIXME referencing bug 159644.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* debugger/Debugger.cpp:
(JSC::Debugger::SetSteppingModeFunctor::SetSteppingModeFunctor):
(JSC::Debugger::SetSteppingModeFunctor::operator()):
(JSC::Debugger::ToggleBreakpointFunctor::ToggleBreakpointFunctor):
(JSC::Debugger::ToggleBreakpointFunctor::operator()):
(JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::ClearCodeBlockDebuggerRequestsFunctor):
(JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator()):
(JSC::Debugger::ClearDebuggerRequestsFunctor::ClearDebuggerRequestsFunctor):
(JSC::Debugger::ClearDebuggerRequestsFunctor::operator()):
* heap/CodeBlockSet.h:
(JSC::CodeBlockSet::iterate):
* heap/HandleSet.h:
(JSC::HandleNode::next):
(JSC::HandleSet::forEachStrongHandle):
* heap/Heap.cpp:
(JSC::GatherHeapSnapshotData::GatherHeapSnapshotData):
(JSC::GatherHeapSnapshotData::operator()):
(JSC::RemoveDeadHeapSnapshotNodes::RemoveDeadHeapSnapshotNodes):
(JSC::RemoveDeadHeapSnapshotNodes::operator()):
(JSC::Heap::protectedGlobalObjectCount):
(JSC::Heap::globalObjectCount):
(JSC::Heap::protectedObjectCount):
(JSC::Heap::protectedObjectTypeCounts):
(JSC::Heap::objectTypeCounts):
(JSC::Heap::deleteAllCodeBlocks):
(JSC::MarkedBlockSnapshotFunctor::MarkedBlockSnapshotFunctor):
(JSC::MarkedBlockSnapshotFunctor::operator()):
(JSC::Zombify::visit):
(JSC::Zombify::operator()):
(JSC::Heap::zombifyDeadObjects):
(JSC::Heap::flushWriteBarrierBuffer):
* heap/Heap.h:
(JSC::Heap::handleSet):
(JSC::Heap::handleStack):
* heap/HeapCell.cpp: Added.
(WTF::printInternal):
* heap/HeapCell.h: Added.
(JSC::HeapCell::HeapCell):
(JSC::HeapCell::zap):
(JSC::HeapCell::isZapped):
* heap/HeapInlines.h:
(JSC::Heap::deprecatedReportExtraMemory):
(JSC::Heap::forEachCodeBlock):
(JSC::Heap::forEachProtectedCell):
(JSC::Heap::allocateWithDestructor):
* heap/HeapStatistics.cpp:
(JSC::StorageStatistics::visit):
(JSC::StorageStatistics::operator()):
* heap/HeapVerifier.cpp:
(JSC::GatherLiveObjFunctor::visit):
(JSC::GatherLiveObjFunctor::operator()):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::allocateBlock):
(JSC::MarkedAllocator::addBlock):
(JSC::MarkedAllocator::reset):
(JSC::MarkedAllocator::lastChanceToFinalize):
(JSC::LastChanceToFinalize::operator()): Deleted.
* heap/MarkedAllocator.h:
(JSC::MarkedAllocator::takeLastActiveBlock):
(JSC::MarkedAllocator::resumeAllocating):
(JSC::MarkedAllocator::forEachBlock):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::create):
(JSC::MarkedBlock::destroy):
(JSC::MarkedBlock::MarkedBlock):
(JSC::MarkedBlock::callDestructor):
(JSC::MarkedBlock::specializedSweep):
(JSC::SetNewlyAllocatedFunctor::SetNewlyAllocatedFunctor):
(JSC::SetNewlyAllocatedFunctor::operator()):
(JSC::MarkedBlock::stopAllocating):
(JSC::MarkedBlock::didRetireBlock):
* heap/MarkedBlock.h:
(JSC::MarkedBlock::CountFunctor::CountFunctor):
(JSC::MarkedBlock::CountFunctor::count):
(JSC::MarkedBlock::CountFunctor::returnValue):
(JSC::MarkedBlock::needsDestruction):
(JSC::MarkedBlock::cellKind):
(JSC::MarkedBlock::size):
(JSC::MarkedBlock::clearNewlyAllocated):
(JSC::MarkedBlock::isMarkedOrNewlyAllocated):
(JSC::MarkedBlock::isLive):
(JSC::MarkedBlock::isLiveCell):
(JSC::MarkedBlock::forEachCell):
(JSC::MarkedBlock::forEachLiveCell):
(JSC::MarkedBlock::forEachDeadCell):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::~MarkedSpace):
(JSC::MarkedSpace::lastChanceToFinalize):
(JSC::MarkedSpace::sweep):
(JSC::MarkedSpace::zombifySweep):
(JSC::MarkedSpace::resetAllocators):
(JSC::MarkedSpace::visitWeakSets):
(JSC::MarkedSpace::reapWeakSets):
(JSC::MarkedSpace::forEachAllocator):
(JSC::MarkedSpace::stopAllocating):
(JSC::MarkedSpace::resumeAllocating):
(JSC::MarkedSpace::isPagedOut):
(JSC::MarkedSpace::shrink):
(JSC::clearNewlyAllocatedInBlock):
(JSC::MarkedSpace::clearNewlyAllocated):
(JSC::MarkedSpace::clearMarks):
(JSC::Free::Free): Deleted.
(JSC::Free::operator()): Deleted.
(JSC::FreeOrShrink::FreeOrShrink): Deleted.
(JSC::FreeOrShrink::operator()): Deleted.
(JSC::VisitWeakSet::VisitWeakSet): Deleted.
(JSC::VisitWeakSet::operator()): Deleted.
(JSC::ReapWeakSet::operator()): Deleted.
(JSC::LastChanceToFinalize::operator()): Deleted.
(JSC::StopAllocatingFunctor::operator()): Deleted.
(JSC::ResumeAllocatingFunctor::operator()): Deleted.
(JSC::ClearNewlyAllocated::operator()): Deleted.
(JSC::VerifyNewlyAllocated::operator()): Deleted.
* heap/MarkedSpace.h:
(JSC::MarkedSpace::forEachLiveCell):
(JSC::MarkedSpace::forEachDeadCell):
(JSC::MarkedSpace::allocatorFor):
(JSC::MarkedSpace::allocateWithDestructor):
(JSC::MarkedSpace::forEachBlock):
(JSC::MarkedSpace::didAddBlock):
(JSC::MarkedSpace::objectCount):
(JSC::MarkedSpace::size):
(JSC::MarkedSpace::capacity):
(JSC::ClearMarks::operator()): Deleted.
(JSC::Sweep::operator()): Deleted.
(JSC::ZombifySweep::operator()): Deleted.
(JSC::MarkCount::operator()): Deleted.
(JSC::Size::operator()): Deleted.
* runtime/JSCell.h:
(JSC::JSCell::zap): Deleted.
(JSC::JSCell::isZapped): Deleted.
* runtime/JSCellInlines.h:
(JSC::allocateCell):
(JSC::JSCell::isObject):
(JSC::isZapped): Deleted.
* runtime/JSGlobalObject.cpp:
* tools/JSDollarVMPrototype.cpp:
(JSC::CellAddressCheckFunctor::CellAddressCheckFunctor):
(JSC::CellAddressCheckFunctor::operator()):

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

23 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/heap/CodeBlockSet.h
Source/JavaScriptCore/heap/HandleSet.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/HeapCell.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/HeapCell.h [new file with mode: 0644]
Source/JavaScriptCore/heap/HeapInlines.h
Source/JavaScriptCore/heap/HeapStatistics.cpp
Source/JavaScriptCore/heap/HeapVerifier.cpp
Source/JavaScriptCore/heap/MarkedAllocator.cpp
Source/JavaScriptCore/heap/MarkedAllocator.h
Source/JavaScriptCore/heap/MarkedBlock.cpp
Source/JavaScriptCore/heap/MarkedBlock.h
Source/JavaScriptCore/heap/MarkedSpace.cpp
Source/JavaScriptCore/heap/MarkedSpace.h
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp

index c4977da..4656bd3 100644 (file)
@@ -445,6 +445,7 @@ set(JavaScriptCore_SOURCES
     heap/HandleSet.cpp
     heap/HandleStack.cpp
     heap/Heap.cpp
+    heap/HeapCell.cpp
     heap/HeapHelperPool.cpp
     heap/HeapProfiler.cpp
     heap/HeapSnapshot.cpp
index fff4c46..efee5d9 100644 (file)
@@ -1,3 +1,176 @@
+2016-07-12  Filip Pizlo  <fpizlo@apple.com>
+
+        MarkedBlocks should know that they can be used for more than JSCells
+        https://bugs.webkit.org/show_bug.cgi?id=159643
+
+        Reviewed by Geoffrey Garen.
+        
+        This teaches the Heap that a MarkedBlock may hold either JSCells, or Auxiliary, which is
+        not a JSCell. It teaches the heap and all of the things that walk the heap to ignore
+        non-JSCells whenever they are looking for global objects, JSObjects, and things to trace
+        for debugging or profiling. The idea is that we will be able to allocate butterflies and
+        typed array backing stores as Auxiliary in MarkedSpace rather than allocating those things
+        in CopiedSpace. That's what bug 159658 is all about.
+        
+        This gives us a new type, called HeapCell, which is just meant to be a class distinct from
+        JSCell or any type we would use for Auxiliary. For convenience, JSCell is a subclass of
+        HeapCell. HeapCell has an enum called HeapCell::Kind, which is either HeapCell::JSCell or
+        HeapCell::Auxiliary. MarkedSpace no longer speaks of JSCells directly except when dealing
+        with destruction.
+        
+        This change required doing a lot of stuff to all of those functor callbacks, since they
+        now take HeapCell* instead of JSCell* and they take an extra HeapCell::Kind argument to
+        tell them if they are dealing with JSCells or Auxiliary. I figured that this would be as
+        good a time as any to convert those functors to being lambda-compatible. This means that
+        operator() must be const. In some cases, converting the operator() to be const would have
+        taken more work than just turning the whole thing into a lambda. Whenever this was the
+        case, I converted the code to use lambdas. I left a lot of functors alone. In cases where
+        the functor would benefit from being a lambda, for example because it would get rid of
+        const_casts or mutables, I put in a FIXME referencing bug 159644.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::SetSteppingModeFunctor::SetSteppingModeFunctor):
+        (JSC::Debugger::SetSteppingModeFunctor::operator()):
+        (JSC::Debugger::ToggleBreakpointFunctor::ToggleBreakpointFunctor):
+        (JSC::Debugger::ToggleBreakpointFunctor::operator()):
+        (JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::ClearCodeBlockDebuggerRequestsFunctor):
+        (JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator()):
+        (JSC::Debugger::ClearDebuggerRequestsFunctor::ClearDebuggerRequestsFunctor):
+        (JSC::Debugger::ClearDebuggerRequestsFunctor::operator()):
+        * heap/CodeBlockSet.h:
+        (JSC::CodeBlockSet::iterate):
+        * heap/HandleSet.h:
+        (JSC::HandleNode::next):
+        (JSC::HandleSet::forEachStrongHandle):
+        * heap/Heap.cpp:
+        (JSC::GatherHeapSnapshotData::GatherHeapSnapshotData):
+        (JSC::GatherHeapSnapshotData::operator()):
+        (JSC::RemoveDeadHeapSnapshotNodes::RemoveDeadHeapSnapshotNodes):
+        (JSC::RemoveDeadHeapSnapshotNodes::operator()):
+        (JSC::Heap::protectedGlobalObjectCount):
+        (JSC::Heap::globalObjectCount):
+        (JSC::Heap::protectedObjectCount):
+        (JSC::Heap::protectedObjectTypeCounts):
+        (JSC::Heap::objectTypeCounts):
+        (JSC::Heap::deleteAllCodeBlocks):
+        (JSC::MarkedBlockSnapshotFunctor::MarkedBlockSnapshotFunctor):
+        (JSC::MarkedBlockSnapshotFunctor::operator()):
+        (JSC::Zombify::visit):
+        (JSC::Zombify::operator()):
+        (JSC::Heap::zombifyDeadObjects):
+        (JSC::Heap::flushWriteBarrierBuffer):
+        * heap/Heap.h:
+        (JSC::Heap::handleSet):
+        (JSC::Heap::handleStack):
+        * heap/HeapCell.cpp: Added.
+        (WTF::printInternal):
+        * heap/HeapCell.h: Added.
+        (JSC::HeapCell::HeapCell):
+        (JSC::HeapCell::zap):
+        (JSC::HeapCell::isZapped):
+        * heap/HeapInlines.h:
+        (JSC::Heap::deprecatedReportExtraMemory):
+        (JSC::Heap::forEachCodeBlock):
+        (JSC::Heap::forEachProtectedCell):
+        (JSC::Heap::allocateWithDestructor):
+        * heap/HeapStatistics.cpp:
+        (JSC::StorageStatistics::visit):
+        (JSC::StorageStatistics::operator()):
+        * heap/HeapVerifier.cpp:
+        (JSC::GatherLiveObjFunctor::visit):
+        (JSC::GatherLiveObjFunctor::operator()):
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::allocateBlock):
+        (JSC::MarkedAllocator::addBlock):
+        (JSC::MarkedAllocator::reset):
+        (JSC::MarkedAllocator::lastChanceToFinalize):
+        (JSC::LastChanceToFinalize::operator()): Deleted.
+        * heap/MarkedAllocator.h:
+        (JSC::MarkedAllocator::takeLastActiveBlock):
+        (JSC::MarkedAllocator::resumeAllocating):
+        (JSC::MarkedAllocator::forEachBlock):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::create):
+        (JSC::MarkedBlock::destroy):
+        (JSC::MarkedBlock::MarkedBlock):
+        (JSC::MarkedBlock::callDestructor):
+        (JSC::MarkedBlock::specializedSweep):
+        (JSC::SetNewlyAllocatedFunctor::SetNewlyAllocatedFunctor):
+        (JSC::SetNewlyAllocatedFunctor::operator()):
+        (JSC::MarkedBlock::stopAllocating):
+        (JSC::MarkedBlock::didRetireBlock):
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::CountFunctor::CountFunctor):
+        (JSC::MarkedBlock::CountFunctor::count):
+        (JSC::MarkedBlock::CountFunctor::returnValue):
+        (JSC::MarkedBlock::needsDestruction):
+        (JSC::MarkedBlock::cellKind):
+        (JSC::MarkedBlock::size):
+        (JSC::MarkedBlock::clearNewlyAllocated):
+        (JSC::MarkedBlock::isMarkedOrNewlyAllocated):
+        (JSC::MarkedBlock::isLive):
+        (JSC::MarkedBlock::isLiveCell):
+        (JSC::MarkedBlock::forEachCell):
+        (JSC::MarkedBlock::forEachLiveCell):
+        (JSC::MarkedBlock::forEachDeadCell):
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::MarkedSpace):
+        (JSC::MarkedSpace::~MarkedSpace):
+        (JSC::MarkedSpace::lastChanceToFinalize):
+        (JSC::MarkedSpace::sweep):
+        (JSC::MarkedSpace::zombifySweep):
+        (JSC::MarkedSpace::resetAllocators):
+        (JSC::MarkedSpace::visitWeakSets):
+        (JSC::MarkedSpace::reapWeakSets):
+        (JSC::MarkedSpace::forEachAllocator):
+        (JSC::MarkedSpace::stopAllocating):
+        (JSC::MarkedSpace::resumeAllocating):
+        (JSC::MarkedSpace::isPagedOut):
+        (JSC::MarkedSpace::shrink):
+        (JSC::clearNewlyAllocatedInBlock):
+        (JSC::MarkedSpace::clearNewlyAllocated):
+        (JSC::MarkedSpace::clearMarks):
+        (JSC::Free::Free): Deleted.
+        (JSC::Free::operator()): Deleted.
+        (JSC::FreeOrShrink::FreeOrShrink): Deleted.
+        (JSC::FreeOrShrink::operator()): Deleted.
+        (JSC::VisitWeakSet::VisitWeakSet): Deleted.
+        (JSC::VisitWeakSet::operator()): Deleted.
+        (JSC::ReapWeakSet::operator()): Deleted.
+        (JSC::LastChanceToFinalize::operator()): Deleted.
+        (JSC::StopAllocatingFunctor::operator()): Deleted.
+        (JSC::ResumeAllocatingFunctor::operator()): Deleted.
+        (JSC::ClearNewlyAllocated::operator()): Deleted.
+        (JSC::VerifyNewlyAllocated::operator()): Deleted.
+        * heap/MarkedSpace.h:
+        (JSC::MarkedSpace::forEachLiveCell):
+        (JSC::MarkedSpace::forEachDeadCell):
+        (JSC::MarkedSpace::allocatorFor):
+        (JSC::MarkedSpace::allocateWithDestructor):
+        (JSC::MarkedSpace::forEachBlock):
+        (JSC::MarkedSpace::didAddBlock):
+        (JSC::MarkedSpace::objectCount):
+        (JSC::MarkedSpace::size):
+        (JSC::MarkedSpace::capacity):
+        (JSC::ClearMarks::operator()): Deleted.
+        (JSC::Sweep::operator()): Deleted.
+        (JSC::ZombifySweep::operator()): Deleted.
+        (JSC::MarkCount::operator()): Deleted.
+        (JSC::Size::operator()): Deleted.
+        * runtime/JSCell.h:
+        (JSC::JSCell::zap): Deleted.
+        (JSC::JSCell::isZapped): Deleted.
+        * runtime/JSCellInlines.h:
+        (JSC::allocateCell):
+        (JSC::JSCell::isObject):
+        (JSC::isZapped): Deleted.
+        * runtime/JSGlobalObject.cpp:
+        * tools/JSDollarVMPrototype.cpp:
+        (JSC::CellAddressCheckFunctor::CellAddressCheckFunctor):
+        (JSC::CellAddressCheckFunctor::operator()):
+
 2016-07-18  Filip Pizlo  <fpizlo@apple.com>
 
         Repeatedly creating and destroying workers that enqueue DFG plans can outpace the DFG worklist, which then causes VM shutdown to stall, which then causes memory growth
index b68a96b..c4b396b 100644 (file)
                DC17E81A1C9C91E9008A6AB3 /* CCallHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */; };
                DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; };
                DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; };
+               DC3D2B0A1D34316200BA918C /* HeapCell.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3D2B091D34316100BA918C /* HeapCell.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               DC3D2B0C1D34377000BA918C /* HeapCell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC3D2B0B1D34376E00BA918C /* HeapCell.cpp */; };
                DC454B8C1D00E822004C18AF /* AirDumpAsJS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC454B8A1D00E81F004C18AF /* AirDumpAsJS.cpp */; };
                DC454B8D1D00E824004C18AF /* AirDumpAsJS.h in Headers */ = {isa = PBXBuildFile; fileRef = DC454B8B1D00E81F004C18AF /* AirDumpAsJS.h */; };
                DC605B5D1CE26EA000593718 /* ProfilerEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC605B591CE26E9800593718 /* ProfilerEvent.cpp */; };
                DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCallHelpers.cpp; sourceTree = "<group>"; };
                DC2143051CA32E52000A8869 /* ICStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ICStats.cpp; sourceTree = "<group>"; };
                DC2143061CA32E52000A8869 /* ICStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICStats.h; sourceTree = "<group>"; };
+               DC3D2B091D34316100BA918C /* HeapCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapCell.h; sourceTree = "<group>"; };
+               DC3D2B0B1D34376E00BA918C /* HeapCell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapCell.cpp; sourceTree = "<group>"; };
                DC454B8A1D00E81F004C18AF /* AirDumpAsJS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirDumpAsJS.cpp; path = b3/air/AirDumpAsJS.cpp; sourceTree = "<group>"; };
                DC454B8B1D00E81F004C18AF /* AirDumpAsJS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirDumpAsJS.h; path = b3/air/AirDumpAsJS.h; sourceTree = "<group>"; };
                DC605B591CE26E9800593718 /* ProfilerEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerEvent.cpp; path = profiler/ProfilerEvent.cpp; sourceTree = "<group>"; };
                                146FA5A81378F6B0003627A3 /* HandleTypes.h */,
                                14BA7A9513AADFF8005B7C2C /* Heap.cpp */,
                                14BA7A9613AADFF8005B7C2C /* Heap.h */,
+                               DC3D2B0B1D34376E00BA918C /* HeapCell.cpp */,
+                               DC3D2B091D34316100BA918C /* HeapCell.h */,
                                0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */,
                                0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */,
                                C2DA778218E259990066FCB6 /* HeapInlines.h */,
                                0FFB921A16D02EC50055A5DB /* DFGBasicBlockInlines.h in Headers */,
                                A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */,
                                0F2BBD961C5FF3F50023EF23 /* B3SparseCollection.h in Headers */,
+                               DC3D2B0A1D34316200BA918C /* HeapCell.h in Headers */,
                                0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
                                0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */,
                                0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */,
                                DC605B5F1CE26EA500593718 /* ProfilerUID.cpp in Sources */,
                                70ECA6071AFDBEA200449739 /* TemplateRegistry.cpp in Sources */,
                                0FC314131814559100033232 /* TempRegisterSet.cpp in Sources */,
+                               DC3D2B0C1D34377000BA918C /* HeapCell.cpp in Sources */,
                                0FA2C17B17D7CF84009D015F /* TestRunnerUtils.cpp in Sources */,
                                A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */,
                                0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */,
index e870677..0fb3d8c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2013, 2014, 2016 Apple Inc. All rights reserved.
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
  *
@@ -40,14 +40,21 @@ namespace {
 using namespace JSC;
 
 struct GatherSourceProviders : public MarkedBlock::VoidFunctor {
-    HashSet<SourceProvider*> sourceProviders;
+    // FIXME: This is a mutable field becaue this isn't a C++ lambda.
+    // https://bugs.webkit.org/show_bug.cgi?id=159644
+    mutable HashSet<SourceProvider*> sourceProviders;
     JSGlobalObject* m_globalObject;
 
     GatherSourceProviders(JSGlobalObject* globalObject)
         : m_globalObject(globalObject) { }
 
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
     {
+        if (kind != HeapCell::JSCell)
+            return IterationStatus::Continue;
+        
+        JSCell* cell = static_cast<JSCell*>(heapCell);
+        
         JSFunction* function = jsDynamicCast<JSFunction*>(cell);
         if (!function)
             return IterationStatus::Continue;
@@ -191,7 +198,7 @@ public:
     {
     }
 
-    bool operator()(CodeBlock* codeBlock)
+    bool operator()(CodeBlock* codeBlock) const
     {
         if (m_debugger == codeBlock->globalObject()->debugger()) {
             if (m_mode == SteppingModeEnabled)
@@ -298,7 +305,7 @@ public:
     {
     }
 
-    bool operator()(CodeBlock* codeBlock)
+    bool operator()(CodeBlock* codeBlock) const
     {
         if (m_debugger == codeBlock->globalObject()->debugger())
             m_debugger->toggleBreakpoint(codeBlock, m_breakpoint, m_enabledOrNot);
@@ -474,7 +481,7 @@ public:
     {
     }
 
-    bool operator()(CodeBlock* codeBlock)
+    bool operator()(CodeBlock* codeBlock) const
     {
         if (codeBlock->hasDebuggerRequests() && m_debugger == codeBlock->globalObject()->debugger())
             codeBlock->clearDebuggerRequests();
@@ -504,7 +511,7 @@ public:
     {
     }
 
-    bool operator()(CodeBlock* codeBlock)
+    bool operator()(CodeBlock* codeBlock) const
     {
         if (codeBlock->hasDebuggerRequests() && m_globalObject == codeBlock->globalObject())
             codeBlock->clearDebuggerRequests();
index 56507c0..8ad66d9 100644 (file)
@@ -82,7 +82,7 @@ public:
     // Visits each CodeBlock in the heap until the visitor function returns true
     // to indicate that it is done iterating, or until every CodeBlock has been
     // visited.
-    template<typename Functor> void iterate(Functor& functor)
+    template<typename Functor> void iterate(const Functor& functor)
     {
         LockHolder locker(m_lock);
         for (auto& codeBlock : m_oldCodeBlocks) {
index f973788..d04318d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #include "Handle.h"
 #include "HandleBlock.h"
+#include "HeapCell.h"
 #include <wtf/DoublyLinkedList.h>
 #include <wtf/HashCountedSet.h>
 #include <wtf/SentinelLinkedList.h>
@@ -79,7 +80,7 @@ public:
 
     unsigned protectedGlobalObjectCount();
 
-    template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet);
+    template<typename Functor> void forEachStrongHandle(const Functor&, const HashCountedSet<JSCell*>& skipSet);
 
 private:
     typedef HandleNode Node;
@@ -180,7 +181,7 @@ inline HandleNode* HandleNode::next()
     return m_next;
 }
 
-template<typename Functor> void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
+template<typename Functor> void HandleSet::forEachStrongHandle(const Functor& functor, const HashCountedSet<JSCell*>& skipSet)
 {
     HandleSet::Node* end = m_strongList.end();
     for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) {
index 5c0f186..f870347 100644 (file)
@@ -252,61 +252,13 @@ static inline bool isValidThreadState(VM* vm)
     return true;
 }
 
-struct Count : public MarkedBlock::CountFunctor {
-    void operator()(JSCell*) { count(1); }
-};
-
-struct CountIfGlobalObject : MarkedBlock::CountFunctor {
-    inline void visit(JSCell* cell)
-    {
-        if (!cell->isObject())
-            return;
-        if (!asObject(cell)->isGlobalObject())
-            return;
-        count(1);
-    }
-    IterationStatus operator()(JSCell* cell)
-    {
-        visit(cell);
-        return IterationStatus::Continue;
-    }
-};
-
-class RecordType {
-public:
-    typedef std::unique_ptr<TypeCountSet> ReturnType;
-
-    RecordType();
-    IterationStatus operator()(JSCell*);
-    ReturnType returnValue();
-
-private:
-    const char* typeName(JSCell*);
-    std::unique_ptr<TypeCountSet> m_typeCountSet;
-};
-
-inline RecordType::RecordType()
-    : m_typeCountSet(std::make_unique<TypeCountSet>())
-{
-}
-
-inline const char* RecordType::typeName(JSCell* cell)
+static inline void recordType(TypeCountSet& set, JSCell* cell)
 {
+    const char* typeName = "[unknown]";
     const ClassInfo* info = cell->classInfo();
-    if (!info || !info->className)
-        return "[unknown]";
-    return info->className;
-}
-
-inline IterationStatus RecordType::operator()(JSCell* cell)
-{
-    m_typeCountSet->add(typeName(cell));
-    return IterationStatus::Continue;
-}
-
-inline std::unique_ptr<TypeCountSet> RecordType::returnValue()
-{
-    return WTFMove(m_typeCountSet);
+    if (info && info->className)
+        typeName = info->className;
+    set.add(typeName);
 }
 
 } // anonymous namespace
@@ -766,9 +718,12 @@ struct GatherHeapSnapshotData : MarkedBlock::CountFunctor {
     {
     }
 
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const
     {
-        cell->methodTable()->heapSnapshot(cell, m_builder);
+        if (kind == HeapCell::JSCell) {
+            JSCell* cell = static_cast<JSCell*>(heapCell);
+            cell->methodTable()->heapSnapshot(cell, m_builder);
+        }
         return IterationStatus::Continue;
     }
 
@@ -791,9 +746,10 @@ struct RemoveDeadHeapSnapshotNodes : MarkedBlock::CountFunctor {
     {
     }
 
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const
     {
-        m_snapshot.sweepCell(cell);
+        if (kind == HeapCell::JSCell)
+            m_snapshot.sweepCell(static_cast<JSCell*>(cell));
         return IterationStatus::Continue;
     }
 
@@ -993,29 +949,64 @@ size_t Heap::capacity()
 
 size_t Heap::protectedGlobalObjectCount()
 {
-    return forEachProtectedCell<CountIfGlobalObject>();
+    size_t result = 0;
+    forEachProtectedCell(
+        [&] (JSCell* cell) {
+            if (cell->isObject() && asObject(cell)->isGlobalObject())
+                result++;
+        });
+    return result;
 }
 
 size_t Heap::globalObjectCount()
 {
     HeapIterationScope iterationScope(*this);
-    return m_objectSpace.forEachLiveCell<CountIfGlobalObject>(iterationScope);
+    size_t result = 0;
+    m_objectSpace.forEachLiveCell(
+        iterationScope,
+        [&] (HeapCell* heapCell, HeapCell::Kind kind) -> IterationStatus {
+            if (kind != HeapCell::JSCell)
+                return IterationStatus::Continue;
+            JSCell* cell = static_cast<JSCell*>(heapCell);
+            if (cell->isObject() && asObject(cell)->isGlobalObject())
+                result++;
+            return IterationStatus::Continue;
+        });
+    return result;
 }
 
 size_t Heap::protectedObjectCount()
 {
-    return forEachProtectedCell<Count>();
+    size_t result = 0;
+    forEachProtectedCell(
+        [&] (JSCell*) {
+            result++;
+        });
+    return result;
 }
 
 std::unique_ptr<TypeCountSet> Heap::protectedObjectTypeCounts()
 {
-    return forEachProtectedCell<RecordType>();
+    std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
+    forEachProtectedCell(
+        [&] (JSCell* cell) {
+            recordType(*result, cell);
+        });
+    return result;
 }
 
 std::unique_ptr<TypeCountSet> Heap::objectTypeCounts()
 {
+    std::unique_ptr<TypeCountSet> result = std::make_unique<TypeCountSet>();
     HeapIterationScope iterationScope(*this);
-    return m_objectSpace.forEachLiveCell<RecordType>(iterationScope);
+    m_objectSpace.forEachLiveCell(
+        iterationScope,
+        [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus {
+            if (kind == HeapCell::JSCell)
+                recordType(*result, static_cast<JSCell*>(cell));
+            return IterationStatus::Continue;
+        });
+    return result;
 }
 
 void Heap::deleteAllCodeBlocks()
@@ -1300,9 +1291,11 @@ struct MarkedBlockSnapshotFunctor : public MarkedBlock::VoidFunctor {
     {
     }
 
-    void operator()(MarkedBlock* block) { m_blocks[m_index++] = block; }
+    void operator()(MarkedBlock* block) const { m_blocks[m_index++] = block; }
 
-    size_t m_index;
+    // FIXME: This is a mutable field becaue this isn't a C++ lambda.
+    // https://bugs.webkit.org/show_bug.cgi?id=159644
+    mutable size_t m_index;
     Vector<MarkedBlock*>& m_blocks;
 };
 
@@ -1573,7 +1566,7 @@ void Heap::collectAllGarbageIfNotDoneRecently()
 
 class Zombify : public MarkedBlock::VoidFunctor {
 public:
-    inline void visit(JSCell* cell)
+    inline void visit(HeapCell* cell) const
     {
         void** current = reinterpret_cast<void**>(cell);
 
@@ -1586,7 +1579,7 @@ public:
         for (; current < limit; current++)
             *current = zombifiedBits;
     }
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
     {
         visit(cell);
         return IterationStatus::Continue;
@@ -1598,7 +1591,7 @@ void Heap::zombifyDeadObjects()
     // Sweep now because destructors will crash once we're zombified.
     m_objectSpace.zombifySweep();
     HeapIterationScope iterationScope(*this);
-    m_objectSpace.forEachDeadCell<Zombify>(iterationScope);
+    m_objectSpace.forEachDeadCell(iterationScope, Zombify());
 }
 
 void Heap::flushWriteBarrierBuffer(JSCell* cell)
index fefdbb1..6e73db5 100644 (file)
@@ -205,9 +205,8 @@ public:
 
     HashSet<MarkedArgumentBuffer*>& markListSet();
     
-    template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
-    template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
-    template<typename Functor> void forEachCodeBlock(Functor&);
+    template<typename Functor> void forEachProtectedCell(const Functor&);
+    template<typename Functor> void forEachCodeBlock(const Functor&);
 
     HandleSet* handleSet() { return &m_handleSet; }
     HandleStack* handleStack() { return &m_handleStack; }
diff --git a/Source/JavaScriptCore/heap/HeapCell.cpp b/Source/JavaScriptCore/heap/HeapCell.cpp
new file mode 100644 (file)
index 0000000..e3a6597
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 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. ``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
+ * 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 "HeapCell.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream& out, HeapCell::Kind kind)
+{
+    switch (kind) {
+    case HeapCell::JSCell:
+        out.print("JSCell");
+        return;
+    case HeapCell::Auxiliary:
+        out.print("Auxiliary");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
diff --git a/Source/JavaScriptCore/heap/HeapCell.h b/Source/JavaScriptCore/heap/HeapCell.h
new file mode 100644 (file)
index 0000000..242cf45
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 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. ``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
+ * 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. 
+ */
+
+#pragma once
+
+namespace JSC {
+
+class HeapCell {
+public:
+    enum Kind : int8_t {
+        JSCell,
+        Auxiliary
+    };
+    
+    HeapCell() { }
+    
+    void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
+    bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::HeapCell::Kind);
+
+} // namespace WTF
+
index a9c419c..3367957 100644 (file)
@@ -165,7 +165,7 @@ inline void Heap::deprecatedReportExtraMemory(size_t size)
         deprecatedReportExtraMemorySlowCase(size);
 }
 
-template<typename Functor> inline void Heap::forEachCodeBlock(Functor& functor)
+template<typename Functor> inline void Heap::forEachCodeBlock(const Functor& functor)
 {
     // We don't know the full set of CodeBlocks until compilation has terminated.
     completeAllJITPlans();
@@ -173,19 +173,11 @@ template<typename Functor> inline void Heap::forEachCodeBlock(Functor& functor)
     return m_codeBlocks.iterate<Functor>(functor);
 }
 
-template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
+template<typename Functor> inline void Heap::forEachProtectedCell(const Functor& functor)
 {
     for (auto& pair : m_protectedValues)
         functor(pair.key);
     m_handleSet.forEachStrongHandle(functor, m_protectedValues);
-
-    return functor.returnValue();
-}
-
-template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
-{
-    Functor functor;
-    return forEachProtectedCell(functor);
 }
 
 inline void* Heap::allocateWithDestructor(size_t bytes)
index 12d12ce..ed5e398 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -146,7 +146,7 @@ class StorageStatistics : public MarkedBlock::VoidFunctor {
 public:
     StorageStatistics();
 
-    IterationStatus operator()(JSCell*);
+    IterationStatus operator()(HeapCell*, HeapCell::Kind) const;
 
     size_t objectWithOutOfLineStorageCount();
     size_t objectCount();
@@ -190,9 +190,13 @@ inline void StorageStatistics::visit(JSCell* cell)
     m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>); 
 }
 
-inline IterationStatus StorageStatistics::operator()(JSCell* cell)
+inline IterationStatus StorageStatistics::operator()(HeapCell* cell, HeapCell::Kind kind) const
 {
-    visit(cell);
+    if (kind == HeapCell::JSCell) {
+        // FIXME: This const_cast exists because this isn't a C++ lambda.
+        // https://bugs.webkit.org/show_bug.cgi?id=159644
+        const_cast<StorageStatistics*>(this)->visit(static_cast<JSCell*>(cell));
+    }
     return IterationStatus::Continue;
 }
 
index 0f4e282..451e77c 100644 (file)
@@ -120,9 +120,13 @@ struct GatherLiveObjFunctor : MarkedBlock::CountFunctor {
         m_list.liveObjects.append(data);
     }
 
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const
     {
-        visit(cell);
+        if (kind == HeapCell::JSCell) {
+            // FIXME: This const_cast exists because this isn't a C++ lambda.
+            // https://bugs.webkit.org/show_bug.cgi?id=159644
+            const_cast<GatherLiveObjFunctor*>(this)->visit(static_cast<JSCell*>(cell));
+        }
         return IterationStatus::Continue;
     }
 
index ef0e77f..e95ee6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -186,7 +186,10 @@ MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes)
 
     size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes);
 
-    return MarkedBlock::create(*m_heap, this, blockSize, cellSize, m_needsDestruction);
+    // FIXME: Support allocating storage in marked blocks. This would mean that allocateBlock()
+    // takes a HeapCell::Kind, or something like that.
+    // https://bugs.webkit.org/show_bug.cgi?id=159658
+    return MarkedBlock::create(*m_heap, this, blockSize, cellSize, m_needsDestruction, HeapCell::JSCell);
 }
 
 void MarkedAllocator::addBlock(MarkedBlock* block)
@@ -233,15 +236,13 @@ void MarkedAllocator::reset()
     }
 }
 
-struct LastChanceToFinalize : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block) { block->lastChanceToFinalize(); }
-};
-
 void MarkedAllocator::lastChanceToFinalize()
 {
     m_blockList.append(m_retiredBlocks);
-    LastChanceToFinalize functor;
-    forEachBlock(functor);
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            block->lastChanceToFinalize();
+        });
 }
 
 } // namespace JSC
index 277ac9a..8e3afa9 100644 (file)
@@ -57,7 +57,7 @@ public:
         return block;
     }
     
-    template<typename Functor> void forEachBlock(Functor&);
+    template<typename Functor> void forEachBlock(const Functor&);
     
     void addBlock(MarkedBlock*);
     void removeBlock(MarkedBlock*);
@@ -151,7 +151,7 @@ inline void MarkedAllocator::resumeAllocating()
     m_lastActiveBlock = 0;
 }
 
-template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor)
+template <typename Functor> inline void MarkedAllocator::forEachBlock(const Functor& functor)
 {
     MarkedBlock* next;
     for (MarkedBlock* block = m_blockList.head(); block; block = next) {
index 3461d28..5737b5e 100644 (file)
@@ -35,14 +35,14 @@ namespace JSC {
 static const bool computeBalance = false;
 static size_t balance;
 
-MarkedBlock* MarkedBlock::create(Heap& heap, MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction)
+MarkedBlock* MarkedBlock::create(Heap& heap, MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction, HeapCell::Kind cellKind)
 {
     if (computeBalance) {
         balance++;
         if (!(balance % 10))
             dataLog("MarkedBlock Balance: ", balance, "\n");
     }
-    MarkedBlock* block = new (NotNull, fastAlignedMalloc(blockSize, capacity)) MarkedBlock(allocator, capacity, cellSize, needsDestruction);
+    MarkedBlock* block = new (NotNull, fastAlignedMalloc(blockSize, capacity)) MarkedBlock(allocator, capacity, cellSize, needsDestruction, cellKind);
     heap.didAllocateBlock(capacity);
     return block;
 }
@@ -60,12 +60,13 @@ void MarkedBlock::destroy(Heap& heap, MarkedBlock* block)
     heap.didFreeBlock(capacity);
 }
 
-MarkedBlock::MarkedBlock(MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction)
+MarkedBlock::MarkedBlock(MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction, HeapCell::Kind cellKind)
     : DoublyLinkedListNode<MarkedBlock>()
     , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
     , m_endAtom((allocator->cellSize() ? atomsPerBlock - m_atomsPerCell : firstAtom()) + 1)
     , m_capacity(capacity)
     , m_needsDestruction(needsDestruction)
+    , m_cellKind(cellKind)
     , m_allocator(allocator)
     , m_state(New) // All cells start out unmarked.
     , m_weakSet(allocator->heap()->vm(), *this)
@@ -74,17 +75,19 @@ MarkedBlock::MarkedBlock(MarkedAllocator* allocator, size_t capacity, size_t cel
     HEAP_LOG_BLOCK_STATE_TRANSITION(this);
 }
 
-inline void MarkedBlock::callDestructor(JSCell* cell)
+inline void MarkedBlock::callDestructor(HeapCell* cell)
 {
     // A previous eager sweep may already have run cell's destructor.
     if (cell->isZapped())
         return;
+    
+    JSCell* jsCell = static_cast<JSCell*>(cell);
 
-    ASSERT(cell->structureID());
-    if (cell->inlineTypeFlags() & StructureIsImmortal)
-        cell->structure(*vm())->classInfo()->methodTable.destroy(cell);
+    ASSERT(jsCell->structureID());
+    if (jsCell->inlineTypeFlags() & StructureIsImmortal)
+        jsCell->structure(*vm())->classInfo()->methodTable.destroy(jsCell);
     else
-        jsCast<JSDestructibleObject*>(cell)->classInfo()->methodTable.destroy(cell);
+        jsCast<JSDestructibleObject*>(jsCell)->classInfo()->methodTable.destroy(jsCell);
     cell->zap();
 }
 
@@ -103,7 +106,7 @@ MarkedBlock::FreeList MarkedBlock::specializedSweep()
         if (blockState == Marked && (m_marks.get(i) || (m_newlyAllocated && m_newlyAllocated->get(i))))
             continue;
 
-        JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+        HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&atoms()[i]);
 
         if (callDestructors && blockState != New)
             callDestructor(cell);
@@ -171,7 +174,7 @@ public:
     {
     }
 
-    IterationStatus operator()(JSCell* cell)
+    IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
     {
         ASSERT(MarkedBlock::blockFor(cell) == m_block);
         m_block->setNewlyAllocated(cell);
@@ -213,7 +216,8 @@ void MarkedBlock::stopAllocating(const FreeList& freeList)
     FreeCell* next;
     for (FreeCell* current = head; current; current = next) {
         next = current->next;
-        reinterpret_cast<JSCell*>(current)->zap();
+        if (m_needsDestruction)
+            reinterpret_cast<HeapCell*>(current)->zap();
         clearNewlyAllocated(current);
     }
     
@@ -290,7 +294,8 @@ void MarkedBlock::didRetireBlock(const FreeList& freeList)
     FreeCell* next;
     for (FreeCell* current = head; current; current = next) {
         next = current->next;
-        reinterpret_cast<JSCell*>(current)->zap();
+        if (m_needsDestruction)
+            reinterpret_cast<HeapCell*>(current)->zap();
     }
 
     ASSERT(m_state == FreeListed);
index 546971c..5747efc 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef MarkedBlock_h
 #define MarkedBlock_h
 
+#include "HeapCell.h"
 #include "HeapOperation.h"
 #include "IterationStatus.h"
 #include "WeakSet.h"
@@ -53,8 +54,6 @@ namespace JSC {
 
     typedef uintptr_t Bits;
 
-    bool isZapped(const JSCell*);
-    
     // A marked block is a page-aligned container for heap-allocated objects.
     // Objects are allocated within cells of the marked block. For a given
     // marked block, all cells have the same size. Objects smaller than the
@@ -99,14 +98,16 @@ namespace JSC {
             typedef size_t ReturnType;
 
             CountFunctor() : m_count(0) { }
-            void count(size_t count) { m_count += count; }
-            ReturnType returnValue() { return m_count; }
+            void count(size_t count) const { m_count += count; }
+            ReturnType returnValue() const { return m_count; }
 
         private:
-            ReturnType m_count;
+            // FIXME: This is mutable because we're using a functor rather than C++ lambdas.
+            // https://bugs.webkit.org/show_bug.cgi?id=159644
+            mutable ReturnType m_count;
         };
 
-        static MarkedBlock* create(Heap&, MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction);
+        static MarkedBlock* create(Heap&, MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction, HeapCell::Kind);
         static void destroy(Heap&, MarkedBlock*);
 
         static bool isAtomAligned(const void*);
@@ -147,16 +148,17 @@ namespace JSC {
 
         size_t cellSize();
         bool needsDestruction() const;
+        HeapCell::Kind cellKind() const;
 
         size_t size();
         size_t capacity();
 
         bool isMarked(const void*);
         bool testAndSetMarked(const void*);
-        bool isLive(const JSCell*);
+        bool isLive(const HeapCell*);
         bool isLiveCell(const void*);
         bool isAtom(const void*);
-        bool isMarkedOrNewlyAllocated(const JSCell*);
+        bool isMarkedOrNewlyAllocated(const HeapCell*);
         void setMarked(const void*);
         void clearMarked(const void*);
 
@@ -170,9 +172,9 @@ namespace JSC {
         void didRetireBlock(const FreeList&);
         void willRemoveBlock();
 
-        template <typename Functor> IterationStatus forEachCell(Functor&);
-        template <typename Functor> IterationStatus forEachLiveCell(Functor&);
-        template <typename Functor> IterationStatus forEachDeadCell(Functor&);
+        template <typename Functor> IterationStatus forEachCell(const Functor&);
+        template <typename Functor> IterationStatus forEachLiveCell(const Functor&);
+        template <typename Functor> IterationStatus forEachDeadCell(const Functor&);
 
     private:
         static const size_t atomAlignmentMask = atomSize - 1;
@@ -182,10 +184,10 @@ namespace JSC {
 
         typedef char Atom[atomSize];
 
-        MarkedBlock(MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction);
+        MarkedBlock(MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction, HeapCell::Kind);
         Atom* atoms();
         size_t atomNumber(const void*);
-        void callDestructor(JSCell*);
+        void callDestructor(HeapCell*);
         template<BlockState, SweepMode, bool callDestructors> FreeList specializedSweep();
         
         MarkedBlock* m_prev;
@@ -198,6 +200,7 @@ namespace JSC {
 
         size_t m_capacity;
         bool m_needsDestruction;
+        HeapCell::Kind m_cellKind;
         MarkedAllocator* m_allocator;
         BlockState m_state;
         WeakSet m_weakSet;
@@ -303,6 +306,11 @@ namespace JSC {
         return m_needsDestruction;
     }
 
+    inline HeapCell::Kind MarkedBlock::cellKind() const
+    {
+        return m_cellKind;
+    }
+
     inline size_t MarkedBlock::size()
     {
         return markCount() * cellSize();
@@ -363,13 +371,13 @@ namespace JSC {
         return false;
     }
 
-    inline bool MarkedBlock::isMarkedOrNewlyAllocated(const JSCell* cell)
+    inline bool MarkedBlock::isMarkedOrNewlyAllocated(const HeapCell* cell)
     {
         ASSERT(m_state == Retired || m_state == Marked);
         return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell));
     }
 
-    inline bool MarkedBlock::isLive(const JSCell* cell)
+    inline bool MarkedBlock::isLive(const HeapCell* cell)
     {
         switch (m_state) {
         case Allocated:
@@ -407,40 +415,43 @@ namespace JSC {
     {
         if (!isAtom(p))
             return false;
-        return isLive(static_cast<const JSCell*>(p));
+        return isLive(static_cast<const HeapCell*>(p));
     }
 
-    template <typename Functor> inline IterationStatus MarkedBlock::forEachCell(Functor& functor)
+    template <typename Functor> inline IterationStatus MarkedBlock::forEachCell(const Functor& functor)
     {
+        HeapCell::Kind kind = m_cellKind;
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
-            JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
-            if (functor(cell) == IterationStatus::Done)
+            HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&atoms()[i]);
+            if (functor(cell, kind) == IterationStatus::Done)
                 return IterationStatus::Done;
         }
         return IterationStatus::Continue;
     }
 
-    template <typename Functor> inline IterationStatus MarkedBlock::forEachLiveCell(Functor& functor)
+    template <typename Functor> inline IterationStatus MarkedBlock::forEachLiveCell(const Functor& functor)
     {
+        HeapCell::Kind kind = m_cellKind;
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
-            JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+            HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&atoms()[i]);
             if (!isLive(cell))
                 continue;
 
-            if (functor(cell) == IterationStatus::Done)
+            if (functor(cell, kind) == IterationStatus::Done)
                 return IterationStatus::Done;
         }
         return IterationStatus::Continue;
     }
 
-    template <typename Functor> inline IterationStatus MarkedBlock::forEachDeadCell(Functor& functor)
+    template <typename Functor> inline IterationStatus MarkedBlock::forEachDeadCell(const Functor& functor)
     {
+        HeapCell::Kind kind = m_cellKind;
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
-            JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+            HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&atoms()[i]);
             if (isLive(cell))
                 continue;
 
-            if (functor(cell) == IterationStatus::Done)
+            if (functor(cell, kind) == IterationStatus::Done)
                 return IterationStatus::Done;
         }
         return IterationStatus::Continue;
index c6d84f0..2c83c07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  *
  *  This library is free software; you can redistribute it and/or
 
 namespace JSC {
 
-struct Free : MarkedBlock::VoidFunctor {
-    Free(MarkedSpace& space) : m_markedSpace(space) { }
-    void operator()(MarkedBlock* block) { m_markedSpace.freeBlock(block); }
-private:
-    MarkedSpace& m_markedSpace;
-};
-
-struct FreeOrShrink : MarkedBlock::VoidFunctor {
-    FreeOrShrink(MarkedSpace& space) : m_markedSpace(space) { }
-    void operator()(MarkedBlock* block) { m_markedSpace.freeOrShrinkBlock(block); }
-private:
-    MarkedSpace& m_markedSpace;
-};
-
-struct VisitWeakSet : MarkedBlock::VoidFunctor {
-    VisitWeakSet(HeapRootVisitor& heapRootVisitor) : m_heapRootVisitor(heapRootVisitor) { }
-    void operator()(MarkedBlock* block) { block->visitWeakSet(m_heapRootVisitor); }
-private:
-    HeapRootVisitor& m_heapRootVisitor;
-};
-
-struct ReapWeakSet : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block) { block->reapWeakSet(); }
-};
-
 MarkedSpace::MarkedSpace(Heap* heap)
     : m_heap(heap)
     , m_capacity(0)
@@ -73,25 +48,29 @@ MarkedSpace::MarkedSpace(Heap* heap)
 
 MarkedSpace::~MarkedSpace()
 {
-    Free free(*this);
-    forEachBlock(free);
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            freeBlock(block);
+        });
     ASSERT(!m_blocks.set().size());
 }
 
-struct LastChanceToFinalize {
-    void operator()(MarkedAllocator& allocator) { allocator.lastChanceToFinalize(); }
-};
-
 void MarkedSpace::lastChanceToFinalize()
 {
     stopAllocating();
-    forEachAllocator<LastChanceToFinalize>();
+    forEachAllocator(
+        [&] (MarkedAllocator& allocator) {
+            allocator.lastChanceToFinalize();
+        });
 }
 
 void MarkedSpace::sweep()
 {
     m_heap->sweeper()->willFinishSweeping();
-    forEachBlock<Sweep>();
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            block->sweep();
+        });
 }
 
 void MarkedSpace::zombifySweep()
@@ -99,7 +78,11 @@ void MarkedSpace::zombifySweep()
     if (Options::logGC())
         dataLog("Zombifying sweep...");
     m_heap->sweeper()->willFinishSweeping();
-    forEachBlock<ZombifySweep>();
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            if (block->needsSweeping())
+                block->sweep();
+        });
 }
 
 void MarkedSpace::resetAllocators()
@@ -122,12 +105,15 @@ void MarkedSpace::resetAllocators()
 
 void MarkedSpace::visitWeakSets(HeapRootVisitor& heapRootVisitor)
 {
-    VisitWeakSet visitWeakSet(heapRootVisitor);
     if (m_heap->operationInProgress() == EdenCollection) {
         for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i)
-            visitWeakSet(m_blocksWithNewObjects[i]);
-    } else
-        forEachBlock(visitWeakSet);
+            m_blocksWithNewObjects[i]->visitWeakSet(heapRootVisitor);
+    } else {
+        forEachBlock(
+            [&] (MarkedBlock* block) {
+                block->visitWeakSet(heapRootVisitor);
+            });
+    }
 }
 
 void MarkedSpace::reapWeakSets()
@@ -135,19 +121,16 @@ void MarkedSpace::reapWeakSets()
     if (m_heap->operationInProgress() == EdenCollection) {
         for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i)
             m_blocksWithNewObjects[i]->reapWeakSet();
-    } else
-        forEachBlock<ReapWeakSet>();
-}
-
-template <typename Functor>
-void MarkedSpace::forEachAllocator()
-{
-    Functor functor;
-    forEachAllocator(functor);
+    } else {
+        forEachBlock(
+            [&] (MarkedBlock* block) {
+                block->reapWeakSet();
+            });
+    }
 }
 
 template <typename Functor>
-void MarkedSpace::forEachAllocator(Functor& functor)
+void MarkedSpace::forEachAllocator(const Functor& functor)
 {
     for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
         functor(allocatorFor(cellSize));
@@ -163,24 +146,22 @@ void MarkedSpace::forEachAllocator(Functor& functor)
     functor(m_destructorSpace.largeAllocator);
 }
 
-struct StopAllocatingFunctor {
-    void operator()(MarkedAllocator& allocator) { allocator.stopAllocating(); }
-};
-
 void MarkedSpace::stopAllocating()
 {
     ASSERT(!isIterating());
-    forEachAllocator<StopAllocatingFunctor>();
+    forEachAllocator(
+        [&] (MarkedAllocator& allocator) {
+            allocator.stopAllocating();
+        });
 }
 
-struct ResumeAllocatingFunctor {
-    void operator()(MarkedAllocator& allocator) { allocator.resumeAllocating(); }
-};
-
 void MarkedSpace::resumeAllocating()
 {
     ASSERT(isIterating());
-    forEachAllocator<ResumeAllocatingFunctor>();
+    forEachAllocator(
+        [&] (MarkedAllocator& allocator) {
+            allocator.resumeAllocating();
+        });
 }
 
 bool MarkedSpace::isPagedOut(double deadline)
@@ -224,8 +205,10 @@ void MarkedSpace::freeOrShrinkBlock(MarkedBlock* block)
 
 void MarkedSpace::shrink()
 {
-    FreeOrShrink freeOrShrink(*this);
-    forEachBlock(freeOrShrink);
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            freeOrShrinkBlock(block);
+        });
 }
 
 static void clearNewlyAllocatedInBlock(MarkedBlock* block)
@@ -235,16 +218,6 @@ static void clearNewlyAllocatedInBlock(MarkedBlock* block)
     block->clearNewlyAllocated();
 }
 
-struct ClearNewlyAllocated : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block) { block->clearNewlyAllocated(); }
-};
-
-#ifndef NDEBUG
-struct VerifyNewlyAllocated : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block) { ASSERT(!block->clearNewlyAllocated()); }
-};
-#endif
-
 void MarkedSpace::clearNewlyAllocated()
 {
     for (size_t i = 0; i < preciseCount; ++i) {
@@ -260,19 +233,23 @@ void MarkedSpace::clearNewlyAllocated()
     // We have to iterate all of the blocks in the large allocators because they are
     // canonicalized as they are used up (see MarkedAllocator::tryAllocateHelper)
     // which creates the m_newlyAllocated bitmap.
-    ClearNewlyAllocated functor;
-    m_normalSpace.largeAllocator.forEachBlock(functor);
-    m_destructorSpace.largeAllocator.forEachBlock(functor);
-
-#ifndef NDEBUG
-    VerifyNewlyAllocated verifyFunctor;
-    forEachBlock(verifyFunctor);
-#endif
+    auto clearNewlyAllocated = [&] (MarkedBlock* block) {
+        block->clearNewlyAllocated();
+    };
+    m_normalSpace.largeAllocator.forEachBlock(clearNewlyAllocated);
+    m_destructorSpace.largeAllocator.forEachBlock(clearNewlyAllocated);
+
+#if !ASSERT_DISABLED
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            ASSERT(!block->clearNewlyAllocated());
+        });
+#endif // !ASSERT_DISABLED
 }
 
 #ifndef NDEBUG 
 struct VerifyMarkedOrRetired : MarkedBlock::VoidFunctor { 
-    void operator()(MarkedBlock* block)
+    void operator()(MarkedBlock* block) const
     {
         switch (block->m_state) {
         case MarkedBlock::Marked:
@@ -290,8 +267,12 @@ void MarkedSpace::clearMarks()
     if (m_heap->operationInProgress() == EdenCollection) {
         for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i)
             m_blocksWithNewObjects[i]->clearMarks();
-    } else
-        forEachBlock<ClearMarks>();
+    } else {
+        forEachBlock(
+            [&] (MarkedBlock* block) {
+                block->clearMarks();
+            });
+    }
 
 #ifndef NDEBUG
     VerifyMarkedOrRetired verifyFunctor;
index c1571e7..7906d9f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -37,33 +37,6 @@ class Heap;
 class HeapIterationScope;
 class LLIntOffsetsExtractor;
 
-struct ClearMarks : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block)
-    {
-        block->clearMarks();
-    }
-};
-
-struct Sweep : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block) { block->sweep(); }
-};
-
-struct ZombifySweep : MarkedBlock::VoidFunctor {
-    void operator()(MarkedBlock* block)
-    {
-        if (block->needsSweeping())
-            block->sweep();
-    }
-};
-
-struct MarkCount : MarkedBlock::CountFunctor {
-    void operator()(MarkedBlock* block) { count(block->markCount()); }
-};
-
-struct Size : MarkedBlock::CountFunctor {
-    void operator()(MarkedBlock* block) { count(block->markCount() * block->cellSize()); }
-};
-
 class MarkedSpace {
     WTF_MAKE_NONCOPYABLE(MarkedSpace);
 public:
@@ -112,12 +85,9 @@ public:
 
     typedef HashSet<MarkedBlock*>::iterator BlockIterator;
 
-    template<typename Functor> typename Functor::ReturnType forEachLiveCell(HeapIterationScope&, Functor&);
-    template<typename Functor> typename Functor::ReturnType forEachLiveCell(HeapIterationScope&);
-    template<typename Functor> typename Functor::ReturnType forEachDeadCell(HeapIterationScope&, Functor&);
-    template<typename Functor> typename Functor::ReturnType forEachDeadCell(HeapIterationScope&);
-    template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
-    template<typename Functor> typename Functor::ReturnType forEachBlock();
+    template<typename Functor> void forEachLiveCell(HeapIterationScope&, const Functor&);
+    template<typename Functor> void forEachDeadCell(HeapIterationScope&, const Functor&);
+    template<typename Functor> void forEachBlock(const Functor&);
 
     void shrink();
     void freeBlock(MarkedBlock*);
@@ -143,8 +113,7 @@ private:
     friend class LLIntOffsetsExtractor;
     friend class JIT;
 
-    template<typename Functor> void forEachAllocator(Functor&);
-    template<typename Functor> void forEachAllocator();
+    template<typename Functor> void forEachAllocator(const Functor&);
 
     Subspace m_destructorSpace;
     Subspace m_normalSpace;
@@ -156,7 +125,7 @@ private:
     Vector<MarkedBlock*> m_blocksWithNewObjects;
 };
 
-template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope&, Functor& functor)
+template<typename Functor> inline void MarkedSpace::forEachLiveCell(HeapIterationScope&, const Functor& functor)
 {
     ASSERT(isIterating());
     BlockIterator end = m_blocks.set().end();
@@ -164,16 +133,9 @@ template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forE
         if ((*it)->forEachLiveCell(functor) == IterationStatus::Done)
             break;
     }
-    return functor.returnValue();
-}
-
-template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope& scope)
-{
-    Functor functor;
-    return forEachLiveCell(scope, functor);
 }
 
-template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope&, Functor& functor)
+template<typename Functor> inline void MarkedSpace::forEachDeadCell(HeapIterationScope&, const Functor& functor)
 {
     ASSERT(isIterating());
     BlockIterator end = m_blocks.set().end();
@@ -181,13 +143,6 @@ template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forE
         if ((*it)->forEachDeadCell(functor) == IterationStatus::Done)
             break;
     }
-    return functor.returnValue();
-}
-
-template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope& scope)
-{
-    Functor functor;
-    return forEachDeadCell(scope, functor);
 }
 
 inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes)
@@ -220,7 +175,7 @@ inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
     return destructorAllocatorFor(bytes).allocate(bytes);
 }
 
-template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock(Functor& functor)
+template <typename Functor> inline void MarkedSpace::forEachBlock(const Functor& functor)
 {
     for (size_t i = 0; i < preciseCount; ++i)
         m_normalSpace.preciseAllocators[i].forEachBlock(functor);
@@ -233,14 +188,6 @@ template <typename Functor> inline typename Functor::ReturnType MarkedSpace::for
     for (size_t i = 0; i < impreciseCount; ++i)
         m_destructorSpace.impreciseAllocators[i].forEachBlock(functor);
     m_destructorSpace.largeAllocator.forEachBlock(functor);
-
-    return functor.returnValue();
-}
-
-template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock()
-{
-    Functor functor;
-    return forEachBlock(functor);
 }
 
 inline void MarkedSpace::didAddBlock(MarkedBlock* block)
@@ -256,12 +203,22 @@ inline void MarkedSpace::didAllocateInBlock(MarkedBlock* block)
 
 inline size_t MarkedSpace::objectCount()
 {
-    return forEachBlock<MarkCount>();
+    size_t result = 0;
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            result += block->markCount();
+        });
+    return result;
 }
 
 inline size_t MarkedSpace::size()
 {
-    return forEachBlock<Size>();
+    size_t result = 0;
+    forEachBlock(
+        [&] (MarkedBlock* block) {
+            result += block->markCount() * block->cellSize();
+        });
+    return result;
 }
 
 inline size_t MarkedSpace::capacity()
index 677c651..8e42ec1 100644 (file)
@@ -28,6 +28,7 @@
 #include "ConstructData.h"
 #include "EnumerationMode.h"
 #include "Heap.h"
+#include "HeapCell.h"
 #include "IndexingType.h"
 #include "JSLock.h"
 #include "JSTypeInfo.h"
@@ -64,7 +65,7 @@ template<typename T> void* allocateCell(Heap&, size_t);
     public:                                                             \
         static const ::JSC::ClassInfo* info() { return &s_info; }
 
-class JSCell {
+class JSCell : public HeapCell {
     friend class JSValue;
     friend class MarkedBlock;
     template<typename T> friend void* allocateCell(Heap&);
@@ -155,9 +156,6 @@ public:
 
     static JSValue toThis(JSCell*, ExecState*, ECMAMode);
 
-    void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
-    bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
-
     static bool canUseFastGetOwnProperty(const Structure&);
     JSValue fastGetOwnProperty(VM&, Structure&, PropertyName);
 
index 5807e5e..d66bfb6 100644 (file)
@@ -145,11 +145,6 @@ void* allocateCell(Heap& heap)
     return allocateCell<T>(heap, sizeof(T));
 }
     
-inline bool isZapped(const JSCell* cell)
-{
-    return cell->isZapped();
-}
-
 inline bool JSCell::isObject() const
 {
     return TypeInfo::isObject(m_type);
index 8329e99..7b2f24f 100644 (file)
@@ -869,7 +869,7 @@ namespace {
 class ObjectsWithBrokenIndexingFinder : public MarkedBlock::VoidFunctor {
 public:
     ObjectsWithBrokenIndexingFinder(MarkedArgumentBuffer&, JSGlobalObject*);
-    IterationStatus operator()(JSCell*);
+    IterationStatus operator()(HeapCell*, HeapCell::Kind) const;
 
 private:
     void visit(JSCell*);
@@ -926,9 +926,13 @@ inline void ObjectsWithBrokenIndexingFinder::visit(JSCell* cell)
     m_foundObjects.append(object);
 }
 
-IterationStatus ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell)
+IterationStatus ObjectsWithBrokenIndexingFinder::operator()(HeapCell* cell, HeapCell::Kind kind) const
 {
-    visit(cell);
+    if (kind == HeapCell::JSCell) {
+        // FIXME: This const_cast exists because this isn't a C++ lambda.
+        // https://bugs.webkit.org/show_bug.cgi?id=159644
+        const_cast<ObjectsWithBrokenIndexingFinder*>(this)->visit(static_cast<JSCell*>(cell));
+    }
     return IterationStatus::Continue;
 }
 
index 1a5e377..f47c547 100644 (file)
@@ -161,7 +161,7 @@ struct CellAddressCheckFunctor : MarkedBlock::CountFunctor {
     {
     }
 
-    IterationStatus operator()(JSCell* cell) const
+    IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const
     {
         if (cell == candidate) {
             found = true;