JSC::Heap should expose a richer API for requesting GCs
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 23:37:52 +0000 (23:37 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2017 23:37:52 +0000 (23:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171690

Reviewed by Geoffrey Garen.
Source/JavaScriptCore:

I want to stop WebCore from requesting synchronous GCs. But various parts of that work
may cause regressions, so I'd like to land it separately from the functionality that is
needed on the JSC side. This change is mostly a JSC-side refactoring that does not
change behavior. In the future I'll land the behavior changes (i.e. not requesting sync
GCs).

This change allows you to enumerate over synchronousness, so that we can make all APIs
take synchronousness as an argument. It replaces the collectAllGarbage API with a
collectNow(Synchronousness, GCRequest) API. GCRequest is a new concept, which subsumes
std::optional<CollectionScope> and gives us the ability to register callbacks along
with a GC. So, you can ask for an async GC and get a callback when it's done.

Also adds ability to request that fastMalloc memory be released after the incremental
sweeper finishes.

* API/JSBase.cpp:
(JSSynchronousGarbageCollectForDebugging):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/FullGCActivityCallback.cpp:
(JSC::FullGCActivityCallback::doCollection):
* heap/FullGCActivityCallback.h:
* heap/GCRequest.cpp: Added.
(JSC::GCRequest::subsumedBy):
(JSC::GCRequest::dump):
* heap/GCRequest.h: Added.
(JSC::GCRequest::GCRequest):
* heap/Heap.cpp:
(JSC::Heap::collect):
(JSC::Heap::collectNow):
(JSC::Heap::collectAsync):
(JSC::Heap::collectSync):
(JSC::Heap::runBeginPhase):
(JSC::Heap::runEndPhase):
(JSC::Heap::requestCollection):
(JSC::Heap::willStartCollection):
(JSC::Heap::sweeper):
(JSC::Heap::collectNowFullIfNotDoneRecently):
(JSC::Heap::shouldDoFullCollection):
(JSC::Heap::collectAllGarbage): Deleted.
(JSC::Heap::collectAllGarbageIfNotDoneRecently): Deleted.
* heap/Heap.h:
* heap/HeapSnapshotBuilder.cpp:
(JSC::HeapSnapshotBuilder::buildSnapshot):
* heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::doSweep):
* heap/IncrementalSweeper.h:
(JSC::IncrementalSweeper::freeFastMallocMemoryAfterSweeping):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::doTestCollectionsIfNeeded):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::sweep):
* heap/Synchronousness.cpp: Added.
(WTF::printInternal):
* heap/Synchronousness.h: Added.
* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::InspectorHeapAgent::gc):
* jsc.cpp:
(functionGCAndSweep):
(runJSC):
* tools/JSDollarVMPrototype.cpp:
(JSC::JSDollarVMPrototype::gc):
* wasm/WasmMemory.cpp:

Source/WebCore:

No new tests because this is just a refactoring.

Change some function calls now that some JSC::Heap APIs got renamed.

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

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

23 files changed:
Source/JavaScriptCore/API/JSBase.cpp
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/heap/FullGCActivityCallback.cpp
Source/JavaScriptCore/heap/FullGCActivityCallback.h
Source/JavaScriptCore/heap/GCRequest.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/GCRequest.h [new file with mode: 0644]
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp
Source/JavaScriptCore/heap/IncrementalSweeper.cpp
Source/JavaScriptCore/heap/IncrementalSweeper.h
Source/JavaScriptCore/heap/MarkedAllocator.cpp
Source/JavaScriptCore/heap/MarkedSpace.cpp
Source/JavaScriptCore/heap/Synchronousness.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/Synchronousness.h [new file with mode: 0644]
Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
Source/JavaScriptCore/wasm/WasmMemory.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/GCController.cpp

index 983acce..d8917a3 100644 (file)
@@ -157,7 +157,7 @@ void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx)
 
     ExecState* exec = toJS(ctx);
     JSLockHolder locker(exec);
-    exec->vm().heap.collectAllGarbage();
+    exec->vm().heap.collectNow(Sync, CollectionScope::Full);
 }
 
 void JSSynchronousEdenCollectForDebugging(JSContextRef ctx)
