Prewarm FontDatabase on process swap
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2018 09:14:37 +0000 (09:14 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2018 09:14:37 +0000 (09:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190312

Reviewed by Chris Dumez.

Source/WebCore:

Implement basic prewarming of FontDatabase. When the domain of the first page load on
a new process is known we pass the list of font families previous used by that domain to the
process. This is used to prewarm CoreText font database. Initialization (which involves lots of
blocking IPC) happens outside the main thread so the fonts are ready to use when needed.

* WebCore.xcodeproj/project.pbxproj:
* page/PrewarmInformation.h: Added.
(WebCore::PrewarmInformation::encode const):
(WebCore::PrewarmInformation::decode):

Add data structure for prewarm information with encode/decode support.

* page/ProcessWarming.cpp:
(WebCore::ProcessWarming::collectPrewarmInformation):
(WebCore::ProcessWarming::prewarmWithInformation):

Prewarming interface to be used from WebKit.

* page/ProcessWarming.h:
* platform/graphics/FontCache.cpp:
(WebCore::FontCache::collectPrewarmInformation const):
(WebCore::FontCache::prewarm):
* platform/graphics/FontCache.h:
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::FontDatabase::collectionForFamily):
(WebCore::FontDatabase::fontForPostScriptName):
(WebCore::FontDatabase::clear):

Add mutex for thread safe access.

(WebCore::FontCache::createFontPlatformData):
(WebCore::FontCache::collectPrewarmInformation const):

Collect font families seen by this process.

(WebCore::FontCache::prewarm):

Prewarm FontDatabase in a dispatch queue.

Source/WebKit:

Add mechanism for caching prewarm information per domain on UI process side. This information
is then passed to newly initialized web processes that are being used for the same domain.

* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigationInternal):

Pass prewarm information on process swap to the new process.

(WebKit::WebProcessPool::didCollectPrewarmInformation):

UI process side cache.

* UIProcess/WebProcessPool.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::didCollectPrewarmInformation):
* UIProcess/WebProcessProxy.h:
* UIProcess/WebProcessProxy.messages.in:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::close):
(WebKit::WebPage::didReceivePolicyDecision):

Collect and cache prewarm information for the previous process on process swap.

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::prewarmGlobally):

Renamed for clarity.

(WebKit::WebProcess::prewarmWithDomainInformation):
(WebKit::WebProcess::sendPrewarmInformation):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/page/PrewarmInformation.h [new file with mode: 0644]
Source/WebCore/page/ProcessWarming.cpp
Source/WebCore/page/ProcessWarming.h
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/UIProcess/WebProcessPool.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/WebProcessProxy.messages.in
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/WebProcess.messages.in

index ec96959..723b2ca 100644 (file)
@@ -1,3 +1,49 @@
+2018-10-09  Antti Koivisto  <antti@apple.com>
+
+        Prewarm FontDatabase on process swap
+        https://bugs.webkit.org/show_bug.cgi?id=190312
+
+        Reviewed by Chris Dumez.
+
+        Implement basic prewarming of FontDatabase. When the domain of the first page load on
+        a new process is known we pass the list of font families previous used by that domain to the
+        process. This is used to prewarm CoreText font database. Initialization (which involves lots of
+        blocking IPC) happens outside the main thread so the fonts are ready to use when needed.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/PrewarmInformation.h: Added.
+        (WebCore::PrewarmInformation::encode const):
+        (WebCore::PrewarmInformation::decode):
+
+        Add data structure for prewarm information with encode/decode support.
+
+        * page/ProcessWarming.cpp:
+        (WebCore::ProcessWarming::collectPrewarmInformation):
+        (WebCore::ProcessWarming::prewarmWithInformation):
+
+        Prewarming interface to be used from WebKit.
+
+        * page/ProcessWarming.h:
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::collectPrewarmInformation const):
+        (WebCore::FontCache::prewarm):
+        * platform/graphics/FontCache.h:
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::FontDatabase::collectionForFamily):
+        (WebCore::FontDatabase::fontForPostScriptName):
+        (WebCore::FontDatabase::clear):
+
+        Add mutex for thread safe access.
+
+        (WebCore::FontCache::createFontPlatformData):
+        (WebCore::FontCache::collectPrewarmInformation const):
+
+        Collect font families seen by this process.
+
+        (WebCore::FontCache::prewarm):
+
+        Prewarm FontDatabase in a dispatch queue.
+
 2018-10-08  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [Cocoa] [WK2] Add support for text alignment and text lists in font attributes
