Title: [186912] trunk
Revision
186912
Author
[email protected]
Date
2015-07-16 15:08:19 -0700 (Thu, 16 Jul 2015)

Log Message

[Content Extensions] Cache domain actions
https://bugs.webkit.org/show_bug.cgi?id=146817

Reviewed by Benjamin Poulain.

Source/WebCore:

Right now we run regular expressions on the domain every time we have any rules that match with if-domain or unless-domain.  
This caches the results of running regular expressions on the domain of the main document's url so we only need to 
run those regular expressions when the main document changes domain.  We also spend less time adding unused actions into HashSets.

All behavior is covered by existing api tests, but I added some to explicitly test if-domain and unless-domain with multiple load types.

* contentextensions/ContentExtension.cpp:
(WebCore::ContentExtensions::ContentExtension::globalDisplayNoneStyleSheet):
(WebCore::ContentExtensions::ContentExtension::cachedDomainActions):
* contentextensions/ContentExtension.h:
(WebCore::ContentExtensions::ContentExtension::identifier):
(WebCore::ContentExtensions::ContentExtension::compiledExtension):
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
* contentextensions/DFABytecodeInterpreter.cpp:
(WebCore::ContentExtensions::getJumpDistance):
(WebCore::ContentExtensions::matchesDomain):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithDomains):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
* contentextensions/DFABytecodeInterpreter.h:

Tools:

* TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
(TestWebKitAPI::TEST_F):
Test if-domain and unless-domain with multiple load types.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (186911 => 186912)


--- trunk/Source/WebCore/ChangeLog	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/ChangeLog	2015-07-16 22:08:19 UTC (rev 186912)
@@ -1,3 +1,34 @@
+2015-07-16  Alex Christensen  <[email protected]>
+
+        [Content Extensions] Cache domain actions
+        https://bugs.webkit.org/show_bug.cgi?id=146817
+
+        Reviewed by Benjamin Poulain.
+
+        Right now we run regular expressions on the domain every time we have any rules that match with if-domain or unless-domain.  
+        This caches the results of running regular expressions on the domain of the main document's url so we only need to 
+        run those regular expressions when the main document changes domain.  We also spend less time adding unused actions into HashSets.
+
+        All behavior is covered by existing api tests, but I added some to explicitly test if-domain and unless-domain with multiple load types.
+
+        * contentextensions/ContentExtension.cpp:
+        (WebCore::ContentExtensions::ContentExtension::globalDisplayNoneStyleSheet):
+        (WebCore::ContentExtensions::ContentExtension::cachedDomainActions):
+        * contentextensions/ContentExtension.h:
+        (WebCore::ContentExtensions::ContentExtension::identifier):
+        (WebCore::ContentExtensions::ContentExtension::compiledExtension):
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
+        * contentextensions/DFABytecodeInterpreter.cpp:
+        (WebCore::ContentExtensions::getJumpDistance):
+        (WebCore::ContentExtensions::matchesDomain):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithDomains):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+        * contentextensions/DFABytecodeInterpreter.h:
+
 2015-07-16  Simon Fraser  <[email protected]>
 
         Fix disappearing position:fixed elements in fixed layout mode

Modified: trunk/Source/WebCore/contentextensions/ContentExtension.cpp (186911 => 186912)


--- trunk/Source/WebCore/contentextensions/ContentExtension.cpp	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtension.cpp	2015-07-16 22:08:19 UTC (rev 186912)
@@ -75,6 +75,21 @@
     return m_globalDisplayNoneStyleSheet.get();
 }
 