index a368176..b7dfa07 100644 (file)
@@ -502,6 +502,7 @@ set(JavaScriptCore_SOURCES
     heap/GCActivityCallback.cpp
     heap/GCConductor.cpp
     heap/GCLogging.cpp
+    heap/GCRequest.cpp
     heap/HandleSet.cpp
     heap/HandleStack.cpp
     heap/Heap.cpp
@@ -528,6 +529,7 @@ set(JavaScriptCore_SOURCES
     heap/StopIfNecessaryTimer.cpp
     heap/Subspace.cpp
     heap/SynchronousStopTheWorldMutatorScheduler.cpp
+    heap/Synchronousness.cpp
     heap/VisitRaceKey.cpp
     heap/Weak.cpp
     heap/WeakBlock.cpp
index 968b8d8..97a5400 100644 (file)
@@ -1,3 +1,74 @@
+2017-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        JSC::Heap should expose a richer API for requesting GCs
+        https://bugs.webkit.org/show_bug.cgi?id=171690
+
+        Reviewed by Geoffrey Garen.
+        
+        I want to stop WebCore from requesting synchronous GCs. But various parts of that work
+        may cause regressions, so I'd like to land it separately from the functionality that is
+        needed on the JSC side. This change is mostly a JSC-side refactoring that does not
+        change behavior. In the future I'll land the behavior changes (i.e. not requesting sync
+        GCs).
+        
+        This change allows you to enumerate over synchronousness, so that we can make all APIs
+        take synchronousness as an argument. It replaces the collectAllGarbage API with a
+        collectNow(Synchronousness, GCRequest) API. GCRequest is a new concept, which subsumes
+        std::optional<CollectionScope> and gives us the ability to register callbacks along
+        with a GC. So, you can ask for an async GC and get a callback when it's done.
+        
+        Also adds ability to request that fastMalloc memory be released after the incremental
+        sweeper finishes.
+        
+        * API/JSBase.cpp:
+        (JSSynchronousGarbageCollectForDebugging):
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * heap/FullGCActivityCallback.cpp:
+        (JSC::FullGCActivityCallback::doCollection):
+        * heap/FullGCActivityCallback.h:
+        * heap/GCRequest.cpp: Added.
+        (JSC::GCRequest::subsumedBy):
+        (JSC::GCRequest::dump):
+        * heap/GCRequest.h: Added.
+        (JSC::GCRequest::GCRequest):
+        * heap/Heap.cpp:
+        (JSC::Heap::collect):
+        (JSC::Heap::collectNow):
+        (JSC::Heap::collectAsync):
+        (JSC::Heap::collectSync):
+        (JSC::Heap::runBeginPhase):
+        (JSC::Heap::runEndPhase):
+        (JSC::Heap::requestCollection):
+        (JSC::Heap::willStartCollection):
+        (JSC::Heap::sweeper):
+        (JSC::Heap::collectNowFullIfNotDoneRecently):
+        (JSC::Heap::shouldDoFullCollection):
+        (JSC::Heap::collectAllGarbage): Deleted.
+        (JSC::Heap::collectAllGarbageIfNotDoneRecently): Deleted.
+        * heap/Heap.h:
+        * heap/HeapSnapshotBuilder.cpp:
+        (JSC::HeapSnapshotBuilder::buildSnapshot):
+        * heap/IncrementalSweeper.cpp:
+        (JSC::IncrementalSweeper::doSweep):
+        * heap/IncrementalSweeper.h:
+        (JSC::IncrementalSweeper::freeFastMallocMemoryAfterSweeping):
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::doTestCollectionsIfNeeded):
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::sweep):
+        * heap/Synchronousness.cpp: Added.
+        (WTF::printInternal):
+        * heap/Synchronousness.h: Added.
+        * inspector/agents/InspectorHeapAgent.cpp:
+        (Inspector::InspectorHeapAgent::gc):
+        * jsc.cpp:
+        (functionGCAndSweep):
+        (runJSC):
+        * tools/JSDollarVMPrototype.cpp:
+        (JSC::JSDollarVMPrototype::gc):
+        * wasm/WasmMemory.cpp:
+
 2017-05-04  Mark Lam  <mark.lam@apple.com>
 
         NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
index 8ad9c44..5220194 100644 (file)
                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9630381D4192C3005609D9 /* DestructionMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F96EBB316676EF6008BADE3 /* CodeBlockWithJITType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F9715301EB28BEB00A1645D /* GCRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F97152E1EB28BE900A1645D /* GCRequest.cpp */; };