index 9cfed03..5bea8a3 100644 (file)
                E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = E44B4BB2141650D7002B1D8B /* SelectorChecker.h */; };
                E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E44FA1841BCA6B5A0091B6EF /* ComposedTreeIterator.h */; };
                E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E45322AA140CE267005A0F92 /* SelectorQuery.h */; };
+               E4605FEC2166480900E53046 /* PrewarmInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4605FEA2166480800E53046 /* PrewarmInformation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E461802D1C8DD2900026C02C /* StyleRelations.h in Headers */ = {isa = PBXBuildFile; fileRef = E461802C1C8DD2900026C02C /* StyleRelations.h */; };
                E461D65F1BB0C80D00CB5645 /* StyleScope.h in Headers */ = {isa = PBXBuildFile; fileRef = E461D65E1BB0C80D00CB5645 /* StyleScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E462A4A0113E71BE004A4220 /* IntPointHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E45390340EAFD637003695C8 /* ScrollViewIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollViewIOS.mm; sourceTree = "<group>"; };
                E453903C0EAFD637003695C8 /* WidgetIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WidgetIOS.mm; sourceTree = "<group>"; };
                E45390AD0EAFF4B5003695C8 /* SystemMemoryIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemMemoryIOS.cpp; sourceTree = "<group>"; };
+               E4605FEA2166480800E53046 /* PrewarmInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrewarmInformation.h; sourceTree = "<group>"; };
                E461802C1C8DD2900026C02C /* StyleRelations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleRelations.h; sourceTree = "<group>"; };
                E461802E1C8DD4D20026C02C /* StyleRelations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleRelations.cpp; sourceTree = "<group>"; };
                E461D65C1BB0C7F000CB5645 /* StyleScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleScope.cpp; sourceTree = "<group>"; };
                                5CFC434E192406A900A0D3B5 /* PointerLockController.cpp */,
                                5CFC434F192406A900A0D3B5 /* PointerLockController.h */,
                                3772B09516535856000A49CA /* PopupOpeningObserver.h */,
+                               E4605FEA2166480800E53046 /* PrewarmInformation.h */,
                                B776D43C1104527500BEB0EC /* PrintContext.cpp */,
                                B776D43A1104525D00BEB0EC /* PrintContext.h */,
                                E42050162141901B0066EF3B /* ProcessWarming.cpp */,
                                CE799F981C6A46BC0097B518 /* ContentSecurityPolicySourceList.h in Headers */,
                                CE799FAC1C6A50660097B518 /* ContentSecurityPolicySourceListDirective.h in Headers */,
                                41D015CA0F4B5C71004A662F /* ContentType.h in Headers */,
+                               E4605FEC2166480900E53046 /* PrewarmInformation.h in Headers */,
                                97627B8E14FB3CEE002CDCA1 /* ContextDestructionObserver.h in Headers */,
                                93B6A0E60B0BCA5C00F5027A /* ContextMenu.h in Headers */,
                                065AD4F50B0C2EDA005A2B1D /* ContextMenuClient.h in Headers */,
diff --git a/Source/WebCore/page/PrewarmInformation.h b/Source/WebCore/page/PrewarmInformation.h
new file mode 100644 (file)
index 0000000..6ce7226
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "FontCache.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct WEBCORE_EXPORT PrewarmInformation {
+    FontPrewarmInformation font;
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<PrewarmInformation> decode(Decoder&);
+};
+
+template<class Encoder>
+void PrewarmInformation::encode(Encoder& encoder) const
+{
+    encoder << font;
+}
+
+template<class Decoder>
+std::optional<PrewarmInformation> PrewarmInformation::decode(Decoder& decoder)
+{
+    PrewarmInformation prewarmInfo;
+    if (!decoder.decode(prewarmInfo.font))
+        return { };
+
+    return prewarmInfo;
+}
+
+}
index d9ee48d..0543ba5 100644 (file)
@@ -58,7 +58,7 @@ void ProcessWarming::initializeNames()
     WebKitFontFamilyNames::init();
 }
     
