The tracking of the coarse-grain Heap state (allocating or not, collector or not...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Oct 2016 02:17:35 +0000 (02:17 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Oct 2016 02:17:35 +0000 (02:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163738

Reviewed by Geoffrey Garen.
Source/JavaScriptCore:

We need to know if we're currently in an allocation slow path, so that code can assert that
it's not being used from inside a destructor that runs during a sweep. We need to know if
we're currently collecting, because some code behaves differently during collection, and
other code wants to assert that it's not being used from inside a visitChildren method that
runs during marking. If we are collecting, we need to know if it's an eden collection or a
full collection. If we are requesting a collection, we need to know if we're requesting an
eden collection, a full collection, or any kind of collection.

Prior to this change, you would reason about all of these things using the HeapOperation. It
had the following states: NoOperation, Allocation, FullCollection, EdenCollection, and
AnyCollection. NoOperation versus Allocation was primarily for asserting that sweep didn't
call arbitrary JS. FullCollection versus EdenCollection was about describing generations. We
would even use HeapOperation in places where we knew that it could only be either Full or
Eden, because we just needed a variable to tell us which generation we were talking about.
It was all very confusing.

Where it completely breaks down is the fact that a concurrent GC has two logical threads, the
mutator and the collector, which can change state independently. The mutator can be
allocating. It can also be doing some work to help the GC. That's three states: running,
allocating, or helping GC. At the same time, the GC thread could either be running or not,
and if it's running, it could be a full collection or an eden collection. Because the mutator
and collector can run at the same time, it means that if we used one enum, we would need nine
states: every combination of mutator running, allocating, or helping GC, crossed with
collector not running, running eden, or running full. So, this change decouples mutator state
from collector state and uses two separate fields with two different types.

Mutator state is described using MutatorState, which can be either MutatorState::Running,
MutatorState::Allocating, or MutatorState::HelpingGC.

Collector state is described using Optional<CollectionScope>. CollectionScope describes how
big the scope of the collection is, and it can be either CollectionScope::Eden or
CollectionScope::Full. If the Optional is Nullopt, it means that we are not collecting. This
way, you can treat collectionScope as a boolean (an Optional is true iff it's engaged). You
can pass around just a CollectionScope if you know that you must be collecting and you just
want to know about the generation. Also, we can use Nullopt in methods that request
collection, which those methods take to mean that they can run any kind of collection (the
old AnyCollection).

Another use of HeapOperation was to answer questions about whether the caller is running as
part of the GC or as part of the mutator. Optional<CollectionScope> does not answer this,
since code that runs in the mutator while the mutator is not HelpingGC at the same time as
the collector is running should run as if it was part of the mutator not as if it was part of
the GC. MutatorState is needed to answer this question, but it doesn't tell the whole story
since code that runs in the collector thread at the same time as the mutator is running
should run as if it was part of the GC not as if it was part of the mutator. So, we need to
know if we're on the collector thread or the mutator thread. We already have a WTF facility
for this, which answers if a thread is a GC thread. But we already use this to answer a
stronger question: are we part of the parallel GC helpers? Some functions in the GC, like
mark bit queries, will work fine in a concurrent collector thread so long as there is no
parallel marking. So, this change also changes WTF's mayBeGCThread to tell what kind of GC
thread we may be: either GCThreadType::Main or GCThreadType::Helper. The parallel GC safety
checks look for GCThreadType::Helper. The "should I run as mutator" query can now be answered
by checking with mayBeGCThread, which returns Optional<GCThreadType>; if engaged, then run as
GC, else run as GC if MutatorState is HelpingGC, else run as mutator.

This doesn't change the way that the GC behaves, but it does change how the GC represents a
fundamental piece of state. So, it's a big change. It should be perf-neutral (still testing).

* API/JSBase.cpp:
(JSSynchronousEdenCollectForDebugging):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::jettison):
* dfg/DFGWorklist.cpp:
* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* heap/AllocatingScope.h: Added.
(JSC::AllocatingScope::AllocatingScope):
(JSC::AllocatingScope::~AllocatingScope):
* heap/AllocationScope.h: Removed.
* heap/CodeBlockSet.cpp:
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
* heap/CodeBlockSet.h:
* heap/CollectionScope.cpp: Added.
(JSC::collectionScopeName):
(WTF::printInternal):
* heap/CollectionScope.h: Added.
* heap/EdenGCActivityCallback.cpp:
(JSC::EdenGCActivityCallback::doCollection):
* heap/FullGCActivityCallback.cpp:
(JSC::FullGCActivityCallback::doCollection):
* heap/GCTypeMap.h:
(JSC::GCTypeMap::operator[]):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::markRoots):
(JSC::Heap::beginMarking):
(JSC::Heap::visitSmallStrings):
(JSC::Heap::updateObjectCounts):
(JSC::Heap::deleteAllCodeBlocks):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::collect):
(JSC::Heap::collectWithoutAnySweep):
(JSC::Heap::collectImpl):
(JSC::Heap::willStartCollection):
(JSC::Heap::flushWriteBarrierBuffer):
(JSC::Heap::pruneStaleEntriesFromWeakGCMaps):
(JSC::Heap::notifyIncrementalSweeper):
(JSC::Heap::updateAllocationLimits):
(JSC::Heap::didFinishCollection):
(JSC::Heap::isValidAllocation):
(JSC::Heap::shouldDoFullCollection):
* heap/Heap.h:
(JSC::Heap::mutatorState):
(JSC::Heap::collectionScope):
(JSC::Heap::operationInProgress): Deleted.
* heap/HeapInlines.h:
(JSC::Heap::shouldCollect):
(JSC::Heap::isCurrentThreadBusy):
(JSC::Heap::isMarked):
(JSC::Heap::reportExtraMemoryVisited):
(JSC::Heap::reportExternalMemoryVisited):
(JSC::Heap::collectAccordingToDeferGCProbability):
(JSC::Heap::isBusy): Deleted.
(JSC::Heap::isCollecting): Deleted.
* heap/HeapObserver.h:
* heap/HeapOperation.cpp: Removed.
* heap/HeapOperation.h: Removed.
* heap/HeapVerifier.cpp:
(JSC::HeapVerifier::initializeGCCycle):
(JSC::HeapVerifier::reportObject):
(JSC::HeapVerifier::collectionTypeName): Deleted.
* heap/HeapVerifier.h:
(JSC::HeapVerifier::GCCycle::collectionTypeName): Deleted.
* heap/HelpingGCScope.h: Added.
(JSC::HelpingGCScope::HelpingGCScope):
(JSC::HelpingGCScope::~HelpingGCScope):
* heap/LargeAllocation.cpp:
(JSC::LargeAllocation::flip):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::doTestCollectionsIfNeeded):
(JSC::MarkedAllocator::allocateSlowCaseImpl):
* heap/MarkedBlock.h:
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::prepareForAllocation):
(JSC::MarkedSpace::visitWeakSets):
(JSC::MarkedSpace::reapWeakSets):
(JSC::MarkedSpace::prepareForMarking):
(JSC::MarkedSpace::beginMarking):
(JSC::MarkedSpace::snapshotUnswept):
* heap/MutatorState.cpp: Added.
(WTF::printInternal):
* heap/MutatorState.h: Added.
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::didStartMarking):
* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::protocolTypeForHeapOperation):
(Inspector::InspectorHeapAgent::didGarbageCollect):
* inspector/agents/InspectorHeapAgent.h:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* jsc.cpp:
(functionFullGC):
(functionEdenGC):
* runtime/Completion.cpp:
(JSC::evaluate):
(JSC::loadAndEvaluateModule):
(JSC::loadModule):
(JSC::linkAndEvaluateModule):
* runtime/JSLock.cpp:
(JSC::JSLock::DropAllLocks::DropAllLocks):
* runtime/SmallStrings.h:
(JSC::SmallStrings::needsToBeVisited):
* runtime/VM.h:
(JSC::VM::isCollectorBusyOnCurrentThread):
(JSC::VM::isCollectorBusy): Deleted.
* tools/JSDollarVMPrototype.cpp:
(JSC::JSDollarVMPrototype::edenGC):

Source/WebCore:

No new tests because no change in behavior.

* bindings/js/GCController.cpp:
(WebCore::GCController::garbageCollectNow):

Source/WTF:

There will soon be different kinds of GC threads, and WTF's "are you a GC thread" thing
should know about this.

* wtf/MainThread.cpp:
(WTF::initializeGCThreads):
(WTF::registerGCThread):
(WTF::mayBeGCThread):
* wtf/MainThread.h:

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

44 files changed:
Source/JavaScriptCore/API/JSBase.cpp
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/ftl/FTLCompile.cpp
Source/JavaScriptCore/heap/AllocatingScope.h [new file with mode: 0644]
Source/JavaScriptCore/heap/AllocationScope.h [deleted file]
Source/JavaScriptCore/heap/CodeBlockSet.cpp
Source/JavaScriptCore/heap/CodeBlockSet.h
Source/JavaScriptCore/heap/CollectionScope.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/CollectionScope.h [moved from Source/JavaScriptCore/heap/HeapOperation.h with 87% similarity]
Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp
Source/JavaScriptCore/heap/FullGCActivityCallback.cpp
Source/JavaScriptCore/heap/GCTypeMap.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/HeapInlines.h
Source/JavaScriptCore/heap/HeapObserver.h
Source/JavaScriptCore/heap/HeapVerifier.cpp
Source/JavaScriptCore/heap/HeapVerifier.h
Source/JavaScriptCore/heap/HelpingGCScope.h [new file with mode: 0644]
Source/JavaScriptCore/heap/LargeAllocation.cpp
Source/JavaScriptCore/heap/MarkedAllocator.cpp
Source/JavaScriptCore/heap/MarkedBlock.h
Source/JavaScriptCore/heap/MarkedSpace.cpp
Source/JavaScriptCore/heap/MutatorState.cpp [moved from Source/JavaScriptCore/heap/HeapOperation.cpp with 79% similarity]
Source/JavaScriptCore/heap/MutatorState.h [new file with mode: 0644]
Source/JavaScriptCore/heap/SlotVisitor.cpp
Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp
Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/JSLock.cpp
Source/JavaScriptCore/runtime/SmallStrings.h
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/MainThread.cpp
Source/WTF/wtf/MainThread.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/GCController.cpp

index 6b2a907..cbad507 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 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
@@ -165,7 +165,7 @@ void JSSynchronousEdenCollectForDebugging(JSContextRef ctx)
 
     ExecState* exec = toJS(ctx);
     JSLockHolder locker(exec);
-    exec->vm().heap.collect(EdenCollection);
+    exec->vm().heap.collect(CollectionScope::Eden);
 }
 
 void JSDisableGCTimer(void)