+const DFABytecodeInterpreter::Actions& ContentExtension::cachedDomainActions(const String& domain)
+{
+    if (m_cachedDomain != domain) {
+        DFABytecodeInterpreter interpreter(m_compiledExtension->domainFiltersBytecode(), m_compiledExtension->domainFiltersBytecodeLength());
+        const uint16_t allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask;
+        auto domainActions = interpreter.interpret(domain.utf8(), allLoadTypesAndResourceTypes);
+        
+        m_cachedDomainActions.clear();
+        for (uint64_t action : domainActions)
+            m_cachedDomainActions.add(action);
+        m_cachedDomain = domain;
+    }
+    return m_cachedDomainActions;
+}
+    
 } // namespace ContentExtensions
 } // namespace WebCore
 

Modified: trunk/Source/WebCore/contentextensions/ContentExtension.h (186911 => 186912)


--- trunk/Source/WebCore/contentextensions/ContentExtension.h	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtension.h	2015-07-16 22:08:19 UTC (rev 186912)
@@ -32,6 +32,7 @@
 
 #if ENABLE(CONTENT_EXTENSIONS)
 
+#include "DFABytecodeInterpreter.h"
 #include "StyleSheetContents.h"
 
 namespace WebCore {
@@ -47,6 +48,7 @@
     const String& identifier() const { return m_identifier; }
     const CompiledContentExtension& compiledExtension() const { return m_compiledExtension.get(); }
     StyleSheetContents* globalDisplayNoneStyleSheet();
+    const DFABytecodeInterpreter::Actions& cachedDomainActions(const String& domain);
 
 private:
     ContentExtension(const String& identifier, Ref<CompiledContentExtension>&&);
@@ -55,6 +57,9 @@
     Ref<CompiledContentExtension> m_compiledExtension;
     RefPtr<StyleSheetContents> m_globalDisplayNoneStyleSheet;
     bool m_parsedGlobalDisplayNoneStyleSheet;
+    
+    String m_cachedDomain;
+    DFABytecodeInterpreter::Actions m_cachedDomainActions;
 };
 
 } // namespace ContentExtensions

Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (186911 => 186912)


--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp	2015-07-16 22:08:19 UTC (rev 186912)
@@ -90,47 +90,22 @@
         const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension();
         
         DFABytecodeInterpreter withoutDomainsInterpreter(compiledExtension.filtersWithoutDomainsBytecode(), compiledExtension.filtersWithoutDomainsBytecodeLength());
-        DFABytecodeInterpreter::Actions triggeredActions = withoutDomainsInterpreter.interpret(urlCString, flags);
+        DFABytecodeInterpreter::Actions withoutDomainsActions = withoutDomainsInterpreter.interpret(urlCString, flags);
         
-        // Check to see if there are any actions triggered with if- or unless-domain and check the domain if there are.
         DFABytecodeInterpreter withDomainsInterpreter(compiledExtension.filtersWithDomainsBytecode(), compiledExtension.filtersWithDomainsBytecodeLength());
+        DFABytecodeInterpreter::Actions withDomainsActions = withDomainsInterpreter.interpretWithDomains(urlCString, flags, contentExtension->cachedDomainActions(resourceLoadInfo.mainDocumentURL.host()));
         
-        DFABytecodeInterpreter::Actions withDomainsPossibleActions = withDomainsInterpreter.interpret(urlCString, flags);
-        if (!withDomainsPossibleActions.isEmpty()) {
-            DFABytecodeInterpreter domainsInterpreter(compiledExtension.domainFiltersBytecode(), compiledExtension.domainFiltersBytecodeLength());
-            DFABytecodeInterpreter::Actions domainsActions = domainsInterpreter.interpret(resourceLoadInfo.mainDocumentURL.host().utf8(), flags);
-            
-            DFABytecodeInterpreter::Actions ifDomainActions;
-            DFABytecodeInterpreter::Actions unlessDomainActions;
-            for (uint64_t action : domainsActions) {
-                if (action & IfDomainFlag)
-                    ifDomainActions.add(action);
-                else
-                    unlessDomainActions.add(action);
-            }
-            
-            for (uint64_t action : withDomainsPossibleActions) {
-                if (ifDomainActions.contains(action)) {
-                    // If an if-domain trigger matches, add the action.
-                    ASSERT(action & IfDomainFlag);
-                    triggeredActions.add(action & ~IfDomainFlag);
-                } else if (!(action & IfDomainFlag) && !unlessDomainActions.contains(action)) {
-                    // If this action did not need an if-domain, it must have been an unless-domain rule.
-                    // Add the action unless it matched an unless-domain trigger.
-                    triggeredActions.add(action);
-                }
-            }
-        }
-        
         const SerializedActionByte* actions = compiledExtension.actions();
         const unsigned actionsLength = compiledExtension.actionsLength();
         
         bool sawIgnorePreviousRules = false;
