Changeset 153699 in webkit


Ignore:
Timestamp:
Aug 4, 2013 8:57:13 AM (11 years ago)
Author:
akling@apple.com
Message:

Inserting a rule into an empty style sheet shouldn't trigger style recalc unless necessary.
<http://webkit.org/b/119475>
<rdar://problem/14643481>

Reviewed by Antti Koivisto.

This is kind of a cheesy optimization, but it turns out that the use case is quite common.
The pattern goes like this:

(1) Create <style> element.
(2) Add it to the document's <head>.
(3) .addRule() one rule through the CSSOM API.

Prior to this patch, (3) would always cause a full (deferred) style recalc.

Now that we exclude empty style sheets from the document's (effective) active set,
we can piggyback on the style invalidation analysis when transitioning from an empty
sheet to a single-rule sheet.

In other words, add a special code path for the first rule insertion into an empty,
in-document style sheet to minimize the amount of invalidation that happens.

  • css/CSSStyleSheet.cpp:

(WebCore::CSSStyleSheet::didMutateRules):
(WebCore::CSSStyleSheet::insertRule):

  • css/CSSStyleSheet.h:

(WebCore::CSSStyleSheet::RuleMutationScope::RuleMutationScope):
(WebCore::CSSStyleSheet::RuleMutationScope::~RuleMutationScope):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r153698 r153699  
     12013-08-04  Andreas Kling  <akling@apple.com>
     2
     3        Inserting a rule into an empty style sheet shouldn't trigger style recalc unless necessary.
     4        <http://webkit.org/b/119475>
     5        <rdar://problem/14643481>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        This is kind of a cheesy optimization, but it turns out that the use case is quite common.
     10        The pattern goes like this:
     11
     12            (1) Create <style> element.
     13            (2) Add it to the document's <head>.
     14            (3) .addRule() one rule through the CSSOM API.
     15
     16        Prior to this patch, (3) would always cause a full (deferred) style recalc.
     17
     18        Now that we exclude empty style sheets from the document's (effective) active set,
     19        we can piggyback on the style invalidation analysis when transitioning from an empty
     20        sheet to a single-rule sheet.
     21
     22        In other words, add a special code path for the first rule insertion into an empty,
     23        in-document style sheet to minimize the amount of invalidation that happens.
     24
     25        * css/CSSStyleSheet.cpp:
     26        (WebCore::CSSStyleSheet::didMutateRules):
     27        (WebCore::CSSStyleSheet::insertRule):
     28        * css/CSSStyleSheet.h:
     29        (WebCore::CSSStyleSheet::RuleMutationScope::RuleMutationScope):
     30        (WebCore::CSSStyleSheet::RuleMutationScope::~RuleMutationScope):
     31
    1322013-08-04  Claudio Saavedra  <csaavedra@igalia.com>
    233
  • trunk/Source/WebCore/css/CSSStyleSheet.cpp

    r153641 r153699  
    148148}
    149149
    150 void CSSStyleSheet::didMutateRules()
     150void CSSStyleSheet::didMutateRules(RuleMutationType mutationType)
    151151{
    152152    ASSERT(m_contents->isMutable());
    153153    ASSERT(m_contents->hasOneClient());
    154154
    155     didMutate();
     155    Document* owner = ownerDocument();
     156    if (!owner)
     157        return;
     158    owner->styleResolverChanged(mutationType == InsertionIntoEmptySheet ? DeferRecalcStyleIfNeeded : DeferRecalcStyle);
    156159}
    157160
     
    276279        return 0;
    277280    }
    278     RuleMutationScope mutationScope(this);
     281
     282    RuleMutationType mutationType = !length() ? InsertionIntoEmptySheet : OtherMutation;
     283    RuleMutationScope mutationScope(this, mutationType);
    279284
    280285    bool success = m_contents->wrapperInsertRule(rule, index);
  • trunk/Source/WebCore/css/CSSStyleSheet.h

    r153641 r153699  
    8686    void setTitle(const String& title) { m_title = title; }
    8787
     88    enum RuleMutationType { OtherMutation, InsertionIntoEmptySheet };
     89
    8890    class RuleMutationScope {
    8991        WTF_MAKE_NONCOPYABLE(RuleMutationScope);
    9092    public:
    91         RuleMutationScope(CSSStyleSheet*);
     93        RuleMutationScope(CSSStyleSheet*, RuleMutationType = OtherMutation);
    9294        RuleMutationScope(CSSRule*);
    9395        ~RuleMutationScope();
     
    9597    private:
    9698        CSSStyleSheet* m_styleSheet;
     99        RuleMutationType m_mutationType;
    97100    };
    98101
    99102    void willMutateRules();
    100     void didMutateRules();
     103    void didMutateRules(RuleMutationType = OtherMutation);
    101104    void didMutate();
    102105   
     
    129132};
    130133
    131 inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSStyleSheet* sheet)
     134inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSStyleSheet* sheet, RuleMutationType mutationType)
    132135    : m_styleSheet(sheet)
     136    , m_mutationType(mutationType)
    133137{
    134138    if (m_styleSheet)
     
    138142inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSRule* rule)
    139143    : m_styleSheet(rule ? rule->parentStyleSheet() : 0)
     144    , m_mutationType(OtherMutation)
    140145{
    141146    if (m_styleSheet)
     
    146151{
    147152    if (m_styleSheet)
    148         m_styleSheet->didMutateRules();
     153        m_styleSheet->didMutateRules(m_mutationType);
    149154}
    150155
Note: See TracChangeset for help on using the changeset viewer.