index 97741fe..395fe2c 100644 (file)
@@ -451,6 +451,7 @@ set(JavaScriptCore_SOURCES
 
     heap/AllocatorAttributes.cpp
     heap/CodeBlockSet.cpp
+    heap/CollectionScope.cpp
     heap/ConservativeRoots.cpp
     heap/DeferGC.cpp
     heap/DestructionMode.cpp
@@ -464,7 +465,6 @@ set(JavaScriptCore_SOURCES
     heap/Heap.cpp
     heap/HeapCell.cpp
     heap/HeapHelperPool.cpp
-    heap/HeapOperation.cpp
     heap/HeapProfiler.cpp
     heap/HeapSnapshot.cpp
     heap/HeapSnapshotBuilder.cpp
@@ -480,6 +480,7 @@ set(JavaScriptCore_SOURCES
     heap/MarkedAllocator.cpp
     heap/MarkedBlock.cpp
     heap/MarkedSpace.cpp
+    heap/MutatorState.cpp
     heap/SlotVisitor.cpp
     heap/Weak.cpp
     heap/WeakBlock.cpp
index 1dd5217..9d67564 100644 (file)
@@ -1,3 +1,185 @@
+2016-10-20  Filip Pizlo  <fpizlo@apple.com>
+
+        The tracking of the coarse-grain Heap state (allocating or not, collector or not, eden vs full) should respect the orthogonality between allocating and collecting
+        https://bugs.webkit.org/show_bug.cgi?id=163738
+
+        Reviewed by Geoffrey Garen.
+        
+        We need to know if we're currently in an allocation slow path, so that code can assert that
+        it's not being used from inside a destructor that runs during a sweep. We need to know if
+        we're currently collecting, because some code behaves differently during collection, and
+        other code wants to assert that it's not being used from inside a visitChildren method that
+        runs during marking. If we are collecting, we need to know if it's an eden collection or a
+        full collection. If we are requesting a collection, we need to know if we're requesting an
+        eden collection, a full collection, or any kind of collection.
+        
+        Prior to this change, you would reason about all of these things using the HeapOperation. It
+        had the following states: NoOperation, Allocation, FullCollection, EdenCollection, and
+        AnyCollection. NoOperation versus Allocation was primarily for asserting that sweep didn't
+        call arbitrary JS. FullCollection versus EdenCollection was about describing generations. We
+        would even use HeapOperation in places where we knew that it could only be either Full or
+        Eden, because we just needed a variable to tell us which generation we were talking about.
+        It was all very confusing.
+        
+        Where it completely breaks down is the fact that a concurrent GC has two logical threads, the
+        mutator and the collector, which can change state independently. The mutator can be
+        allocating. It can also be doing some work to help the GC. That's three states: running,
+        allocating, or helping GC. At the same time, the GC thread could either be running or not,
+        and if it's running, it could be a full collection or an eden collection. Because the mutator
+        and collector can run at the same time, it means that if we used one enum, we would need nine
+        states: every combination of mutator running, allocating, or helping GC, crossed with
+        collector not running, running eden, or running full. So, this change decouples mutator state
+        from collector state and uses two separate fields with two different types.
+        
+        Mutator state is described using MutatorState, which can be either MutatorState::Running,
+        MutatorState::Allocating, or MutatorState::HelpingGC.
+        
+        Collector state is described using Optional<CollectionScope>. CollectionScope describes how
+        big the scope of the collection is, and it can be either CollectionScope::Eden or
+        CollectionScope::Full. If the Optional is Nullopt, it means that we are not collecting. This
+        way, you can treat collectionScope as a boolean (an Optional is true iff it's engaged). You
+        can pass around just a CollectionScope if you know that you must be collecting and you just
+        want to know about the generation. Also, we can use Nullopt in methods that request
+        collection, which those methods take to mean that they can run any kind of collection (the
+        old AnyCollection).
+        
+        Another use of HeapOperation was to answer questions about whether the caller is running as
+        part of the GC or as part of the mutator. Optional<CollectionScope> does not answer this,
+        since code that runs in the mutator while the mutator is not HelpingGC at the same time as
+        the collector is running should run as if it was part of the mutator not as if it was part of
+        the GC. MutatorState is needed to answer this question, but it doesn't tell the whole story
+        since code that runs in the collector thread at the same time as the mutator is running
+        should run as if it was part of the GC not as if it was part of the mutator. So, we need to
+        know if we're on the collector thread or the mutator thread. We already have a WTF facility
+        for this, which answers if a thread is a GC thread. But we already use this to answer a
+        stronger question: are we part of the parallel GC helpers? Some functions in the GC, like
+        mark bit queries, will work fine in a concurrent collector thread so long as there is no
+        parallel marking. So, this change also changes WTF's mayBeGCThread to tell what kind of GC
+        thread we may be: either GCThreadType::Main or GCThreadType::Helper. The parallel GC safety
+        checks look for GCThreadType::Helper. The "should I run as mutator" query can now be answered
+        by checking with mayBeGCThread, which returns Optional<GCThreadType>; if engaged, then run as
+        GC, else run as GC if MutatorState is HelpingGC, else run as mutator.
+        
+        This doesn't change the way that the GC behaves, but it does change how the GC represents a
+        fundamental piece of state. So, it's a big change. It should be perf-neutral (still testing).
+
+        * API/JSBase.cpp:
+        (JSSynchronousEdenCollectForDebugging):
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::jettison):
+        * dfg/DFGWorklist.cpp:
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * heap/AllocatingScope.h: Added.
+        (JSC::AllocatingScope::AllocatingScope):
+        (JSC::AllocatingScope::~AllocatingScope):
+        * heap/AllocationScope.h: Removed.
+        * heap/CodeBlockSet.cpp:
+        (JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
+        * heap/CodeBlockSet.h:
+        * heap/CollectionScope.cpp: Added.
+        (JSC::collectionScopeName):
+        (WTF::printInternal):
+        * heap/CollectionScope.h: Added.
+        * heap/EdenGCActivityCallback.cpp:
+        (JSC::EdenGCActivityCallback::doCollection):
+        * heap/FullGCActivityCallback.cpp:
+        (JSC::FullGCActivityCallback::doCollection):
+        * heap/GCTypeMap.h:
+        (JSC::GCTypeMap::operator[]):
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::lastChanceToFinalize):
+        (JSC::Heap::markRoots):
+        (JSC::Heap::beginMarking):
+        (JSC::Heap::visitSmallStrings):
+        (JSC::Heap::updateObjectCounts):
+        (JSC::Heap::deleteAllCodeBlocks):
+        (JSC::Heap::deleteUnmarkedCompiledCode):
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::collect):
+        (JSC::Heap::collectWithoutAnySweep):
+        (JSC::Heap::collectImpl):
+        (JSC::Heap::willStartCollection):
+        (JSC::Heap::flushWriteBarrierBuffer):
+        (JSC::Heap::pruneStaleEntriesFromWeakGCMaps):
+        (JSC::Heap::notifyIncrementalSweeper):
+        (JSC::Heap::updateAllocationLimits):
+        (JSC::Heap::didFinishCollection):
+        (JSC::Heap::isValidAllocation):
+        (JSC::Heap::shouldDoFullCollection):
+        * heap/Heap.h:
+        (JSC::Heap::mutatorState):
+        (JSC::Heap::collectionScope):
+        (JSC::Heap::operationInProgress): Deleted.
+        * heap/HeapInlines.h:
+        (JSC::Heap::shouldCollect):
+        (JSC::Heap::isCurrentThreadBusy):
+        (JSC::Heap::isMarked):
+        (JSC::Heap::reportExtraMemoryVisited):
+        (JSC::Heap::reportExternalMemoryVisited):
+        (JSC::Heap::collectAccordingToDeferGCProbability):
+        (JSC::Heap::isBusy): Deleted.
+        (JSC::Heap::isCollecting): Deleted.
+        * heap/HeapObserver.h:
+        * heap/HeapOperation.cpp: Removed.
+        * heap/HeapOperation.h: Removed.
+        * heap/HeapVerifier.cpp:
+        (JSC::HeapVerifier::initializeGCCycle):
+        (JSC::HeapVerifier::reportObject):
+        (JSC::HeapVerifier::collectionTypeName): Deleted.
+        * heap/HeapVerifier.h:
+        (JSC::HeapVerifier::GCCycle::collectionTypeName): Deleted.
+        * heap/HelpingGCScope.h: Added.
+        (JSC::HelpingGCScope::HelpingGCScope):
+        (JSC::HelpingGCScope::~HelpingGCScope):
+        * heap/LargeAllocation.cpp:
+        (JSC::LargeAllocation::flip):
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::doTestCollectionsIfNeeded):
+        (JSC::MarkedAllocator::allocateSlowCaseImpl):
+        * heap/MarkedBlock.h:
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::prepareForAllocation):
+        (JSC::MarkedSpace::visitWeakSets):
+        (JSC::MarkedSpace::reapWeakSets):
+        (JSC::MarkedSpace::prepareForMarking):
+        (JSC::MarkedSpace::beginMarking):
+        (JSC::MarkedSpace::snapshotUnswept):
+        * heap/MutatorState.cpp: Added.
+        (WTF::printInternal):
+        * heap/MutatorState.h: Added.
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::didStartMarking):
+        * inspector/agents/InspectorHeapAgent.cpp:
+        (Inspector::protocolTypeForHeapOperation):
+        (Inspector::InspectorHeapAgent::didGarbageCollect):
+        * inspector/agents/InspectorHeapAgent.h:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        * jsc.cpp:
+        (functionFullGC):
+        (functionEdenGC):
+        * runtime/Completion.cpp:
+        (JSC::evaluate):
+        (JSC::loadAndEvaluateModule):
+        (JSC::loadModule):
+        (JSC::linkAndEvaluateModule):
+        * runtime/JSLock.cpp:
+        (JSC::JSLock::DropAllLocks::DropAllLocks):
+        * runtime/SmallStrings.h:
+        (JSC::SmallStrings::needsToBeVisited):
+        * runtime/VM.h:
+        (JSC::VM::isCollectorBusyOnCurrentThread):
+        (JSC::VM::isCollectorBusy): Deleted.
+        * tools/JSDollarVMPrototype.cpp:
+        (JSC::JSDollarVMPrototype::edenGC):
+
 2016-10-20  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] Drop isEnvironmentRecord type info flag and use JSType information instead
index 0966e47..fd42b9c 100644 (file)
                0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8364B7164B0C110053329A /* DFGBranchDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */; };
-               0F86A26D1D6F796500CB0C92 /* HeapOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F86A26C1D6F796200CB0C92 /* HeapOperation.cpp */; };
                0F86A26F1D6F7B3300CB0C92 /* GCTypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F86A26E1D6F7B3100CB0C92 /* GCTypeMap.h */; };
                0F86AE201C5311C5006BE8EC /* B3ComputeDivisionMagic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F86AE1F1C5311C5006BE8EC /* B3ComputeDivisionMagic.h */; };
                0F885E111849A3BE00F1E3FA /* BytecodeUseDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */; };
                0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */; };
                0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */; };
+               0FA762041DB9242600B7A2FD /* CollectionScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA762001DB9242300B7A2FD /* CollectionScope.cpp */; };
+               0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762011DB9242300B7A2FD /* CollectionScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FA762061DB9243100B7A2FD /* MutatorState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA762021DB9242300B7A2FD /* MutatorState.cpp */; };
+               0FA762071DB9243300B7A2FD /* MutatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762031DB9242300B7A2FD /* MutatorState.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FA762091DB9283E00B7A2FD /* HelpingGCScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */; };
+               0FA7620B1DB959F900B7A2FD /* AllocatingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */; };
                0FA7A8EB18B413C80052371D /* Reg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA7A8E918B413C80052371D /* Reg.cpp */; };
                0FA7A8EC18B413C80052371D /* Reg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA7A8EA18B413C80052371D /* Reg.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FA7A8EE18CE4FD80052371D /* ScratchRegisterAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA7A8ED18CE4FD80052371D /* ScratchRegisterAllocator.cpp */; };
                0FB4FB731BC843140025CA5A /* FTLLazySlowPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB4FB701BC843140025CA5A /* FTLLazySlowPath.cpp */; };
                0FB4FB741BC843140025CA5A /* FTLLazySlowPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4FB711BC843140025CA5A /* FTLLazySlowPath.h */; };
                0FB4FB751BC843140025CA5A /* FTLLazySlowPathCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4FB721BC843140025CA5A /* FTLLazySlowPathCall.h */; };