+               0F9715311EB28BEE00A1645D /* GCRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97152F1EB28BE900A1645D /* GCRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F9749711687ADE400A4FF6A /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F978B3B1AAEA71D007C7369 /* ConstantMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */; };
                0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */; };
                0FD3E40C1B618B6600C80E1E /* ObjectPropertyConditionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3E4061B618B6600C80E1E /* ObjectPropertyConditionSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FD3E40D1B618B6600C80E1E /* PropertyCondition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */; };
                0FD3E40E1B618B6600C80E1E /* PropertyCondition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3E4081B618B6600C80E1E /* PropertyCondition.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FD79A2D1EBBBDBB00DA88D3 /* Synchronousness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD79A2C1EBBBDB200DA88D3 /* Synchronousness.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FD79A2E1EBBBDC000DA88D3 /* Synchronousness.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD79A2B1EBBBDB200DA88D3 /* Synchronousness.cpp */; };
                0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD81AD0154FB4EB00983E72 /* DFGDominators.h */; };
                0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; };
                0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F9630381D4192C3005609D9 /* DestructionMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DestructionMode.h; sourceTree = "<group>"; };
                0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
                0F96EBB116676EF4008BADE3 /* CodeBlockWithJITType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockWithJITType.h; sourceTree = "<group>"; };
+               0F97152E1EB28BE900A1645D /* GCRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCRequest.cpp; sourceTree = "<group>"; };
+               0F97152F1EB28BE900A1645D /* GCRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCRequest.h; sourceTree = "<group>"; };
                0F97496F1687ADE200A4FF6A /* JSCellInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCellInlines.h; sourceTree = "<group>"; };
                0F978B3A1AAEA71D007C7369 /* ConstantMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantMode.cpp; sourceTree = "<group>"; };
                0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreciseJumpTargets.cpp; sourceTree = "<group>"; };
                0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyCondition.cpp; sourceTree = "<group>"; };
                0FD3E4081B618B6600C80E1E /* PropertyCondition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyCondition.h; sourceTree = "<group>"; };
                0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlockInlines.h; path = dfg/DFGBasicBlockInlines.h; sourceTree = "<group>"; };
+               0FD79A2B1EBBBDB200DA88D3 /* Synchronousness.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Synchronousness.cpp; sourceTree = "<group>"; };
+               0FD79A2C1EBBBDB200DA88D3 /* Synchronousness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Synchronousness.h; sourceTree = "<group>"; };
                0FD81AD0154FB4EB00983E72 /* DFGDominators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDominators.h; path = dfg/DFGDominators.h; sourceTree = "<group>"; };
                0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCapabilities.cpp; path = dfg/DFGCapabilities.cpp; sourceTree = "<group>"; };
                0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCapabilities.h; path = dfg/DFGCapabilities.h; sourceTree = "<group>"; };
                                0F2B66AB17B6B53D00A7AE3F /* GCIncomingRefCountedSetInlines.h */,
                                2ADFA26218EF3540004F9FCC /* GCLogging.cpp */,
                                2AABCDE618EF294200002096 /* GCLogging.h */,
+                               0F97152E1EB28BE900A1645D /* GCRequest.cpp */,
+                               0F97152F1EB28BE900A1645D /* GCRequest.h */,
                                2A343F7418A1748B0039B085 /* GCSegmentedArray.h */,
                                2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */,
                                0F86A26E1D6F7B3100CB0C92 /* GCTypeMap.h */,
                                0F7DF1321E2970D50095951B /* Subspace.h */,
                                0F7DF1331E2970D50095951B /* SubspaceInlines.h */,
                                0FD0E5ED1E468A540006AB08 /* SweepingScope.h */,
+                               0FD79A2B1EBBBDB200DA88D3 /* Synchronousness.cpp */,
+                               0FD79A2C1EBBBDB200DA88D3 /* Synchronousness.h */,
                                0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */,
                                0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */,
                                141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
                                0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */,
                                0FBE0F7716C1DB120082C5E8 /* DFGUnificationPhase.h in Headers */,
                                0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */,
+                               0F9715311EB28BEE00A1645D /* GCRequest.h in Headers */,
                                0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */,
                                0F2BDC481522802900CD8910 /* DFGValueSource.h in Headers */,
                                0F0123331944EA1B00843A0C /* DFGValueStrength.h in Headers */,
                                A55D93A6185012A800400DED /* ScriptFunctionCall.h in Headers */,
                                A54CF2FA184EAEDA00237F19 /* ScriptObject.h in Headers */,
                                A55165D51BDF135A003B75C1 /* ScriptProfilingScope.h in Headers */,
+                               0FD79A2D1EBBBDBB00DA88D3 /* Synchronousness.h in Headers */,
                                A54CF2F6184EAB2400237F19 /* ScriptValue.h in Headers */,
                                A7299DA617D12858005F5FF9 /* SetConstructor.h in Headers */,
                                A790DD6E182F499700588807 /* SetIteratorPrototype.h in Headers */,
                                0FEC85901BDACDC70080FF74 /* AirValidate.cpp in Sources */,
                                0F9630391D4192C6005609D9 /* AllocatorAttributes.cpp in Sources */,
                                147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,
+                               0F9715301EB28BEB00A1645D /* GCRequest.cpp in Sources */,
                                79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */,
                                0F743BAA16B88249009F9277 /* ARM64Disassembler.cpp in Sources */,
                                86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */,
                                DC605B5D1CE26EA000593718 /* ProfilerEvent.cpp in Sources */,
                                0F190CAC189D82F6000AE5F0 /* ProfilerJettisonReason.cpp in Sources */,
                                0FF729B3166AD35C000F5BA3 /* ProfilerOrigin.cpp in Sources */,
+                               0FD79A2E1EBBBDC000DA88D3 /* Synchronousness.cpp in Sources */,
                                0FF729B4166AD35C000F5BA3 /* ProfilerOriginStack.cpp in Sources */,
                                0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
                                0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