-void ProcessWarming::prewarm()
+void ProcessWarming::prewarmGlobally()
 {
     initializeNames();
     
@@ -76,4 +76,16 @@ void ProcessWarming::prewarm()
 #endif
 }
 
+WebCore::PrewarmInformation ProcessWarming::collectPrewarmInformation()
+{
+    PrewarmInformation info;
+    info.font = FontCache::singleton().collectPrewarmInformation();
+    return info;
+}
+
+void ProcessWarming::prewarmWithInformation(const PrewarmInformation& prewarmInfo)
+{
+    FontCache::singleton().prewarm(prewarmInfo.font);
+}
+
 }
index 0ceef72..cf17eaa 100644 (file)
 
 #pragma once
 
+#include "PrewarmInformation.h"
+
 namespace WebCore {
 
 class WEBCORE_EXPORT ProcessWarming {
 public:
     static void initializeNames();
-    static void prewarm();
+    static void prewarmGlobally();
+
+    static PrewarmInformation collectPrewarmInformation();
+    static void prewarmWithInformation(const PrewarmInformation&);
 };
 
 }
index 4b7c1ee..f98b9c5 100644 (file)
@@ -482,6 +482,16 @@ void FontCache::invalidate()
 }
 
 #if !PLATFORM(COCOA)