-               0FB530391D90404C00F28AE3 /* AllocationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB530381D90404600F28AE3 /* AllocationScope.h */; };
                0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; };
                0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */; };
                2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */; };
                2A4EC90C1860D6C20094F782 /* WriteBarrierBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A6F462517E959CE00C45C98 /* HeapOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */; };
                2A83638518D7D0EE0000EBCC /* EdenGCActivityCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A83638318D7D0EE0000EBCC /* EdenGCActivityCallback.cpp */; };
                2A83638618D7D0EE0000EBCC /* EdenGCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A83638418D7D0EE0000EBCC /* EdenGCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = "<group>"; };
                0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };
                0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; };
-               0F86A26C1D6F796200CB0C92 /* HeapOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapOperation.cpp; sourceTree = "<group>"; };
                0F86A26E1D6F7B3100CB0C92 /* GCTypeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCTypeMap.h; sourceTree = "<group>"; };
                0F86AE1F1C5311C5006BE8EC /* B3ComputeDivisionMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ComputeDivisionMagic.h; path = b3/B3ComputeDivisionMagic.h; sourceTree = "<group>"; };
                0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeUseDef.h; sourceTree = "<group>"; };
                0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeFlags.cpp; path = dfg/DFGNodeFlags.cpp; sourceTree = "<group>"; };
                0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeFlags.h; path = dfg/DFGNodeFlags.h; sourceTree = "<group>"; };
                0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeType.h; path = dfg/DFGNodeType.h; sourceTree = "<group>"; };
+               0FA762001DB9242300B7A2FD /* CollectionScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollectionScope.cpp; sourceTree = "<group>"; };
+               0FA762011DB9242300B7A2FD /* CollectionScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionScope.h; sourceTree = "<group>"; };
+               0FA762021DB9242300B7A2FD /* MutatorState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MutatorState.cpp; sourceTree = "<group>"; };
+               0FA762031DB9242300B7A2FD /* MutatorState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutatorState.h; sourceTree = "<group>"; };
+               0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpingGCScope.h; sourceTree = "<group>"; };
+               0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocatingScope.h; sourceTree = "<group>"; };
                0FA7A8E918B413C80052371D /* Reg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Reg.cpp; sourceTree = "<group>"; };
                0FA7A8EA18B413C80052371D /* Reg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reg.h; sourceTree = "<group>"; };
                0FA7A8ED18CE4FD80052371D /* ScratchRegisterAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScratchRegisterAllocator.cpp; sourceTree = "<group>"; };
                0FB4FB701BC843140025CA5A /* FTLLazySlowPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLazySlowPath.cpp; path = ftl/FTLLazySlowPath.cpp; sourceTree = "<group>"; };
                0FB4FB711BC843140025CA5A /* FTLLazySlowPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLazySlowPath.h; path = ftl/FTLLazySlowPath.h; sourceTree = "<group>"; };
                0FB4FB721BC843140025CA5A /* FTLLazySlowPathCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLazySlowPathCall.h; path = ftl/FTLLazySlowPathCall.h; sourceTree = "<group>"; };
-               0FB530381D90404600F28AE3 /* AllocationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllocationScope.h; sourceTree = "<group>"; };
                0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyOperandValueProfile.h; sourceTree = "<group>"; };
                0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyOperandValueProfile.cpp; sourceTree = "<group>"; };
                0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodOfGettingAValueProfile.h; sourceTree = "<group>"; };
                2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSManagedValueInternal.h; sourceTree = "<group>"; };
                2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierBuffer.cpp; sourceTree = "<group>"; };
                2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierBuffer.h; sourceTree = "<group>"; };
-               2A6F462517E959CE00C45C98 /* HeapOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapOperation.h; sourceTree = "<group>"; };
                2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferGC.cpp; sourceTree = "<group>"; };
                2A83638318D7D0EE0000EBCC /* EdenGCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdenGCActivityCallback.cpp; sourceTree = "<group>"; };
                2A83638418D7D0EE0000EBCC /* EdenGCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdenGCActivityCallback.h; sourceTree = "<group>"; };
                142E312A134FF0A600AFADB5 /* heap */ = {
                        isa = PBXGroup;
                        children = (
-                               0FB530381D90404600F28AE3 /* AllocationScope.h */,
+                               0FA7620A1DB959F600B7A2FD /* AllocatingScope.h */,
                                0F9630351D4192C3005609D9 /* AllocatorAttributes.cpp */,
                                0F9630361D4192C3005609D9 /* AllocatorAttributes.h */,
                                0F070A421D543A89006E7232 /* CellContainer.h */,
                                0FD8A31117D4326C00CA2C40 /* CodeBlockSet.cpp */,
                                0FD8A31217D4326C00CA2C40 /* CodeBlockSet.h */,
                                0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */,
+                               0FA762001DB9242300B7A2FD /* CollectionScope.cpp */,
+                               0FA762011DB9242300B7A2FD /* CollectionScope.h */,
                                146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
                                149DAAF212EB559D0083B12B /* ConservativeRoots.h */,
                                2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
                                C2DA778218E259990066FCB6 /* HeapInlines.h */,
                                2AD8932917E3868F00668276 /* HeapIterationScope.h */,
                                A5339EC81BB4B4510054F005 /* HeapObserver.h */,
-                               0F86A26C1D6F796200CB0C92 /* HeapOperation.cpp */,
-                               2A6F462517E959CE00C45C98 /* HeapOperation.h */,
                                A5398FA91C750D950060A963 /* HeapProfiler.cpp */,
                                A5398FAA1C750D950060A963 /* HeapProfiler.h */,
                                14F97446138C853E00DA1C67 /* HeapRootVisitor.h */,
                                0FADE6721D4D23BC00768457 /* HeapUtil.h */,
                                FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */,
                                FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */,
+                               0FA762081DB9283C00B7A2FD /* HelpingGCScope.h */,
                                C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */,
                                C25F8BCC157544A900245B71 /* IncrementalSweeper.h */,
                                0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */,
                                0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */,
                                142D6F0E13539A4100B02E86 /* MarkStack.cpp */,
                                142D6F0F13539A4100B02E86 /* MarkStack.h */,
+                               0FA762021DB9242300B7A2FD /* MutatorState.cpp */,
+                               0FA762031DB9242300B7A2FD /* MutatorState.h */,
                                ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
                                C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
                                14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
                                0FEC85031BDACDAC0080FF74 /* B3BasicBlockUtils.h in Headers */,
                                0FEC85041BDACDAC0080FF74 /* B3BlockWorklist.h in Headers */,
                                0FEC85061BDACDAC0080FF74 /* B3CheckSpecial.h in Headers */,
+                               0FA762071DB9243300B7A2FD /* MutatorState.h in Headers */,
                                0FEC85081BDACDAC0080FF74 /* B3CheckValue.h in Headers */,
                                0FEC850A1BDACDAC0080FF74 /* B3Common.h in Headers */,
                                DC454B8D1D00E824004C18AF /* AirDumpAsJS.h in Headers */,
                                62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
                                0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
                                0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
-                               0FB530391D90404C00F28AE3 /* AllocationScope.h in Headers */,
                                627673241B680C1E00FD9F2E /* CallMode.h in Headers */,
                                0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
                                0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */,
                                2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */,
                                BC3046070E1F497F003232CF /* Error.h in Headers */,
                                BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */,
+                               0FA7620B1DB959F900B7A2FD /* AllocatingScope.h in Headers */,
+                               0FA762091DB9283E00B7A2FD /* HelpingGCScope.h in Headers */,
                                FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */,
                                BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */,
                                BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */,
                                2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */,
                                A5339EC91BB4B4600054F005 /* HeapObserver.h in Headers */,
                                AD2FCBEB1DB58DAD00B3E736 /* JSWebAssemblyTable.h in Headers */,
-                               2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */,
                                14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */,
                                C24D31E3161CD695002AA4DB /* HeapStatistics.h in Headers */,
                                C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */,
                                A18193E31B4E0CDB00FC1029 /* IntlCollatorConstructor.lut.h in Headers */,
                                A1B9E23E1B4E0D6700BC7FED /* IntlCollatorPrototype.h in Headers */,
                                A18193E41B4E0CDB00FC1029 /* IntlCollatorPrototype.lut.h in Headers */,
+                               0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
                                A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */,
                                FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */,
                                A1587D701B4DC14100D69849 /* IntlDateTimeFormatConstructor.h in Headers */,
                                A78A977A179738B8009DF744 /* DFGPlan.cpp in Sources */,
                                0FBE0F7416C1DB090082C5E8 /* DFGPredictionInjectionPhase.cpp in Sources */,
                                0FFFC95D14EF90B300C72532 /* DFGPredictionPropagationPhase.cpp in Sources */,
-                               0F86A26D1D6F796500CB0C92 /* HeapOperation.cpp in Sources */,
                                0F3E01AA19D353A500F61B7F /* DFGPrePostNumbering.cpp in Sources */,
                                0F2B9CEC19D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp in Sources */,
                                0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */,
                                A58E35911860DECF001F24FE /* InjectedScriptHost.cpp in Sources */,
                                A513E5CA185F9624007E95AD /* InjectedScriptManager.cpp in Sources */,
                                A5840E20187B7B8600843B10 /* InjectedScriptModule.cpp in Sources */,
+                               0FA762041DB9242600B7A2FD /* CollectionScope.cpp in Sources */,
                                148A7BEF1B82975A002D9157 /* InlineCallFrame.cpp in Sources */,
                                0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */,
                                A5CEEE14187F3BAD00E55C99 /* InspectorAgent.cpp in Sources */,
                                DC17E8171C9C91D6008A6AB3 /* ShadowChicken.cpp in Sources */,
                                A7299D9D17D12837005F5FF9 /* JSSet.cpp in Sources */,
                                A790DD6F182F499700588807 /* JSSetIterator.cpp in Sources */,
+                               0FA762061DB9243100B7A2FD /* MutatorState.cpp in Sources */,
                                1428083A107EC0750013E7B2 /* CLoopStack.cpp in Sources */,
                                147F39D5107EC37600427A48 /* JSString.cpp in Sources */,
                                70EC0EC21AA0D7DA00B6AAFA /* JSStringIterator.cpp in Sources */,
index 947985d..b152112 100644 (file)
@@ -3474,7 +3474,7 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
         // This accomplishes (1), and does its own book-keeping about whether it has already happened.
         if (!jitCode()->dfgCommon()->invalidate()) {
             // We've already been invalidated.
-            RELEASE_ASSERT(this != replacement() || (m_vm->heap.isCollecting() && !Heap::isMarked(ownerScriptExecutable())));
+            RELEASE_ASSERT(this != replacement() || (m_vm->heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable())));
             return;
         }
     }
@@ -3506,7 +3506,7 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
 
     // Jettison can happen during GC. We don't want to install code to a dead executable
     // because that would add a dead object to the remembered set.
-    if (m_vm->heap.isCollecting() && !Heap::isMarked(ownerScriptExecutable()))
+    if (m_vm->heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable()))
         return;
 
     // This accomplishes (2).
index 5a01612..0ce6979 100644 (file)
@@ -103,9 +103,10 @@ protected:
         if (Options::verboseCompilationQueue())
             dataLog(m_worklist, ": Compiling ", m_plan->key(), " asynchronously\n");
         