index a71c766..ffd63b0 100644 (file)
@@ -42,7 +42,7 @@ FullGCActivityCallback::FullGCActivityCallback(Heap* heap)
 void FullGCActivityCallback::doCollection()
 {
     Heap& heap = m_vm->heap;
-    m_didSyncGCRecently = false;
+    m_didGCRecently = false;
 
 #if !PLATFORM(IOS)
     double startTime = WTF::monotonicallyIncreasingTime();
index 43d53b8..da89c7d 100644 (file)
@@ -35,15 +35,15 @@ public:
 
     void doCollection() override;
 
-    bool didSyncGCRecently() const { return m_didSyncGCRecently; }
-    void setDidSyncGCRecently() { m_didSyncGCRecently = true; }
+    bool didGCRecently() const { return m_didGCRecently; }
+    void setDidGCRecently() { m_didGCRecently = true; }
 
 protected:
     Seconds lastGCLength() override;
     double gcTimeSlice(size_t bytes) override;
     double deathRate() override;
 
-    bool m_didSyncGCRecently { false };
+    bool m_didGCRecently { false };
 };
 
 inline RefPtr<FullGCActivityCallback> GCActivityCallback::createFullTimer(Heap* heap)
diff --git a/Source/JavaScriptCore/heap/GCRequest.cpp b/Source/JavaScriptCore/heap/GCRequest.cpp
new file mode 100644 (file)
index 0000000..e62dfc4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "GCRequest.h"
+
+namespace JSC {
+
+bool GCRequest::subsumedBy(const GCRequest& other) const
+{
+    // If we have callbacks, then there is no chance that we're subsumed by an existing request.
+    if (didFinishEndPhase)
+        return false;
+    
+    if (other.scope == CollectionScope::Full)
+        return true;
+    
+    if (scope) {
+        // If we're eden, then we're subsumed by the other scope because the other scope is either eden
+        // or disengaged (so either eden or full). If we're full, then we're not subsumed, for the same
+        // reason.
+        return scope == CollectionScope::Eden;
+    }
+    
+    // At this point we know that other.scope is either not engaged or Eden, and this.scope is not
+    // engaged. So, we're expecting to do either an eden or full collection, and the other scope is
+    // either the same or is requesting specifically a full collection. We are subsumed if the other
+    // scope is disengaged (so same as us).
+    return !other.scope;
+}
+
+void GCRequest::dump(PrintStream& out) const
+{
+    out.print("{scope = ", scope, ", didFinishEndPhase = ", didFinishEndPhase ? "engaged" : "null", "}");
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/heap/GCRequest.h b/Source/JavaScriptCore/heap/GCRequest.h
new file mode 100644 (file)
index 0000000..2e81c02
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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 "CollectionScope.h"
+#include <wtf/Optional.h>
+#include <wtf/PrintStream.h>
+#include <wtf/RefPtr.h>
+#include <wtf/SharedTask.h>
+
+namespace JSC {
+
+struct GCRequest {
+    GCRequest() { }
+    
+    GCRequest(CollectionScope scope)
+        : scope(scope)
+    {
+    }
+    
+    GCRequest(std::optional<CollectionScope> scope)
+        : scope(scope)
+    {
+    }
+    
+    bool subsumedBy(const GCRequest& other) const;
+    
+    void dump(PrintStream&) const;
+    
+    std::optional<CollectionScope> scope;
+    RefPtr<SharedTask<void()>> didFinishEndPhase;
+};
+
+} // namespace JSC
+
index 2d7b8f5..79bc9c0 100644 (file)
@@ -940,31 +940,52 @@ void Heap::sweepSynchronously()
     }
 }
 