+
+FontPrewarmInformation FontCache::collectPrewarmInformation() const
+{
+    return { };
+}
+
+void FontCache::prewarm(const FontPrewarmInformation&)
+{
+}
+
 RefPtr<Font> FontCache::similarFont(const FontDescription&, const AtomicString&)
 {
     return nullptr;
index e95d2da..aa56f1b 100644 (file)
@@ -38,6 +38,7 @@
 #include <wtf/Forward.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
+#include <wtf/WorkQueue.h>
 #include <wtf/text/AtomicStringHash.h>
 #include <wtf/text/WTFString.h>
 
@@ -67,6 +68,8 @@ typedef IMLangFontLink IMLangFontLinkType;
 #endif
 #endif
 
+using FontPrewarmInformation = Vector<String>;
+
 // This key contains the FontDescription fields other than family that matter when fetching FontDatas (platform fonts).
 struct FontDescriptionKey {
     FontDescriptionKey() = default;
@@ -235,6 +238,9 @@ public:
     bool shouldMockBoldSystemFontForAccessibility() const { return m_shouldMockBoldSystemFontForAccessibility; }
     void setShouldMockBoldSystemFontForAccessibility(bool shouldMockBoldSystemFontForAccessibility) { m_shouldMockBoldSystemFontForAccessibility = shouldMockBoldSystemFontForAccessibility; }
 
+    FontPrewarmInformation collectPrewarmInformation() const;
+    void prewarm(const FontPrewarmInformation&);
+
 private:
     FontCache();
     ~FontCache() = delete;
@@ -258,6 +264,9 @@ private:
     bool m_shouldMockBoldSystemFontForAccessibility { false };
 
 #if PLATFORM(COCOA)
+    HashSet<String> m_seenFamiliesForPrewarming;
+    RefPtr<WorkQueue> m_prewarmQueue;
+
     friend class ComplexTextController;
 #endif
     friend class Font;
index aa11f0d..82243af 100644 (file)
@@ -887,6 +887,8 @@ public:
 
     const InstalledFontFamily& collectionForFamily(const String& familyName)
     {
+        std::lock_guard<Lock> locker(m_descriptorMapLock);
+
         auto folded = familyName.foldCase();
         return m_familyNameToFontDescriptors.ensure(folded, [&] {
             auto familyNameString = folded.createCFString();
@@ -911,6 +913,8 @@ public:
 
     const InstalledFont& fontForPostScriptName(const AtomicString& postScriptName)
     {
+        std::lock_guard<Lock> locker(m_descriptorMapLock);
+
         const auto& folded = FontCascadeDescription::foldedFamilyName(postScriptName);
         return m_postScriptNameToFontDescriptors.ensure(folded, [&] {
             auto postScriptNameString = folded.createCFString();
@@ -932,6 +936,8 @@ public:
 
     void clear()
     {
+        std::lock_guard<Lock> locker(m_descriptorMapLock);
+
         m_familyNameToFontDescriptors.clear();
         m_postScriptNameToFontDescriptors.clear();
     }
@@ -944,6 +950,7 @@ private:
     {
     }
 
+    Lock m_descriptorMapLock;
     HashMap<String, InstalledFontFamily> m_familyNameToFontDescriptors;
     HashMap<String, InstalledFont> m_postScriptNameToFontDescriptors;
     AllowUserInstalledFonts m_allowUserInstalledFonts;
@@ -1264,6 +1271,9 @@ std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDe
     if (!font)
         return nullptr;
 
+    if (fontDescription.shouldAllowUserInstalledFonts() == AllowUserInstalledFonts::No)
+        m_seenFamiliesForPrewarming.add(FontCascadeDescription::foldedFamilyName(family));
+
     bool syntheticBold, syntheticOblique;
     std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(font.get(), fontDescription).boldObliquePair();
 
@@ -1502,4 +1512,29 @@ Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescripti
     return fontForPlatformData(platformData);
 }
 
+FontPrewarmInformation FontCache::collectPrewarmInformation() const
+{
+    FontPrewarmInformation fontPrewarmInformation;
+    fontPrewarmInformation = copyToVector(m_seenFamiliesForPrewarming);
+    return fontPrewarmInformation;
+}
+
+void FontCache::prewarm(const FontPrewarmInformation& fontPrewarmInformation)
+{
+    auto& families = fontPrewarmInformation;
+
+    if (families.isEmpty())
+        return;
+
+    if (!m_prewarmQueue)
+        m_prewarmQueue = WorkQueue::create("WebKit font prewarm queue");
+
+    auto& database = FontDatabase::singletonDisallowingUserInstalledFonts();
+
+    m_prewarmQueue->dispatch([&database, families = families.isolatedCopy()] {
+        for (auto& family : families)
+            database.collectionForFamily(family);
+    });
+}
+
 }
index 232478d..efec299 100644 (file)
@@ -1,3 +1,44 @@
+2018-10-09  Antti Koivisto  <antti@apple.com>
+
+        Prewarm FontDatabase on process swap
+        https://bugs.webkit.org/show_bug.cgi?id=190312
+
+        Reviewed by Chris Dumez.
+
+        Add mechanism for caching prewarm information per domain on UI process side. This information
+        is then passed to newly initialized web processes that are being used for the same domain.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::processForNavigationInternal):
+
+        Pass prewarm information on process swap to the new process.
+
+        (WebKit::WebProcessPool::didCollectPrewarmInformation):
+
+        UI process side cache.
+
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::didCollectPrewarmInformation):
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/WebProcessProxy.messages.in:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::close):
+        (WebKit::WebPage::didReceivePolicyDecision):
+
+        Collect and cache prewarm information for the previous process on process swap.
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::prewarmGlobally):
+
+        Renamed for clarity.
+
+        (WebKit::WebProcess::prewarmWithDomainInformation):
+        (WebKit::WebProcess::sendPrewarmInformation):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2018-10-08  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [Cocoa] [WK2] Add support for text alignment and text lists in font attributes
index f499473..8e92632 100644 (file)
@@ -190,6 +190,7 @@ struct ExceptionDetails;
 struct FileChooserSettings;
 struct GlobalWindowIdentifier;
 struct MediaStreamRequest;
+struct PrewarmInformation;
 struct SecurityOriginData;
 struct ShareData;
 struct TextAlternativeWithRange;
index 8175a3c..5f566d7 100644 (file)
@@ -85,6 +85,7 @@
 #include <WebCore/NetworkStorageSession.h>
 #include <WebCore/PlatformScreen.h>
 #include <WebCore/Process.h>
+#include <WebCore/ProcessWarming.h>
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/URLParser.h>
 #include <pal/SessionID.h>
@@ -736,7 +737,7 @@ WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDa
         ASSERT(!m_prewarmedProcess);
         m_prewarmedProcess = &process;
         
-        m_prewarmedProcess->send(Messages::WebProcess::Prewarm(), 0);
+        m_prewarmedProcess->send(Messages::WebProcess::PrewarmGlobally(), 0);
     }
 
     if (m_serviceWorkerProcessesTerminationTimer.isActive())
@@ -2173,8 +2174,14 @@ Ref<WebProcessProxy> WebProcessPool::processForNavigationInternal(WebPageProxy&
     }
 
     action = PolicyAction::Suspend;
-    if (RefPtr<WebProcessProxy> process = tryTakePrewarmedProcess(page.websiteDataStore()))
+
+    if (RefPtr<WebProcessProxy> process = tryTakePrewarmedProcess(page.websiteDataStore())) {
+        if (auto* prewarmInformation = m_prewarmInformationPerRegistrableDomain.get(toRegistrableDomain(targetURL)))
+            process->send(Messages::WebProcess::PrewarmWithDomainInformation(*prewarmInformation), 0);
+
         return process.releaseNonNull();
+    }
+
     return createNewWebProcess(page.websiteDataStore());
 }
 