-        RELEASE_ASSERT(!m_plan->vm->heap.isCollecting());
+        // There's no way for the GC to be safepointing since we own rightToRun.
+        RELEASE_ASSERT(m_plan->vm->heap.mutatorState() != MutatorState::HelpingGC);
         m_plan->compileInThread(*m_longLivedState, &m_data);
-        RELEASE_ASSERT(m_plan->stage == Plan::Cancelled || !m_plan->vm->heap.isCollecting());
+        RELEASE_ASSERT(m_plan->stage == Plan::Cancelled || m_plan->vm->heap.mutatorState() != MutatorState::HelpingGC);
         
         {
             LockHolder locker(*m_worklist.m_lock);
@@ -123,7 +124,7 @@ protected:
             
             m_worklist.m_planCompiled.notifyAll();
         }
-        RELEASE_ASSERT(!m_plan->vm->heap.isCollecting());
+        RELEASE_ASSERT(m_plan->vm->heap.mutatorState() != MutatorState::HelpingGC);
         
         return WorkResult::Continue;
     }
index 39eb666..68659a8 100644 (file)
@@ -65,7 +65,7 @@ void compile(State& state, Safepoint::Result& safepointResult)
 
     if (safepointResult.didGetCancelled())
         return;
-    RELEASE_ASSERT(!state.graph.m_vm.heap.isCollecting());
+    RELEASE_ASSERT(state.graph.m_vm.heap.mutatorState() != MutatorState::HelpingGC);
     
     if (state.allocationFailed)
         return;
diff --git a/Source/JavaScriptCore/heap/AllocatingScope.h b/Source/JavaScriptCore/heap/AllocatingScope.h
new file mode 100644 (file)
index 0000000..1d13ae0
--- /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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Heap.h"
+
+namespace JSC {
+
+class AllocatingScope {
+public:
+    AllocatingScope(Heap& heap)
+        : m_heap(heap)
+    {
+        RELEASE_ASSERT(m_heap.m_mutatorState == MutatorState::Running);
+        m_heap.m_mutatorState = MutatorState::Allocating;
+    }
+    
+    ~AllocatingScope()
+    {
+        RELEASE_ASSERT(m_heap.m_mutatorState == MutatorState::Allocating);
+        m_heap.m_mutatorState = MutatorState::Running;
+    }
+
+private:
+    Heap& m_heap;
+};
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/heap/AllocationScope.h b/Source/JavaScriptCore/heap/AllocationScope.h
deleted file mode 100644 (file)
index 2e4a654..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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
-
-#include "Heap.h"
-
-namespace JSC {
-
-class AllocationScope {
-public:
-    AllocationScope(Heap& heap)
-        : m_heap(heap)
-        , m_lastOperation(m_heap.m_operationInProgress)
-    {
-        ASSERT(m_lastOperation == NoOperation || m_lastOperation == Allocation);
-        m_heap.m_operationInProgress = Allocation;
-    }
-    
-    ~AllocationScope()
-    {
-        ASSERT(m_heap.m_operationInProgress == Allocation);
-        m_heap.m_operationInProgress = m_lastOperation;
-    }
-private:
-    Heap& m_heap;
-    HeapOperation m_lastOperation;
-};
-
-} // namespace JSC
-
index c9ab0be..ec07db2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 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
@@ -77,10 +77,10 @@ void CodeBlockSet::lastChanceToFinalize()
         codeBlock->classInfo()->methodTable.destroy(codeBlock);
 }
 
-void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
+void CodeBlockSet::deleteUnmarkedAndUnreferenced(CollectionScope scope)
 {
     LockHolder locker(&m_lock);
-    HashSet<CodeBlock*>& set = collectionType == EdenCollection ? m_newCodeBlocks : m_oldCodeBlocks;
+    HashSet<CodeBlock*>& set = scope == CollectionScope::Eden ? m_newCodeBlocks : m_oldCodeBlocks;
     Vector<CodeBlock*> unmarked;
     for (CodeBlock* codeBlock : set) {
         if (Heap::isMarked(codeBlock))
@@ -94,7 +94,7 @@ void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
     }
 
     // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
-    if (collectionType == EdenCollection)
+    if (scope == CollectionScope::Eden)
         promoteYoungCodeBlocks(locker);
 }
 
index fd3800e..68caf30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2014, 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
@@ -25,8 +25,8 @@
 
 #pragma once
 
+#include "CollectionScope.h"
 #include "GCSegmentedArray.h"
-#include "HeapOperation.h"
 #include <wtf/HashSet.h>
 #include <wtf/Lock.h>
 #include <wtf/Noncopyable.h>
@@ -67,7 +67,7 @@ public:
     
     // Delete all code blocks that are only referenced by this set (i.e. owned
     // by this set), and that have not been marked.
-    void deleteUnmarkedAndUnreferenced(HeapOperation);
+    void deleteUnmarkedAndUnreferenced(CollectionScope);
     
     // Add all currently executing CodeBlocks to the remembered set to be 
     // re-scanned during the next collection.
diff --git a/Source/JavaScriptCore/heap/CollectionScope.cpp b/Source/JavaScriptCore/heap/CollectionScope.cpp
new file mode 100644 (file)
index 0000000..b2990e7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CollectionScope.h"
+
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+const char* collectionScopeName(CollectionScope scope)
+{
+    switch (scope) {
+    case CollectionScope::Eden:
+        return "Eden";
+    case CollectionScope::Full:
+        return "Full";
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream& out, JSC::CollectionScope scope)
+{
+    out.print(JSC::collectionScopeName(scope));
+}
+
+} // namespace WTF
+
similarity index 87%
rename from Source/JavaScriptCore/heap/HeapOperation.h
rename to Source/JavaScriptCore/heap/CollectionScope.h
index fbb8283..9b4f487 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * 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
@@ -27,7 +27,9 @@
 
 namespace JSC {
 
-enum HeapOperation { NoOperation, Allocation, FullCollection, EdenCollection, AnyCollection };
+enum class CollectionScope { Eden, Full };
+
+const char* collectionScopeName(CollectionScope);
 
 } // namespace JSC
 
@@ -35,6 +37,7 @@ namespace WTF {
 
 class PrintStream;
 
-void printInternal(PrintStream& out, JSC::HeapOperation);
+void printInternal(PrintStream& out, JSC::CollectionScope);
 
 } // namespace WTF
+
index 7774075..1d2a6fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 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
@@ -39,7 +39,7 @@ EdenGCActivityCallback::EdenGCActivityCallback(Heap* heap)
 
 void EdenGCActivityCallback::doCollection()
 {
-    m_vm->heap.collect(EdenCollection);
+    m_vm->heap.collect(CollectionScope::Eden);
 }
 
 double EdenGCActivityCallback::lastGCLength()
index 91051a6..5ddfa87 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014, 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
@@ -55,7 +55,7 @@ void FullGCActivityCallback::doCollection()
     }
 #endif
 
-    heap.collect(FullCollection);
+    heap.collect(CollectionScope::Full);
 }
 
 double FullGCActivityCallback::lastGCLength()
index d0df25c..9e19e67 100644 (file)
@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include "HeapOperation.h"
+#include "CollectionScope.h"
 #include <wtf/Assertions.h>
 
 namespace JSC {
@@ -35,20 +35,28 @@ struct GCTypeMap {
     T eden;
     T full;
     
-    T& operator[](HeapOperation operation)
+    T& operator[](CollectionScope scope)
     {
-        if (operation == FullCollection)
+        switch (scope) {
+        case CollectionScope::Full:
             return full;
-        ASSERT(operation == EdenCollection);
-        return eden;
+        case CollectionScope::Eden:
+            return eden;
+        }
+        ASSERT_NOT_REACHED();
+        return full;
     }
     
-    const T& operator[](HeapOperation operation) const
+    const T& operator[](CollectionScope scope) const
     {
-        if (operation == FullCollection)
+        switch (scope) {
+        case CollectionScope::Full:
             return full;
-        ASSERT(operation == EdenCollection);
-        return eden;
+        case CollectionScope::Eden:
+            return eden;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return full;
     }
 };
 
index 3e408f6..35a6b48 100644 (file)
@@ -39,6 +39,7 @@
 #include "HeapSnapshot.h"
 #include "HeapStatistics.h"
 #include "HeapVerifier.h"
+#include "HelpingGCScope.h"
 #include "IncrementalSweeper.h"
 #include "Interpreter.h"
 #include "JITStubRoutineSet.h"
@@ -140,15 +141,15 @@ HashMap<const char*, GCTypeMap<SimpleStats>>& timingStats()
     return *result;
 }
 
-SimpleStats& timingStats(const char* name, HeapOperation operation)
+SimpleStats& timingStats(const char* name, CollectionScope scope)
 {
-    return timingStats().add(name, GCTypeMap<SimpleStats>()).iterator->value[operation];
+    return timingStats().add(name, GCTypeMap<SimpleStats>()).iterator->value[scope];
 }
 
 class TimingScope {
 public:
-    TimingScope(HeapOperation operation, const char* name)
-        : m_operation(operation)
+    TimingScope(Optional<CollectionScope> scope, const char* name)
+        : m_scope(scope)
         , m_name(name)
     {
         if (measurePhaseTiming())
@@ -156,18 +157,18 @@ public:
     }
     
     TimingScope(Heap& heap, const char* name)
-        : TimingScope(heap.operationInProgress(), name)
+        : TimingScope(heap.collectionScope(), name)
     {
     }
     
-    void setOperation(HeapOperation operation)
+    void setScope(Optional<CollectionScope> scope)
     {
-        m_operation = operation;
+        m_scope = scope;
     }
     
-    void setOperation(Heap& heap)
+    void setScope(Heap& heap)
     {
-        setOperation(heap.operationInProgress());
+        setScope(heap.collectionScope());
     }
     
     ~TimingScope()
@@ -175,13 +176,13 @@ public:
         if (measurePhaseTiming()) {
             double after = monotonicallyIncreasingTimeMS();
             double timing = after - m_before;
-            SimpleStats& stats = timingStats(m_name, m_operation);
+            SimpleStats& stats = timingStats(m_name, *m_scope);
             stats.add(timing);
-            dataLog("[GC:", m_operation, "] ", m_name, " took: ", timing, " ms (average ", stats.mean(), " ms).\n");
+            dataLog("[GC:", *m_scope, "] ", m_name, " took: ", timing, " ms (average ", stats.mean(), " ms).\n");
         }
     }
 private:
-    HeapOperation m_operation;
+    Optional<CollectionScope> m_scope;
     double m_before;
     const char* m_name;
 };
@@ -203,7 +204,6 @@ Heap::Heap(VM* vm, HeapType heapType)
     , m_maxHeapSize(m_minBytesPerCycle)
     , m_shouldDoFullCollection(false)
     , m_totalBytesVisited(0)
-    , m_operationInProgress(NoOperation)
     , m_objectSpace(this)
     , m_extraMemorySize(0)
     , m_deprecatedExtraMemorySize(0)
@@ -252,7 +252,8 @@ bool Heap::isPagedOut(double deadline)
 void Heap::lastChanceToFinalize()
 {
     RELEASE_ASSERT(!m_vm->entryScope);
-    RELEASE_ASSERT(m_operationInProgress == NoOperation);
+    RELEASE_ASSERT(!m_collectionScope);
+    RELEASE_ASSERT(m_mutatorState == MutatorState::Running);
 
     m_arrayBuffers.lastChanceToFinalize();
     m_codeBlocks->lastChanceToFinalize();
@@ -408,7 +409,7 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
         }
 #endif // ENABLE(SAMPLING_PROFILER)
 