-        if (!triggeredActions.isEmpty()) {
-            Vector<unsigned> actionLocations;
-            actionLocations.reserveInitialCapacity(triggeredActions.size());
-            for (auto actionLocation : triggeredActions)
-                actionLocations.append(static_cast<unsigned>(actionLocation));
+        if (!withoutDomainsActions.isEmpty() || !withDomainsActions.isEmpty()) {
+            Vector<uint32_t> actionLocations;
+            actionLocations.reserveInitialCapacity(withoutDomainsActions.size() + withDomainsActions.size());
+            for (uint64_t actionLocation : withoutDomainsActions)
+                actionLocations.uncheckedAppend(static_cast<uint32_t>(actionLocation));
+            for (uint64_t actionLocation : withDomainsActions)
+                actionLocations.uncheckedAppend(static_cast<uint32_t>(actionLocation));
             std::sort(actionLocations.begin(), actionLocations.end());
 
             // Add actions in reverse order to properly deal with IgnorePreviousRules.

Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (186911 => 186912)


--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp	2015-07-16 22:08:19 UTC (rev 186912)
@@ -86,12 +86,22 @@
     }
 }
 
+static inline bool matchesDomain(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& domainActions)
+{
+    bool ifDomain = actionAndFlags & IfDomainFlag;
+    bool domain = domainActions.contains(actionAndFlags);
+    return ifDomain == domain;
+}
+
 void DFABytecodeInterpreter::interpretAppendAction(uint32_t& programCounter, Actions& actions, bool ifDomain)
 {
     ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendAction
         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionWithIfDomain
         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionDefaultStylesheet);
-    actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))));
+    uint64_t action = "" ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction)));
+    if (!m_domainActions || matchesDomain(action, *m_domainActions))
+        actions.add(action);
+    
     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfDomain));
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet));
@@ -104,13 +114,16 @@
     uint16_t flagsToCheck = getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
 
     uint16_t loadTypeFlags = flagsToCheck & LoadTypeMask;
-    uint16_t ressourceTypeFlags = flagsToCheck & ResourceTypeMask;
+    uint16_t resourceTypeFlags = flagsToCheck & ResourceTypeMask;
     
     bool loadTypeMatches = loadTypeFlags ? (loadTypeFlags & flags) : true;
-    bool ressourceTypeMatches = ressourceTypeFlags ? (ressourceTypeFlags & flags) : true;
+    bool resourceTypeMatches = resourceTypeFlags ? (resourceTypeFlags & flags) : true;
     
-    if (loadTypeMatches && ressourceTypeMatches)
-        actions.add((ifDomain ? IfDomainFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t))));
+    if (loadTypeMatches && resourceTypeMatches) {
+        uint64_t actionAndFlags = (ifDomain ? IfDomainFlag : 0) | (static_cast<uint64_t>(flagsToCheck) << 32) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t)));
+        if (!m_domainActions || matchesDomain(actionAndFlags, *m_domainActions))
+            actions.add(actionAndFlags);
+    }
     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain));
 }
@@ -142,6 +155,15 @@
     return actions;
 }
     
+DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpretWithDomains(const CString& urlCString, uint16_t flags, const DFABytecodeInterpreter::Actions& domainActions)
+{
+    ASSERT(!m_domainActions);
+    m_domainActions = &domainActions;
+    DFABytecodeInterpreter::Actions actions = interpret(urlCString, flags);
+    m_domainActions = nullptr;
+    return actions;
+}
+
 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpret(const CString& urlCString, uint16_t flags)
 {
     const char* url = ""

Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h (186911 => 186912)


--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h	2015-07-16 22:08:19 UTC (rev 186912)
@@ -50,6 +50,7 @@
     typedef HashSet<uint64_t, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> Actions;
     
     Actions interpret(const CString&, uint16_t flags);
+    Actions interpretWithDomains(const CString&, uint16_t flags, const DFABytecodeInterpreter::Actions& domainActions);
     Actions actionsForDefaultStylesheetFromDFARoot();
 
 private:
@@ -57,6 +58,7 @@
     void interpretTestFlagsAndAppendAction(unsigned& programCounter, uint16_t flags, Actions&, bool ifDomain);
     const DFABytecode* m_bytecode;
     const unsigned m_bytecodeLength;
+    const DFABytecodeInterpreter::Actions* m_domainActions { nullptr };
 };
 
 } // namespace ContentExtensions

Modified: trunk/Tools/ChangeLog (186911 => 186912)


--- trunk/Tools/ChangeLog	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Tools/ChangeLog	2015-07-16 22:08:19 UTC (rev 186912)
@@ -1,3 +1,14 @@
+2015-07-16  Alex Christensen  <[email protected]>
+
+        [Content Extensions] Cache domain actions
+        https://bugs.webkit.org/show_bug.cgi?id=146817
+
+        Reviewed by Benjamin Poulain.
+
+        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+        (TestWebKitAPI::TEST_F):
+        Test if-domain and unless-domain with multiple load types.
+
 2015-07-16  Benjamin Poulain  <[email protected]>
 
         [Content extensions] Combine suffixes when generating NFAs

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (186911 => 186912)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp	2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp	2015-07-16 22:08:19 UTC (rev 186912)
@@ -1204,6 +1204,38 @@
         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
     EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
     testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+    
+    auto backend6 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\",\"*w3c.org\"],\"resource-type\":[\"document\",\"script\"]}},"
+        "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore\",\"if-domain\":[\"*webkit.org\",\"w3c.org\"]}},"
+        "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\",\"whatwg.org\"],\"resource-type\":[\"script\",\"image\"],\"load-type\":[\"third-party\"]}}]");
+    EXPECT_EQ(nullptr, backend6.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+    testRequest(backend6, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest("http://whatwg.org"), { });
+    testRequest(backend6, mainDocumentRequest("http://sub.webkit.org"), { });
+    testRequest(backend6, mainDocumentRequest("http://sub.w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org"), { });
+    testRequest(backend6, mainDocumentRequest("http://webkit.org/ignore"), { }, true);
+    testRequest(backend6, mainDocumentRequest("http://w3c.org/ignore"), { }, true);
+    testRequest(backend6, mainDocumentRequest("http://whatwg.org/ignore"), { });
+    testRequest(backend6, mainDocumentRequest("http://sub.webkit.org/ignore"), { }, true);
+    testRequest(backend6, mainDocumentRequest("http://sub.w3c.org/ignore"), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org/ignore"), { });
+    testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://webkit.org/", ResourceType::Image), { });
+    testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://w3c.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+    testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://webkit.org/", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://webkit.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://w3c.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://example.com/", ResourceType::Script), { });
+    testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://webkit.org/", ResourceType::Image), { }, true);
+    testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.com/", ResourceType::Image), { });
+    testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+    testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://example.org/", ResourceType::Document), { });
+    testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Font), { });
+    testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Image), { }, true);
+    testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Font), { }, true);
+    testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Script), { });
+    testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://example.com/", ResourceType::Script), { });
 }
     
 TEST_F(ContentExtensionTest, InvalidJSON)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to