<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[175772] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/175772">175772</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-11-07 18:05:36 -0800 (Fri, 07 Nov 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make the Selector's specificity part of Selector matching
https://bugs.webkit.org/show_bug.cgi?id=138486

Reviewed by Andreas Kling.

In CSS Selectors Level 4, the specificity of selectors is computed dynamically
based on which element is being matched.

For example, a selector:
    :matches(#foo, .bar, baz)
has a specificity of
    (1, 0, 0) on &lt;baz id=foo class=bar&gt;
    (0, 1, 0) on &lt;baz class=bar&gt;
    (0, 0, 1) on &lt;baz&gt;

Previously, the specificity of each selector was computed statically when populating
RuleSet. With more recent CSS, this gives us the wrong specificity because we do not know
how the selectors applies to the target.

This patch moves one tiny step in the direction of dynamic specificity. The specificity
is removed from RuleSet and is moved inside Selector Matching.

There is one bit worth keeping static: matching based on rule hash. This path is important
to avoid spending time compiling trivial selectors.
In order to keep rule hash matching working, the RuleData store which specificity class
the rule has in addition to the information about matching/not-matching. When going through
the fast path in ElementCollector, we compute the right specificity based on the type
of rule-hash matching.

* css/CSSSelector.cpp:
(WebCore::CSSSelector::specificityForOneSelector):
* css/CSSSelector.h:
* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::addMatchedRule):
(WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
(WebCore::ElementRuleCollector::ruleMatches):
(WebCore::ElementRuleCollector::collectMatchingRulesForList):
(WebCore::compareRules):
* css/ElementRuleCollector.h:
* css/RuleSet.cpp:
(WebCore::computeMatchBasedOnRuleHash):
(WebCore::RuleData::RuleData):
(WebCore::isSelectorMatchingHTMLBasedOnRuleHash): Deleted.
* css/RuleSet.h:
(WebCore::RuleData::matchBasedOnRuleHash):
(WebCore::RuleData::hasRightmostSelectorMatchingHTMLBasedOnRuleHash): Deleted.
(WebCore::RuleData::specificity): Deleted.
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::match):
* css/SelectorChecker.h:
* css/StyleResolver.h:
(WebCore::checkRegionSelector):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
* cssjit/SelectorCompiler.h:
(WebCore::SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction):
(WebCore::SelectorCompiler::querySelectorSimpleSelectorCheckerFunction):
(WebCore::SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext):
(WebCore::SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext):
(WebCore::SelectorCompiler::simpleSelectorCheckerFunction): Deleted.
(WebCore::SelectorCompiler::selectorCheckerFunctionWithCheckingContext): Deleted.
* dom/SelectorQuery.cpp:
(WebCore::SelectorDataList::selectorMatches):
(WebCore::SelectorDataList::selectorClosest):
(WebCore::SelectorDataList::executeCompiledSimpleSelectorChecker):
(WebCore::SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext):
(WebCore::SelectorDataList::executeCompiledSingleMultiSelectorData):
(WebCore::SelectorDataList::execute):
* dom/SelectorQuery.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSSelectorcpp">trunk/Source/WebCore/css/CSSSelector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSSelectorh">trunk/Source/WebCore/css/CSSSelector.h</a></li>
<li><a href="#trunkSourceWebCorecssElementRuleCollectorcpp">trunk/Source/WebCore/css/ElementRuleCollector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssElementRuleCollectorh">trunk/Source/WebCore/css/ElementRuleCollector.h</a></li>
<li><a href="#trunkSourceWebCorecssRuleSetcpp">trunk/Source/WebCore/css/RuleSet.cpp</a></li>
<li><a href="#trunkSourceWebCorecssRuleSeth">trunk/Source/WebCore/css/RuleSet.h</a></li>
<li><a href="#trunkSourceWebCorecssSelectorCheckercpp">trunk/Source/WebCore/css/SelectorChecker.cpp</a></li>
<li><a href="#trunkSourceWebCorecssSelectorCheckerh">trunk/Source/WebCore/css/SelectorChecker.h</a></li>
<li><a href="#trunkSourceWebCorecssStyleResolverh">trunk/Source/WebCore/css/StyleResolver.h</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilerh">trunk/Source/WebCore/cssjit/SelectorCompiler.h</a></li>
<li><a href="#trunkSourceWebCoredomSelectorQuerycpp">trunk/Source/WebCore/dom/SelectorQuery.cpp</a></li>
<li><a href="#trunkSourceWebCoredomSelectorQueryh">trunk/Source/WebCore/dom/SelectorQuery.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/ChangeLog        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -1,3 +1,76 @@
</span><ins>+2014-11-07  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Make the Selector's specificity part of Selector matching
+        https://bugs.webkit.org/show_bug.cgi?id=138486
+
+        Reviewed by Andreas Kling.
+
+        In CSS Selectors Level 4, the specificity of selectors is computed dynamically
+        based on which element is being matched.
+
+        For example, a selector:
+            :matches(#foo, .bar, baz)
+        has a specificity of
+            (1, 0, 0) on &lt;baz id=foo class=bar&gt;
+            (0, 1, 0) on &lt;baz class=bar&gt;
+            (0, 0, 1) on &lt;baz&gt;
+
+        Previously, the specificity of each selector was computed statically when populating
+        RuleSet. With more recent CSS, this gives us the wrong specificity because we do not know
+        how the selectors applies to the target.
+
+        This patch moves one tiny step in the direction of dynamic specificity. The specificity
+        is removed from RuleSet and is moved inside Selector Matching.
+
+        There is one bit worth keeping static: matching based on rule hash. This path is important
+        to avoid spending time compiling trivial selectors.
+        In order to keep rule hash matching working, the RuleData store which specificity class
+        the rule has in addition to the information about matching/not-matching. When going through
+        the fast path in ElementCollector, we compute the right specificity based on the type
+        of rule-hash matching.
+
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::specificityForOneSelector):
+        * css/CSSSelector.h:
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::addMatchedRule):
+        (WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
+        (WebCore::ElementRuleCollector::ruleMatches):
+        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
+        (WebCore::compareRules):
+        * css/ElementRuleCollector.h:
+        * css/RuleSet.cpp:
+        (WebCore::computeMatchBasedOnRuleHash):
+        (WebCore::RuleData::RuleData):
+        (WebCore::isSelectorMatchingHTMLBasedOnRuleHash): Deleted.
+        * css/RuleSet.h:
+        (WebCore::RuleData::matchBasedOnRuleHash):
+        (WebCore::RuleData::hasRightmostSelectorMatchingHTMLBasedOnRuleHash): Deleted.
+        (WebCore::RuleData::specificity): Deleted.
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::match):
+        * css/SelectorChecker.h:
+        * css/StyleResolver.h:
+        (WebCore::checkRegionSelector):
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
+        * cssjit/SelectorCompiler.h:
+        (WebCore::SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction):
+        (WebCore::SelectorCompiler::querySelectorSimpleSelectorCheckerFunction):
+        (WebCore::SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext):
+        (WebCore::SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext):
+        (WebCore::SelectorCompiler::simpleSelectorCheckerFunction): Deleted.
+        (WebCore::SelectorCompiler::selectorCheckerFunctionWithCheckingContext): Deleted.
+        * dom/SelectorQuery.cpp:
+        (WebCore::SelectorDataList::selectorMatches):
+        (WebCore::SelectorDataList::selectorClosest):
+        (WebCore::SelectorDataList::executeCompiledSimpleSelectorChecker):
+        (WebCore::SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext):
+        (WebCore::SelectorDataList::executeCompiledSingleMultiSelectorData):
+        (WebCore::SelectorDataList::execute):
+        * dom/SelectorQuery.h:
+
</ins><span class="cx"> 2014-11-07  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSP is enforced for eval in report-only mode on first page load
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSSelectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSelector.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSelector.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/CSSSelector.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx"> {
</span><span class="cx">     switch (match()) {
</span><span class="cx">     case Id:
</span><del>-        return 0x10000;
</del><ins>+        return static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassA);
</ins><span class="cx"> 
</span><span class="cx">     case PagePseudoClass:
</span><span class="cx">         break;
</span><span class="lines">@@ -125,11 +125,11 @@
</span><span class="cx">     case Contain:
</span><span class="cx">     case Begin:
</span><span class="cx">     case End:
</span><del>-        return 0x100;
</del><ins>+        return static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassB);
</ins><span class="cx">     case Tag:
</span><del>-        return (tagQName().localName() != starAtom) ? 1 : 0;
</del><ins>+        return (tagQName().localName() != starAtom) ? static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassC) : 0;
</ins><span class="cx">     case PseudoElement:
</span><del>-        return 1;
</del><ins>+        return static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassC);
</ins><span class="cx">     case Unknown:
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSSelectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSelector.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSelector.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/CSSSelector.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -29,6 +29,12 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx">     class CSSSelectorList;
</span><span class="cx"> 
</span><ins>+    enum class SelectorSpecificityIncrement {
+        ClassA = 0x10000,
+        ClassB = 0x100,
+        ClassC = 1
+    };
+
</ins><span class="cx">     // this class represents a selector for a StyleRule
</span><span class="cx">     class CSSSelector {
</span><span class="cx">         WTF_MAKE_FAST_ALLOCATED;
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -86,11 +86,11 @@
</span><span class="cx">     return m_matchedRuleList;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void ElementRuleCollector::addMatchedRule(const RuleData* rule)
</del><ins>+inline void ElementRuleCollector::addMatchedRule(const MatchedRule&amp; matchedRule)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_matchedRules)
</span><del>-        m_matchedRules = std::make_unique&lt;Vector&lt;const RuleData*, 32&gt;&gt;();
-    m_matchedRules-&gt;append(rule);
</del><ins>+        m_matchedRules = std::make_unique&lt;Vector&lt;MatchedRule, 32&gt;&gt;();
+    m_matchedRules-&gt;append(matchedRule);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ElementRuleCollector::clearMatchedRules()
</span><span class="lines">@@ -202,18 +202,18 @@
</span><span class="cx"> 
</span><span class="cx">     sortMatchedRules();
</span><span class="cx"> 
</span><del>-    Vector&lt;const RuleData*, 32&gt;&amp; matchedRules = *m_matchedRules;
</del><ins>+    Vector&lt;MatchedRule, 32&gt;&amp; matchedRules = *m_matchedRules;
</ins><span class="cx">     if (m_mode == SelectorChecker::Mode::CollectingRules) {
</span><del>-        for (unsigned i = 0; i &lt; matchedRules.size(); ++i)
-            m_matchedRuleList.append(matchedRules[i]-&gt;rule());
</del><ins>+        for (const MatchedRule&amp; matchedRule : matchedRules)
+            m_matchedRuleList.append(matchedRule.ruleData-&gt;rule());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Now transfer the set of matched rules over to our list of declarations.
</span><del>-    for (unsigned i = 0; i &lt; matchedRules.size(); i++) {
-        if (m_style &amp;&amp; matchedRules[i]-&gt;containsUncommonAttributeSelector())
</del><ins>+    for (const MatchedRule&amp; matchedRule : matchedRules) {
+        if (m_style &amp;&amp; matchedRule.ruleData-&gt;containsUncommonAttributeSelector())
</ins><span class="cx">             m_style-&gt;setUnique();
</span><del>-        m_result.addMatchedProperties(matchedRules[i]-&gt;rule()-&gt;properties(), matchedRules[i]-&gt;rule(), matchedRules[i]-&gt;linkMatchType(), matchedRules[i]-&gt;propertyWhitelistType(MatchingUARulesScope::isMatchingUARules()));
</del><ins>+        m_result.addMatchedProperties(matchedRule.ruleData-&gt;rule()-&gt;properties(), matchedRule.ruleData-&gt;rule(), matchedRule.ruleData-&gt;linkMatchType(), matchedRule.ruleData-&gt;propertyWhitelistType(MatchingUARulesScope::isMatchingUARules()));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -274,12 +274,31 @@
</span><span class="cx">     sortAndTransferMatchedRules();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool ElementRuleCollector::ruleMatches(const RuleData&amp; ruleData)
</del><ins>+inline bool ElementRuleCollector::ruleMatches(const RuleData&amp; ruleData, unsigned&amp; specificity)
</ins><span class="cx"> {
</span><span class="cx">     // We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
</span><span class="cx">     // This is limited to HTML only so we don't need to check the namespace (because of tag name match).
</span><del>-    if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() &amp;&amp; m_element.isHTMLElement()) {
</del><ins>+    MatchBasedOnRuleHash matchBasedOnRuleHash = ruleData.matchBasedOnRuleHash();
+    if (matchBasedOnRuleHash != MatchBasedOnRuleHash::None &amp;&amp; m_element.isHTMLElement()) {
</ins><span class="cx">         ASSERT_WITH_MESSAGE(m_pseudoStyleRequest.pseudoId == NOPSEUDO, &quot;If we match based on the rule hash while collecting for a particular pseudo element ID, we would add incorrect rules for that pseudo element ID. We should never end in ruleMatches() with a pseudo element if the ruleData cannot match any pseudo element.&quot;);
</span><ins>+
+        switch (matchBasedOnRuleHash) {
+        case MatchBasedOnRuleHash::None:
+            ASSERT_NOT_REACHED();
+            break;
+        case MatchBasedOnRuleHash::Universal:
+            specificity = 0;
+            break;
+        case MatchBasedOnRuleHash::ClassA:
+            specificity = static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassA);
+            break;
+        case MatchBasedOnRuleHash::ClassB:
+            specificity = static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassB);
+            break;
+        case MatchBasedOnRuleHash::ClassC:
+            specificity = static_cast&lt;unsigned&gt;(SelectorSpecificityIncrement::ClassC);
+            break;
+        }
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -296,12 +315,15 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (compiledSelectorChecker &amp;&amp; ruleData.compilationStatus() == SelectorCompilationStatus::SimpleSelectorChecker) {
</span><del>-        SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, ruleData.compilationStatus());
-        ASSERT_WITH_MESSAGE(!selectorChecker(&amp;m_element) || m_pseudoStyleRequest.pseudoId == NOPSEUDO, &quot;When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.&quot;);
</del><ins>+        SelectorCompiler::RuleCollectorSimpleSelectorChecker selectorChecker = SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction(compiledSelectorChecker, ruleData.compilationStatus());
+#if !ASSERT_MSG_DISABLED
+        unsigned ignoreSpecificity;
+        ASSERT_WITH_MESSAGE(!selectorChecker(&amp;m_element, &amp;ignoreSpecificity) || m_pseudoStyleRequest.pseudoId == NOPSEUDO, &quot;When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.&quot;);
+#endif
</ins><span class="cx"> #if CSS_SELECTOR_JIT_PROFILING
</span><span class="cx">         ruleData.compiledSelectorUsed();
</span><span class="cx"> #endif
</span><del>-        return selectorChecker(&amp;m_element);
</del><ins>+        return selectorChecker(&amp;m_element, &amp;specificity);
</ins><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx"> 
</span><span class="lines">@@ -315,18 +337,18 @@
</span><span class="cx">     if (compiledSelectorChecker) {
</span><span class="cx">         ASSERT(ruleData.compilationStatus() == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
</span><span class="cx"> 
</span><del>-        SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, ruleData.compilationStatus());
</del><ins>+        SelectorCompiler::RuleCollectorSelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, ruleData.compilationStatus());
</ins><span class="cx"> 
</span><span class="cx"> #if CSS_SELECTOR_JIT_PROFILING
</span><span class="cx">         ruleData.compiledSelectorUsed();
</span><span class="cx"> #endif
</span><del>-        return selectorChecker(&amp;m_element, &amp;context);
</del><ins>+        return selectorChecker(&amp;m_element, &amp;context, &amp;specificity);
</ins><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx"> 
</span><span class="cx">     // Slow path.
</span><span class="cx">     SelectorChecker selectorChecker(m_element.document());
</span><del>-    return selectorChecker.match(ruleData.selector(), &amp;m_element, context);
</del><ins>+    return selectorChecker.match(ruleData.selector(), &amp;m_element, context, specificity);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ElementRuleCollector::collectMatchingRulesForList(const Vector&lt;RuleData&gt;* rules, const MatchRequest&amp; matchRequest, StyleResolver::RuleRange&amp; ruleRange)
</span><span class="lines">@@ -354,23 +376,24 @@
</span><span class="cx">         if (m_sameOriginOnly &amp;&amp; !ruleData.hasDocumentSecurityOrigin())
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        if (ruleMatches(ruleData)) {
</del><ins>+        unsigned specificity;
+        if (ruleMatches(ruleData, specificity)) {
</ins><span class="cx">             // Update our first/last rule indices in the matched rules array.
</span><span class="cx">             ++ruleRange.lastRuleIndex;
</span><span class="cx">             if (ruleRange.firstRuleIndex == -1)
</span><span class="cx">                 ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
</span><span class="cx"> 
</span><span class="cx">             // Add this rule to our list of matched rules.
</span><del>-            addMatchedRule(&amp;ruleData);
</del><ins>+            addMatchedRule({&amp;ruleData, specificity});
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool compareRules(const RuleData* r1, const RuleData* r2)
</del><ins>+static inline bool compareRules(MatchedRule r1, MatchedRule r2)
</ins><span class="cx"> {
</span><del>-    unsigned specificity1 = r1-&gt;specificity();
-    unsigned specificity2 = r2-&gt;specificity();
-    return (specificity1 == specificity2) ? r1-&gt;position() &lt; r2-&gt;position() : specificity1 &lt; specificity2;
</del><ins>+    unsigned specificity1 = r1.specificity;
+    unsigned specificity2 = r2.specificity;
+    return (specificity1 == specificity2) ? r1.ruleData-&gt;position() &lt; r2.ruleData-&gt;position() : specificity1 &lt; specificity2;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ElementRuleCollector::sortMatchedRules()
</span></span></pre></div>
<a id="trunkSourceWebCorecssElementRuleCollectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/ElementRuleCollector.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/ElementRuleCollector.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/ElementRuleCollector.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -38,6 +38,11 @@
</span><span class="cx"> class RuleSet;
</span><span class="cx"> class SelectorFilter;
</span><span class="cx"> 
</span><ins>+struct MatchedRule {
+    const RuleData* ruleData;
+    unsigned specificity;
+};
+
</ins><span class="cx"> class ElementRuleCollector {
</span><span class="cx"> public:
</span><span class="cx">     ElementRuleCollector(Element&amp; element, RenderStyle* style, const DocumentRuleSets&amp; ruleSets, const SelectorFilter&amp; selectorFilter)
</span><span class="lines">@@ -81,12 +86,12 @@
</span><span class="cx">     void collectMatchingRules(const MatchRequest&amp;, StyleResolver::RuleRange&amp;);
</span><span class="cx">     void collectMatchingRulesForRegion(const MatchRequest&amp;, StyleResolver::RuleRange&amp;);
</span><span class="cx">     void collectMatchingRulesForList(const Vector&lt;RuleData&gt;*, const MatchRequest&amp;, StyleResolver::RuleRange&amp;);
</span><del>-    bool ruleMatches(const RuleData&amp;);
</del><ins>+    bool ruleMatches(const RuleData&amp;, unsigned &amp;specificity);
</ins><span class="cx"> 
</span><span class="cx">     void sortMatchedRules();
</span><span class="cx">     void sortAndTransferMatchedRules();
</span><span class="cx"> 
</span><del>-    void addMatchedRule(const RuleData*);
</del><ins>+    void addMatchedRule(const MatchedRule&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Element&amp; m_element;
</span><span class="cx">     RenderStyle* m_style;
</span><span class="lines">@@ -100,7 +105,7 @@
</span><span class="cx">     SelectorChecker::Mode m_mode;
</span><span class="cx">     bool m_canUseFastReject;
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;Vector&lt;const RuleData*, 32&gt;&gt; m_matchedRules;
</del><ins>+    std::unique_ptr&lt;Vector&lt;MatchedRule, 32&gt;&gt; m_matchedRules;
</ins><span class="cx"> 
</span><span class="cx">     // Output.
</span><span class="cx">     Vector&lt;RefPtr&lt;StyleRule&gt;&gt; m_matchedRuleList;
</span></span></pre></div>
<a id="trunkSourceWebCorecssRuleSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/RuleSet.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/RuleSet.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/RuleSet.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -53,18 +53,28 @@
</span><span class="cx"> 
</span><span class="cx"> // -----------------------------------------------------------------
</span><span class="cx"> 
</span><del>-static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector&amp; selector)
</del><ins>+static inline MatchBasedOnRuleHash computeMatchBasedOnRuleHash(const CSSSelector&amp; selector)
</ins><span class="cx"> {
</span><span class="cx">     if (selector.tagHistory())
</span><del>-        return false;
</del><ins>+        return MatchBasedOnRuleHash::None;
</ins><span class="cx"> 
</span><span class="cx">     if (selector.match() == CSSSelector::Tag) {
</span><del>-        const AtomicString&amp; selectorNamespace = selector.tagQName().namespaceURI();
-        return selectorNamespace == starAtom || selectorNamespace == xhtmlNamespaceURI;
</del><ins>+        const QualifiedName&amp; tagQualifiedName = selector.tagQName();
+        const AtomicString&amp; selectorNamespace = tagQualifiedName.namespaceURI();
+        if (selectorNamespace == starAtom || selectorNamespace == xhtmlNamespaceURI) {
+            if (tagQualifiedName == anyQName())
+                return MatchBasedOnRuleHash::Universal;
+            return MatchBasedOnRuleHash::ClassC;
+        }
+        return MatchBasedOnRuleHash::None;
</ins><span class="cx">     }
</span><span class="cx">     if (SelectorChecker::isCommonPseudoClassSelector(&amp;selector))
</span><del>-        return true;
-    return selector.match() == CSSSelector::Id || selector.match() == CSSSelector::Class;
</del><ins>+        return MatchBasedOnRuleHash::ClassB;
+    if (selector.match() == CSSSelector::Id)
+        return MatchBasedOnRuleHash::ClassA;
+    if (selector.match() == CSSSelector::Class)
+        return MatchBasedOnRuleHash::ClassB;
+    return MatchBasedOnRuleHash::None;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool selectorCanMatchPseudoElement(const CSSSelector&amp; rootSelector)
</span><span class="lines">@@ -149,8 +159,7 @@
</span><span class="cx">     , m_selectorIndex(selectorIndex)
</span><span class="cx">     , m_hasDocumentSecurityOrigin(addRuleFlags &amp; RuleHasDocumentSecurityOrigin)
</span><span class="cx">     , m_position(position)
</span><del>-    , m_specificity(selector()-&gt;specificity())
-    , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(*selector()))
</del><ins>+    , m_matchBasedOnRuleHash(static_cast&lt;unsigned&gt;(computeMatchBasedOnRuleHash(*selector())))
</ins><span class="cx">     , m_canMatchPseudoElement(selectorCanMatchPseudoElement(*selector()))
</span><span class="cx">     , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector()))
</span><span class="cx">     , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
</span></span></pre></div>
<a id="trunkSourceWebCorecssRuleSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/RuleSet.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/RuleSet.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/RuleSet.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -54,6 +54,14 @@
</span><span class="cx"> class StyleRuleRegion;
</span><span class="cx"> class StyleSheetContents;
</span><span class="cx"> 
</span><ins>+enum class MatchBasedOnRuleHash : unsigned {
+    None,
+    Universal,
+    ClassA,
+    ClassB,
+    ClassC
+};
+
</ins><span class="cx"> class RuleData {
</span><span class="cx"> public:
</span><span class="cx">     static const unsigned maximumSelectorComponentCount = 8192;
</span><span class="lines">@@ -66,9 +74,8 @@
</span><span class="cx">     unsigned selectorIndex() const { return m_selectorIndex; }
</span><span class="cx"> 
</span><span class="cx">     bool canMatchPseudoElement() const { return m_canMatchPseudoElement; }
</span><del>-    bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
</del><ins>+    MatchBasedOnRuleHash matchBasedOnRuleHash() const { return static_cast&lt;MatchBasedOnRuleHash&gt;(m_matchBasedOnRuleHash); }
</ins><span class="cx">     bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
</span><del>-    unsigned specificity() const { return m_specificity; }
</del><span class="cx">     unsigned linkMatchType() const { return m_linkMatchType; }
</span><span class="cx">     bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
</span><span class="cx">     PropertyWhitelistType propertyWhitelistType(bool isMatchingUARules = false) const { return isMatchingUARules ? PropertyWhitelistNone : static_cast&lt;PropertyWhitelistType&gt;(m_propertyWhitelistType); }
</span><span class="lines">@@ -101,8 +108,7 @@
</span><span class="cx">     // This number was picked fairly arbitrarily. We can probably lower it if we need to.
</span><span class="cx">     // Some simple testing showed &lt;100,000 RuleData's on large sites.
</span><span class="cx">     unsigned m_position : 18;
</span><del>-    unsigned m_specificity : 24;
-    unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
</del><ins>+    unsigned m_matchBasedOnRuleHash : 3;
</ins><span class="cx">     unsigned m_canMatchPseudoElement : 1;
</span><span class="cx">     unsigned m_containsUncommonAttributeSelector : 1;
</span><span class="cx">     unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorChecker.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -168,7 +168,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext&amp; providedContext) const
</del><ins>+bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext&amp; providedContext, unsigned&amp; specificity) const
</ins><span class="cx"> {
</span><span class="cx">     CheckingContextWithStatus context(providedContext, selector, element);
</span><span class="cx">     PseudoId pseudoId = NOPSEUDO;
</span><span class="lines">@@ -176,6 +176,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (context.pseudoId != NOPSEUDO &amp;&amp; context.pseudoId != pseudoId)
</span><span class="cx">         return false;
</span><ins>+
+    specificity = selector-&gt;specificity();
</ins><span class="cx">     if (context.pseudoId == NOPSEUDO &amp;&amp; pseudoId != NOPSEUDO) {
</span><span class="cx">         if (context.resolvingMode == Mode::ResolvingStyle &amp;&amp; pseudoId &lt; FIRST_INTERNAL_PSEUDOID)
</span><span class="cx">             context.elementStyle-&gt;setHasPseudoStyle(pseudoId);
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorChecker.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorChecker.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/SelectorChecker.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">     struct CheckingContextWithStatus;
</span><span class="cx"> 
</span><del>-    bool match(const CSSSelector*, Element*, const CheckingContext&amp;) const;
</del><ins>+    bool match(const CSSSelector*, Element*, const CheckingContext&amp;, unsigned&amp; specificity) const;
</ins><span class="cx"> 
</span><span class="cx">     static bool tagMatches(const Element*, const QualifiedName&amp;);
</span><span class="cx">     static bool isCommonPseudoClassSelector(const CSSSelector*);
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleResolverh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleResolver.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleResolver.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/css/StyleResolver.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -572,7 +572,8 @@
</span><span class="cx">     SelectorChecker selectorChecker(regionElement-&gt;document());
</span><span class="cx">     for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
</span><span class="cx">         SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><del>-        if (selectorChecker.match(s, regionElement, selectorCheckingContext))
</del><ins>+        unsigned ignoredSpecificity;
+        if (selectorChecker.match(s, regionElement, selectorCheckingContext, ignoredSpecificity))
</ins><span class="cx">             return true;
</span><span class="cx">     }
</span><span class="cx">     return false;
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -357,9 +357,7 @@
</span><span class="cx">     StackAllocator::StackReference m_lastVisitedElement;
</span><span class="cx">     StackAllocator::StackReference m_startElement;
</span><span class="cx"> 
</span><del>-#if CSS_SELECTOR_JIT_DEBUGGING
</del><span class="cx">     const CSSSelector* m_originalSelector;
</span><del>-#endif
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> const Assembler::RegisterID SelectorCodeGenerator::returnRegister = JSC::GPRInfo::returnValueGPR;
</span><span class="lines">@@ -798,9 +796,7 @@
</span><span class="cx">     , m_functionType(FunctionType::SimpleSelectorChecker)
</span><span class="cx">     , m_visitedMode(VisitedMode::None)
</span><span class="cx">     , m_descendantBacktrackingStartInUse(false)
</span><del>-#if CSS_SELECTOR_JIT_DEBUGGING
</del><span class="cx">     , m_originalSelector(rootSelector)
</span><del>-#endif
</del><span class="cx"> {
</span><span class="cx"> #if CSS_SELECTOR_JIT_DEBUGGING
</span><span class="cx">     dataLogF(&quot;Compiling \&quot;%s\&quot;\n&quot;, m_originalSelector-&gt;selectorText().utf8().data());
</span><span class="lines">@@ -1609,6 +1605,14 @@
</span><span class="cx">         generateRequestedPseudoElementEqualsToSelectorPseudoElement(failureOnFunctionEntry, m_selectorFragments.first(), checkingContextRegister);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (m_selectorContext == SelectorContext::RuleCollector) {
+        unsigned specificity = m_originalSelector-&gt;specificity();
+        if (m_functionType == FunctionType::SelectorCheckerWithCheckingContext)
+            m_assembler.store32(Assembler::TrustedImm32(specificity), JSC::GPRInfo::argumentGPR2);
+        else
+            m_assembler.store32(Assembler::TrustedImm32(specificity), JSC::GPRInfo::argumentGPR1);
+    }
+
</ins><span class="cx">     computeBacktrackingMemoryRequirements(m_selectorFragments);
</span><span class="cx">     unsigned availableRegisterCount = m_registerAllocator.reserveCallerSavedRegisters(m_selectorFragments.registerRequirements);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -77,22 +77,37 @@
</span><span class="cx">     QuerySelector
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-typedef unsigned (*SimpleSelectorChecker)(Element*);
-typedef unsigned (*SelectorCheckerWithCheckingContext)(Element*, const SelectorChecker::CheckingContext*);
</del><ins>+typedef unsigned (*RuleCollectorSimpleSelectorChecker)(Element*, unsigned*);
+typedef unsigned (*QuerySelectorSimpleSelectorChecker)(Element*);
+
+typedef unsigned (*RuleCollectorSelectorCheckerWithCheckingContext)(Element*, const SelectorChecker::CheckingContext*, unsigned*);
+typedef unsigned (*QuerySelectorSelectorCheckerWithCheckingContext)(Element*, const SelectorChecker::CheckingContext*);
+
</ins><span class="cx"> SelectorCompilationStatus compileSelector(const CSSSelector*, JSC::VM*, SelectorContext, JSC::MacroAssemblerCodeRef&amp; outputCodeRef);
</span><span class="cx"> 
</span><del>-inline SimpleSelectorChecker simpleSelectorCheckerFunction(void* executableAddress, SelectorCompilationStatus compilationStatus)
</del><ins>+inline RuleCollectorSimpleSelectorChecker ruleCollectorSimpleSelectorCheckerFunction(void* executableAddress, SelectorCompilationStatus compilationStatus)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(compilationStatus, compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker);
</span><del>-    return reinterpret_cast&lt;SimpleSelectorChecker&gt;(executableAddress);
</del><ins>+    return reinterpret_cast&lt;RuleCollectorSimpleSelectorChecker&gt;(executableAddress);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline SelectorCheckerWithCheckingContext selectorCheckerFunctionWithCheckingContext(void* executableAddress, SelectorCompilationStatus compilationStatus)
</del><ins>+inline QuerySelectorSimpleSelectorChecker querySelectorSimpleSelectorCheckerFunction(void* executableAddress, SelectorCompilationStatus compilationStatus)
</ins><span class="cx"> {
</span><ins>+    ASSERT_UNUSED(compilationStatus, compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker);
+    return reinterpret_cast&lt;QuerySelectorSimpleSelectorChecker&gt;(executableAddress);
+}
+
+inline RuleCollectorSelectorCheckerWithCheckingContext ruleCollectorSelectorCheckerFunctionWithCheckingContext(void* executableAddress, SelectorCompilationStatus compilationStatus)
+{
</ins><span class="cx">     ASSERT_UNUSED(compilationStatus, compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
</span><del>-    return reinterpret_cast&lt;SelectorCheckerWithCheckingContext&gt;(executableAddress);
</del><ins>+    return reinterpret_cast&lt;RuleCollectorSelectorCheckerWithCheckingContext&gt;(executableAddress);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline QuerySelectorSelectorCheckerWithCheckingContext querySelectorSelectorCheckerFunctionWithCheckingContext(void* executableAddress, SelectorCompilationStatus compilationStatus)
+{
+    ASSERT_UNUSED(compilationStatus, compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
+    return reinterpret_cast&lt;QuerySelectorSelectorCheckerWithCheckingContext&gt;(executableAddress);
+}
</ins><span class="cx"> 
</span><span class="cx"> } // namespace SelectorCompiler
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomSelectorQuerycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/SelectorQuery.cpp (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/SelectorQuery.cpp        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -117,7 +117,8 @@
</span><span class="cx">     SelectorChecker selectorChecker(element.document());
</span><span class="cx">     SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">     selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &amp;rootNode;
</span><del>-    return selectorChecker.match(selectorData.selector, &amp;element, selectorCheckingContext);
</del><ins>+    unsigned ignoredSpecificity;
+    return selectorChecker.match(selectorData.selector, &amp;element, selectorCheckingContext, ignoredSpecificity);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Element* SelectorDataList::selectorClosest(const SelectorData&amp; selectorData, Element&amp; element, const ContainerNode&amp; rootNode) const
</span><span class="lines">@@ -126,7 +127,8 @@
</span><span class="cx">     SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">     selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &amp;rootNode;
</span><span class="cx">     Element* currentNode = &amp;element;
</span><del>-    if (!selectorChecker.match(selectorData.selector, currentNode, selectorCheckingContext))
</del><ins>+    unsigned ignoredSpecificity;
+    if (!selectorChecker.match(selectorData.selector, currentNode, selectorCheckingContext, ignoredSpecificity))
</ins><span class="cx">         return nullptr;
</span><span class="cx">     return currentNode;
</span><span class="cx"> }
</span><span class="lines">@@ -381,7 +383,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx"> template &lt;typename SelectorQueryTrait&gt;
</span><del>-ALWAYS_INLINE void SelectorDataList::executeCompiledSimpleSelectorChecker(const ContainerNode&amp; searchRootNode, SelectorCompiler::SimpleSelectorChecker selectorChecker, typename SelectorQueryTrait::OutputType&amp; output, const SelectorData&amp; selectorData) const
</del><ins>+ALWAYS_INLINE void SelectorDataList::executeCompiledSimpleSelectorChecker(const ContainerNode&amp; searchRootNode, SelectorCompiler::QuerySelectorSimpleSelectorChecker selectorChecker, typename SelectorQueryTrait::OutputType&amp; output, const SelectorData&amp; selectorData) const
</ins><span class="cx"> {
</span><span class="cx">     for (auto&amp; element : elementDescendants(const_cast&lt;ContainerNode&amp;&gt;(searchRootNode))) {
</span><span class="cx"> #if CSS_SELECTOR_JIT_PROFILING
</span><span class="lines">@@ -398,7 +400,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename SelectorQueryTrait&gt;
</span><del>-ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode&amp; rootNode, const ContainerNode&amp; searchRootNode, SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker, typename SelectorQueryTrait::OutputType&amp; output, const SelectorData&amp; selectorData) const
</del><ins>+ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode&amp; rootNode, const ContainerNode&amp; searchRootNode, SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext selectorChecker, typename SelectorQueryTrait::OutputType&amp; output, const SelectorData&amp; selectorData) const
</ins><span class="cx"> {
</span><span class="cx">     SelectorChecker::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules);
</span><span class="cx">     checkingContext.scope = rootNode.isDocumentNode() ? nullptr : &amp;rootNode;
</span><span class="lines">@@ -431,11 +433,11 @@
</span><span class="cx">             bool matched = false;
</span><span class="cx">             void* compiledSelectorChecker = m_selectors[i].compiledSelectorCodeRef.code().executableAddress();
</span><span class="cx">             if (m_selectors[i].compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) {
</span><del>-                SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, m_selectors[i].compilationStatus);
</del><ins>+                SelectorCompiler::QuerySelectorSimpleSelectorChecker selectorChecker = SelectorCompiler::querySelectorSimpleSelectorCheckerFunction(compiledSelectorChecker, m_selectors[i].compilationStatus);
</ins><span class="cx">                 matched = selectorChecker(&amp;element);
</span><span class="cx">             } else {
</span><span class="cx">                 ASSERT(m_selectors[i].compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
</span><del>-                SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, m_selectors[i].compilationStatus);
</del><ins>+                SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, m_selectors[i].compilationStatus);
</ins><span class="cx">                 matched = selectorChecker(&amp;element, &amp;checkingContext);
</span><span class="cx">             }
</span><span class="cx">             if (matched) {
</span><span class="lines">@@ -524,11 +526,11 @@
</span><span class="cx">         const SelectorData&amp; selectorData = m_selectors.first();
</span><span class="cx">         void* compiledSelectorChecker = selectorData.compiledSelectorCodeRef.code().executableAddress();
</span><span class="cx">         if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) {
</span><del>-            SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, selectorData.compilationStatus);
</del><ins>+            SelectorCompiler::QuerySelectorSimpleSelectorChecker selectorChecker = SelectorCompiler::querySelectorSimpleSelectorCheckerFunction(compiledSelectorChecker, selectorData.compilationStatus);
</ins><span class="cx">             executeCompiledSimpleSelectorChecker&lt;SelectorQueryTrait&gt;(*searchRootNode, selectorChecker, output, selectorData);
</span><span class="cx">         } else {
</span><span class="cx">             ASSERT(selectorData.compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
</span><del>-            SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, selectorData.compilationStatus);
</del><ins>+            SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, selectorData.compilationStatus);
</ins><span class="cx">             executeCompiledSelectorCheckerWithCheckingContext&lt;SelectorQueryTrait&gt;(rootNode, *searchRootNode, selectorChecker, output, selectorData);
</span><span class="cx">         }
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceWebCoredomSelectorQueryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/SelectorQuery.h (175771 => 175772)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/SelectorQuery.h        2014-11-08 00:40:54 UTC (rev 175771)
+++ trunk/Source/WebCore/dom/SelectorQuery.h        2014-11-08 02:05:36 UTC (rev 175772)
</span><span class="lines">@@ -89,8 +89,8 @@
</span><span class="cx">     template &lt;typename SelectorQueryTrait&gt; void executeSingleSelectorData(const ContainerNode&amp; rootNode, const SelectorData&amp;, typename SelectorQueryTrait::OutputType&amp;) const;
</span><span class="cx">     template &lt;typename SelectorQueryTrait&gt; void executeSingleMultiSelectorData(const ContainerNode&amp; rootNode, typename SelectorQueryTrait::OutputType&amp;) const;
</span><span class="cx"> #if ENABLE(CSS_SELECTOR_JIT)
</span><del>-    template &lt;typename SelectorQueryTrait&gt; void executeCompiledSimpleSelectorChecker(const ContainerNode&amp; searchRootNode, SelectorCompiler::SimpleSelectorChecker, typename SelectorQueryTrait::OutputType&amp;, const SelectorData&amp;) const;
-    template &lt;typename SelectorQueryTrait&gt; void executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode&amp; rootNode, const ContainerNode&amp; searchRootNode, SelectorCompiler::SelectorCheckerWithCheckingContext, typename SelectorQueryTrait::OutputType&amp;, const SelectorData&amp;) const;
</del><ins>+    template &lt;typename SelectorQueryTrait&gt; void executeCompiledSimpleSelectorChecker(const ContainerNode&amp; searchRootNode, SelectorCompiler::QuerySelectorSimpleSelectorChecker, typename SelectorQueryTrait::OutputType&amp;, const SelectorData&amp;) const;
+    template &lt;typename SelectorQueryTrait&gt; void executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode&amp; rootNode, const ContainerNode&amp; searchRootNode, SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext, typename SelectorQueryTrait::OutputType&amp;, const SelectorData&amp;) const;
</ins><span class="cx">     template &lt;typename SelectorQueryTrait&gt; void executeCompiledSingleMultiSelectorData(const ContainerNode&amp; rootNode, typename SelectorQueryTrait::OutputType&amp;) const;
</span><span class="cx">     static bool compileSelector(const SelectorData&amp;, const ContainerNode&amp; rootNode);
</span><span class="cx"> #endif // ENABLE(CSS_SELECTOR_JIT)
</span></span></pre>
</div>
</div>

</body>
</html>