Title: [180192] trunk/Source/WebCore
Revision
180192
Author
akl...@apple.com
Date
2015-02-16 17:06:45 -0800 (Mon, 16 Feb 2015)

Log Message

GC (almost) immediately when navigating under memory pressure.
<https://webkit.org/b/141663>

Reviewed by Geoffrey Garen.

Since the PageCache is already disabled in memory pressure situations,
we know that detaching the old window shell on navigation is basically
guaranteed to generate a bunch of garbage, we can soften the memory
peak a bit by doing a GC right away instead of scheduling one for soon(tm).

* bindings/js/GCController.cpp:
(WebCore::GCController::GCController):
(WebCore::GCController::garbageCollectSoon):
(WebCore::GCController::garbageCollectOnNextRunLoop):
(WebCore::GCController::gcTimerFired):
* bindings/js/GCController.h:

    Add a GCController::garbageCollectOnNextRunLoop() complement to the
    "soon" and "now" options. There was already a zero timer in here for
    non-CF builds, so I just used that same timer to implement this
    and have the non-CF code path call garbageCollectOnNextRunLoop().

* bindings/js/ScriptController.cpp:
(WebCore::collectGarbageAfterWindowShellDestruction):
(WebCore::ScriptController::~ScriptController):
(WebCore::ScriptController::clearWindowShell):

    Under system memory pressure conditions, schedule a full GC on next
    runloop iteration instead of just asking for it to happen soon.
    We do it on next runloop to ensure that there's no pointer to the
    window object on the stack.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (180191 => 180192)


--- trunk/Source/WebCore/ChangeLog	2015-02-17 01:05:28 UTC (rev 180191)
+++ trunk/Source/WebCore/ChangeLog	2015-02-17 01:06:45 UTC (rev 180192)
@@ -1,3 +1,37 @@
+2015-02-16  Andreas Kling  <akl...@apple.com>
+
+        GC (almost) immediately when navigating under memory pressure.
+        <https://webkit.org/b/141663>
+
+        Reviewed by Geoffrey Garen.
+
+        Since the PageCache is already disabled in memory pressure situations,
+        we know that detaching the old window shell on navigation is basically
+        guaranteed to generate a bunch of garbage, we can soften the memory
+        peak a bit by doing a GC right away instead of scheduling one for soon(tm).
+
+        * bindings/js/GCController.cpp:
+        (WebCore::GCController::GCController):
+        (WebCore::GCController::garbageCollectSoon):
+        (WebCore::GCController::garbageCollectOnNextRunLoop):
+        (WebCore::GCController::gcTimerFired):
+        * bindings/js/GCController.h:
+
+            Add a GCController::garbageCollectOnNextRunLoop() complement to the
+            "soon" and "now" options. There was already a zero timer in here for
+            non-CF builds, so I just used that same timer to implement this
+            and have the non-CF code path call garbageCollectOnNextRunLoop().
+
+        * bindings/js/ScriptController.cpp:
+        (WebCore::collectGarbageAfterWindowShellDestruction):
+        (WebCore::ScriptController::~ScriptController):
+        (WebCore::ScriptController::clearWindowShell):
+
+            Under system memory pressure conditions, schedule a full GC on next
+            runloop iteration instead of just asking for it to happen soon.
+            We do it on next runloop to ensure that there's no pointer to the
+            window object on the stack.
+
 2015-02-16  Enrica Casucci  <enr...@apple.com>
 
         Emoji sequences do not render properly.

Modified: trunk/Source/WebCore/bindings/js/GCController.cpp (180191 => 180192)


--- trunk/Source/WebCore/bindings/js/GCController.cpp	2015-02-17 01:05:28 UTC (rev 180191)
+++ trunk/Source/WebCore/bindings/js/GCController.cpp	2015-02-17 01:06:45 UTC (rev 180192)
@@ -50,9 +50,7 @@
 }
 
 GCController::GCController()
