Bug 76019 - Improve bit-packing of CSSValue, CSSPrimitiveValue and CSSValueList.
Summary: Improve bit-packing of CSSValue, CSSPrimitiveValue and CSSValueList.
Status: RESOLVED WONTFIX
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Luke Macpherson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-10 18:52 PST by Luke Macpherson
Modified: 2012-01-18 04:57 PST (History)
12 users (show)

See Also:


Attachments
Patch (40.79 KB, patch)
2012-01-10 19:16 PST, Luke Macpherson
no flags Details | Formatted Diff | Diff
Patch (38.92 KB, patch)
2012-01-11 14:01 PST, Luke Macpherson
no flags Details | Formatted Diff | Diff
Patch (39.17 KB, patch)
2012-01-11 15:49 PST, Luke Macpherson
no flags Details | Formatted Diff | Diff
Patch (39.23 KB, patch)
2012-01-11 20:24 PST, Luke Macpherson
kling: review-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Luke Macpherson 2012-01-10 18:52:17 PST
Improve bit-packing of CSSValue, CSSPrimitiveValue and CSSValueList.
Comment 1 Luke Macpherson 2012-01-10 19:16:17 PST
Created attachment 121961 [details]
Patch
Comment 2 Andreas Kling 2012-01-11 06:00:14 PST
The CSSPrimitiveValue::UnitTypes change (reassignment of enum values) is web- and API-facing, as you can retrieve the primitive value type via CSSPrimitiveValue.primitiveType.

Not sure that's something we want to do.
Comment 3 Luke Macpherson 2012-01-11 13:53:06 PST
I'll move that part into a separate CL - saving that bit isn't particularly critical anyway (due to padding).
Comment 4 Luke Macpherson 2012-01-11 14:01:03 PST
Created attachment 122092 [details]
Patch
Comment 5 WebKit Review Bot 2012-01-11 14:21:20 PST
Comment on attachment 122092 [details]
Patch

Attachment 122092 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/11170556
Comment 6 Early Warning System Bot 2012-01-11 14:55:29 PST
Comment on attachment 122092 [details]
Patch

Attachment 122092 [details] did not pass qt-ews (qt):
Output: http://queues.webkit.org/results/11213166
Comment 7 Gyuyoung Kim 2012-01-11 15:20:05 PST
Comment on attachment 122092 [details]
Patch

Attachment 122092 [details] did not pass efl-ews (efl):
Output: http://queues.webkit.org/results/11219003
Comment 8 Tony Chang 2012-01-11 15:45:57 PST
Comment on attachment 122092 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=122092&action=review

Luke, can you get some numbers on how much memory this saves?  E.g., you could instrument the code to count how many CSSValues there are at a given time.

> Source/WebCore/css/CSSPrimitiveValue.h:61
> +    unsigned char m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes
> +    mutable bool m_hasCachedCSSText : 1;
> +    bool m_isQuirkValue : 1;

This adds up to 9.  Is that intentional?  I didn't think the bits packed across classes.
Comment 9 Luke Macpherson 2012-01-11 15:49:14 PST
Created attachment 122112 [details]
Patch
Comment 10 Luke Macpherson 2012-01-11 15:52:08 PST
(In reply to comment #8)
> (From update of attachment 122092 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=122092&action=review
> 
> Luke, can you get some numbers on how much memory this saves?  E.g., you could instrument the code to count how many CSSValues there are at a given time.
> 
> > Source/WebCore/css/CSSPrimitiveValue.h:61
> > +    unsigned char m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes
> > +    mutable bool m_hasCachedCSSText : 1;
> > +    bool m_isQuirkValue : 1;
> 
> This adds up to 9.  Is that intentional?  I didn't think the bits packed across classes.

Yes. It doesn't really matter here as this is going to pad out to 4-8 bytes anyway. And no, that's not a regression. Getting it down to six is something I think is doable, but I'll save that for another patch.
Comment 11 Luke Macpherson 2012-01-11 16:38:47 PST
(In reply to comment #8)
> (From update of attachment 122092 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=122092&action=review
> 
> Luke, can you get some numbers on how much memory this saves?  E.g., you could instrument the code to count how many CSSValues there are at a given time.

Some quick instrumentation shows that for gmail I have 6422 CSSValues allocated simultaneously, and 5321 of those are CSSPrimitiveValue. So for gmail I would only expect this change to save 4k of memory in that case, since CSSPrimitiveValue's size is unchanged, while all other descendants of CSSValue are 4 bytes smaller.

The other value of this change is that it restores separation of concerns to the codebase - member variables of CSSPrimitiveValue no longer leak into CSSValue, whose sole purpose becomes a devirtualized dispatcher for concrete value types.
Comment 12 Luke Macpherson 2012-01-11 20:24:40 PST
Created attachment 122162 [details]
Patch
Comment 13 Andreas Kling 2012-01-13 05:43:05 PST
Comment on attachment 122162 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=122162&action=review

> Source/WebCore/css/CSSPrimitiveValue.h:57
> +    CSSPrimitiveValueBase() : CSSValue(PrimitiveClass), m_primitiveUnitType(0), m_hasCachedCSSText(false), m_isQuirkValue(false) { }
> +    CSSPrimitiveValueBase(ClassType type) : CSSValue(type), m_primitiveUnitType(0), m_hasCachedCSSText(false), m_isQuirkValue(false) { }

These constructors should be protected, nobody should ever construct a standalone CSSPrimitiveValueBase.
Comment 14 Andreas Kling 2012-01-13 05:50:14 PST
Comment on attachment 122162 [details]
Patch

I'm not convinced we should be introducing bitfield refcounts, it feels like we're scratching at something of a Pandora's box here:

- It introduces an arbitrary inconsistency in how many refs different objects can have.
- It's no longer possible to take the address of a ref counter. (Something the JSC JIT has used in the past, not sure if we'll need it again.)

The CSSPrimitiveValueBase change is great on its own.
Comment 15 Ryosuke Niwa 2012-01-17 15:29:33 PST
I don't think we want to make this change. In addition to the points kling pointed out, using bitfields for the ref-count will make ref/deref slower and bloats the code size where these functions are called. Also, implementing an variant makes the future refactoring harder.
Comment 16 Luke Macpherson 2012-01-17 16:11:07 PST
(In reply to comment #15)
Ok, let me respond to the points raised:
1) It introduces an arbitrary inconsistency in how many refs different objects can have.
Are there any cases where this is actually important? Code would have to be pretty poorly designed to require more than 67 million references to a single CSSValue, and even then I have ASSERTs to catch this case in debug mode.

2) It's no longer possible to take the address of a ref counter. (Something the JSC JIT has used in the past, not sure if we'll need it again.)
While I'm wary of debating what code might look like in the future, JIT code should probably be calling a code stub to access values like this, not reaching into data structures directly.

3) Using bitfields for the ref-count will make ref/deref slower and bloats the code size where these functions are called.
This is probably incorrect for modern processors, where code tends to be cache and bus limited. Packing common fields like this is likely to actually yield improved performance in practice through better cache utilization, though I suspect it would be too insignificant to measure in this case.

4). Implementing an variant makes the future refactoring harder.
RefPtr and friends are designed to use templates to handle this exact situation. They do not require classes to extend RefCounted. You can therefore re-factor RefCounted completely independently of other RefPtr-able objects.
Comment 17 Antti Koivisto 2012-01-18 04:57:30 PST
There are also plans for a wider refactoring of the stylesheet structures which may remove the need for refcounting for common CSSValues. I agree with kling and rniwa, we shouldn't do this now. Marking as WONTFIX to indicate this.