GC timer should intelligently choose between EdenCollections and FullCollections
authormhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 22:21:51 +0000 (22:21 +0000)
committermhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 22:21:51 +0000 (22:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=128261

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Most of the GCs while browsing the web are due to the GC timer. Currently the GC timer
always does FullCollections. To reduce the impact of the GC timer on the system this patch
changes Heap so that it has two timers, one for each type of collection. The FullCollection
timer is notified at the end of EdenCollections how much the Heap has grown since the last
FullCollection and when somebody notifies the Heap of abandoned memory (which wouldn't be
detected by an EdenCollection).

* heap/GCActivityCallback.cpp:
(JSC::GCActivityCallback::GCActivityCallback):
(JSC::GCActivityCallback::doWork):
(JSC::FullGCActivityCallback::FullGCActivityCallback):
(JSC::FullGCActivityCallback::doCollection):
(JSC::EdenGCActivityCallback::EdenGCActivityCallback):
(JSC::EdenGCActivityCallback::doCollection):
(JSC::GCActivityCallback::scheduleTimer):
(JSC::GCActivityCallback::cancelTimer):
(JSC::GCActivityCallback::didAllocate):
(JSC::GCActivityCallback::willCollect):
(JSC::GCActivityCallback::cancel):
* heap/GCActivityCallback.h:
(JSC::GCActivityCallback::GCActivityCallback):
(JSC::GCActivityCallback::createFullTimer):
(JSC::GCActivityCallback::createEdenTimer):
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::didAbandon):
(JSC::Heap::willStartCollection):
(JSC::Heap::updateAllocationLimits):
(JSC::Heap::setFullActivityCallback):
(JSC::Heap::setEdenActivityCallback):
(JSC::Heap::fullActivityCallback):
(JSC::Heap::edenActivityCallback):
(JSC::Heap::setGarbageCollectionTimerEnabled):
(JSC::Heap::didAllocate):
* heap/Heap.h:
* heap/HeapTimer.cpp:
(JSC::HeapTimer::timerDidFire):

Source/WebCore:

No new tests.

* platform/ios/WebSafeGCActivityCallbackIOS.h: Update WebSafeGCActivityCallback
appropriately for the introduction of another type of GCActivityCallback.

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

21 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/EdenGCActivityCallback.h [new file with mode: 0644]
Source/JavaScriptCore/heap/FullGCActivityCallback.cpp [new file with mode: 0644]
Source/JavaScriptCore/heap/FullGCActivityCallback.h [new file with mode: 0644]
Source/JavaScriptCore/heap/GCActivityCallback.cpp
Source/JavaScriptCore/heap/GCActivityCallback.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/HeapOperation.h
Source/JavaScriptCore/heap/HeapStatistics.cpp
Source/JavaScriptCore/heap/HeapTimer.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/Options.h
Source/WebCore/ChangeLog
Source/WebCore/platform/ios/WebSafeGCActivityCallbackIOS.h