@@ -2248,4 +2255,17 @@ void WebProcessPool::sendDisplayConfigurationChangedMessageForTesting()
 #endif
 }
 
+void WebProcessPool::didCollectPrewarmInformation(const String& registrableDomain, const WebCore::PrewarmInformation& prewarmInformation)
+{
+    static const size_t maximumSizeToPreventUnlimitedGrowth = 100;
+    if (m_prewarmInformationPerRegistrableDomain.size() == maximumSizeToPreventUnlimitedGrowth)
+        m_prewarmInformationPerRegistrableDomain.remove(m_prewarmInformationPerRegistrableDomain.begin());
+
+    auto& value = m_prewarmInformationPerRegistrableDomain.ensure(registrableDomain, [] {
+        return std::make_unique<WebCore::PrewarmInformation>();
+    }).iterator->value;
+
+    *value = prewarmInformation;
+}
+
 } // namespace WebKit
index 144428b..a239ea0 100644 (file)
@@ -444,6 +444,8 @@ public:
     void unregisterSuspendedPageProxy(SuspendedPageProxy&);
     void didReachGoodTimeToPrewarm();
 
+    void didCollectPrewarmInformation(const String& registrableDomain, const WebCore::PrewarmInformation&);
+
     void screenPropertiesStateChanged();
 
     void addMockMediaDevice(const WebCore::MockMediaDevice&);
@@ -696,6 +698,8 @@ private:
 
     HashMap<WebCore::SecurityOriginData, Vector<SuspendedPageProxy*>> m_suspendedPages;
     HashMap<String, RefPtr<WebProcessProxy>> m_swappedProcessesPerRegistrableDomain;
+
+    HashMap<String, std::unique_ptr<WebCore::PrewarmInformation>> m_prewarmInformationPerRegistrableDomain;
 };
 
 template<typename T>
index 9e844cd..d671d6a 100644 (file)
@@ -53,6 +53,7 @@
 #include "WebsiteData.h"
 #include "WebsiteDataFetchOption.h"
 #include <WebCore/DiagnosticLoggingKeys.h>
+#include <WebCore/PrewarmInformation.h>
 #include <WebCore/PublicSuffix.h>
 #include <WebCore/SuddenTermination.h>
 #include <WebCore/URL.h>
@@ -1433,6 +1434,11 @@ void WebProcessProxy::didCheckProcessLocalPortForActivity(uint64_t callbackIdent
     callback(isLocallyReachable ? MessagePortChannelProvider::HasActivity::Yes : MessagePortChannelProvider::HasActivity::No);
 }
 
+void WebProcessProxy::didCollectPrewarmInformation(const String& domain, const WebCore::PrewarmInformation& prewarmInformation)
+{
+    processPool().didCollectPrewarmInformation(domain, prewarmInformation);
+}
+
 #if PLATFORM(WATCHOS)
 
 void WebProcessProxy::takeBackgroundActivityTokenForFullscreenInput()
index e0a67cb..325acbf 100644 (file)
@@ -314,6 +314,8 @@ private:
 
     bool canTerminateChildProcess();
 
+    void didCollectPrewarmInformation(const String& domain, const WebCore::PrewarmInformation&);
+
     void logDiagnosticMessageForResourceLimitTermination(const String& limitKey);
 
     enum class IsWeak { No, Yes };