-#if !USE(CF)
     : m_GCTimer(*this, &GCController::gcTimerFired)
-#endif
 {
 }
 
@@ -67,17 +65,20 @@
     JSLockHolder lock(JSDOMWindow::commonVM());
     JSDOMWindow::commonVM().heap.reportAbandonedObjectGraph();
 #else
+    garbageCollectOnNextRunLoop();
+#endif
+}
+
+void GCController::garbageCollectOnNextRunLoop()
+{
     if (!m_GCTimer.isActive())
         m_GCTimer.startOneShot(0);
-#endif
 }
 
-#if !USE(CF)
 void GCController::gcTimerFired()
 {
     collect(nullptr);
 }
-#endif
 
 void GCController::garbageCollectNow()
 {

Modified: trunk/Source/WebCore/bindings/js/GCController.h (180191 => 180192)


--- trunk/Source/WebCore/bindings/js/GCController.h	2015-02-17 01:05:28 UTC (rev 180191)
+++ trunk/Source/WebCore/bindings/js/GCController.h	2015-02-17 01:06:45 UTC (rev 180192)
@@ -26,12 +26,9 @@
 #ifndef GCController_h
 #define GCController_h
 
-#if USE(CF)
 #include <wtf/FastMalloc.h>
 #include <wtf/Noncopyable.h>
-#else
 #include "Timer.h"
-#endif
 
 namespace WebCore {
 
@@ -42,6 +39,7 @@
     public:
         WEBCORE_EXPORT void garbageCollectSoon();
         WEBCORE_EXPORT void garbageCollectNow(); // It's better to call garbageCollectSoon, unless you have a specific reason not to.
+        void garbageCollectOnNextRunLoop();
 
         WEBCORE_EXPORT void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing.
         WEBCORE_EXPORT void releaseExecutableMemory();
@@ -51,10 +49,8 @@
     private:
         GCController(); // Use gcController() instead
 
-#if !USE(CF)
         void gcTimerFired();
         Timer m_GCTimer;
-#endif
     };
 
     // Function to obtain the global GC controller.

Modified: trunk/Source/WebCore/bindings/js/ScriptController.cpp (180191 => 180192)


--- trunk/Source/WebCore/bindings/js/ScriptController.cpp	2015-02-17 01:05:28 UTC (rev 180191)
+++ trunk/Source/WebCore/bindings/js/ScriptController.cpp	2015-02-17 01:06:45 UTC (rev 180192)
@@ -35,6 +35,7 @@
 #include "JSDocument.h"
 #include "JSMainThreadExecState.h"
 #include "MainFrame.h"
+#include "MemoryPressureHandler.h"
 #include "NP_jsobject.h"
 #include "Page.h"
 #include "PageConsoleClient.h"
@@ -60,6 +61,18 @@
 
 namespace WebCore {
 
+static void collectGarbageAfterWindowShellDestruction()
+{
+    // Make sure to GC Extra Soon(tm) during memory pressure conditions
+    // to soften high peaks of memory usage during navigation.
+    if (memoryPressureHandler().isUnderMemoryPressure()) {
+        // NOTE: We do the collection on next runloop to ensure that there's no pointer
+        //       to the window object on the stack.
+        gcController().garbageCollectOnNextRunLoop();
+    } else
+        gcController().garbageCollectSoon();
+}
+
 void ScriptController::initializeThreading()
 {
 #if !PLATFORM(IOS)
@@ -98,7 +111,7 @@
             iter->value->window()->setConsoleClient(nullptr);
             destroyWindowShell(*iter->key);
         }
-        gcController().garbageCollectSoon();
+        collectGarbageAfterWindowShellDestruction();
     }
 }
 
@@ -227,7 +240,7 @@
     // It's likely that resetting our windows created a lot of garbage, unless
     // it went in a back/forward cache.
     if (!goingIntoPageCache)
-        gcController().garbageCollectSoon();
+        collectGarbageAfterWindowShellDestruction();
 }
 
 JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to