index 36c9bc6..b827cc3 100644 (file)
@@ -215,6 +215,8 @@ set(JavaScriptCore_SOURCES
     heap/CopiedSpace.cpp
     heap/CopyVisitor.cpp
     heap/DeferGC.cpp
+    heap/EdenGCActivityCallback.cpp
+    heap/FullGCActivityCallback.cpp
     heap/GCActivityCallback.cpp
     heap/GCThread.cpp
     heap/GCThreadSharedData.cpp
index 14ade25..c57bcd0 100644 (file)
@@ -1,3 +1,131 @@
+2014-03-13  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        GC timer should intelligently choose between EdenCollections and FullCollections
+        https://bugs.webkit.org/show_bug.cgi?id=128261
+
+        Reviewed by Geoffrey Garen.
+
+        Most of the GCs while browsing the web are due to the GC timer. Currently the GC timer 
+        always does FullCollections. To reduce the impact of the GC timer on the system this patch
+        changes Heap so that it has two timers, one for each type of collection. The FullCollection
+        timer is notified at the end of EdenCollections how much the Heap has grown since the last 
+        FullCollection and when somebody notifies the Heap of abandoned memory (which wouldn't be 
+        detected by an EdenCollection).
+
+        * heap/GCActivityCallback.cpp:
+        (JSC::GCActivityCallback::GCActivityCallback):
+        (JSC::GCActivityCallback::doWork):
+        (JSC::FullGCActivityCallback::FullGCActivityCallback):
+        (JSC::FullGCActivityCallback::doCollection):
+        (JSC::EdenGCActivityCallback::EdenGCActivityCallback):
+        (JSC::EdenGCActivityCallback::doCollection):
+        (JSC::GCActivityCallback::scheduleTimer):
+        (JSC::GCActivityCallback::cancelTimer):
+        (JSC::GCActivityCallback::didAllocate):
+        (JSC::GCActivityCallback::willCollect):
+        (JSC::GCActivityCallback::cancel):
+        * heap/GCActivityCallback.h:
+        (JSC::GCActivityCallback::GCActivityCallback):
+        (JSC::GCActivityCallback::createFullTimer):
+        (JSC::GCActivityCallback::createEdenTimer):
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::didAbandon):
+        (JSC::Heap::willStartCollection):
+        (JSC::Heap::updateAllocationLimits):
+        (JSC::Heap::setFullActivityCallback):
+        (JSC::Heap::setEdenActivityCallback):
+        (JSC::Heap::fullActivityCallback):
+        (JSC::Heap::edenActivityCallback):
+        (JSC::Heap::setGarbageCollectionTimerEnabled):
+        (JSC::Heap::didAllocate):
+        * heap/Heap.h:
+        * heap/HeapTimer.cpp:
+        (JSC::HeapTimer::timerDidFire):
+
+<<<<<<< .mine
+2014-03-18  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        GC timer should intelligently choose between EdenCollections and FullCollections
+        https://bugs.webkit.org/show_bug.cgi?id=128261
+
+        Reviewed by Geoffrey Garen.
+
+        Most of the GCs while browsing the web are due to the GC timer. Currently the GC timer 
+        always does FullCollections. To reduce the impact of the GC timer on the system this patch
+        changes Heap so that it has two timers, one for each type of collection. The FullCollection
+        timer is notified at the end of EdenCollections how much the Heap has grown since the last 
+        FullCollection and when somebody notifies the Heap of abandoned memory (which usually wouldn't 
+        be detected by an EdenCollection).
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * heap/EdenGCActivityCallback.cpp: Added.
+        (JSC::EdenGCActivityCallback::EdenGCActivityCallback):
+        (JSC::EdenGCActivityCallback::doCollection):
+        (JSC::EdenGCActivityCallback::lastGCLength):
+        (JSC::EdenGCActivityCallback::deathRate):
+        (JSC::EdenGCActivityCallback::gcTimeSlice):
+        * heap/EdenGCActivityCallback.h: Added.
+        (JSC::EdenGCActivityCallback::EdenGCActivityCallback):
+        (JSC::GCActivityCallback::createEdenTimer):
+        * heap/FullGCActivityCallback.cpp: Added.
+        (JSC::FullGCActivityCallback::FullGCActivityCallback):
+        (JSC::FullGCActivityCallback::doCollection):
+        (JSC::FullGCActivityCallback::lastGCLength):
+        (JSC::FullGCActivityCallback::deathRate):
+        (JSC::FullGCActivityCallback::gcTimeSlice):
+        * heap/FullGCActivityCallback.h: Added.
+        (JSC::FullGCActivityCallback::FullGCActivityCallback):
+        (JSC::GCActivityCallback::createFullTimer):
+        * heap/GCActivityCallback.cpp:
+        (JSC::GCActivityCallback::GCActivityCallback):
+        (JSC::GCActivityCallback::doWork):
+        (JSC::GCActivityCallback::scheduleTimer):
+        (JSC::GCActivityCallback::cancelTimer):
+        (JSC::GCActivityCallback::didAllocate):
+        (JSC::GCActivityCallback::willCollect):
+        (JSC::GCActivityCallback::cancel):
+        * heap/GCActivityCallback.h:
+        (JSC::GCActivityCallback::GCActivityCallback):
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::reportAbandonedObjectGraph):
+        (JSC::Heap::didAbandon):
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::collect):
+        (JSC::Heap::willStartCollection):
+        (JSC::Heap::updateAllocationLimits):
+        (JSC::Heap::didFinishCollection):
+        (JSC::Heap::setFullActivityCallback):
+        (JSC::Heap::setEdenActivityCallback):
+        (JSC::Heap::fullActivityCallback):
+        (JSC::Heap::edenActivityCallback):
+        (JSC::Heap::setGarbageCollectionTimerEnabled):
+        (JSC::Heap::didAllocate):
+        (JSC::Heap::shouldDoFullCollection):
+        * heap/Heap.h:
+        (JSC::Heap::lastFullGCLength):
+        (JSC::Heap::lastEdenGCLength):
+        (JSC::Heap::increaseLastFullGCLength):
+        (JSC::Heap::sizeBeforeLastEdenCollection):
+        (JSC::Heap::sizeAfterLastEdenCollection):
+        (JSC::Heap::sizeBeforeLastFullCollection):
+        (JSC::Heap::sizeAfterLastFullCollection):
+        * heap/HeapOperation.h:
+        * heap/HeapStatistics.cpp:
+        (JSC::HeapStatistics::showObjectStatistics):
+        * heap/HeapTimer.cpp:
+        (JSC::HeapTimer::timerDidFire):
+        * jsc.cpp:
+        (functionFullGC):
+        (functionEdenGC):
+        * runtime/Options.h:
+
+=======
 2014-03-19  Filip Pizlo  <fpizlo@apple.com>
 
         REGRESSION(r165459): It broke 109 jsc stress test on ARM Thumb2 and Mac 32 bit
         * runtime/JSStringJoiner.cpp:
         (JSC::JSStringJoiner::join):
 
+>>>>>>> .r165925
 2014-03-18  Filip Pizlo  <fpizlo@apple.com>
 
         Get rid of Flush in SSA
index 2bf0998..fb498a8 100644 (file)
@@ -557,6 +557,10 @@ javascriptcore_sources += \
     Source/JavaScriptCore/heap/DeferGC.cpp \
        Source/JavaScriptCore/heap/DeferGC.h \
     Source/JavaScriptCore/heap/DelayedReleaseScope.h \
+       Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp \
+       Source/JavaScriptCore/heap/EdenGCActivityCallback.h \
+       Source/JavaScriptCore/heap/FullGCActivityCallback.cpp \
+       Source/JavaScriptCore/heap/FullGCActivityCallback.h \
        Source/JavaScriptCore/heap/GCActivityCallback.cpp \
        Source/JavaScriptCore/heap/GCActivityCallback.h \
        Source/JavaScriptCore/heap/GCSegmentedArray.h \
index 4ec62ca..b296c28 100644 (file)
     <ClCompile Include="..\heap\CopiedSpace.cpp" />
     <ClCompile Include="..\heap\CopyVisitor.cpp" />
     <ClCompile Include="..\heap\DeferGC.cpp" />
+    <ClCompile Include="..\heap\EdenGCActivityCallback.cpp" />
+    <ClCompile Include="..\heap\FullGCActivityCallback.cpp" />
     <ClCompile Include="..\heap\GCActivityCallback.cpp" />
     <ClCompile Include="..\heap\GCThread.cpp" />
     <ClCompile Include="..\heap\GCThreadSharedData.cpp" />
     <ClInclude Include="..\heap\CopyWriteBarrier.h" />
     <ClInclude Include="..\heap\DeferGC.h" />
     <ClInclude Include="..\heap\DelayedReleaseScope.h" />
+    <ClInclude Include="..\heap\EdenGCActivityCallback.h" />
+    <ClInclude Include="..\heap\FullGCActivityCallback.h" />
     <ClInclude Include="..\heap\GCActivityCallback.h" />
     <ClInclude Include="..\heap\GCSegmentedArray.h" />
     <ClInclude Include="..\heap\GCSegmentedArrayInlines.h" />
index fe99a63..3a8168e 100644 (file)
     <ClCompile Include="..\heap\CopyVisitor.cpp">
       <Filter>heap</Filter>
     </ClCompile>
+    <ClCompile Include="..\heap\EdenGCActivityCallback.cpp">
+      <Filter>heap</Filter>
+    </ClCompile>
+    <ClCompile Include="..\heap\FullGCActivityCallback.cpp">
+      <Filter>heap</Filter>
+    </ClCompile>
     <ClCompile Include="..\heap\GCActivityCallback.cpp">
       <Filter>heap</Filter>
     </ClCompile>
     <ClInclude Include="..\heap\DeferGC.h">
       <Filter>heap</Filter>
     </ClInclude>