index bad9159..32fda8b 100644 (file)
@@ -64,6 +64,8 @@ messages -> WebProcessProxy LegacyReceiver {
     DidDeliverMessagePortMessages(uint64_t messageBatchIdentifier)
     DidCheckProcessLocalPortForActivity(uint64_t callbackIdentifier, bool isLocallyReachable)
 
+    DidCollectPrewarmInformation(String domain, struct WebCore::PrewarmInformation prewarmInformation)
+
 #if PLATFORM(COCOA)
     CacheMediaMIMETypes(Vector<String> types)
 #endif
index c9d1724..2981ffd 100644 (file)
@@ -1173,9 +1173,12 @@ void WebPage::close()
     m_isClosed = true;
 
     // If there is still no URL, then we never loaded anything in this page, so nothing to report.
-    if (!mainWebFrame()->url().isEmpty())
+    if (!mainWebFrame()->url().isEmpty()) {
         reportUsedFeatures();
 
+        WebProcess::singleton().sendPrewarmInformation(toRegistrableDomain(mainWebFrame()->url()));
+    }
+
     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::singleton().injectedBundle())
         WebProcess::singleton().injectedBundle()->willDestroyPage(this);
 
@@ -2873,6 +2876,8 @@ void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, Po
     if (policyAction == PolicyAction::Suspend) {
         ASSERT(frame == m_mainFrame);
         setIsSuspended(true);
+
+        WebProcess::singleton().sendPrewarmInformation(toRegistrableDomain(mainWebFrame()->url()));
     }
     frame->didReceivePolicyDecision(listenerID, policyAction, navigationID, downloadID, WTFMove(websitePolicies));
 }
index bed287d..fb2d03a 100644 (file)
@@ -420,9 +420,14 @@ void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
     RELEASE_LOG(Process, "%p - WebProcess::initializeWebProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
 }
 
-void WebProcess::prewarm()
+void WebProcess::prewarmGlobally()
 {
-    WebCore::ProcessWarming::prewarm();
+    WebCore::ProcessWarming::prewarmGlobally();
+}
+
+void WebProcess::prewarmWithDomainInformation(const WebCore::PrewarmInformation& prewarmInformation)
+{
+    WebCore::ProcessWarming::prewarmWithInformation(prewarmInformation);
 }
 
 void WebProcess::registerURLSchemeAsEmptyDocument(const String& urlScheme)
@@ -1459,6 +1464,13 @@ void WebProcess::processDidResume()
 #endif
 }
 
+void WebProcess::sendPrewarmInformation(const String& registrableDomain)
+{
+    if (registrableDomain.isEmpty())
+        return;
+    parentProcessConnection()->send(Messages::WebProcessProxy::DidCollectPrewarmInformation(registrableDomain, WebCore::ProcessWarming::collectPrewarmInformation()), 0);
+}
+
 void WebProcess::pageDidEnterWindow(uint64_t pageID)
 {
     m_pagesInWindows.add(pageID);
index 638976f..5a451d2 100644 (file)
@@ -71,6 +71,7 @@ struct MessagePortIdentifier;
 struct MessageWithMessagePorts;
 struct MockMediaDevice;
 struct PluginInfo;
+struct PrewarmInformation;
 struct SecurityOriginData;
 struct SoupNetworkProxySettings;
 
@@ -200,6 +201,8 @@ public:
     void cancelPrepareToSuspend();
     void processDidResume();
 
+    void sendPrewarmInformation(const String& registrableDomain);
+
 #if PLATFORM(IOS)
     void resetAllGeolocationPermissions();
 #endif
@@ -245,7 +248,8 @@ private:
     void initializeWebProcess(WebProcessCreationParameters&&);
     void platformInitializeWebProcess(WebProcessCreationParameters&&);
 
-    void prewarm();
+    void prewarmGlobally();
+    void prewarmWithDomainInformation(const WebCore::PrewarmInformation&);
 
 #if USE(OS_STATE)
     void registerWithStateDumper();
index 0bca4b9..6898634 100644 (file)
@@ -26,8 +26,9 @@ messages -> WebProcess LegacyReceiver {
     # Create a new page.
     CreateWebPage(uint64_t newPageID, struct WebKit::WebPageCreationParameters pageCreationParameters)
 
-    Prewarm();
+    PrewarmGlobally();
+    PrewarmWithDomainInformation(struct WebCore::PrewarmInformation prewarmInformation)
+
     # Global preferences.
     SetCacheModel(uint32_t cacheModel)