Changeset 183124 in webkit
- Timestamp:
- Apr 22, 2015 1:05:06 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r183117 r183124 1 2015-04-22 Mark Lam <mark.lam@apple.com> 2 3 Give the heap object iterators the ability to return early. 4 https://bugs.webkit.org/show_bug.cgi?id=144011 5 6 Reviewed by Michael Saboff. 7 8 JSDollarVMPrototype::isValidCell() uses a heap object iterator to validate 9 candidate cell pointers, and, when in use, is called a lot more often than 10 the normal way those iterators are used. As a result, I see my instrumented 11 VM killed with a SIGXCPU (CPU time limit exceeded). This patch gives the 12 callback functor the ability to tell the iterators to return early when the 13 functor no longer needs to continue iterating. With this, my instrumented 14 VM is useful again for debugging. 15 16 Since heap iteration is not something that we do in a typical fast path, 17 I don't expect this to have any noticeable impact on performance. 18 19 I also renamed ObjectAddressCheckFunctor to CellAddressCheckFunctor since 20 it checks JSCell addresses, not just JSObjects. 21 22 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 23 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: 24 * JavaScriptCore.xcodeproj/project.pbxproj: 25 * debugger/Debugger.cpp: 26 * heap/GCLogging.cpp: 27 (JSC::LoggingFunctor::operator()): 28 * heap/Heap.cpp: 29 (JSC::Zombify::visit): 30 (JSC::Zombify::operator()): 31 * heap/HeapStatistics.cpp: 32 (JSC::StorageStatistics::visit): 33 (JSC::StorageStatistics::operator()): 34 * heap/HeapVerifier.cpp: 35 (JSC::GatherLiveObjFunctor::visit): 36 (JSC::GatherLiveObjFunctor::operator()): 37 * heap/MarkedBlock.cpp: 38 (JSC::SetNewlyAllocatedFunctor::operator()): 39 * heap/MarkedBlock.h: 40 (JSC::MarkedBlock::forEachCell): 41 (JSC::MarkedBlock::forEachLiveCell): 42 (JSC::MarkedBlock::forEachDeadCell): 43 * heap/MarkedSpace.h: 44 (JSC::MarkedSpace::forEachLiveCell): 45 (JSC::MarkedSpace::forEachDeadCell): 46 * inspector/agents/InspectorRuntimeAgent.cpp: 47 (Inspector::TypeRecompiler::visit): 48 (Inspector::TypeRecompiler::operator()): 49 * runtime/IterationStatus.h: Added. 50 * runtime/JSGlobalObject.cpp: 51 * runtime/VM.cpp: 52 (JSC::StackPreservingRecompiler::visit): 53 (JSC::StackPreservingRecompiler::operator()): 54 * tools/JSDollarVMPrototype.cpp: 55 (JSC::CellAddressCheckFunctor::CellAddressCheckFunctor): 56 (JSC::CellAddressCheckFunctor::operator()): 57 (JSC::JSDollarVMPrototype::isValidCell): 58 (JSC::ObjectAddressCheckFunctor::ObjectAddressCheckFunctor): Deleted. 59 (JSC::ObjectAddressCheckFunctor::operator()): Deleted. 60 1 61 2015-04-22 Yusuke Suzuki <utatane.tea@gmail.com> 2 62 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r183072 r183124 1526 1526 <ClInclude Include="..\runtime\InternalFunction.h" /> 1527 1527 <ClInclude Include="..\runtime\Intrinsic.h" /> 1528 <ClInclude Include="..\runtime\IterationStatus.h" /> 1528 1529 <ClInclude Include="..\runtime\IteratorOperations.h" /> 1529 1530 <ClInclude Include="..\runtime\JSAPIValueWrapper.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r182997 r183124 2679 2679 <Filter>runtime</Filter> 2680 2680 </ClInclude> 2681 <ClInclude Include="..\runtime\IterationStatus.h"> 2682 <Filter>runtime</Filter> 2683 </ClInclude> 2681 2684 <ClInclude Include="..\runtime\IteratorOperations.h"> 2682 2685 <Filter>runtime</Filter> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r183072 r183124 1655 1655 FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */; }; 1656 1656 FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1657 FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */; };1658 FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */; };1659 1657 FE384EE51ADDB7AD0055DE2C /* JSDollarVM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */; }; 1660 1658 FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1661 1659 FE384EE71ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */; }; 1662 1660 FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1661 FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */; }; 1662 FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */; }; 1663 FE4D55B81AE716CA0052E459 /* IterationStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4D55B71AE716CA0052E459 /* IterationStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1663 1664 FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; }; 1664 1665 FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3447 3448 FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntCLoop.cpp; path = llint/LLIntCLoop.cpp; sourceTree = "<group>"; }; 3448 3449 FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCLoop.h; path = llint/LLIntCLoop.h; sourceTree = "<group>"; }; 3449 FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionOverrides.cpp; sourceTree = "<group>"; };3450 FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionOverrides.h; sourceTree = "<group>"; };3451 3450 FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; }; 3452 3451 FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVM.h; sourceTree = "<group>"; }; 3453 3452 FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVMPrototype.cpp; sourceTree = "<group>"; }; 3454 3453 FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVMPrototype.h; sourceTree = "<group>"; }; 3454 FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionOverrides.cpp; sourceTree = "<group>"; }; 3455 FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionOverrides.h; sourceTree = "<group>"; }; 3456 FE4D55B71AE716CA0052E459 /* IterationStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IterationStatus.h; sourceTree = "<group>"; }; 3455 3457 FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; }; 3456 3458 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; }; … … 4452 4454 70113D491A8DB093003848C4 /* IteratorOperations.cpp */, 4453 4455 70113D4A1A8DB093003848C4 /* IteratorOperations.h */, 4456 FE4D55B71AE716CA0052E459 /* IterationStatus.h */, 4454 4457 93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */, 4455 4458 938772E5038BFE19008635CE /* JSArray.h */, … … 5589 5592 0FE050281AA9095600D33B33 /* ScopedArguments.h in Headers */, 5590 5593 52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */, 5594 FE4D55B81AE716CA0052E459 /* IterationStatus.h in Headers */, 5591 5595 C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */, 5592 5596 52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */, -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r182038 r183124 45 45 Recompiler(JSC::Debugger*); 46 46 ~Recompiler(); 47 voidoperator()(JSCell*);47 IterationStatus operator()(JSCell*); 48 48 49 49 private: 50 50 typedef HashSet<FunctionExecutable*> FunctionExecutableSet; 51 51 typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; 52 53 void visit(JSCell*); 52 54 53 55 JSC::Debugger* m_debugger; … … 70 72 } 71 73 72 inline void Recompiler:: operator()(JSCell* cell)74 inline void Recompiler::visit(JSCell* cell) 73 75 { 74 76 if (!cell->inherits(JSFunction::info())) … … 91 93 if (m_debugger == function->scope()->globalObject()->debugger()) 92 94 m_sourceProviders.add(executable->source().provider(), exec); 95 } 96 97 inline IterationStatus Recompiler::operator()(JSCell* cell) 98 { 99 visit(cell); 100 return IterationStatus::Continue; 93 101 } 94 102 -
trunk/Source/JavaScriptCore/heap/GCLogging.cpp
r166838 r183124 64 64 } 65 65 66 voidoperator()(JSCell* cell)66 IterationStatus operator()(JSCell* cell) 67 67 { 68 68 m_liveCells.append(cell); 69 69 MarkedBlock::blockFor(cell)->clearMarked(cell); 70 return IterationStatus::Continue; 70 71 } 71 72 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r182927 r183124 241 241 242 242 struct MarkObject : public MarkedBlock::VoidFunctor { 243 void operator()(JSCell* cell)243 inline void visit(JSCell* cell) 244 244 { 245 245 if (cell->isZapped()) … … 247 247 Heap::heap(cell)->setMarked(cell); 248 248 } 249 IterationStatus operator()(JSCell* cell) 250 { 251 visit(cell); 252 return IterationStatus::Continue; 253 } 249 254 }; 250 255 … … 254 259 255 260 struct CountIfGlobalObject : MarkedBlock::CountFunctor { 256 void operator()(JSCell* cell) { 261 inline void visit(JSCell* cell) 262 { 257 263 if (!cell->isObject()) 258 264 return; … … 261 267 count(1); 262 268 } 269 IterationStatus operator()(JSCell* cell) 270 { 271 visit(cell); 272 return IterationStatus::Continue; 273 } 263 274 }; 264 275 … … 268 279 269 280 RecordType(); 270 voidoperator()(JSCell*);281 IterationStatus operator()(JSCell*); 271 282 ReturnType returnValue(); 272 283 … … 289 300 } 290 301 291 inline voidRecordType::operator()(JSCell* cell)302 inline IterationStatus RecordType::operator()(JSCell* cell) 292 303 { 293 304 m_typeCountSet->add(typeName(cell)); 305 return IterationStatus::Continue; 294 306 } 295 307 … … 1423 1435 class Zombify : public MarkedBlock::VoidFunctor { 1424 1436 public: 1425 void operator()(JSCell* cell)1437 inline void visit(JSCell* cell) 1426 1438 { 1427 1439 void** current = reinterpret_cast<void**>(cell); … … 1435 1447 for (; current < limit; current++) 1436 1448 *current = zombifiedBits; 1449 } 1450 IterationStatus operator()(JSCell* cell) 1451 { 1452 visit(cell); 1453 return IterationStatus::Continue; 1437 1454 } 1438 1455 }; -
trunk/Source/JavaScriptCore/heap/HeapStatistics.cpp
r174509 r183124 168 168 StorageStatistics(); 169 169 170 voidoperator()(JSCell*);170 IterationStatus operator()(JSCell*); 171 171 172 172 size_t objectWithOutOfLineStorageCount(); … … 177 177 178 178 private: 179 void visit(JSCell*); 180 179 181 size_t m_objectWithOutOfLineStorageCount; 180 182 size_t m_objectCount; … … 191 193 } 192 194 193 inline void StorageStatistics:: operator()(JSCell* cell)195 inline void StorageStatistics::visit(JSCell* cell) 194 196 { 195 197 if (!cell->isObject()) … … 208 210 m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>); 209 211 m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>); 212 } 213 214 inline IterationStatus StorageStatistics::operator()(JSCell* cell) 215 { 216 visit(cell); 217 return IterationStatus::Continue; 210 218 } 211 219 -
trunk/Source/JavaScriptCore/heap/HeapVerifier.cpp
r176424 r183124 123 123 } 124 124 125 void operator()(JSCell* cell)125 inline void visit(JSCell* cell) 126 126 { 127 127 if (!cell->isObject()) … … 129 129 LiveObjectData data(asObject(cell)); 130 130 m_list.liveObjects.append(data); 131 } 132 133 IterationStatus operator()(JSCell* cell) 134 { 135 visit(cell); 136 return IterationStatus::Continue; 131 137 } 132 138 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp
r182747 r183124 158 158 } 159 159 160 voidoperator()(JSCell* cell)160 IterationStatus operator()(JSCell* cell) 161 161 { 162 162 ASSERT(MarkedBlock::blockFor(cell) == m_block); 163 163 m_block->setNewlyAllocated(cell); 164 return IterationStatus::Continue; 164 165 } 165 166 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r182878 r183124 26 26 27 27 #include "HeapOperation.h" 28 #include "IterationStatus.h" 28 29 #include "WeakSet.h" 29 30 #include <wtf/Bitmap.h> … … 180 181 void willRemoveBlock(); 181 182 182 template <typename Functor> voidforEachCell(Functor&);183 template <typename Functor> voidforEachLiveCell(Functor&);184 template <typename Functor> voidforEachDeadCell(Functor&);183 template <typename Functor> IterationStatus forEachCell(Functor&); 184 template <typename Functor> IterationStatus forEachLiveCell(Functor&); 185 template <typename Functor> IterationStatus forEachDeadCell(Functor&); 185 186 186 187 static ptrdiff_t offsetOfMarks() { return OBJECT_OFFSETOF(MarkedBlock, m_marks); } … … 445 446 } 446 447 447 template <typename Functor> inline voidMarkedBlock::forEachCell(Functor& functor)448 template <typename Functor> inline IterationStatus MarkedBlock::forEachCell(Functor& functor) 448 449 { 449 450 for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { 450 451 JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]); 451 functor(cell); 452 if (functor(cell) == IterationStatus::Done) 453 return IterationStatus::Done; 452 454 } 453 } 454 455 template <typename Functor> inline void MarkedBlock::forEachLiveCell(Functor& functor) 455 return IterationStatus::Continue; 456 } 457 458 template <typename Functor> inline IterationStatus MarkedBlock::forEachLiveCell(Functor& functor) 456 459 { 457 460 for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { … … 460 463 continue; 461 464 462 functor(cell); 465 if (functor(cell) == IterationStatus::Done) 466 return IterationStatus::Done; 463 467 } 464 } 465 466 template <typename Functor> inline void MarkedBlock::forEachDeadCell(Functor& functor) 468 return IterationStatus::Continue; 469 } 470 471 template <typename Functor> inline IterationStatus MarkedBlock::forEachDeadCell(Functor& functor) 467 472 { 468 473 for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { … … 471 476 continue; 472 477 473 functor(cell); 478 if (functor(cell) == IterationStatus::Done) 479 return IterationStatus::Done; 474 480 } 481 return IterationStatus::Continue; 475 482 } 476 483 -
trunk/Source/JavaScriptCore/heap/MarkedSpace.h
r182747 r183124 180 180 ASSERT(isIterating()); 181 181 BlockIterator end = m_blocks.set().end(); 182 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) 183 (*it)->forEachLiveCell(functor); 182 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) { 183 if ((*it)->forEachLiveCell(functor) == IterationStatus::Done) 184 break; 185 } 184 186 return functor.returnValue(); 185 187 } … … 195 197 ASSERT(isIterating()); 196 198 BlockIterator end = m_blocks.set().end(); 197 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) 198 (*it)->forEachDeadCell(functor); 199 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) { 200 if ((*it)->forEachDeadCell(functor) == IterationStatus::Done) 201 break; 202 } 199 203 return functor.returnValue(); 200 204 } -
trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
r180913 r183124 310 310 class TypeRecompiler : public MarkedBlock::VoidFunctor { 311 311 public: 312 inline void operator()(JSCell* cell)312 inline void visit(JSCell* cell) 313 313 { 314 314 if (!cell->inherits(FunctionExecutable::info())) … … 318 318 executable->clearCodeIfNotCompiling(); 319 319 executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); 320 } 321 inline IterationStatus operator()(JSCell* cell) 322 { 323 visit(cell); 324 return IterationStatus::Continue; 320 325 } 321 326 }; -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r182994 r183124 540 540 public: 541 541 ObjectsWithBrokenIndexingFinder(MarkedArgumentBuffer&, JSGlobalObject*); 542 voidoperator()(JSCell*);542 IterationStatus operator()(JSCell*); 543 543 544 544 private: 545 void visit(JSCell*); 546 545 547 MarkedArgumentBuffer& m_foundObjects; 546 548 JSGlobalObject* m_globalObject; … … 563 565 } 564 566 565 void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell)567 inline void ObjectsWithBrokenIndexingFinder::visit(JSCell* cell) 566 568 { 567 569 if (!cell->isObject()) … … 593 595 594 596 m_foundObjects.append(object); 597 } 598 599 IterationStatus ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell) 600 { 601 visit(cell); 602 return IterationStatus::Continue; 595 603 } 596 604 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r182915 r183124 492 492 struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor { 493 493 HashSet<FunctionExecutable*> currentlyExecutingFunctions; 494 void operator()(JSCell* cell)494 inline void visit(JSCell* cell) 495 495 { 496 496 if (!cell->inherits(FunctionExecutable::info())) … … 500 500 return; 501 501 executable->clearCodeIfNotCompiling(); 502 } 503 IterationStatus operator()(JSCell* cell) 504 { 505 visit(cell); 506 return IterationStatus::Continue; 502 507 } 503 508 }; -
trunk/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
r183027 r183124 153 153 } 154 154 155 struct ObjectAddressCheckFunctor : MarkedBlock::CountFunctor {156 ObjectAddressCheckFunctor(JSCell* candidate)155 struct CellAddressCheckFunctor : MarkedBlock::CountFunctor { 156 CellAddressCheckFunctor(JSCell* candidate) 157 157 : candidate(candidate) 158 158 { 159 159 } 160 160 161 voidoperator()(JSCell* cell)162 { 163 if (cell == candidate) 161 IterationStatus operator()(JSCell* cell) 162 { 163 if (cell == candidate) { 164 164 found = true; 165 return IterationStatus::Done; 166 } 167 return IterationStatus::Continue; 165 168 } 166 169 … … 172 175 { 173 176 HeapIterationScope iterationScope(*heap); 174 ObjectAddressCheckFunctor functor(candidate);177 CellAddressCheckFunctor functor(candidate); 175 178 heap->objectSpace().forEachLiveCell(iterationScope, functor); 176 179 return functor.found;
Note: See TracChangeset
for help on using the changeset viewer.