+    <ClInclude Include="..\heap\EdenGCActivityCallback.h">
+      <Filter>heap</Filter>
+    </ClInclude>
+    <ClInclude Include="..\heap\FullGCActivityCallback.h">
+      <Filter>heap</Filter>
+    </ClInclude>
     <ClInclude Include="..\heap\GCActivityCallback.h">
       <Filter>heap</Filter>
     </ClInclude>
index 4e81df4..8bcb965 100644 (file)
                2A68295B1875F80500B6C3E2 /* CopyWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.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, ); }; };
+               2A83638918D7D0FE0000EBCC /* FullGCActivityCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A83638718D7D0FE0000EBCC /* FullGCActivityCallback.cpp */; };
+               2A83638A18D7D0FE0000EBCC /* FullGCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A83638818D7D0FE0000EBCC /* FullGCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAAA31018BD49D100394CC8 /* StructureIDBlob.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AACE63A18CA5A0300ED0191 /* GCActivityCallback.cpp */; };
                2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AACE63B18CA5A0300ED0191 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyWriteBarrier.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>"; };
+               2A83638718D7D0FE0000EBCC /* FullGCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FullGCActivityCallback.cpp; sourceTree = "<group>"; };
+               2A83638818D7D0FE0000EBCC /* FullGCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullGCActivityCallback.h; sourceTree = "<group>"; };
                2AAAA31018BD49D100394CC8 /* StructureIDBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDBlob.h; sourceTree = "<group>"; };
                2AACE63A18CA5A0300ED0191 /* GCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallback.cpp; sourceTree = "<group>"; };
                2AACE63B18CA5A0300ED0191 /* GCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCActivityCallback.h; sourceTree = "<group>"; };
                                2A4EC90A1860D6C20094F782 /* WriteBarrierBuffer.h */,
                                0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */,
                                0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */,
+                               2A83638318D7D0EE0000EBCC /* EdenGCActivityCallback.cpp */,
+                               2A83638418D7D0EE0000EBCC /* EdenGCActivityCallback.h */,
+                               2A83638718D7D0FE0000EBCC /* FullGCActivityCallback.cpp */,
+                               2A83638818D7D0FE0000EBCC /* FullGCActivityCallback.h */,
                        );
                        path = heap;
                        sourceTree = "<group>";
                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
                                A584032018BFFBE1005A0811 /* InspectorAgent.h in Headers */,
                                2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */,
+                               2A83638618D7D0EE0000EBCC /* EdenGCActivityCallback.h in Headers */,
+                               2A83638A18D7D0FE0000EBCC /* FullGCActivityCallback.h in Headers */,
                                2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */,
                                A54E8EB118BFFBBE00556D28 /* GCSegmentedArrayInlines.h in Headers */,
                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
                                147F39C2107EC37600427A48 /* Completion.cpp in Sources */,
                                146B16D812EB5B59001BEC1B /* ConservativeRoots.cpp in Sources */,
                                A5FD0079189B051000633231 /* ConsoleMessage.cpp in Sources */,
+                               2A83638518D7D0EE0000EBCC /* EdenGCActivityCallback.cpp in Sources */,
                                1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
                                A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
                                C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
                                0F919D10157F3329004A4E7D /* JSSegmentedVariableObject.cpp in Sources */,
                                A7299D9D17D12837005F5FF9 /* JSSet.cpp in Sources */,
                                A790DD6F182F499700588807 /* JSSetIterator.cpp in Sources */,
+                               2A83638918D7D0FE0000EBCC /* FullGCActivityCallback.cpp in Sources */,
                                1428083A107EC0750013E7B2 /* JSStack.cpp in Sources */,
                                147F39D5107EC37600427A48 /* JSString.cpp in Sources */,
                                2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */,
