Bug 102901 - Implement CSSValue::equals(const CSSValue&) to optimise CSSValue comparison
Summary: Implement CSSValue::equals(const CSSValue&) to optimise CSSValue comparison
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Alexander Shalamov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-21 01:42 PST by Alexander Pavlov (apavlov)
Modified: 2013-10-17 13:05 PDT (History)
20 users (show)

See Also:


Attachments
Patch 1 (66.98 KB, patch)
2012-11-29 04:46 PST, Alexander Shalamov
no flags Details | Formatted Diff | Diff
Patch 2 (66.84 KB, patch)
2012-11-30 01:08 PST, Alexander Shalamov
buildbot: commit-queue-
Details | Formatted Diff | Diff
Patch 3 (67.09 KB, patch)
2012-12-03 05:03 PST, Alexander Shalamov
buildbot: commit-queue-
Details | Formatted Diff | Diff
Patch 4 (67.02 KB, patch)
2012-12-04 09:40 PST, Alexander Shalamov
koivisto: review-
Details | Formatted Diff | Diff
Patch 5 (80.28 KB, patch)
2013-01-17 00:21 PST, Alexander Shalamov
buildbot: commit-queue-
Details | Formatted Diff | Diff
Patch 6 (80.29 KB, patch)
2013-01-21 01:30 PST, Alexander Shalamov
koivisto: review+
Details | Formatted Diff | Diff
Patch 7 (85.24 KB, patch)
2013-01-28 01:24 PST, Alexander Shalamov
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
Patch 8 (85.20 KB, patch)
2013-02-11 00:28 PST, Alexander Shalamov
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Pavlov (apavlov) 2012-11-21 01:42:37 PST
This can immensely speed up CSSValue comparisons.
Comment 1 Alexander Shalamov 2012-11-29 04:46:06 PST
Created attachment 176706 [details]
Patch 1

First patch for initial review.
Comment 2 WebKit Review Bot 2012-11-29 04:50:39 PST
Attachment 176706 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/ChangeLog', u'Source/WebCor..." exit_code: 1
Source/WebCore/css/CSSCalculationValue.h:64:  enum members should use InterCaps with an initial capital letter.  [readability/enum_casing] [4]
Source/WebCore/css/CSSCalculationValue.h:65:  enum members should use InterCaps with an initial capital letter.  [readability/enum_casing] [4]
Total errors found: 2 in 68 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 3 Alexander Pavlov (apavlov) 2012-11-29 05:08:11 PST
Comment on attachment 176706 [details]
Patch 1

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

A small style sanity check

> Source/WebCore/css/CSSValue.cpp:101
> +        ;    }

inadvertent change?

> Source/WebCore/css/Counter.h:49
> +        && listStyle() == rhs.listStyle()

Continuation lines should be indented relative to the first line

> Source/WebCore/css/DashboardRegion.h:36
> +        && m_isCircle == rhs.m_isCircle && m_isRectangle == rhs.m_isRectangle

Ditto

> Source/WebCore/css/Rect.h:45
> +        && *m_left == *rhs.m_left && *m_bottom == *rhs.m_bottom;

Ditto
Comment 4 Alexander Shalamov 2012-11-30 01:08:05 PST
Created attachment 176917 [details]
Patch 2

- Removed extra ";" : Source/WebCore/css/CSSValue.cpp:101
- Fixed indentation for: Source/WebCore/css/Counter.h:49, Source/WebCore/css/DashboardRegion.h:36, Source/WebCore/css/Rect.h:45
- Fixed CSSCalcExpressionNode::Type enum to make style checker happy
Comment 5 Build Bot 2012-12-01 01:50:56 PST
Comment on attachment 176917 [details]
Patch 2

Attachment 176917 [details] did not pass win-ews (win):
Output: http://queues.webkit.org/results/15060635
Comment 6 Alexander Shalamov 2012-12-03 05:03:36 PST
Created attachment 177233 [details]
Patch 3

- Added #include "CSSPrimitiveValueMappings.h" to CSSValue.cpp
Comment 7 Build Bot 2012-12-03 05:39:51 PST
Comment on attachment 177233 [details]
Patch 3