-        if (m_operationInProgress == FullCollection) {
+        if (m_collectionScope == CollectionScope::Full) {
             m_opaqueRoots.clear();
             m_slotVisitor.clearMarkStack();
         }
@@ -431,7 +432,7 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
                         slotVisitor = m_availableParallelSlotVisitors.takeLast();
                 }
 
-                WTF::registerGCThread();
+                WTF::registerGCThread(GCThreadType::Helper);
 
                 {
                     ParallelModeEnabler parallelModeEnabler(*slotVisitor);
@@ -526,7 +527,7 @@ void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
 void Heap::beginMarking()
 {
     TimingScope timingScope(*this, "Heap::beginMarking");
-    if (m_operationInProgress == FullCollection)
+    if (m_collectionScope == CollectionScope::Full)
         m_codeBlocks->clearMarksForFullCollection();
     
     {
@@ -544,7 +545,7 @@ void Heap::visitExternalRememberedSet()
 
 void Heap::visitSmallStrings()
 {
-    if (!m_vm->smallStrings.needsToBeVisited(m_operationInProgress))
+    if (!m_vm->smallStrings.needsToBeVisited(*m_collectionScope))
         return;
 
     m_vm->smallStrings.visitStrongReferences(m_slotVisitor);
@@ -763,7 +764,7 @@ void Heap::updateObjectCounts(double gcStartTime)
         dataLogF("\nNumber of live Objects after GC %lu, took %.6f secs\n", static_cast<unsigned long>(visitCount), WTF::monotonicallyIncreasingTime() - gcStartTime);
     }
     
-    if (m_operationInProgress == FullCollection)
+    if (m_collectionScope == CollectionScope::Full)
         m_totalBytesVisited = 0;
 
     m_totalBytesVisitedThisCycle = m_slotVisitor.bytesVisited() + threadBytesVisited();
@@ -871,7 +872,7 @@ void Heap::deleteAllCodeBlocks()
     // If JavaScript is running, it's not safe to delete all JavaScript code, since
     // we'll end up returning to deleted code.
     RELEASE_ASSERT(!m_vm->entryScope);
-    ASSERT(m_operationInProgress == NoOperation);
+    ASSERT(!m_collectionScope);
 
     completeAllJITPlans();
 
@@ -908,7 +909,7 @@ void Heap::clearUnmarkedExecutables()
 void Heap::deleteUnmarkedCompiledCode()
 {
     clearUnmarkedExecutables();
-    m_codeBlocks->deleteUnmarkedAndUnreferenced(m_operationInProgress);
+    m_codeBlocks->deleteUnmarkedAndUnreferenced(*m_collectionScope);
     m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines();
 }
 
@@ -932,7 +933,7 @@ void Heap::collectAllGarbage()
     if (!m_isSafeToCollect)
         return;
 
-    collectWithoutAnySweep(FullCollection);
+    collectWithoutAnySweep(CollectionScope::Full);
 
     DeferGCForAWhile deferGC(*this);
     if (UNLIKELY(Options::useImmortalObjects()))
@@ -955,29 +956,29 @@ void Heap::collectAllGarbage()
     sweepAllLogicallyEmptyWeakBlocks();
 }
 
-void Heap::collect(HeapOperation collectionType)
+void Heap::collect(Optional<CollectionScope> scope)
 {
     SuperSamplerScope superSamplerScope(false);
     if (!m_isSafeToCollect)
         return;
-
-    collectWithoutAnySweep(collectionType);
+    
+    collectWithoutAnySweep(scope);
 }
 
-NEVER_INLINE void Heap::collectWithoutAnySweep(HeapOperation collectionType)
+NEVER_INLINE void Heap::collectWithoutAnySweep(Optional<CollectionScope> scope)
 {
     void* stackTop;
     ALLOCATE_AND_GET_REGISTER_STATE(registers);
 
-    collectImpl(collectionType, wtfThreadData().stack().origin(), &stackTop, registers);
+    collectImpl(scope, wtfThreadData().stack().origin(), &stackTop, registers);
 
     sanitizeStackForVM(m_vm);
 }
 
-NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
+NEVER_INLINE void Heap::collectImpl(Optional<CollectionScope> scope, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters)
 {
     SuperSamplerScope superSamplerScope(false);
-    TimingScope collectImplTimingScope(collectionType, "Heap::collectImpl");
+    TimingScope collectImplTimingScope(scope, "Heap::collectImpl");
     
 #if ENABLE(ALLOCATION_LOGGING)
     dataLogF("JSC GC starting collection.\n");
@@ -990,81 +991,78 @@ NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOri
     }
     
     double gcStartTime;
-    {
-        TimingScope earlyTimingScope(collectionType, "Heap::collectImpl before markRoots");
-
-        if (vm()->typeProfiler()) {
-            DeferGCForAWhile awhile(*this);
-            vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC"));
-        }
-
+    
+    if (vm()->typeProfiler()) {
+        DeferGCForAWhile awhile(*this);
+        vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC"));
+    }
+    
 #if ENABLE(JIT)
-        {
-            DeferGCForAWhile awhile(*this);
-            JITWorklist::instance()->completeAllForVM(*m_vm);
-        }
+    {
+        DeferGCForAWhile awhile(*this);
+        JITWorklist::instance()->completeAllForVM(*m_vm);
+    }
 #endif // ENABLE(JIT)
-
-        vm()->shadowChicken().update(*vm(), vm()->topCallFrame);
-
-        RELEASE_ASSERT(!m_deferralDepth);
-        ASSERT(vm()->currentThreadIsHoldingAPILock());
-        RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
-        ASSERT(m_isSafeToCollect);
-        RELEASE_ASSERT(m_operationInProgress == NoOperation);
-
-        suspendCompilerThreads();
-        willStartCollection(collectionType);
+    
+    vm()->shadowChicken().update(*vm(), vm()->topCallFrame);
+    
+    RELEASE_ASSERT(!m_deferralDepth);
+    ASSERT(vm()->currentThreadIsHoldingAPILock());
+    RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
+    ASSERT(m_isSafeToCollect);
+    RELEASE_ASSERT(!m_collectionScope);
+    
+    suspendCompilerThreads();
+    willStartCollection(scope);
+    {
+        HelpingGCScope helpingHeapScope(*this);
+        
+        collectImplTimingScope.setScope(*this);
         
-        collectImplTimingScope.setOperation(*this);
-        earlyTimingScope.setOperation(*this);
-
         gcStartTime = WTF::monotonicallyIncreasingTime();
         if (m_verifier) {
             // Verify that live objects from the last GC cycle haven't been corrupted by
             // mutators before we begin this new GC cycle.
             m_verifier->verify(HeapVerifier::Phase::BeforeGC);
-
+            
             m_verifier->initializeGCCycle();
             m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
         }
-
+        
         flushOldStructureIDTables();
         stopAllocation();
         prepareForMarking();
         flushWriteBarrierBuffer();
-
+        
         if (HasOwnPropertyCache* cache = vm()->hasOwnPropertyCache())
             cache->clear();
+        
+        markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters);
+        
+        if (m_verifier) {
+            m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
+            m_verifier->verify(HeapVerifier::Phase::AfterMarking);
+        }
+        
+        if (vm()->typeProfiler())
+            vm()->typeProfiler()->invalidateTypeSetCache();
+        
+        reapWeakHandles();
+        pruneStaleEntriesFromWeakGCMaps();
+        sweepArrayBuffers();
+        snapshotUnswept();
+        finalizeUnconditionalFinalizers();
+        removeDeadCompilerWorklistEntries();
+        deleteUnmarkedCompiledCode();
+        deleteSourceProviderCaches();
+        
+        notifyIncrementalSweeper();
+        m_codeBlocks->writeBarrierCurrentlyExecuting(this);
+        m_codeBlocks->clearCurrentlyExecuting();
+        
+        prepareForAllocation();
+        updateAllocationLimits();
     }
-
-    markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters);
-    
-    TimingScope lateTimingScope(*this, "Heap::collectImpl after markRoots");
-
-    if (m_verifier) {
-        m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
-        m_verifier->verify(HeapVerifier::Phase::AfterMarking);
-    }
-
-    if (vm()->typeProfiler())
-        vm()->typeProfiler()->invalidateTypeSetCache();
-
-    reapWeakHandles();
-    pruneStaleEntriesFromWeakGCMaps();
-    sweepArrayBuffers();
-    snapshotUnswept();
-    finalizeUnconditionalFinalizers();
-    removeDeadCompilerWorklistEntries();
-    deleteUnmarkedCompiledCode();
-    deleteSourceProviderCaches();
-
-    notifyIncrementalSweeper();
-    m_codeBlocks->writeBarrierCurrentlyExecuting(this);
-    m_codeBlocks->clearCurrentlyExecuting();
-
-    prepareForAllocation();
-    updateAllocationLimits();
     didFinishCollection(gcStartTime);
     resumeCompilerThreads();
     sweepLargeAllocations();
@@ -1103,22 +1101,22 @@ void Heap::suspendCompilerThreads()
 #endif
 }
 