diff --git a/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp b/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp
new file mode 100644 (file)
index 0000000..500ad55
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 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 "EdenGCActivityCallback.h"
+
+#include "VM.h"
+
+namespace JSC {
+
+#if USE(CF) || PLATFORM(EFL)
+
+EdenGCActivityCallback::EdenGCActivityCallback(Heap* heap)
+    : GCActivityCallback(heap)
+{
+}
+
+void EdenGCActivityCallback::doCollection()
+{
+    m_vm->heap.collect(EdenCollection);
+}
+
+double EdenGCActivityCallback::lastGCLength()
+{
+    return m_vm->heap.lastEdenGCLength();
+}
+
+double EdenGCActivityCallback::deathRate()
+{
+    Heap* heap = &m_vm->heap;
+    size_t sizeBefore = heap->sizeBeforeLastEdenCollection();
+    size_t sizeAfter = heap->sizeAfterLastEdenCollection();
+    if (!sizeBefore)
+        return 1.0;
+    return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
+}
+
+double EdenGCActivityCallback::gcTimeSlice(size_t bytes)
+{
+    return std::min((static_cast<double>(bytes) / MB) * Options::percentCPUPerMBForEdenTimer(), Options::collectionTimerMaxPercentCPU());
+}
+
+#else
+
+EdenGCActivityCallback::EdenGCActivityCallback(Heap* heap)
+    : GCActivityCallback(heap->vm())
+{
+}
+
+void EdenGCActivityCallback::doCollection()
+{
+}
+
+double EdenGCActivityCallback::lastGCLength()
+{
+    return 0;
+}
+
+double EdenGCActivityCallback::deathRate()
+{
+    return 0;
+}
+
+double EdenGCActivityCallback::gcTimeSlice(size_t)
+{
+    return 0;
+}
+
+#endif // USE(CF) || PLATFORM(EFL)
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/EdenGCActivityCallback.h b/Source/JavaScriptCore/heap/EdenGCActivityCallback.h
new file mode 100644 (file)
index 0000000..e04d33e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef EdenGCActivityCallback_h
+#define EdenGCActivityCallback_h
+
+#include "GCActivityCallback.h"
+
+namespace JSC {
+
+class EdenGCActivityCallback : public GCActivityCallback {
+public:
+    EdenGCActivityCallback(Heap*);
+
+    virtual void doCollection() override;
+
+protected:
+#if USE(CF)
+    EdenGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+        : GCActivityCallback(heap, runLoop)
+    {
+    }
+#endif
+
+    virtual double lastGCLength() override;
+    virtual double gcTimeSlice(size_t bytes) override;
+    virtual double deathRate() override;
+};
+
+inline PassRefPtr<GCActivityCallback> GCActivityCallback::createEdenTimer(Heap* heap)
+{
+    return s_shouldCreateGCTimer ? adoptRef(new EdenGCActivityCallback(heap)) : nullptr;
+}
+
+} // namespace JSC
+
+#endif // EdenGCActivityCallback_h
diff --git a/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp b/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp
new file mode 100644 (file)
index 0000000..76c678d
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 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 "FullGCActivityCallback.h"
+
+#include "VM.h"
+
+namespace JSC {
+
+#if USE(CF) || PLATFORM(EFL)
+
+#if !PLATFORM(IOS)
+const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
+#endif
+
+FullGCActivityCallback::FullGCActivityCallback(Heap* heap)
+    : GCActivityCallback(heap)
+{
+}
+
+void FullGCActivityCallback::doCollection()
+{
+    Heap* heap = &m_vm->heap;
+
+#if !PLATFORM(IOS)
+    double startTime = WTF::monotonicallyIncreasingTime();
+    if (heap->isPagedOut(startTime + pagingTimeOut)) {
+        cancel();
+        heap->increaseLastFullGCLength(pagingTimeOut);
+        return;
+    }
+#endif
+
+    heap->collect(FullCollection);
+}
+
+double FullGCActivityCallback::lastGCLength()
+{
+    return m_vm->heap.lastFullGCLength();
+}
+
+double FullGCActivityCallback::deathRate()
+{
+    Heap* heap = &m_vm->heap;
+    size_t sizeBefore = heap->sizeBeforeLastFullCollection();
+    size_t sizeAfter = heap->sizeAfterLastFullCollection();
+    if (!sizeBefore)
+        return 1.0;
+    return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
+}
+
+double FullGCActivityCallback::gcTimeSlice(size_t bytes)
+{
+    return std::min((static_cast<double>(bytes) / MB) * Options::percentCPUPerMBForFullTimer(), Options::collectionTimerMaxPercentCPU());
+}
+
+#else
+
+FullGCActivityCallback::FullGCActivityCallback(Heap* heap)
+    : GCActivityCallback(heap)
+{
+}
+
+void FullGCActivityCallback::doCollection()
+{
+}
+
+double FullGCActivityCallback::lastGCLength()
+{
+    return 0;
+}
+
+double FullGCActivityCallback::deathRate()
+{
+    return 0;
+}
+
+double FullGCActivityCallback::gcTimeSlice(size_t)
+{
+    return 0;
+}
+
+#endif // USE(CF) || PLATFORM(EFL)
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/heap/FullGCActivityCallback.h b/Source/JavaScriptCore/heap/FullGCActivityCallback.h
new file mode 100644 (file)
index 0000000..39ec5d4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef FullGCActivityCallback_h
+#define FullGCActivityCallback_h
+
+#include "GCActivityCallback.h"
+
+namespace JSC {
+
+class FullGCActivityCallback : public GCActivityCallback {
+public:
+    FullGCActivityCallback(Heap*);
+
+    virtual void doCollection() override;
+
+protected:
+#if USE(CF)
+    FullGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+        : GCActivityCallback(heap, runLoop)
+    {
+    }
+#endif
+
+    virtual double lastGCLength() override;
+    virtual double gcTimeSlice(size_t bytes) override;
+    virtual double deathRate() override;
+};
+
+inline PassRefPtr<GCActivityCallback> GCActivityCallback::createFullTimer(Heap* heap)
+{
+    return s_shouldCreateGCTimer ? adoptRef(new FullGCActivityCallback(heap)) : nullptr;
+}
+
+} // namespace JSC
+
+#endif // FullGCActivityCallback_h
index f4edd6b..d324b37 100644 (file)
@@ -47,39 +47,26 @@ bool GCActivityCallback::s_shouldCreateGCTimer = true;
 
 #if USE(CF) || PLATFORM(EFL)
 
-const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
-const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
 const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
 
-#if !PLATFORM(IOS)
-const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
-#endif
-
-#if !USE(CF)
-const double hour = 60 * 60;
-#endif
-
 #if USE(CF)
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+GCActivityCallback::GCActivityCallback(Heap* heap)
     : GCActivityCallback(heap->vm(), CFRunLoopGetCurrent())
-    , m_delay(s_decade)
 {
 }
 
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+GCActivityCallback::GCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
     : GCActivityCallback(heap->vm(), runLoop)
-    , m_delay(s_decade)
 {
 }
 #elif PLATFORM(EFL)
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+GCActivityCallback::GCActivityCallback(Heap* heap)
     : GCActivityCallback(heap->vm(), WTF::isMainThread())
-    , m_delay(hour)
 {
 }
 #endif
 
-void DefaultGCActivityCallback::doWork()
+void GCActivityCallback::doWork()
 {
     Heap* heap = &m_vm->heap;
     if (!isEnabled())
@@ -91,20 +78,11 @@ void DefaultGCActivityCallback::doWork()
         return;
     }
 
-#if !PLATFORM(IOS)
-    double startTime = WTF::monotonicallyIncreasingTime();
-    if (heap->isPagedOut(startTime + pagingTimeOut)) {
-        heap->activityCallback()->cancel();
-        heap->increaseLastGCLength(pagingTimeOut);
-        return;
-    }
-#endif
-    heap->gcTimerDidFire();
-    heap->collect();
+    doCollection();
 }
-    
+
 #if USE(CF)
-void DefaultGCActivityCallback::scheduleTimer(double newDelay)
+void GCActivityCallback::scheduleTimer(double newDelay)
 {
     if (newDelay * timerSlop > m_delay)
         return;
@@ -113,13 +91,13 @@ void DefaultGCActivityCallback::scheduleTimer(double newDelay)
     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta);
 }
 
-void DefaultGCActivityCallback::cancelTimer()
+void GCActivityCallback::cancelTimer()
 {
     m_delay = s_decade;
     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
 }
 #elif PLATFORM(EFL)