-void Heap::collectAllGarbage()
+void Heap::collect(Synchronousness synchronousness, GCRequest request)
 {
-    if (!m_isSafeToCollect)
+    switch (synchronousness) {
+    case Async:
+        collectAsync(request);
+        return;
+    case Sync:
+        collectSync(request);
         return;
-    
-    collectSync(CollectionScope::Full);
-
-    DeferGCForAWhile deferGC(*this);
-    if (UNLIKELY(Options::useImmortalObjects()))
-        sweeper()->stopSweeping();
-
-    bool alreadySweptInCollectSync = Options::sweepSynchronously();
-    if (!alreadySweptInCollectSync) {
-        if (Options::logGC())
-            dataLog("[GC<", RawPointer(this), ">: ");
-        sweepSynchronously();
-        if (Options::logGC())
-            dataLog("]\n");
     }
-    m_objectSpace.assertNoUnswept();
+    RELEASE_ASSERT_NOT_REACHED();
+}
 
-    sweepAllLogicallyEmptyWeakBlocks();
+void Heap::collectNow(Synchronousness synchronousness, GCRequest request)
+{
+    switch (synchronousness) {
+    case Async: {
+        collectAsync(request);
+        stopIfNecessary();
+        return;
+    }
+        
+    case Sync: {
+        collectSync(request);
+        
+        DeferGCForAWhile deferGC(*this);
+        if (UNLIKELY(Options::useImmortalObjects()))
+            sweeper().stopSweeping();
+        
+        bool alreadySweptInCollectSync = Options::sweepSynchronously();
+        if (!alreadySweptInCollectSync) {
+            if (Options::logGC())
+                dataLog("[GC<", RawPointer(this), ">: ");
+            sweepSynchronously();
+            if (Options::logGC())
+                dataLog("]\n");
+        }
+        m_objectSpace.assertNoUnswept();
+        
+        sweepAllLogicallyEmptyWeakBlocks();
+        return;
+    } }
+    RELEASE_ASSERT_NOT_REACHED();
 }
 
-void Heap::collectAsync(std::optional<CollectionScope> scope)
+void Heap::collectAsync(GCRequest request)
 {
     if (!m_isSafeToCollect)
         return;
@@ -972,38 +993,25 @@ void Heap::collectAsync(std::optional<CollectionScope> scope)
     bool alreadyRequested = false;
     {
         LockHolder locker(*m_threadLock);
-        for (std::optional<CollectionScope> request : m_requests) {
-            if (scope) {
-                if (scope == CollectionScope::Eden) {
-                    alreadyRequested = true;
-                    break;
-                } else {
-                    RELEASE_ASSERT(scope == CollectionScope::Full);
-                    if (request == CollectionScope::Full) {
-                        alreadyRequested = true;
-                        break;
-                    }
-                }
-            } else {
-                if (!request || request == CollectionScope::Full) {
-                    alreadyRequested = true;
-                    break;
-                }
+        for (const GCRequest& previousRequest : m_requests) {
+            if (request.subsumedBy(previousRequest)) {
+                alreadyRequested = true;
+                break;
             }
         }
     }
     if (alreadyRequested)
         return;
 
-    requestCollection(scope);
+    requestCollection(request);
 }
 
-void Heap::collectSync(std::optional<CollectionScope> scope)
+void Heap::collectSync(GCRequest request)
 {
     if (!m_isSafeToCollect)
         return;
     
-    waitForCollection(requestCollection(scope));
+    waitForCollection(requestCollection(request));
 }
 
 bool Heap::shouldCollectInCollectorThread(const AbstractLocker&)
@@ -1108,12 +1116,11 @@ NEVER_INLINE bool Heap::runNotRunningPhase(GCConductor conn)
 NEVER_INLINE bool Heap::runBeginPhase(GCConductor conn)
 {
     m_currentGCStartTime = MonotonicTime::now();
-        
-    std::optional<CollectionScope> scope;
+    
     {
         LockHolder locker(*m_threadLock);
         RELEASE_ASSERT(!m_requests.isEmpty());
-        scope = m_requests.first();
+        m_currentRequest = m_requests.first();
     }
         
     if (Options::logGC())
@@ -1125,8 +1132,8 @@ NEVER_INLINE bool Heap::runBeginPhase(GCConductor conn)
         dataLog("Collection scope already set during GC: ", *m_collectionScope, "\n");
         RELEASE_ASSERT_NOT_REACHED();
     }
-        
-    willStartCollection(scope);
+    
+    willStartCollection();
         
     if (UNLIKELY(m_verifier)) {
         // Verify that live objects from the last GC cycle haven't been corrupted by
@@ -1394,7 +1401,10 @@ NEVER_INLINE bool Heap::runEndPhase(GCConductor conn)
     }
 
     didFinishCollection();
-
+    
+    if (m_currentRequest.didFinishEndPhase)
+        m_currentRequest.didFinishEndPhase->run();
+    
     if (false) {
         dataLog("Heap state after GC:\n");
         m_objectSpace.dumpBits();
@@ -1956,7 +1966,7 @@ void Heap::finalize()
     }
 }
 
-Heap::Ticket Heap::requestCollection(std::optional<CollectionScope> scope)
+Heap::Ticket Heap::requestCollection(GCRequest request)
 {
     stopIfNecessary();
     
@@ -1974,7 +1984,7 @@ Heap::Ticket Heap::requestCollection(std::optional<CollectionScope> scope)
         m_worldState.exchangeOr(mutatorHasConnBit);
     }
     
-    m_requests.append(scope);
+    m_requests.append(request);
     m_lastGrantedTicket++;
     if (!(m_worldState.load() & mutatorHasConnBit))
         m_threadCondition->notifyOne(locker);
@@ -2005,12 +2015,12 @@ void Heap::suspendCompilerThreads()
 #endif
 }
 
-void Heap::willStartCollection(std::optional<CollectionScope> scope)
+void Heap::willStartCollection()
 {
     if (Options::logGC())
         dataLog("=> ");
     
-    if (shouldDoFullCollection(scope)) {
+    if (shouldDoFullCollection()) {
         m_collectionScope = CollectionScope::Full;
         m_shouldDoFullCollection = false;
         if (Options::logGC())
@@ -2229,9 +2239,9 @@ GCActivityCallback* Heap::edenActivityCallback()
     return m_edenActivityCallback.get();
 }
 
-IncrementalSweeper* Heap::sweeper()
+IncrementalSweeper& Heap::sweeper()
 {
-    return m_sweeper.get();
+    return *m_sweeper;
 }
 
 void Heap::setGarbageCollectionTimerEnabled(bool enable)
@@ -2284,31 +2294,31 @@ void Heap::addExecutable(ExecutableBase* executable)
     m_executables.append(executable);
 }
 
-void Heap::collectAllGarbageIfNotDoneRecently()
+void Heap::collectNowFullIfNotDoneRecently(Synchronousness synchronousness)
 {
     if (!m_fullActivityCallback) {
-        collectAllGarbage();
+        collectNow(synchronousness, CollectionScope::Full);
         return;
     }
 
-    if (m_fullActivityCallback->didSyncGCRecently()) {
+    if (m_fullActivityCallback->didGCRecently()) {
         // A synchronous GC was already requested recently so we merely accelerate next collection.
         reportAbandonedObjectGraph();
         return;
     }
 
-    m_fullActivityCallback->setDidSyncGCRecently();
-    collectAllGarbage();
+    m_fullActivityCallback->setDidGCRecently();
+    collectNow(synchronousness, CollectionScope::Full);
 }
 
-bool Heap::shouldDoFullCollection(std::optional<CollectionScope> scope) const
+bool Heap::shouldDoFullCollection() const
 {
     if (!Options::useGenerationalGC())
         return true;
 
-    if (!scope)
+    if (!m_currentRequest.scope)
         return m_shouldDoFullCollection || webAssemblyFastMemoriesThisCycleAtThreshold();
-    return *scope == CollectionScope::Full;
+    return *m_currentRequest.scope == CollectionScope::Full;
 }
 
 void Heap::addLogicallyEmptyWeakBlock(WeakBlock* block)
index 4b63fc4..d85d8da 100644 (file)
@@ -28,6 +28,7 @@
 #include "DeleteAllCodeEffort.h"
 #include "GCConductor.h"
 #include "GCIncomingRefCountedSet.h"
+#include "GCRequest.h"
 #include "HandleSet.h"
 #include "HandleStack.h"
 #include "HeapObserver.h"
@@ -38,6 +39,7 @@
 #include "MutatorState.h"
 #include "Options.h"
 #include "StructureIDTable.h"
+#include "Synchronousness.h"
 #include "TinyBloomFilter.h"
 #include "UnconditionalFinalizer.h"
 #include "VisitRaceKey.h"
@@ -146,7 +148,7 @@ public:
     JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
     JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
 
-    JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
+    JS_EXPORT_PRIVATE IncrementalSweeper& sweeper();
 
     void addObserver(HeapObserver* observer) { m_observers.append(observer); }
     void removeObserver(HeapObserver* observer) { m_observers.removeFirst(observer); }
@@ -169,8 +171,6 @@ public:
 
     JS_EXPORT_PRIVATE bool isHeapSnapshotting() const;
 
-    JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
-    JS_EXPORT_PRIVATE void collectAllGarbage();
     JS_EXPORT_PRIVATE void sweepSynchronously();
 
     bool shouldCollectHeuristic();
@@ -180,14 +180,22 @@ public:
     // and std::nullopt collections are stronger than Eden collections. std::nullopt means that the GC can
     // choose Eden or Full. This implies that if you request a GC while that GC is ongoing, nothing
     // will happen.
-    JS_EXPORT_PRIVATE void collectAsync(std::optional<CollectionScope> = std::nullopt);
+    JS_EXPORT_PRIVATE void collectAsync(GCRequest = GCRequest());
     
     // Queue up a collection and wait for it to complete. This won't return until you get your own
     // complete collection. For example, if there was an ongoing asynchronous collection at the time
     // you called this, then this would wait for that one to complete and then trigger your
     // collection and then return. In weird cases, there could be multiple GC requests in the backlog
     // and this will wait for that backlog before running its GC and returning.
-    JS_EXPORT_PRIVATE void collectSync(std::optional<CollectionScope> = std::nullopt);
+    JS_EXPORT_PRIVATE void collectSync(GCRequest = GCRequest());
+    
+    JS_EXPORT_PRIVATE void collect(Synchronousness, GCRequest = GCRequest());
+    
+    // Like collect(), but in the case of Async this will stopIfNecessary() and in the case of
+    // Sync this will sweep synchronously.
+    JS_EXPORT_PRIVATE void collectNow(Synchronousness, GCRequest = GCRequest());
+    
+    JS_EXPORT_PRIVATE void collectNowFullIfNotDoneRecently(Synchronousness);
     
     void collectIfNecessaryOrDefer(GCDeferralContext* = nullptr);
 
@@ -438,7 +446,7 @@ private:
     bool stopTheMutator();
     void resumeTheMutator();
     
-    void stopIfNecessarySlow();
+    JS_EXPORT_PRIVATE void stopIfNecessarySlow();
     bool stopIfNecessarySlow(unsigned extraStateBits);
     
     template<typename Func>
@@ -465,11 +473,11 @@ private:
     void notifyThreadStopping(const AbstractLocker&);
     
     typedef uint64_t Ticket;
-    Ticket requestCollection(std::optional<CollectionScope>);
+    Ticket requestCollection(GCRequest);
     void waitForCollection(Ticket);
     
     void suspendCompilerThreads();
-    void willStartCollection(std::optional<CollectionScope>);
+    void willStartCollection();
     void prepareForMarking();
     
     void gatherStackRoots(ConservativeRoots&);
@@ -503,7 +511,7 @@ private:
     void sweepAllLogicallyEmptyWeakBlocks();
     bool sweepNextLogicallyEmptyWeakBlock();
 
-    bool shouldDoFullCollection(std::optional<CollectionScope> requestedCollectionScope) const;
+    bool shouldDoFullCollection() const;
 
     void incrementDeferralDepth();
     void decrementDeferralDepth();
@@ -664,7 +672,8 @@ private:
     MonotonicTime m_afterGC;
     MonotonicTime m_stopTime;
     
-    Deque<std::optional<CollectionScope>> m_requests;
+    Deque<GCRequest> m_requests;
+    GCRequest m_currentRequest;
     Ticket m_lastServedTicket { 0 };
     Ticket m_lastGrantedTicket { 0 };
     CollectorPhase m_currentPhase { CollectorPhase::NotRunning };
index 5e59475..632183d 100644 (file)
@@ -58,7 +58,7 @@ void HeapSnapshotBuilder::buildSnapshot()
     m_snapshot = std::make_unique<HeapSnapshot>(m_profiler.mostRecentSnapshot());
     {
         m_profiler.setActiveSnapshotBuilder(this);
-        m_profiler.vm().heap.collectAllGarbage();
+        m_profiler.vm().heap.collectNow(Sync, CollectionScope::Full);
         m_profiler.setActiveSnapshotBuilder(nullptr);
     }
     m_snapshot->finalize();
index 29bd4b2..289ff9a 100644 (file)
@@ -66,6 +66,10 @@ void IncrementalSweeper::doSweep(MonotonicTime sweepBeginTime)
         return;
     }
 
+    if (m_shouldFreeFastMallocMemoryAfterSweeping) {
+        WTF::releaseFastMallocFreeMemory();
+        m_shouldFreeFastMallocMemoryAfterSweeping = false;
+    }
     cancelTimer();
 }
 
index 48834b1..dc1997e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2017 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,6 +39,7 @@ public:
     JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*);
 
     JS_EXPORT_PRIVATE void startSweeping();