Attachment 177233 [details] did not pass win-ews (win):
Output: http://queues.webkit.org/results/15101481
Comment 8 Darin Adler 2012-12-03 10:39:06 PST
I did not have a chance to read the patch, but I do have a comment: It’s good to implement equality checks. But it’s usually not safe to have a == operator that is virtual, since it’s so easy to slice rather than comparing correctly. I think we probably want a named function rather than the == operator here.
Comment 9 Alexander Shalamov 2012-12-03 10:59:00 PST
(In reply to comment #8)
> I did not have a chance to read the patch, but I do have a comment: It’s good to implement equality checks. But it’s usually not safe to have a == operator that is virtual, since it’s so easy to slice rather than comparing correctly. I think we probably want a named function rather than the == operator here.

There is no virtual operator in CSSValue, if I would have added virtual method / operator, that would have increased the size of CSSValue and it's children.

I could rename operator== to method bool CSSValue::equals(const CSSValue&) const;
Comment 10 Alexander Shalamov 2012-12-04 09:40:26 PST
Created attachment 177501 [details]
Patch 4

- rebased to master
- Fix for win bot compilation error. CSSPrimitiveValue conversion operator was generated twice.
Comment 11 Antti Koivisto 2012-12-18 04:51:21 PST
Comment on attachment 177501 [details]
Patch 4

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

This introduces lots of new code, some of it pretty complex, and I suspect we lack sufficient test coverage for it. Since the operators are already used it should be possible to write a layout test that systematically tests them in all the value types (at minimum verifying that equal values really compare equal).

> Source/WebCore/css/CSSBasicShapes.cpp:81
> +    if (type() == shape.type()) {
> +        const CSSBasicShapeRectangle& rhs = static_cast<const CSSBasicShapeRectangle&>(shape);

It would be nicer to use early returns. 

if (type() != shape.type())
    return false;
...

to avoid indenting large blocks. This comment applies to many places in this patch.

> Source/WebCore/css/CSSBasicShapes.cpp:82
> +        return *m_x == *rhs.m_x && *m_y == *rhs.m_y && *m_width == *rhs.m_width && *m_height == *rhs.m_height

Do we know m_x and pals can't be null? This patch has lots of unexplained dereferencing.

> Source/WebCore/css/CSSBasicShapes.cpp:84
> +            && m_radiusX ? rhs.m_radiusX && *m_radiusX == *rhs.m_radiusX : !rhs.m_radiusX
> +            && m_radiusY ? rhs.m_radiusY && *m_radiusY == *rhs.m_radiusY : !rhs.m_radiusY;

This is fairly hard to read. It might be useful to have an inline template function for comparing CSSValue pointers. 

Some CSSValues, especially CSSPrimitiveValues are shared via CSSValuePool. Equality test should always involve pointer comparison first.

> Source/WebCore/css/CSSBorderImageSliceValue.cpp:53
> +bool CSSBorderImageSliceValue::operator==(const CSSBorderImageSliceValue& rhs) const

I think elsewhere we generally use 'other' as variable name in operator==. 'rsh' sounds strange.

> Source/WebCore/css/CSSPrimitiveValue.cpp:1261
> +    if (m_primitiveUnitType == rhs.m_primitiveUnitType)
> +        switch (m_primitiveUnitType) {

Use early return.

> Source/WebCore/css/CSSValue.cpp:293
> +    if (m_classType == rhs.m_classType) {
> +        switch (m_classType) {

Use early return.
Comment 12 Antti Koivisto 2012-12-18 04:58:23 PST
> There is no virtual operator in CSSValue, if I would have added virtual method / operator, that would have increased the size of CSSValue and it's children.
> 
> I could rename operator== to method bool CSSValue::equals(const CSSValue&) const;

This is still essentially a virtual method with vtable implemented by hand. I agree with Daring that having this as a named function would be better. CSSValue are always pointers and the required dereferencing is bug prone and looks ugly too.
Comment 13 Alexander Shalamov 2013-01-17 00:21:04 PST
Created attachment 183132 [details]
Patch 5

Fixed patch according to Antti's comments:

- Renamed operator== to equals method
- Added template function to compare two RefPtrs that contain CSSValue objects
- Used early returns wherever possible
- Added layout test. Test creates stylesheet and then inserts html snippet with inline style that duplicates style in document stylesheet. If inline style and document style css property have equal cssvalues, inline style is removed from inserted element.
Comment 14 Build Bot 2013-01-17 10:55:20 PST
Comment on attachment 183132 [details]
Patch 5

Attachment 183132 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/15942085
Comment 15 Build Bot 2013-01-17 11:23:58 PST
Comment on attachment 183132 [details]
Patch 5

Attachment 183132 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/15914936
Comment 16 Alexander Shalamov 2013-01-21 01:30:30 PST
Created attachment 183732 [details]
Patch 6

- Fixed dashboard region value comparison.
Comment 17 Alexander Pavlov (apavlov) 2013-01-21 02:29:56 PST
Comment on attachment 183732 [details]
Patch 6

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

> Source/WebCore/css/CSSBasicShapes.cpp:80
> +    if (type() != shape.type())

For all CSSBasicShapes, you can use the corresponding Type literal instead of type() for the sake of speed, since this->type() value is known at compile time, and there's no need to invoke another virtual method.

> Source/WebCore/css/CSSGradientValue.h:59
> +        && compareCSSValuePtr<CSSPrimitiveValue>(m_position, other.m_position);

missing indent
Comment 18 Antti Koivisto 2013-01-21 03:07:54 PST
Comment on attachment 183732 [details]
Patch 6

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

r=me with some comments.

> LayoutTests/cssom/cssvalue-comparison-expected.txt:4
> +PASS Two CSSValues "20%" for property "width" are equal. 

This could also include a test per type sanity checking that non-equal values don't compare equal.

> Source/WebCore/css/CSSValue.cpp:81
> +template<class ChildClassType>
> +inline static bool compareCSSValues(const CSSValue& first, const CSSValue& second)
> +{
> +    return static_cast<const ChildClassType&>(first).equals(static_cast<const ChildClassType&>(second));
> +}

This helper could be just above the only function that uses it.

> Source/WebCore/css/CSSValue.h:246
> +    size_t size = firstVector.size();
> +    if (size == secondVector.size()) {
> +        for (size_t i = 0; i < size; i++) {

Could do early return instead.

> Source/WebCore/css/FontValue.cpp:75
> +    return compareCSSValuePtr<CSSPrimitiveValue>(style, other.style)
> +        && compareCSSValuePtr<CSSPrimitiveValue>(variant, other.variant)
> +        && compareCSSValuePtr<CSSPrimitiveValue>(weight, other.weight)
> +        && compareCSSValuePtr<CSSPrimitiveValue>(size, other.size)
> +        && compareCSSValuePtr<CSSPrimitiveValue>(lineHeight, other.lineHeight)
> +        && compareCSSValuePtr<CSSValueList>(family, other.family);

Shouldn't the compiler be able to figure out the template argument type without providing it explicitly pretty much everywhere?
Comment 19 Ryosuke Niwa 2013-01-21 03:14:19 PST
Excellent! Thanks for the patch. I can make a lot of improvements in the editing code now.
Comment 20 Alexander Shalamov 2013-01-28 01:24:57 PST
Created attachment 184951 [details]
Patch 7

Fixes based on review comments from Alexander and Antti.
- Used literal to compare CSSBasicShapes type
- Fixed indent in Source/WebCore/css/CSSGradientValue.h:59
- Added test for non-equality of cssvalue objects
- Moved helper function above the function in CSSValue.cpp
- Return early in Source/WebCore/css/CSSValue.h:246
- Omit template arguments whenever possible (hopefully msvc could deduct template parameter from arguments)
Comment 21 Alexander Pavlov (apavlov) 2013-02-06 05:06:11 PST
Alexander,

Did you mean to set r? on your patch? Otherwise it is not visible in the review queue.

(In reply to comment #20)
> Created an attachment (id=184951) [details]
> Patch 7
> 
> Fixes based on review comments from Alexander and Antti.
> - Used literal to compare CSSBasicShapes type
> - Fixed indent in Source/WebCore/css/CSSGradientValue.h:59
> - Added test for non-equality of cssvalue objects
> - Moved helper function above the function in CSSValue.cpp
> - Return early in Source/WebCore/css/CSSValue.h:246
> - Omit template arguments whenever possible (hopefully msvc could deduct template parameter from arguments)
Comment 22 WebKit Review Bot 2013-02-06 05:56:19 PST
Comment on attachment 184951 [details]
Patch 7

Rejecting attachment 184951 [details] from commit-queue.

Failed to run "['/mnt/git/webkit-commit-queue/Tools/Scripts/webkit-patch', '--status-host=queues.webkit.org', '--bot-id=gce-cq-04', 'apply-attachment', '--no-update', '--non-interactive', 184951, '--port=chromium-xvfb']" exit_code: 2 cwd: /mnt/git/webkit-commit-queue

Last 500 characters of output:
SSShaderValue.cpp
patching file Source/WebCore/css/WebKitCSSShaderValue.h
patching file Source/WebCore/css/WebKitCSSTransformValue.h
patching file Source/WebCore/editing/EditingStyle.cpp
patching file Source/WebCore/svg/SVGColor.cpp
patching file Source/WebCore/svg/SVGColor.h
patching file Source/WebCore/svg/SVGPaint.cpp
patching file Source/WebCore/svg/SVGPaint.h

Failed to run "[u'/mnt/git/webkit-commit-queue/Tools/Scripts/svn-apply', '--force']" exit_code: 1 cwd: /mnt/git/webkit-commit-queue

Full output: http://queues.webkit.org/results/16401105
Comment 23 Alexander Shalamov 2013-02-10 23:33:59 PST
(In reply to comment #21)
> Alexander,
> 
> Did you mean to set r? on your patch? Otherwise it is not visible in the review queue.
> 
> (In reply to comment #20)
> > Created an attachment (id=184951) [details] [details]
> > Patch 7
> > 
> > Fixes based on review comments from Alexander and Antti.
> > - Used literal to compare CSSBasicShapes type
> > - Fixed indent in Source/WebCore/css/CSSGradientValue.h:59
> > - Added test for non-equality of cssvalue objects
> > - Moved helper function above the function in CSSValue.cpp
> > - Return early in Source/WebCore/css/CSSValue.h:246
> > - Omit template arguments whenever possible (hopefully msvc could deduct template parameter from arguments)

I need to rebase it to master.
Comment 24 Alexander Shalamov 2013-02-11 00:28:53 PST
Created attachment 187521 [details]
Patch 8

Rebased to master
Modified changelog
Comment 25 WebKit Review Bot 2013-02-11 03:02:34 PST
Comment on attachment 187521 [details]
Patch 8

Clearing flags on attachment: 187521

Committed r142444: <http://trac.webkit.org/changeset/142444>
Comment 26 WebKit Review Bot 2013-02-11 03:02:41 PST
All reviewed patches have been landed.  Closing bug.
Comment 27 Nico Weber 2013-10-17 10:53:44 PDT
Comment on attachment 187521 [details]
Patch 8

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

> Source/WebCore/css/CSSGradientValue.cpp:1170
> +        equalXorY == !other.m_firstX || !other.m_firstY;

This should probably be "=", not "=="? I suppose this branch has no test?
Comment 28 Darin Adler 2013-10-17 10:55:36 PDT
(In reply to comment #27)
> > Source/WebCore/css/CSSGradientValue.cpp:1170
> > +        equalXorY == !other.m_firstX || !other.m_firstY;
> 
> This should probably be "=", not "=="? I suppose this branch has no test?

Good catch. We should make a test.
Comment 29 Nico Weber 2013-10-17 12:02:20 PDT
(In reply to comment #28)
> (In reply to comment #27)
> > > Source/WebCore/css/CSSGradientValue.cpp:1170
> > > +        equalXorY == !other.m_firstX || !other.m_firstY;
> > 
> > This should probably be "=", not "=="? I suppose this branch has no test?
> 
> Good catch. We should make a test.

I have a fix (and test) for this, will upload soon.
Comment 30 Nico Weber 2013-10-17 13:05:17 PDT
(In reply to comment #29)
> (In reply to comment #28)
> > (In reply to comment #27)
> > > > Source/WebCore/css/CSSGradientValue.cpp:1170
> > > > +        equalXorY == !other.m_firstX || !other.m_firstY;
> > > 
> > > This should probably be "=", not "=="? I suppose this branch has no test?
> > 
> > Good catch. We should make a test.
> 
> I have a fix (and test) for this, will upload soon.

https://bugs.webkit.org/show_bug.cgi?id=122987