-void DefaultGCActivityCallback::scheduleTimer(double newDelay)
+void GCActivityCallback::scheduleTimer(double newDelay)
 {
     if (newDelay * timerSlop > m_delay)
         return;
@@ -131,14 +109,14 @@ void DefaultGCActivityCallback::scheduleTimer(double newDelay)
     m_timer = add(newDelay, this);
 }
 
-void DefaultGCActivityCallback::cancelTimer()
+void GCActivityCallback::cancelTimer()
 {
-    m_delay = hour;
+    m_delay = s_hour;
     stop();
 }
 #endif
 
-void DefaultGCActivityCallback::didAllocate(size_t bytes)
+void GCActivityCallback::didAllocate(size_t bytes)
 {
 #if PLATFORM(EFL)
     if (!isEnabled())
@@ -151,42 +129,41 @@ void DefaultGCActivityCallback::didAllocate(size_t bytes)
     // We pretend it's one byte so that we don't ignore this allocation entirely.
     if (!bytes)
         bytes = 1;
-    Heap* heap = static_cast<Heap*>(&m_vm->heap);
-    double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
-    double newDelay = heap->lastGCLength() / gcTimeSlice;
+    double bytesExpectedToReclaim = static_cast<double>(bytes) * deathRate();
+    double newDelay = lastGCLength() / gcTimeSlice(bytesExpectedToReclaim);
     scheduleTimer(newDelay);
 }
 
-void DefaultGCActivityCallback::willCollect()
+void GCActivityCallback::willCollect()
 {
     cancelTimer();
 }
 
-void DefaultGCActivityCallback::cancel()
+void GCActivityCallback::cancel()
 {
     cancelTimer();
 }
 
 #else
 
-DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+GCActivityCallback::GCActivityCallback(Heap* heap)
     : GCActivityCallback(heap->vm())
 {
 }
 
-void DefaultGCActivityCallback::doWork()
+void GCActivityCallback::doWork()
 {
 }
 
-void DefaultGCActivityCallback::didAllocate(size_t)
+void GCActivityCallback::didAllocate(size_t)
 {
 }
 
-void DefaultGCActivityCallback::willCollect()
+void GCActivityCallback::willCollect()
 {
 }
 
-void DefaultGCActivityCallback::cancel()
+void GCActivityCallback::cancel()
 {
 }
 
index 59dea91..339118b 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "HeapTimer.h"
 #include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
 
 #if USE(CF)
 #include <CoreFoundation/CoreFoundation.h>
@@ -41,28 +41,44 @@ namespace JSC {
 
 class Heap;
 
-class GCActivityCallback : public HeapTimer {
+class GCActivityCallback : public HeapTimer, public ThreadSafeRefCounted<GCActivityCallback> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    virtual void didAllocate(size_t) { }
-    virtual void willCollect() { }
-    virtual void cancel() { }
+    static PassRefPtr<GCActivityCallback> createFullTimer(Heap*);
+    static PassRefPtr<GCActivityCallback> createEdenTimer(Heap*);
+
+    GCActivityCallback(Heap*);
+
+    virtual void doWork() override;
+
+    virtual void doCollection() = 0;
+
+    virtual void didAllocate(size_t);
+    virtual void willCollect();
+    virtual void cancel();
     bool isEnabled() const { return m_enabled; }
     void setEnabled(bool enabled) { m_enabled = enabled; }
 
     static bool s_shouldCreateGCTimer;
 
 protected:
+    virtual double lastGCLength() = 0;
+    virtual double gcTimeSlice(size_t bytes) = 0;
+    virtual double deathRate() = 0;
+
 #if USE(CF)
     GCActivityCallback(VM* vm, CFRunLoopRef runLoop)
         : HeapTimer(vm, runLoop)
         , m_enabled(true)
+        , m_delay(s_decade)
     {
     }
 #elif PLATFORM(EFL)
+    static constexpr double s_hour = 3600;
     GCActivityCallback(VM* vm, bool flag)
         : HeapTimer(vm)
         , m_enabled(flag)
+        , m_delay(s_hour)
     {
     }
 #else
@@ -74,23 +90,10 @@ protected:
 #endif
 
     bool m_enabled;
-};
-
-class DefaultGCActivityCallback : public GCActivityCallback {
-public:
-    static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
-
-    DefaultGCActivityCallback(Heap*);
-
-    JS_EXPORT_PRIVATE virtual void didAllocate(size_t) override;
-    JS_EXPORT_PRIVATE virtual void willCollect() override;
-    JS_EXPORT_PRIVATE virtual void cancel() override;
-
-    JS_EXPORT_PRIVATE virtual void doWork() override;
 
 #if USE(CF)
 protected:
-    JS_EXPORT_PRIVATE DefaultGCActivityCallback(Heap*, CFRunLoopRef);
+    JS_EXPORT_PRIVATE GCActivityCallback(Heap*, CFRunLoopRef);
 #endif
 #if USE(CF) || PLATFORM(EFL)
 protected:
@@ -102,11 +105,6 @@ private:
 #endif
 };
 
-inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
-{
-    return GCActivityCallback::s_shouldCreateGCTimer ? adoptPtr(new DefaultGCActivityCallback(heap)) : nullptr;
-}
-
-}
+} // namespace JSC
 
 #endif
index cce7f6a..0b25c4f 100644 (file)
@@ -28,6 +28,8 @@
 #include "CopyVisitorInlines.h"
 #include "DFGWorklist.h"
 #include "DelayedReleaseScope.h"
+#include "EdenGCActivityCallback.h"
+#include "FullGCActivityCallback.h"
 #include "GCActivityCallback.h"
 #include "GCIncomingRefCountedSetInlines.h"
 #include "HeapIterationScope.h"
@@ -253,8 +255,12 @@ Heap::Heap(VM* vm, HeapType heapType)
     , m_ramSize(ramSize())
     , m_minBytesPerCycle(minHeapSize(m_heapType, m_ramSize))
     , m_sizeAfterLastCollect(0)
+    , m_sizeAfterLastFullCollect(0)
+    , m_sizeBeforeLastFullCollect(0)
+    , m_sizeAfterLastEdenCollect(0)
+    , m_sizeBeforeLastEdenCollect(0)
     , m_bytesAllocatedThisCycle(0)
-    , m_bytesAbandonedThisCycle(0)
+    , m_bytesAbandonedSinceLastFullCollect(0)
     , m_maxEdenSize(m_minBytesPerCycle)
     , m_maxHeapSize(m_minBytesPerCycle)
     , m_shouldDoFullCollection(false)