-void Heap::willStartCollection(HeapOperation collectionType)
+void Heap::willStartCollection(Optional<CollectionScope> scope)
 {
     if (Options::logGC())
         dataLog("=> ");
     
-    if (shouldDoFullCollection(collectionType)) {
-        m_operationInProgress = FullCollection;
+    if (shouldDoFullCollection(scope)) {
+        m_collectionScope = CollectionScope::Full;
         m_shouldDoFullCollection = false;
         if (Options::logGC())
             dataLog("FullCollection, ");
     } else {
-        m_operationInProgress = EdenCollection;
+        m_collectionScope = CollectionScope::Eden;
         if (Options::logGC())
             dataLog("EdenCollection, ");
     }
-    if (m_operationInProgress == FullCollection) {
+    if (m_collectionScope == CollectionScope::Full) {
         m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
         m_extraMemorySize = 0;
         m_deprecatedExtraMemorySize = 0;
@@ -1129,7 +1127,7 @@ void Heap::willStartCollection(HeapOperation collectionType)
         if (m_fullActivityCallback)
             m_fullActivityCallback->willCollect();
     } else {
-        ASSERT(m_operationInProgress == EdenCollection);
+        ASSERT(m_collectionScope == CollectionScope::Eden);
         m_sizeBeforeLastEdenCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
     }
 
@@ -1147,7 +1145,7 @@ void Heap::flushOldStructureIDTables()
 
 void Heap::flushWriteBarrierBuffer()
 {
-    if (m_operationInProgress == EdenCollection) {
+    if (m_collectionScope == CollectionScope::Eden) {
         m_writeBarrierBuffer.flush(*this);
         return;
     }
@@ -1171,7 +1169,7 @@ void Heap::reapWeakHandles()
 
 void Heap::pruneStaleEntriesFromWeakGCMaps()
 {
-    if (m_operationInProgress != FullCollection)
+    if (m_collectionScope != CollectionScope::Full)
         return;
     for (auto& pruneCallback : m_weakGCMaps.values())
         pruneCallback();
@@ -1195,7 +1193,7 @@ void Heap::deleteSourceProviderCaches()
 
 void Heap::notifyIncrementalSweeper()
 {
-    if (m_operationInProgress == FullCollection) {
+    if (m_collectionScope == CollectionScope::Full) {
         if (!m_logicallyEmptyWeakBlocks.isEmpty())
             m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0;
     }
@@ -1243,7 +1241,7 @@ void Heap::updateAllocationLimits()
     if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
         HeapStatistics::exitWithFailure();
 
-    if (m_operationInProgress == FullCollection) {
+    if (m_collectionScope == CollectionScope::Full) {
         // To avoid pathological GC churn in very small and very large heaps, we set
         // the new allocation limit based on the current size of the heap, with a
         // fixed minimum.
@@ -1298,8 +1296,8 @@ void Heap::updateAllocationLimits()
 void Heap::didFinishCollection(double gcStartTime)
 {
     double gcEndTime = WTF::monotonicallyIncreasingTime();
-    HeapOperation operation = m_operationInProgress;
-    if (m_operationInProgress == FullCollection)
+    CollectionScope scope = *m_collectionScope;
+    if (scope == CollectionScope::Full)
         m_lastFullGCLength = gcEndTime - gcStartTime;
     else
         m_lastEdenGCLength = gcEndTime - gcStartTime;
@@ -1322,11 +1320,11 @@ void Heap::didFinishCollection(double gcStartTime)
         removeDeadHeapSnapshotNodes(*heapProfiler);
     }
 
-    RELEASE_ASSERT(m_operationInProgress == EdenCollection || m_operationInProgress == FullCollection);
-    m_operationInProgress = NoOperation;
+    RELEASE_ASSERT(m_collectionScope);
+    m_collectionScope = Nullopt;
 
     for (auto* observer : m_observers)
-        observer->didGarbageCollect(operation);
+        observer->didGarbageCollect(scope);
 }
 
 void Heap::resumeCompilerThreads()
@@ -1388,7 +1386,7 @@ bool Heap::isValidAllocation(size_t)
     if (!isValidThreadState(m_vm))
         return false;
 
-    if (m_operationInProgress != NoOperation)
+    if (isCurrentThreadBusy())
         return false;
     
     return true;
@@ -1465,24 +1463,14 @@ void Heap::flushWriteBarrierBuffer(JSCell* cell)
     m_writeBarrierBuffer.add(cell);
 }
 
-bool Heap::shouldDoFullCollection(HeapOperation requestedCollectionType) const
+bool Heap::shouldDoFullCollection(Optional<CollectionScope> scope) const
 {
     if (!Options::useGenerationalGC())
         return true;
 
-    switch (requestedCollectionType) {
-    case EdenCollection:
-        return false;
-    case FullCollection:
-        return true;
-    case AnyCollection:
+    if (!scope)
         return m_shouldDoFullCollection;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        return false;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return false;
+    return *scope == CollectionScope::Full;
 }
 
 void Heap::addLogicallyEmptyWeakBlock(WeakBlock* block)
index 85b3525..0a490de 100644 (file)
 #pragma once
 
 #include "ArrayBuffer.h"
+#include "CollectionScope.h"
 #include "GCIncomingRefCountedSet.h"
 #include "HandleSet.h"
 #include "HandleStack.h"
 #include "HeapObserver.h"
-#include "HeapOperation.h"
 #include "ListableHandler.h"
 #include "MachineStackMarker.h"
 #include "MarkedAllocator.h"
 #include "MarkedBlock.h"
 #include "MarkedBlockSet.h"
 #include "MarkedSpace.h"
+#include "MutatorState.h"
 #include "Options.h"
 #include "SlotVisitor.h"
 #include "StructureIDTable.h"
@@ -48,7 +49,6 @@
 
 namespace JSC {
 
-class AllocationScope;
 class CodeBlock;
 class CodeBlockSet;
 class GCDeferralContext;
@@ -61,6 +61,7 @@ class Heap;
 class HeapProfiler;
 class HeapRootVisitor;
 class HeapVerifier;
+class HelpingGCScope;
 class IncrementalSweeper;
 class JITStubRoutine;
 class JITStubRoutineSet;
@@ -139,11 +140,13 @@ public:
     void addObserver(HeapObserver* observer) { m_observers.append(observer); }
     void removeObserver(HeapObserver* observer) { m_observers.removeFirst(observer); }
 
-    // true if collection is in progress
-    bool isCollecting();
-    HeapOperation operationInProgress() { return m_operationInProgress; }
-    // true if an allocation or collection is in progress
-    bool isBusy();
+    MutatorState mutatorState() const { return m_mutatorState; }
+    Optional<CollectionScope> collectionScope() const { return m_collectionScope; }
+
+    // We're always busy on the collection threads. On the main thread, this returns true if we're
+    // helping heap.
+    bool isCurrentThreadBusy();
+    
     MarkedSpace::Subspace& subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
     MarkedSpace::Subspace& subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); }
     MarkedSpace::Subspace& subspaceForAuxiliaryData() { return m_objectSpace.subspaceForAuxiliaryData(); }
@@ -171,7 +174,7 @@ public:
     JS_EXPORT_PRIVATE void collectAllGarbage();
 
     bool shouldCollect();
-    JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
+    JS_EXPORT_PRIVATE void collect(Optional<CollectionScope> = Nullopt);
     bool collectIfNecessaryOrDefer(GCDeferralContext* = nullptr); // Returns true if it did collect.
     void collectAccordingToDeferGCProbability();
 
@@ -268,7 +271,7 @@ public:
     const unsigned* addressOfBarrierThreshold() const { return &m_barrierThreshold; }
 
 private:
-    friend class AllocationScope;
+    friend class AllocatingScope;
     friend class CodeBlock;
     friend class DeferGC;
     friend class DeferGCForAWhile;
@@ -278,6 +281,7 @@ private:
     friend class HandleSet;
     friend class HeapUtil;
     friend class HeapVerifier;
+    friend class HelpingGCScope;
     friend class JITStubRoutine;
     friend class LLIntOffsetsExtractor;
     friend class MarkedSpace;
@@ -293,7 +297,7 @@ private:
     template<typename T> friend void* allocateCell(Heap&, GCDeferralContext*);
     template<typename T> friend void* allocateCell(Heap&, GCDeferralContext*, size_t);
 
-    void collectWithoutAnySweep(HeapOperation collectionType = AnyCollection);
+    void collectWithoutAnySweep(Optional<CollectionScope> = Nullopt);
 
     void* allocateWithDestructor(size_t); // For use with objects with destructors.
     void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
@@ -312,10 +316,10 @@ private:
     JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
     JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
 
-    void collectImpl(HeapOperation, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
+    void collectImpl(Optional<CollectionScope>, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
 
     void suspendCompilerThreads();
-    void willStartCollection(HeapOperation collectionType);
+    void willStartCollection(Optional<CollectionScope>);
     void flushOldStructureIDTables();
     void flushWriteBarrierBuffer();
     void stopAllocation();
@@ -366,7 +370,7 @@ private:
     void sweepAllLogicallyEmptyWeakBlocks();
     bool sweepNextLogicallyEmptyWeakBlock();
 
-    bool shouldDoFullCollection(HeapOperation requestedCollectionType) const;
+    bool shouldDoFullCollection(Optional<CollectionScope> requestedCollectionScope) const;
 
     void incrementDeferralDepth();
     void decrementDeferralDepth();
@@ -394,7 +398,8 @@ private:
     size_t m_totalBytesVisited;
     size_t m_totalBytesVisitedThisCycle;
     
-    HeapOperation m_operationInProgress;
+    Optional<CollectionScope> m_collectionScope;
+    MutatorState m_mutatorState { MutatorState::Running };
     StructureIDTable m_structureIDTable;
     MarkedSpace m_objectSpace;
     GCIncomingRefCountedSet<ArrayBuffer> m_arrayBuffers;
index d8c0db0..e9a8e92 100644 (file)
@@ -45,21 +45,16 @@ inline bool Heap::shouldCollect()
         return false;
     if (!m_isSafeToCollect)
         return false;
-    if (m_operationInProgress != NoOperation)
+    if (collectionScope() || mutatorState() == MutatorState::HelpingGC)
         return false;
     if (Options::gcMaxHeapSize())
         return m_bytesAllocatedThisCycle > Options::gcMaxHeapSize();
     return m_bytesAllocatedThisCycle > m_maxEdenSize;
 }
 
-inline bool Heap::isBusy()
+inline bool Heap::isCurrentThreadBusy()
 {
-    return m_operationInProgress != NoOperation;
-}
-
-inline bool Heap::isCollecting()
-{
-    return m_operationInProgress == FullCollection || m_operationInProgress == EdenCollection;
+    return mayBeGCThread() || mutatorState() != MutatorState::Running;
 }
 
 ALWAYS_INLINE Heap* Heap::heap(const HeapCell* cell)
@@ -76,7 +71,7 @@ inline Heap* Heap::heap(const JSValue v)
 
 ALWAYS_INLINE bool Heap::isMarked(const void* rawCell)
 {
-    ASSERT(!mayBeGCThread());
+    ASSERT(mayBeGCThread() != GCThreadType::Helper);
     HeapCell* cell = bitwise_cast<HeapCell*>(rawCell);
     if (cell->isLargeAllocation())
         return cell->largeAllocation().isMarked();
@@ -161,7 +156,7 @@ inline void Heap::reportExtraMemoryAllocated(size_t size)
 inline void Heap::reportExtraMemoryVisited(CellState oldState, size_t size)
 {
     // We don't want to double-count the extra memory that was reported in previous collections.
-    if (operationInProgress() == EdenCollection && oldState == CellState::OldGrey)
+    if (collectionScope() == CollectionScope::Eden && oldState == CellState::OldGrey)
         return;
 
     size_t* counter = &m_extraMemorySize;
@@ -177,7 +172,7 @@ inline void Heap::reportExtraMemoryVisited(CellState oldState, size_t size)
 inline void Heap::reportExternalMemoryVisited(CellState oldState, size_t size)
 {
     // We don't want to double-count the external memory that was reported in previous collections.
-    if (operationInProgress() == EdenCollection && oldState == CellState::OldGrey)
+    if (collectionScope() == CollectionScope::Eden && oldState == CellState::OldGrey)
         return;
 
     size_t* counter = &m_externalMemorySize;
@@ -372,7 +367,7 @@ inline bool Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
 
 inline void Heap::collectAccordingToDeferGCProbability()
 {
-    if (isDeferred() || !m_isSafeToCollect || m_operationInProgress != NoOperation)
+    if (isDeferred() || !m_isSafeToCollect || collectionScope() || mutatorState() == MutatorState::HelpingGC)
         return;
 
     if (randomNumber() < Options::deferGCProbability()) {
index 7abe60d..ccbb7e6 100644 (file)
@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include "HeapOperation.h"
+#include "CollectionScope.h"
 
 namespace JSC {
 
@@ -33,7 +33,7 @@ class HeapObserver {
 public:
     virtual ~HeapObserver() { }
     virtual void willGarbageCollect() = 0;
-    virtual void didGarbageCollect(HeapOperation) = 0;
+    virtual void didGarbageCollect(CollectionScope) = 0;
 };
 
 } // namespace JSC
index 153881f..c779cf1 100644 (file)
@@ -43,24 +43,6 @@ HeapVerifier::HeapVerifier(Heap* heap, unsigned numberOfGCCyclesToRecord)
     m_cycles = std::make_unique<GCCycle[]>(m_numberOfCycles);
 }
 
-const char* HeapVerifier::collectionTypeName(HeapOperation type)
-{
-    switch (type) {
-    case NoOperation:
-        return "NoOperation";
-    case AnyCollection:
-        return "AnyCollection";
-    case Allocation:
-        return "Allocation";
-    case EdenCollection:
-        return "EdenCollection";
-    case FullCollection:
-        return "FullCollection";
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return nullptr; // Silencing a compiler warning.
-}
-
 const char* HeapVerifier::phaseName(HeapVerifier::Phase phase)
 {
     switch (phase) {
@@ -81,7 +63,7 @@ void HeapVerifier::initializeGCCycle()
 {
     Heap* heap = m_heap;
     incrementCycle();
-    currentCycle().collectionType = heap->operationInProgress();
+    currentCycle().scope = *heap->collectionScope();
 }
 
 struct GatherLiveObjFunctor : MarkedBlock::CountFunctor {
@@ -195,7 +177,7 @@ void HeapVerifier::reportObject(LiveObjectData& objData, int cycleIndex, HeapVer
 
     if (objData.isConfirmedDead) {
         dataLogF("FOUND dead obj %p in GC[%d] %s list '%s'\n",
-            obj, cycleIndex, cycle.collectionTypeName(), list.name);
+            obj, cycleIndex, collectionScopeName(cycle.scope), list.name);
         return;
     }
 
@@ -206,7 +188,7 @@ void HeapVerifier::reportObject(LiveObjectData& objData, int cycleIndex, HeapVer
     dataLogF("FOUND obj %p type '%s' butterfly %p (base %p) in GC[%d] %s list '%s'\n",
         obj, structure->classInfo()->className,
         butterfly, butterflyBase,
-        cycleIndex, cycle.collectionTypeName(), list.name);
+        cycleIndex, collectionScopeName(cycle.scope), list.name);
 }
 
 void HeapVerifier::checkIfRecorded(JSObject* obj)
index 50551ec..d736b47 100644 (file)
@@ -54,7 +54,6 @@ public:
     // object was in any of those lists.
     JS_EXPORT_PRIVATE void checkIfRecorded(JSObject*);
 
-    static const char* collectionTypeName(HeapOperation);
     static const char* phaseName(Phase);
 
 private:
@@ -65,14 +64,9 @@ private:
         {
         }
 
-        HeapOperation collectionType;
+        CollectionScope scope;
         LiveObjectList before;
         LiveObjectList after;
-
-        const char* collectionTypeName() const
-        {
-            return HeapVerifier::collectionTypeName(collectionType);
-        }
     };
 
     void incrementCycle() { m_currentCycle = (m_currentCycle + 1) % m_numberOfCycles; }
diff --git a/Source/JavaScriptCore/heap/HelpingGCScope.h b/Source/JavaScriptCore/heap/HelpingGCScope.h
new file mode 100644 (file)
index 0000000..e8f4085
--- /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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Heap.h"
+
+namespace JSC {
+
+class HelpingGCScope {
+public:
+    HelpingGCScope(Heap& heap)
+        : m_heap(heap)
+        , m_oldState(m_heap.m_mutatorState)
+    {
+        m_heap.m_mutatorState = MutatorState::HelpingGC;
+    }
+    
+    ~HelpingGCScope()
+    {
+        m_heap.m_mutatorState = m_oldState;
+    }
+
+private:
+    Heap& m_heap;
+    MutatorState m_oldState;
+};
+
+} // namespace JSC
+
index 09ca109..eb839dd 100644 (file)
@@ -77,7 +77,7 @@ void LargeAllocation::reapWeakSet()
 
 void LargeAllocation::flip()
 {
-    ASSERT(heap()->operationInProgress() == FullCollection);
+    ASSERT(heap()->collectionScope() == CollectionScope::Full);
     clearMarked();
 }
 
index 72d9230..2ceadaa 100644 (file)
@@ -26,7 +26,7 @@
 #include "config.h"
 #include "MarkedAllocator.h"
 
-#include "AllocationScope.h"
+#include "AllocatingScope.h"
 #include "GCActivityCallback.h"
 #include "Heap.h"
 #include "IncrementalSweeper.h"
@@ -185,7 +185,6 @@ ALWAYS_INLINE void MarkedAllocator::doTestCollectionsIfNeeded(GCDeferralContext*
             else
                 m_heap->collectAllGarbage();
         }
-        ASSERT(m_heap->m_operationInProgress == NoOperation);
     }
     if (++allocationCount >= Options::slowPathAllocsBetweenGCs())
         allocationCount = 0;
@@ -214,10 +213,10 @@ void* MarkedAllocator::allocateSlowCaseImpl(GCDeferralContext* deferralContext,
     
     didConsumeFreeList();
     
+    AllocatingScope healpingHeap(*m_heap);
+
     m_heap->collectIfNecessaryOrDefer(deferralContext);
     
-    AllocationScope allocationScope(*m_heap);
-
     void* result = tryAllocateWithoutCollecting();
     
     if (LIKELY(result != 0))
index 8db44c4..90a02b8 100644 (file)
@@ -25,7 +25,6 @@
 #include "DestructionMode.h"
 #include "FreeList.h"
 #include "HeapCell.h"
-#include "HeapOperation.h"
 #include "IterationStatus.h"
 #include "WeakSet.h"
 #include <wtf/Atomics.h>
index a5b0397..b0500e3 100644 (file)
@@ -338,7 +338,7 @@ void MarkedSpace::prepareForAllocation()
 
     m_activeWeakSets.takeFrom(m_newActiveWeakSets);
     
-    if (m_heap->operationInProgress() == EdenCollection)
+    if (m_heap->collectionScope() == CollectionScope::Eden)
         m_largeAllocationsNurseryOffsetForSweep = m_largeAllocationsNurseryOffset;
     else
         m_largeAllocationsNurseryOffsetForSweep = 0;
@@ -355,7 +355,7 @@ void MarkedSpace::visitWeakSets(HeapRootVisitor& heapRootVisitor)
     
     m_newActiveWeakSets.forEach(visit);
     
-    if (m_heap->operationInProgress() == FullCollection)
+    if (m_heap->collectionScope() == CollectionScope::Full)
         m_activeWeakSets.forEach(visit);
 }
 
@@ -367,7 +367,7 @@ void MarkedSpace::reapWeakSets()
     
     m_newActiveWeakSets.forEach(visit);
     
-    if (m_heap->operationInProgress() == FullCollection)
+    if (m_heap->collectionScope() == CollectionScope::Full)
         m_activeWeakSets.forEach(visit);
 }
 
@@ -383,7 +383,7 @@ void MarkedSpace::stopAllocating()
 
 void MarkedSpace::prepareForMarking()
 {
-    if (m_heap->operationInProgress() == EdenCollection)
+    if (m_heap->collectionScope() == CollectionScope::Eden)
         m_largeAllocationsOffsetForThisCollection = m_largeAllocationsNurseryOffset;
     else
         m_largeAllocationsOffsetForThisCollection = 0;
@@ -453,7 +453,7 @@ void MarkedSpace::shrink()
 
 void MarkedSpace::beginMarking()
 {
-    if (m_heap->operationInProgress() == FullCollection) {
+    if (m_heap->collectionScope() == CollectionScope::Full) {
         forEachAllocator(
             [&] (MarkedAllocator& allocator) -> IterationStatus {
                 allocator.beginMarkingForFullCollection();
@@ -597,7 +597,7 @@ MarkedBlock::Handle* MarkedSpace::findEmptyBlockToSteal()
 
 void MarkedSpace::snapshotUnswept()
 {
-    if (m_heap->operationInProgress() == EdenCollection) {
+    if (m_heap->collectionScope() == CollectionScope::Eden) {
         forEachAllocator(
             [&] (MarkedAllocator& allocator) -> IterationStatus {
                 allocator.snapshotUnsweptForEdenCollection();
similarity index 79%
rename from Source/JavaScriptCore/heap/HeapOperation.cpp
rename to Source/JavaScriptCore/heap/MutatorState.cpp
index 8715314..8368f43 100644 (file)
  */
 
 #include "config.h"
-#include "HeapOperation.h"
+#include "MutatorState.h"
 
 #include <wtf/PrintStream.h>
 
-namespace WTF {
-
 using namespace JSC;
 
-void printInternal(PrintStream& out, HeapOperation operation)
+namespace WTF {
+
+void printInternal(PrintStream& out, MutatorState state)
 {
-    switch (operation) {
-    case NoOperation:
-        out.print("None");
+    switch (state) {
+    case MutatorState::Running:
+        out.print("Running");
         return;
-    case Allocation:
-        out.print("Alloc");
+    case MutatorState::Allocating:
+        out.print("Allocating");
         return;
-    case FullCollection:
-        out.print("Full");
-        return;
-    case EdenCollection:
-        out.print("Eden");
-        return;
-    case AnyCollection:
-        out.print("Any");
+    case MutatorState::HelpingGC:
+        out.print("HelpingGC");
         return;
     }
     RELEASE_ASSERT_NOT_REACHED();
@@ -56,5 +50,3 @@ void printInternal(PrintStream& out, HeapOperation operation)
 
 } // namespace WTF
 
-
-
diff --git a/Source/JavaScriptCore/heap/MutatorState.h b/Source/JavaScriptCore/heap/MutatorState.h
new file mode 100644 (file)
index 0000000..65b61f7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace JSC {
+
+enum class MutatorState {
+    // The mutator is running when it's not inside a Heap slow path.
+    Running,
+    
+    // The mutator is in an allocation slow path.
+    Allocating,
+    
+    // The mutator was asked by the GC to do some work.
+    HelpingGC
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&, JSC::MutatorState);
+
+} // namespace WTF
+
index 6856d8f..a804e89 100644 (file)
@@ -96,7 +96,7 @@ SlotVisitor::~SlotVisitor()
 
 void SlotVisitor::didStartMarking()
 {
-    if (heap()->operationInProgress() == FullCollection)
+    if (heap()->collectionScope() == CollectionScope::Full)
         ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
     else
         reset();
index 17e5e4d..404169f 100644 (file)
@@ -320,17 +320,16 @@ void InspectorHeapAgent::getRemoteObject(ErrorString& errorString, int heapObjec
     result = injectedScript.wrapObject(cell, objectGroup, true);
 }
 
-static Inspector::Protocol::Heap::GarbageCollection::Type protocolTypeForHeapOperation(HeapOperation operation)
+static Inspector::Protocol::Heap::GarbageCollection::Type protocolTypeForHeapOperation(CollectionScope scope)
 {
-    switch (operation) {
-    case FullCollection:
+    switch (scope) {
+    case CollectionScope::Full:
         return Inspector::Protocol::Heap::GarbageCollection::Type::Full;
-    case EdenCollection:
+    case CollectionScope::Eden:
         return Inspector::Protocol::Heap::GarbageCollection::Type::Partial;
-    default:
-        ASSERT_NOT_REACHED();
-        return Inspector::Protocol::Heap::GarbageCollection::Type::Full;
     }
+    ASSERT_NOT_REACHED();
+    return Inspector::Protocol::Heap::GarbageCollection::Type::Full;
 }
 
 void InspectorHeapAgent::willGarbageCollect()
@@ -341,7 +340,7 @@ void InspectorHeapAgent::willGarbageCollect()
     m_gcStartTime = m_environment.executionStopwatch()->elapsedTime();
 }
 
-void InspectorHeapAgent::didGarbageCollect(HeapOperation operation)
+void InspectorHeapAgent::didGarbageCollect(CollectionScope scope)
 {
     ASSERT(m_enabled);
     ASSERT(!std::isnan(m_gcStartTime));
@@ -356,7 +355,7 @@ void InspectorHeapAgent::didGarbageCollect(HeapOperation operation)
     // VM as the inspected page.
 
     GarbageCollectionData data;
-    data.type = protocolTypeForHeapOperation(operation);
+    data.type = protocolTypeForHeapOperation(scope);
     data.startTime = m_gcStartTime;
     data.endTime = m_environment.executionStopwatch()->elapsedTime();
 
index 18e8dc3..ba7382b 100644 (file)
@@ -60,7 +60,7 @@ public:
 
     // HeapObserver
     void willGarbageCollect() override;
-    void didGarbageCollect(JSC::HeapOperation) override;
+    void didGarbageCollect(JSC::CollectionScope) override;
 
 protected:
     void clearHeapSnapshots();
index 91920dc..71cfa1a 100644 (file)
@@ -755,9 +755,9 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, J
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(!throwScope.exception());
-    ASSERT(!vm.isCollectorBusy());
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
 
     if (UNLIKELY(!vm.isSafeToRecurseSoft()))
@@ -900,8 +900,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(!throwScope.exception());
-    ASSERT(!vm.isCollectorBusy());
-    if (vm.isCollectorBusy())
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
+    if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
 
     bool isJSCall = (callType == CallType::JS);
@@ -962,10 +962,10 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(!throwScope.exception());
-    ASSERT(!vm.isCollectorBusy());
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
     // We throw in this case because we have to return something "valid" but we're
     // already in an invalid state.
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return checkedReturn(throwStackOverflowError(callFrame, throwScope));
 
     bool isJSConstruct = (constructType == ConstructType::JS);
@@ -1028,7 +1028,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
     auto throwScope = DECLARE_THROW_SCOPE(vm);
     ASSERT(!throwScope.exception());
     
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return CallFrameClosure();
 
     // Compile the callee:
@@ -1053,9 +1053,9 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
     VM& vm = *closure.vm;
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
-    ASSERT(!vm.isCollectorBusy());
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
 
     StackStats::CheckPoint stackCheckPoint;
@@ -1076,9 +1076,9 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
 
     ASSERT(scope->vm() == &callFrame->vm());
     ASSERT(!throwScope.exception());
-    ASSERT(!vm.isCollectorBusy());
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
 
     VMEntryScope entryScope(vm, scope->globalObject());
@@ -1182,9 +1182,9 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
 
     ASSERT(scope->vm() == &callFrame->vm());
     ASSERT(!throwScope.exception());
-    ASSERT(!vm.isCollectorBusy());
+    ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
-    if (vm.isCollectorBusy())
+    if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
 
     VMEntryScope entryScope(vm, scope->globalObject());
index b17c25f..a8e7da4 100644 (file)
@@ -1677,14 +1677,14 @@ EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    exec->heap()->collect(FullCollection);
+    exec->heap()->collect(CollectionScope::Full);
     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
 }
 
 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    exec->heap()->collect(EdenCollection);
+    exec->heap()->collect(CollectionScope::Eden);
     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastEdenCollection()));
 }
 
index d0aea68..731d861 100644 (file)
@@ -91,7 +91,7 @@ JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, N
     JSLockHolder lock(vm);
     auto scope = DECLARE_CATCH_SCOPE(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!vm.isCollectorBusy());
+    RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
 
     CodeProfiling profile(source);
 
@@ -174,7 +174,7 @@ JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const String& moduleNa
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
     return loadAndEvaluateModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), initiator);
 }
@@ -185,7 +185,7 @@ JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const SourceCode& sour
     JSLockHolder lock(vm);
     auto scope = DECLARE_THROW_SCOPE(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!vm.isCollectorBusy());
+    RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
 
     Symbol* key = createSymbolForEntryPointModule(vm);
 
@@ -212,7 +212,7 @@ JSInternalPromise* loadModule(ExecState* exec, const String& moduleName, JSValue
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
     return loadModule(lock, exec, exec->vmEntryGlobalObject(), Identifier::fromString(exec, moduleName), initiator);
 }
@@ -223,7 +223,7 @@ JSInternalPromise* loadModule(ExecState* exec, const SourceCode& source, JSValue
     JSLockHolder lock(vm);
     auto scope = DECLARE_THROW_SCOPE(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!vm.isCollectorBusy());
+    RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
 
     Symbol* key = createSymbolForEntryPointModule(vm);
 
@@ -241,7 +241,7 @@ JSValue linkAndEvaluateModule(ExecState* exec, const Identifier& moduleKey, JSVa
 {
     JSLockHolder lock(exec);
     RELEASE_ASSERT(exec->vm().atomicStringTable() == wtfThreadData().atomicStringTable());
-    RELEASE_ASSERT(!exec->vm().isCollectorBusy());
+    RELEASE_ASSERT(!exec->vm().isCollectorBusyOnCurrentThread());
 
     JSGlobalObject* globalObject = exec->vmEntryGlobalObject();
     return globalObject->moduleLoader()->linkAndEvaluateModule(exec, identifierToJSValue(exec->vm(), moduleKey), initiator);
index 09250f6..82a2171 100644 (file)
@@ -267,7 +267,7 @@ JSLock::DropAllLocks::DropAllLocks(VM* vm)
 {
     if (!m_vm)
         return;
-    RELEASE_ASSERT(!m_vm->apiLock().currentThreadIsHoldingLock() || !m_vm->isCollectorBusy());
+    RELEASE_ASSERT(!m_vm->apiLock().currentThreadIsHoldingLock() || !m_vm->isCollectorBusyOnCurrentThread());
     m_droppedLockCount = m_vm->apiLock().dropAllLocks(this);
 }
 
index 0e02c1d..263b427 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2015 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2009, 2015-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
@@ -113,9 +113,9 @@ public:
     JSString* nullObjectString() const { return m_nullObjectString; }
     JSString* undefinedObjectString() const { return m_undefinedObjectString; }
 
-    bool needsToBeVisited(HeapOperation collectionType) const
+    bool needsToBeVisited(CollectionScope scope) const
     {
-        if (collectionType == FullCollection)
+        if (scope == CollectionScope::Full)
             return true;
         return m_needsToBeVisited;
     }
index f55f3d3..a97f181 100644 (file)
@@ -576,7 +576,7 @@ public:
 #endif
     JS_EXPORT_PRIVATE void dumpRegExpTrace();
 
-    bool isCollectorBusy() { return heap.isBusy(); }
+    bool isCollectorBusyOnCurrentThread() { return heap.isCurrentThreadBusy(); }
 
 #if ENABLE(GC_VALIDATION)
     bool isInitializingObject() const; 
index b52840a..bc5e869 100644 (file)
@@ -130,7 +130,7 @@ void JSDollarVMPrototype::edenGC(ExecState* exec)
 {
     if (!ensureCurrentThreadOwnsJSLock(exec))
         return;
-    exec->heap()->collect(EdenCollection);
+    exec->heap()->collect(CollectionScope::Eden);
 }
 
 static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
index 30ec9d9..fb77570 100644 (file)
@@ -1,3 +1,19 @@
+2016-10-20  Filip Pizlo  <fpizlo@apple.com>
+
+        The tracking of the coarse-grain Heap state (allocating or not, collector or not, eden vs full) should respect the orthogonality between allocating and collecting
+        https://bugs.webkit.org/show_bug.cgi?id=163738
+
+        Reviewed by Geoffrey Garen.
+        
+        There will soon be different kinds of GC threads, and WTF's "are you a GC thread" thing
+        should know about this.
+
+        * wtf/MainThread.cpp:
+        (WTF::initializeGCThreads):
+        (WTF::registerGCThread):
+        (WTF::mayBeGCThread):
+        * wtf/MainThread.h:
+
 2016-10-19  Sam Weinig  <sam@webkit.org>
 
         Add convenience function that combines WTF::visit(...) with WTF::makeVisitor(...)
index 1e4daae..946f02e 100644 (file)
@@ -190,14 +190,14 @@ bool canAccessThreadLocalDataForThread(ThreadIdentifier threadId)
 }
 #endif
 
-static ThreadSpecific<bool>* isGCThread;
+static ThreadSpecific<Optional<GCThreadType>>* isGCThread;
 
 void initializeGCThreads()
 {
-    isGCThread = new ThreadSpecific<bool>();
+    isGCThread = new ThreadSpecific<Optional<GCThreadType>>();
 }
 
-void registerGCThread()
+void registerGCThread(GCThreadType type)
 {
     if (!isGCThread) {
         // This happens if we're running in a process that doesn't care about
@@ -205,7 +205,7 @@ void registerGCThread()
         return;
     }
 
-    **isGCThread = true;
+    **isGCThread = type;
 }
 
 bool isMainThreadOrGCThread()
@@ -216,9 +216,13 @@ bool isMainThreadOrGCThread()
     return isMainThread();
 }
 
-bool mayBeGCThread()
+Optional<GCThreadType> mayBeGCThread()
 {
-    return isGCThread && isGCThread->isSet() && **isGCThread;
+    if (!isGCThread)
+        return Nullopt;
+    if (!isGCThread->isSet())
+        return Nullopt;
+    return **isGCThread;
 }
 
 } // namespace WTF
index d7adc6c..402a18c 100644 (file)
 #include <functional>
 #include <stdint.h>
 #include <wtf/Function.h>
+#include <wtf/Optional.h>
 
 namespace WTF {
 
+class PrintStream;
+
 typedef uint32_t ThreadIdentifier;
 
 // Must be called from the main thread.
@@ -67,8 +70,15 @@ inline bool isUIThread() { return isMainThread(); }
 
 void initializeGCThreads();
 
-WTF_EXPORT_PRIVATE void registerGCThread();
-WTF_EXPORT_PRIVATE bool mayBeGCThread();
+enum class GCThreadType {
+    Main,
+    Helper
+};
+
+void printInternal(PrintStream&, GCThreadType);
+
+WTF_EXPORT_PRIVATE void registerGCThread(GCThreadType);
+WTF_EXPORT_PRIVATE Optional<GCThreadType> mayBeGCThread();
 WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread();
 
 // NOTE: these functions are internal to the callOnMainThread implementation.
@@ -88,6 +98,7 @@ void initializeMainThreadToProcessMainThreadPlatform();
 
 } // namespace WTF
 
+using WTF::GCThreadType;
 using WTF::callOnMainThread;
 using WTF::canAccessThreadLocalDataForThread;
 using WTF::isMainThread;
index 12329aa..b7bf90b 100644 (file)
@@ -1,3 +1,15 @@
+2016-10-20  Filip Pizlo  <fpizlo@apple.com>
+
+        The tracking of the coarse-grain Heap state (allocating or not, collector or not, eden vs full) should respect the orthogonality between allocating and collecting
+        https://bugs.webkit.org/show_bug.cgi?id=163738
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests because no change in behavior.
+
+        * bindings/js/GCController.cpp:
+        (WebCore::GCController::garbageCollectNow):
+
 2016-10-20  Chris Dumez  <cdumez@apple.com>
 
         [Bindings] Start using signature->idlType instead of signature->type in the overload resolution code
index acfba39..bff3b0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2014, 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
@@ -82,7 +82,7 @@ void GCController::gcTimerFired()
 void GCController::garbageCollectNow()
 {
     JSLockHolder lock(JSDOMWindow::commonVM());
-    if (!JSDOMWindow::commonVM().heap.isBusy()) {
+    if (!JSDOMWindow::commonVM().heap.isCurrentThreadBusy()) {
         JSDOMWindow::commonVM().heap.collectAllGarbage();
         WTF::releaseFastMallocFreeMemory();
     }
@@ -92,7 +92,7 @@ void GCController::garbageCollectNowIfNotDoneRecently()
 {
 #if USE(CF) || USE(GLIB)
     JSLockHolder lock(JSDOMWindow::commonVM());
-    if (!JSDOMWindow::commonVM().heap.isBusy())
+    if (!JSDOMWindow::commonVM().heap.isCurrentThreadBusy())
         JSDOMWindow::commonVM().heap.collectAllGarbageIfNotDoneRecently();
 #else
     garbageCollectSoon();