+    void freeFastMallocMemoryAfterSweeping() { m_shouldFreeFastMallocMemoryAfterSweeping = true; }
 
     JS_EXPORT_PRIVATE void doWork() override;
     bool sweepNextBlock();
@@ -49,6 +50,7 @@ private:
     void scheduleTimer();
     
     MarkedAllocator* m_currentAllocator;
+    bool m_shouldFreeFastMallocMemoryAfterSweeping { false };
 };
 
 } // namespace JSC
index 5ee544a..ebac139 100644 (file)
@@ -182,7 +182,7 @@ ALWAYS_INLINE void MarkedAllocator::doTestCollectionsIfNeeded(GCDeferralContext*
             if (deferralContext)
                 deferralContext->m_shouldGC = true;
             else
-                m_heap->collectAllGarbage();
+                m_heap->collectNow(Sync, CollectionScope::Full);
         }
     }
     if (++allocationCount >= Options::slowPathAllocsBetweenGCs())
index 0dee44e..a36c2f0 100644 (file)
@@ -225,7 +225,7 @@ void MarkedSpace::lastChanceToFinalize()
 
 void MarkedSpace::sweep()
 {
-    m_heap->sweeper()->stopSweeping();
+    m_heap->sweeper().stopSweeping();
     forEachAllocator(
         [&] (MarkedAllocator& allocator) -> IterationStatus {
             allocator.sweep();
diff --git a/Source/JavaScriptCore/heap/Synchronousness.cpp b/Source/JavaScriptCore/heap/Synchronousness.cpp
new file mode 100644 (file)
index 0000000..dd8e559
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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 "Synchronousness.h"
+
+#include <wtf/PrintStream.h>
+
+using namespace JSC;
+
+namespace WTF {
+
+void printInternal(PrintStream& out, Synchronousness synchronousness)
+{
+    switch (synchronousness) {
+    case Async:
+        out.print("Async");
+        return;
+    case Sync:
+        out.print("Sync");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
diff --git a/Source/JavaScriptCore/heap/Synchronousness.h b/Source/JavaScriptCore/heap/Synchronousness.h
new file mode 100644 (file)
index 0000000..2c941d9
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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 Synchronousness {
+    Async,
+    Sync
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream& out, JSC::Synchronousness);
+
+} // namespace WTF
+
index b33ae98..7e83df2 100644 (file)
@@ -91,7 +91,7 @@ void InspectorHeapAgent::gc(ErrorString&)
     VM& vm = m_environment.vm();
     JSLockHolder lock(vm);
     sanitizeStackForVM(&vm);
-    vm.heap.collectAllGarbage();
+    vm.heap.collectNow(Sync, CollectionScope::Full);
 }
 
 void InspectorHeapAgent::snapshot(ErrorString&, double* timestamp, String* snapshotData)
index e256450..52b84ff 100644 (file)
@@ -2025,7 +2025,7 @@ EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    exec->heap()->collectAllGarbage();
+    exec->heap()->collectNow(Sync, CollectionScope::Full);
     return JSValue::encode(jsNumber(exec->heap()->sizeAfterLastFullCollection()));
 }
 
@@ -3858,7 +3858,7 @@ int runJSC(CommandLine options, const Func& func)
     if (Options::gcAtEnd()) {
         // We need to hold the API lock to do a GC.
         JSLockHolder locker(&vm);
-        vm.heap.collectAllGarbage();
+        vm.heap.collectNow(Sync, CollectionScope::Full);
     }
 
     if (options.m_dumpSamplingProfilerData) {
index 0c0f771..af7472b 100644 (file)
@@ -118,7 +118,7 @@ void JSDollarVMPrototype::gc(ExecState* exec)
 {
     if (!ensureCurrentThreadOwnsJSLock(exec))
         return;
-    exec->heap()->collectAllGarbage();
+    exec->heap()->collectNow(Sync, CollectionScope::Full);
 }
     
 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
index 7e6f5e6..58a567c 100644 (file)
@@ -151,9 +151,9 @@ void* tryGetFastMemory(VM& vm)
             dataLogLnIf(verbose, "tryGetFastMemory re-using ", RawPointer(memory));
         else if (currentlyAllocatedFastMemories.load(std::memory_order_acquire) >= 1) {
             // No memory was available in the cache, but we know there's at least one currently live. Maybe GC will find a free one.
-            // FIXME collectSync(Full) and custom eager destruction of wasm memories could be better. For now use collectAllGarbage. Also, nothing tells us the current VM is holding onto fast memories. https://bugs.webkit.org/show_bug.cgi?id=170748
+            // FIXME collectSync(Full) and custom eager destruction of wasm memories could be better. For now use collectNow. Also, nothing tells us the current VM is holding onto fast memories. https://bugs.webkit.org/show_bug.cgi?id=170748
             dataLogLnIf(verbose, "tryGetFastMemory waiting on GC and retrying");
-            vm.heap.collectAllGarbage();
+            vm.heap.collectNow(Sync, CollectionScope::Full);
             memory = tryGetCachedFastMemory();
             dataLogLnIf(verbose, "tryGetFastMemory waited on GC and retried ", memory? "successfully" : "unseccessfully");
         }
index f285f55..4a0c4df 100644 (file)
@@ -1,3 +1,19 @@
+2017-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        JSC::Heap should expose a richer API for requesting GCs
+        https://bugs.webkit.org/show_bug.cgi?id=171690
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests because this is just a refactoring.
+        
+        Change some function calls now that some JSC::Heap APIs got renamed.
+
+        * bindings/js/GCController.cpp:
+        (WebCore::collect):
+        (WebCore::GCController::garbageCollectNow):
+        (WebCore::GCController::garbageCollectNowIfNotDoneRecently):
+
 2017-05-04  Mark Lam  <mark.lam@apple.com>
 
         NeverDestroyed<String>(ASCIILiteral(...)) is not thread safe.
index 08b1e1f..5afa36e 100644 (file)
@@ -41,7 +41,7 @@ namespace WebCore {
 static void collect(void*)
 {
     JSLockHolder lock(commonVM());
-    commonVM().heap.collectAllGarbage();
+    commonVM().heap.collectNow(Sync, CollectionScope::Full);
 }
 
 GCController& GCController::singleton()
@@ -83,7 +83,7 @@ void GCController::garbageCollectNow()
 {
     JSLockHolder lock(commonVM());
     if (!commonVM().heap.isCurrentThreadBusy()) {
-        commonVM().heap.collectAllGarbage();
+        commonVM().heap.collectNow(Sync, CollectionScope::Full);
         WTF::releaseFastMallocFreeMemory();
     }
 }
@@ -93,7 +93,7 @@ void GCController::garbageCollectNowIfNotDoneRecently()
 #if USE(CF) || USE(GLIB)
     JSLockHolder lock(commonVM());
     if (!commonVM().heap.isCurrentThreadBusy())
-        commonVM().heap.collectAllGarbageIfNotDoneRecently();
+        commonVM().heap.collectNowFullIfNotDoneRecently(Sync);
 #else
     garbageCollectSoon();
 #endif