@@ -274,9 +280,15 @@ Heap::Heap(VM* vm, HeapType heapType)
     , m_isSafeToCollect(false)
     , m_writeBarrierBuffer(256)
     , m_vm(vm)
-    , m_lastGCLength(0)
+    , m_lastFullGCLength(0)
+    , m_lastEdenGCLength(0)
     , m_lastCodeDiscardTime(WTF::monotonicallyIncreasingTime())
-    , m_activityCallback(DefaultGCActivityCallback::create(this))
+    , m_fullActivityCallback(GCActivityCallback::createFullTimer(this))
+#if ENABLE(GGC)
+    , m_edenActivityCallback(GCActivityCallback::createEdenTimer(this))
+#else
+    , m_edenActivityCallback(m_fullActivityCallback)
+#endif
     , m_sweeper(IncrementalSweeper::create(this))
     , m_deferralDepth(0)
 {
@@ -323,7 +335,7 @@ void Heap::reportAbandonedObjectGraph()
 {
     // Our clients don't know exactly how much memory they
     // are abandoning so we just guess for them.
-    double abandonedBytes = 0.10 * m_sizeAfterLastCollect;
+    double abandonedBytes = 0.1 * m_sizeAfterLastCollect;
 
     // We want to accelerate the next collection. Because memory has just 
     // been abandoned, the next collection has the potential to 
@@ -334,9 +346,11 @@ void Heap::reportAbandonedObjectGraph()
 
 void Heap::didAbandon(size_t bytes)
 {
-    if (m_activityCallback)
-        m_activityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedThisCycle);
-    m_bytesAbandonedThisCycle += bytes;
+    if (m_fullActivityCallback) {
+        m_fullActivityCallback->didAllocate(
+            m_sizeAfterLastCollect - m_sizeAfterLastFullCollect + m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
+    }
+    m_bytesAbandonedSinceLastFullCollect += bytes;
 }
 
 void Heap::protect(JSValue k)
@@ -846,8 +860,7 @@ void Heap::collectAllGarbage()
     if (!m_isSafeToCollect)
         return;
 
-    m_shouldDoFullCollection = true;
-    collect();
+    collect(FullCollection);
 
     SamplingRegion samplingRegion("Garbage Collection: Sweeping");
     DelayedReleaseScope delayedReleaseScope(m_objectSpace);
@@ -857,7 +870,7 @@ void Heap::collectAllGarbage()
 
 static double minute = 60.0;
 
-void Heap::collect()
+void Heap::collect(HeapOperation collectionType)
 {
 #if ENABLE(ALLOCATION_LOGGING)
     dataLogF("JSC GC starting collection.\n");
@@ -880,7 +893,7 @@ void Heap::collect()
     RELEASE_ASSERT(m_operationInProgress == NoOperation);
 
     suspendCompilerThreads();
-    willStartCollection();
+    willStartCollection(collectionType);
 
     double gcStartTime = WTF::monotonicallyIncreasingTime();
 
@@ -927,10 +940,10 @@ void Heap::suspendCompilerThreads()
 #endif
 }
 
-void Heap::willStartCollection()
+void Heap::willStartCollection(HeapOperation collectionType)
 {
     GCPHASE(StartingCollection);
-    if (shouldDoFullCollection()) {
+    if (shouldDoFullCollection(collectionType)) {
         m_operationInProgress = FullCollection;
         m_slotVisitor.clearMarkStack();
         m_shouldDoFullCollection = false;
@@ -941,11 +954,19 @@ void Heap::willStartCollection()
         if (Options::logGC())
             dataLog("EdenCollection, ");
     }
-    if (m_operationInProgress == FullCollection)
+    if (m_operationInProgress == FullCollection) {
+        m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
         m_extraMemoryUsage = 0;
 
-    if (m_activityCallback)
-        m_activityCallback->willCollect();
+        if (m_fullActivityCallback)
+            m_fullActivityCallback->willCollect();
+    } else {
+        ASSERT(m_operationInProgress == EdenCollection);
+        m_sizeBeforeLastEdenCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle;
+    }
+
+    if (m_edenActivityCallback)
+        m_edenActivityCallback->willCollect();
 }
 
 void Heap::deleteOldCode(double gcStartTime)
@@ -1043,20 +1064,26 @@ void Heap::updateAllocationLimits()
         // fixed minimum.
         m_maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize));
         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
+        m_sizeAfterLastFullCollect = currentHeapSize;
+        m_bytesAbandonedSinceLastFullCollect = 0;
     } else {
         ASSERT(currentHeapSize >= m_sizeAfterLastCollect);
         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
+        m_sizeAfterLastEdenCollect = currentHeapSize;
         double edenToOldGenerationRatio = (double)m_maxEdenSize / (double)m_maxHeapSize;
         double minEdenToOldGenerationRatio = 1.0 / 3.0;
         if (edenToOldGenerationRatio < minEdenToOldGenerationRatio)
             m_shouldDoFullCollection = true;
         m_maxHeapSize += currentHeapSize - m_sizeAfterLastCollect;
         m_maxEdenSize = m_maxHeapSize - currentHeapSize;
+        if (m_fullActivityCallback) {
+            ASSERT(currentHeapSize >= m_sizeAfterLastFullCollect);
+            m_fullActivityCallback->didAllocate(currentHeapSize - m_sizeAfterLastFullCollect);
+        }
     }
 
     m_sizeAfterLastCollect = currentHeapSize;
     m_bytesAllocatedThisCycle = 0;
-    m_bytesAbandonedThisCycle = 0;
 
     if (Options::logGC())
         dataLog(currentHeapSize / 1024, " kb, ");
@@ -1066,7 +1093,10 @@ void Heap::didFinishCollection(double gcStartTime)
 {
     GCPHASE(FinishingCollection);
     double gcEndTime = WTF::monotonicallyIncreasingTime();
-    m_lastGCLength = gcEndTime - gcStartTime;
+    if (m_operationInProgress == FullCollection)
+        m_lastFullGCLength = gcEndTime - gcStartTime;
+    else
+        m_lastEdenGCLength = gcEndTime - gcStartTime;
 
     if (Options::recordGCPauseTimes())
         HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime);
@@ -1102,14 +1132,24 @@ void Heap::markDeadObjects()
     m_objectSpace.forEachDeadCell<MarkObject>(iterationScope);
 }
 
-void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
+void Heap::setFullActivityCallback(PassRefPtr<FullGCActivityCallback> activityCallback)
 {
-    m_activityCallback = activityCallback;
+    m_fullActivityCallback = activityCallback;
 }
 
-GCActivityCallback* Heap::activityCallback()
+void Heap::setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback> activityCallback)
 {
-    return m_activityCallback.get();
+    m_edenActivityCallback = activityCallback;
+}
+
+GCActivityCallback* Heap::fullActivityCallback()
+{
+    return m_fullActivityCallback.get();
+}
+
+GCActivityCallback* Heap::edenActivityCallback()
+{
+    return m_edenActivityCallback.get();
 }
 
 void Heap::setIncrementalSweeper(PassOwnPtr<IncrementalSweeper> sweeper)
@@ -1124,14 +1164,16 @@ IncrementalSweeper* Heap::sweeper()
 
 void Heap::setGarbageCollectionTimerEnabled(bool enable)
 {
-    if (m_activityCallback)
-        m_activityCallback->setEnabled(enable);
+    if (m_fullActivityCallback)
+        m_fullActivityCallback->setEnabled(enable);
+    if (m_edenActivityCallback)
+        m_edenActivityCallback->setEnabled(enable);
 }
 
 void Heap::didAllocate(size_t bytes)
 {
-    if (m_activityCallback)
-        m_activityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedThisCycle);
+    if (m_edenActivityCallback)
+        m_edenActivityCallback->didAllocate(m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect);
     m_bytesAllocatedThisCycle += bytes;
 }
 
@@ -1214,11 +1256,27 @@ void Heap::flushWriteBarrierBuffer(JSCell* cell)
 #endif
 }
 
-bool Heap::shouldDoFullCollection() const
+bool Heap::shouldDoFullCollection(HeapOperation requestedCollectionType) const
 {
 #if ENABLE(GGC)
-    return Options::alwaysDoFullCollection() || m_shouldDoFullCollection;
+    if (Options::alwaysDoFullCollection())
+        return true;
+
+    switch (requestedCollectionType) {
+    case EdenCollection:
+        return false;
+    case FullCollection:
+        return true;
+    case AnyCollection:
+        return m_shouldDoFullCollection;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return false;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return false;
 #else
+    UNUSED_PARAM(requestedCollectionType);
     return true;
 #endif
 }
index 4e25e82..e8a9a03 100644 (file)
@@ -52,6 +52,8 @@ namespace JSC {
     class CopiedSpace;
     class CodeBlock;
     class ExecutableBase;
+    class EdenGCActivityCallback;
+    class FullGCActivityCallback;
     class GCActivityCallback;
     class GCAwareJITStubRoutine;
     class GlobalCodeBlock;
@@ -118,8 +120,10 @@ namespace JSC {
         MarkedSpace& objectSpace() { return m_objectSpace; }
         MachineThreads& machineThreads() { return m_machineThreads; }
 
-        JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
-        JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>);
+        JS_EXPORT_PRIVATE GCActivityCallback* fullActivityCallback();
+        JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
+        JS_EXPORT_PRIVATE void setFullActivityCallback(PassRefPtr<FullGCActivityCallback>);
+        JS_EXPORT_PRIVATE void setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback>);
         JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
 
         JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
@@ -148,9 +152,7 @@ namespace JSC {
 
         JS_EXPORT_PRIVATE void collectAllGarbage();
         bool shouldCollect();
-        void gcTimerDidFire() { m_shouldDoFullCollection = true; }
-        void setShouldDoFullCollection(bool shouldDoFullCollection) { m_shouldDoFullCollection = shouldDoFullCollection; }
-        JS_EXPORT_PRIVATE void collect();
+        JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
         bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
 
         void reportExtraMemoryCost(size_t cost);
@@ -186,8 +188,14 @@ namespace JSC {
         void didFinishIterating();
         void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
 
-        double lastGCLength() { return m_lastGCLength; }
-        void increaseLastGCLength(double amount) { m_lastGCLength += amount; }
+        double lastFullGCLength() const { return m_lastFullGCLength; }
+        double lastEdenGCLength() const { return m_lastEdenGCLength; }
+        void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
+
+        size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
+        size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
+        size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
+        size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
 
         JS_EXPORT_PRIVATE void deleteAllCompiledCode();
         void deleteAllUnlinkedFunctionCode();
@@ -252,7 +260,7 @@ namespace JSC {
         JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
 
         void suspendCompilerThreads();
-        void willStartCollection();
+        void willStartCollection(HeapOperation collectionType);
         void deleteOldCode(double gcStartTime);
         void flushOldStructureIDTables();
         void flushWriteBarrierBuffer();
@@ -296,7 +304,7 @@ namespace JSC {
         void zombifyDeadObjects();
         void markDeadObjects();
 
-        bool shouldDoFullCollection() const;
+        bool shouldDoFullCollection(HeapOperation requestedCollectionType) const;
         size_t sizeAfterCollect();
 
         JSStack& stack();
@@ -309,9 +317,13 @@ namespace JSC {
         const size_t m_ramSize;
         const size_t m_minBytesPerCycle;
         size_t m_sizeAfterLastCollect;
+        size_t m_sizeAfterLastFullCollect;
+        size_t m_sizeBeforeLastFullCollect;
+        size_t m_sizeAfterLastEdenCollect;
+        size_t m_sizeBeforeLastEdenCollect;
 
         size_t m_bytesAllocatedThisCycle;
-        size_t m_bytesAbandonedThisCycle;
+        size_t m_bytesAbandonedSinceLastFullCollect;
         size_t m_maxEdenSize;
         size_t m_maxHeapSize;
         bool m_shouldDoFullCollection;
@@ -349,12 +361,14 @@ namespace JSC {
         WriteBarrierBuffer m_writeBarrierBuffer;
 
         VM* m_vm;
-        double m_lastGCLength;
+        double m_lastFullGCLength;
+        double m_lastEdenGCLength;
         double m_lastCodeDiscardTime;
 
         DoublyLinkedList<ExecutableBase> m_compiledCode;
         
-        OwnPtr<GCActivityCallback> m_activityCallback;
+        RefPtr<GCActivityCallback> m_fullActivityCallback;
+        RefPtr<GCActivityCallback> m_edenActivityCallback;
         OwnPtr<IncrementalSweeper> m_sweeper;
         Vector<MarkedBlock*> m_blockSnapshot;
         
index 769127e..272e3c0 100644 (file)
@@ -28,7 +28,7 @@
 
 namespace JSC {
 
-enum HeapOperation { NoOperation, Allocation, FullCollection, EdenCollection };
+enum HeapOperation { NoOperation, Allocation, FullCollection, EdenCollection, AnyCollection };
 
 } // namespace JSC
 
index bcedef5..ebf3de2 100644 (file)
@@ -233,7 +233,7 @@ void HeapStatistics::showObjectStatistics(Heap* heap)
     dataLogF("\n=== Heap Statistics: ===\n");
     dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB));
     dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB));
-    dataLogF("pause time: %lfms\n\n", heap->m_lastGCLength);
+    dataLogF("pause time: %lfms\n\n", heap->m_lastFullGCLength);
 
     StorageStatistics storageStatistics;
     {
index e93e31d..9660d66 100644 (file)
@@ -85,8 +85,10 @@ void HeapTimer::timerDidFire(CFRunLoopTimerRef timer, void* context)
     }
 
     HeapTimer* heapTimer = 0;
-    if (vm->heap.activityCallback() && vm->heap.activityCallback()->m_timer.get() == timer)
-        heapTimer = vm->heap.activityCallback();
+    if (vm->heap.fullActivityCallback() && vm->heap.fullActivityCallback()->m_timer.get() == timer)
+        heapTimer = vm->heap.fullActivityCallback();
+    else if (vm->heap.edenActivityCallback() && vm->heap.edenActivityCallback()->m_timer.get() == timer)
+        heapTimer = vm->heap.edenActivityCallback();
     else if (vm->heap.sweeper()->m_timer.get() == timer)
         heapTimer = vm->heap.sweeper();
     else
index d091f13..4eadf4f 100644 (file)
@@ -577,18 +577,14 @@ EncodedJSValue JSC_HOST_CALL functionGCAndSweep(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    Heap* heap = exec->heap();
-    heap->setShouldDoFullCollection(true);
-    exec->heap()->collect();
+    exec->heap()->collect(FullCollection);
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
 {
     JSLockHolder lock(exec);
-    Heap* heap = exec->heap();
-    heap->setShouldDoFullCollection(false);
-    heap->collect();
+    exec->heap()->collect(EdenCollection);
     return JSValue::encode(jsUndefined());
 }
 
index 8974455..5f8caf4 100644 (file)
@@ -242,6 +242,10 @@ typedef OptionRange optionRange;
     v(double, minCopiedBlockUtilization, 0.9) \
     v(double, minMarkedBlockUtilization, 0.9) \
     \
+    v(double, percentCPUPerMBForFullTimer, 0.0003125) \
+    v(double, percentCPUPerMBForEdenTimer, 0.0025) \
+    v(double, collectionTimerMaxPercentCPU, 0.05) \
+    \
     v(bool, forceWeakRandomSeed, false) \
     v(unsigned, forcedWeakRandomSeed, 0) \
     \
index c89629d..54b1f98 100644 (file)
@@ -1,3 +1,30 @@
+2014-03-13  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        GC timer should intelligently choose between EdenCollections and FullCollections
+        https://bugs.webkit.org/show_bug.cgi?id=128261
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests.
+
+        * platform/ios/WebSafeGCActivityCallbackIOS.h: Update WebSafeGCActivityCallback
+        appropriately for the introduction of another type of GCActivityCallback.
+
+<<<<<<< .mine
+2014-03-18  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        GC timer should intelligently choose between EdenCollections and FullCollections
+        https://bugs.webkit.org/show_bug.cgi?id=128261
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests.
+
+        Updated WebSafeGCActivityCallbacks for both Eden and Full timers.
+
+        * platform/ios/WebSafeGCActivityCallbackIOS.h:
+
+=======
 2014-03-19  Antti Koivisto  <antti@apple.com>
 
         Crash with long selector list
         (WebCore::RTCPeerConnection::hasLocalStreamWithTrackId):
         * Modules/mediastream/RTCPeerConnection.h:
 
+>>>>>>> .r165925
 2014-03-18  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r165815.
index e66377a..2e92ce4 100644 (file)
 #define WebSafeGCActivityCallbackIOS_h
 
 #include "WebCoreThread.h"
-#include <JavaScriptCore/GCActivityCallback.h>
+#include <JavaScriptCore/EdenGCActivityCallback.h>
+#include <JavaScriptCore/FullGCActivityCallback.h>
 
 namespace WebCore {
 
-class WebSafeGCActivityCallback final : public JSC::DefaultGCActivityCallback {
+class WebSafeFullGCActivityCallback final : public JSC::FullGCActivityCallback {
 public:
-    static PassOwnPtr<WebSafeGCActivityCallback> create(JSC::Heap* heap)
+    static PassOwnPtr<WebSafeFullGCActivityCallback> create(JSC::Heap* heap)
     {
-        return adoptPtr(new WebSafeGCActivityCallback(heap));
+        return adoptPtr(new WebSafeFullGCActivityCallback(heap));
     }
 
-    virtual ~WebSafeGCActivityCallback() override { }
+    virtual ~WebSafeFullGCActivityCallback() override { }
 
 private:
-    WebSafeGCActivityCallback(JSC::Heap* heap)
-        : JSC::DefaultGCActivityCallback(heap, WebThreadRunLoop())
+    WebSafeFullGCActivityCallback(JSC::Heap* heap)
+        : JSC::FullGCActivityCallback(heap, WebThreadRunLoop())
     {
     }
 };
 
+class WebSafeEdenGCActivityCallback final : public JSC::EdenGCActivityCallback {
+public:
+    static PassOwnPtr<WebSafeEdenGCActivityCallback> create(JSC::Heap* heap)
+    {
+        return adoptPtr(new WebSafeEdenGCActivityCallback(heap));
+    }
+
+    virtual ~WebSafeEdenGCActivityCallback() override { }
+
+private:
+    WebSafeEdenGCActivityCallback(JSC::Heap* heap)
+        : JSC::EdenGCActivityCallback(heap, WebThreadRunLoop())
+    {
+    }
+};
 } // namespace WebCore
 
 #endif // WebSafeGCActivityCallbackIOS_h