Bug 110926

Summary: Can't use fastGetAttribute with WebCore::HTMLNames::classAttr when element is a SVGStyledElement
Product: WebKit Reporter: Tim 'mithro' Ansell <mithro>
Component: SVGAssignee: Nobody <webkit-unassigned>
Status: RESOLVED CONFIGURATION CHANGED    
Severity: Normal CC: abarth, arv, bfulgham, buildbot, cmarcelo, d-r, eric, esprehn+autocc, fmalita, gtk-ews, haraken, japhet, kling, krit, ojan.autocc, pdr, philn, rniwa, schenney, webkit-bug-importer, webkit.review.bot, xan.lopez, zimmermann
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Only use fast path when you don't have a SVG element.
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch darin: review-

Tim 'mithro' Ansell
Reported 2013-02-26 16:49:39 PST
Created attachment 190393 [details] Only use fast path when you don't have a SVG element. The problem is that HTMLNames::classAttr for SVG elements is animatable, so we need to use getAttribute rather than fastGetAttribute. Please see http://code.google.com/p/chromium/issues/detail?id=178030 for more complete details.
Attachments
Only use fast path when you don't have a SVG element. (4.36 KB, patch)
2013-02-26 16:49 PST, Tim 'mithro' Ansell
no flags
Patch (5.34 KB, patch)
2013-02-26 17:11 PST, Tim 'mithro' Ansell
no flags
Patch (5.41 KB, patch)
2013-02-26 18:12 PST, Tim 'mithro' Ansell
no flags
Patch (6.70 KB, patch)
2013-02-26 19:05 PST, Tim 'mithro' Ansell
no flags
Patch (3.03 KB, patch)
2013-02-26 19:36 PST, Tim 'mithro' Ansell
no flags
Patch (4.14 KB, patch)
2013-02-26 20:09 PST, Tim 'mithro' Ansell
no flags
Patch (4.22 KB, patch)
2013-02-26 20:16 PST, Tim 'mithro' Ansell
no flags
Patch (4.75 KB, patch)
2013-03-05 14:28 PST, Tim 'mithro' Ansell
no flags
Patch (4.24 KB, patch)
2013-04-01 19:28 PDT, Tim 'mithro' Ansell
no flags
Patch (4.80 KB, patch)
2013-04-01 21:13 PDT, Tim 'mithro' Ansell
no flags
Patch (4.87 KB, patch)
2013-04-01 21:21 PDT, Tim 'mithro' Ansell
darin: review-
WebKit Review Bot
Comment 1 2013-02-26 16:52:17 PST
Attachment 190393 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/bindings/scripts/CodeGenerator.pm', u'Source/WebCore/dom/Element.cpp', u'Source/WebCore/dom/Element.h']" exit_code: 1 Source/WebCore/dom/Element.h:794: One line control clauses should not use braces. [whitespace/braces] [4] Source/WebCore/dom/Element.h:792: An else statement can be removed when the prior "if" concludes with a return, break, continue or goto statement. [readability/control_flow] [4] Source/WebCore/dom/Element.h:796: One line control clauses should not use braces. [whitespace/braces] [4] Total errors found: 3 in 2 files If any of these errors are false positives, please file a bug against check-webkit-style.
Early Warning System Bot
Comment 2 2013-02-26 17:01:59 PST
Comment on attachment 190393 [details] Only use fast path when you don't have a SVG element. Attachment 190393 [details] did not pass qt-ews (qt): Output: http://webkit-commit-queue.appspot.com/results/16815011
kov's GTK+ EWS bot
Comment 3 2013-02-26 17:10:43 PST
Comment on attachment 190393 [details] Only use fast path when you don't have a SVG element. Attachment 190393 [details] did not pass gtk-ews (gtk): Output: http://webkit-commit-queue.appspot.com/results/16823001
Tim 'mithro' Ansell
Comment 4 2013-02-26 17:11:43 PST
Early Warning System Bot
Comment 5 2013-02-26 17:27:43 PST
Early Warning System Bot
Comment 6 2013-02-26 17:34:33 PST
Build Bot
Comment 7 2013-02-26 17:37:14 PST
Tim 'mithro' Ansell
Comment 8 2013-02-26 18:12:52 PST
Early Warning System Bot
Comment 9 2013-02-26 18:29:01 PST
Early Warning System Bot
Comment 10 2013-02-26 18:31:07 PST
Tim 'mithro' Ansell
Comment 11 2013-02-26 19:05:49 PST
Philip Rogers
Comment 12 2013-02-26 19:19:20 PST
Comment on attachment 190417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=190417&action=review I'm not a reviewer nor am I very familiar with this code, so please take my suggestions with a grain of salt! Do you mind adding a test to this patch? Just a simple test that crashes without your patch and succeeds with it should be enough. Do you mind testing the performance of this patch? Could dromaeo be affected, for instance (http://dromaeo.com)? Is JSC affected by this bug as well? > Source/WebCore/ChangeLog:4 > + use the fastGetAttribute. Please put the bug url below the short summary but above the full ChangeLog entry. http://www.webkit.org/coding/contributing.html#changelogs has an example of this. Just a minor suggestion: you may want to rephrase your summary with just what the patch does. For example: "Use fastGetAttribute for className on HTML nodes but not SVG nodes" > Source/WebCore/bindings/scripts/CodeGenerator.pm:597 > +{ See comment below > Source/WebCore/bindings/scripts/CodeGenerator.pm:643 > + $functionName = "tryFastGetAttribute"; Can you split this into a separate patch? > Source/WebCore/dom/Element.cpp:-2562 > -#ifndef NDEBUG I'm not sure this is a good idea: previously this was guarded with NDEBUG but now it will always get compiled in. Is removing this required? > Source/WebCore/dom/Element.h:794 > +inline const AtomicString& Element::tryFastGetAttribute(const QualifiedName& name) const I think this can be removed as well.
Tim 'mithro' Ansell
Comment 13 2013-02-26 19:36:16 PST
Tim 'mithro' Ansell
Comment 14 2013-02-26 19:38:24 PST
Minimal patch uploaded with fixes as recommended by pdr. Yet to create a test case.
Tim 'mithro' Ansell
Comment 15 2013-02-26 20:09:48 PST
Tim 'mithro' Ansell
Comment 16 2013-02-26 20:10:28 PST
Added a test case.
Tim 'mithro' Ansell
Comment 17 2013-02-26 20:16:00 PST
Philip Rogers
Comment 18 2013-02-26 20:45:00 PST
Comment on attachment 190429 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=190429&action=review I added a couple minor nits about the test. I'm going to cc Kentaro Hara who may be able to review the performance side of this patch or suggest a specific benchmark. > LayoutTests/dom/svg/svg-className-lookup-crash.htm:1 > +<body> Please add: <!DOCTYPE html> <html> Proper html makes the parser panda happy :) > LayoutTests/dom/svg/svg-className-lookup-crash.htm:4 > +var svgElement1 = document.createElementNS("http://www.w3.org/2000/svg", "view"); Is this necessary since we already have a <view> above? > LayoutTests/dom/svg/svg-className-lookup-crash.htm:13 > + window.testRunner.dumpAsText(); This is a great test but we can actually make it even better by printing the class name result: if (window.testRunner) { document.write("Accessing a SVGStyledElement's class attribute should not crash. The expected className is myClass, the actual class was " + result); testRunner.dumpAsText(); }
Andreas Kling
Comment 19 2013-02-27 05:05:27 PST
Comment on attachment 190429 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=190429&action=review > Source/WebCore/dom/Element.h:831 > +#if ENABLE(SVG) > + return isSVGElement() ? getAttribute(WebCore::HTMLNames::classAttr) : fastGetAttribute(WebCore::HTMLNames::classAttr); > +#else > + return fastGetAttribute(WebCore::HTMLNames::classAttr); > +#endif You could check Element::hasClass() before calling fastGetAttribute() in the non-SVGElement case(s). This would avoid iterating over the attribute storage when there is no class attribute to be found.
Andreas Kling
Comment 20 2013-02-27 05:08:27 PST
(In reply to comment #19) > (From update of attachment 190429 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=190429&action=review > > > Source/WebCore/dom/Element.h:831 > > +#if ENABLE(SVG) > > + return isSVGElement() ? getAttribute(WebCore::HTMLNames::classAttr) : fastGetAttribute(WebCore::HTMLNames::classAttr); > > +#else > > + return fastGetAttribute(WebCore::HTMLNames::classAttr); > > +#endif > > You could check Element::hasClass() before calling fastGetAttribute() in the non-SVGElement case(s). > This would avoid iterating over the attribute storage when there is no class attribute to be found. Also, the code would look slightly nicer with an early return instead of the ternary operator: inline const AtomicString& Element::getClassAttribute() { #if ENABLE(SVG) if (isSVGElement()) return getAttribute(HTMLNames::classAttr); #endif if (!hasClass()) return nullAtom; return fastGetAttribute(HTMLNames::classAttr); }
Erik Arvidsson
Comment 21 2013-02-27 09:10:05 PST
Comment on attachment 190429 [details] Patch I like this approach. Andreas: I'm not sure that the hasClass test is worth it? It all depends on how often we expect people to read className of an element that does not have a class attribute. In the old days with Sizzle and all I would say it was really common but now that most people have transitioned to querySelector it is clearly less common.
Erik Arvidsson
Comment 22 2013-02-27 09:11:28 PST
Comment on attachment 190429 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=190429&action=review >> LayoutTests/dom/svg/svg-className-lookup-crash.htm:13 >> + window.testRunner.dumpAsText(); > > This is a great test but we can actually make it even better by printing the class name result: > if (window.testRunner) { > document.write("Accessing a SVGStyledElement's class attribute should not crash. The expected className is myClass, the actual class was " + result); > testRunner.dumpAsText(); > } Or just switch to js-test-pre/post and use shouldBe
Andreas Kling
Comment 23 2013-02-27 09:15:41 PST
(In reply to comment #21) > (From update of attachment 190429 [details]) > I like this approach. > > Andreas: I'm not sure that the hasClass test is worth it? It all depends on how often we expect people to read className of an element that does not have a class attribute. In the old days with Sizzle and all I would say it was really common but now that most people have transitioned to querySelector it is clearly less common. I don't feel strongly about the hasClass() check. It's probably not worth it.
Darin Adler
Comment 24 2013-02-27 09:35:21 PST
Comment on attachment 190429 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=190429&action=review > Source/WebCore/dom/Element.h:828 > + return isSVGElement() ? getAttribute(WebCore::HTMLNames::classAttr) : fastGetAttribute(WebCore::HTMLNames::classAttr); Is this faster than just calling getAttribute?
Tim 'mithro' Ansell
Comment 25 2013-03-04 14:51:25 PST
So I'm unsure what you want me to do to get this bug committed?
Erik Arvidsson
Comment 26 2013-03-05 09:16:43 PST
(In reply to comment #25) > So I'm unsure what you want me to do to get this bug committed? There are some comments in the code review that you have not yet resolved.
Tim 'mithro' Ansell
Comment 27 2013-03-05 14:28:04 PST
Darin Adler
Comment 28 2013-03-05 14:54:40 PST
Comment on attachment 191566 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=191566&action=review review- because of the hasClass thing -- I’m also pretty sure we don’t need a new getClassAttribute function > Source/WebCore/dom/Element.h:830 > +inline const AtomicString& Element::getClassAttribute() const > +{ > +#if ENABLE(SVG) > + if (isSVGElement()) > + return getAttribute(HTMLNames::classAttr); > +#endif > + if (!hasClass()) > + return nullAtom; > + return fastGetAttribute(HTMLNames::classAttr); > +} The consensus in the comments seems to be that the hasClass check is not a worthwhile optimization. If we do want it, then I believe the hasClass check can go before the SVG element check. Is this measurably more efficient than calling getAttribute(classAttr)? I suspect it is not. And if not, then we should have the code generator call getAttribute and not add a new getClassAttribute function. If this is, then we should consider doing this for every attribute other than styleAttr. The only thing that is specific to the class attribute here is the hasClass function. Otherwise this looks pretty good to me.
Tim 'mithro' Ansell
Comment 29 2013-03-05 20:33:36 PST
It is my understanding that using just getAttribute rather than fastGetAttribute is a significant speed reduction. In the history of this file the code was changed to just do a getAttribute and was reverted for performance reasons. On SVG we *can't* use fastGetAttribute as class is animatable. I believe getAttribute is slow because it has to synchronize with animatable values (I don't know what that actually means however).
Eric Seidel (no email)
Comment 30 2013-03-08 13:40:33 PST
Comment on attachment 191566 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=191566&action=review >> Source/WebCore/dom/Element.h:830 >> +} > > The consensus in the comments seems to be that the hasClass check is not a worthwhile optimization. > > If we do want it, then I believe the hasClass check can go before the SVG element check. > > Is this measurably more efficient than calling getAttribute(classAttr)? I suspect it is not. And if not, then we should have the code generator call getAttribute and not add a new getClassAttribute function. > > If this is, then we should consider doing this for every attribute other than styleAttr. The only thing that is specific to the class attribute here is the hasClass function. > > Otherwise this looks pretty good to me. I believe this bug is fallout from performance optimizations we made for className in the bindings generator. getAttribute, as you know, is very slow. At least compared to fastGetAttribute. Normally, we can use fastGetAttribute for everything. Unfortunately the SVG spec says that "class" is an animatable attribute. meaning, we can't use fastGetAttribute for it class on an SVGStyledElement. Arv thought he fixed this back in bug 105565, but not quite. We can still end up calling fastGetAttribute(className) on an SVGElement with animated class and hit an ASSERT in debug. :( We stumbled upon this while investigating an unrelated crasher from the fuzzer.
Eric Seidel (no email)
Comment 31 2013-03-08 13:45:53 PST
(In reply to comment #28) > (From update of attachment 191566 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=191566&action=review > > Is this measurably more efficient than calling getAttribute(classAttr)? I suspect it is not. And if not, then we should have the code generator call getAttribute and not add a new getClassAttribute function. Calling fastGetAttribute(classAttr) is measurably more efficient than calling getAttribute(classAttr). We go to great lengths to avoid getAttribute in many places: http://trac.webkit.org/browser/trunk/Source/WebCore/css/StyleResolver.cpp#L985 I guess that call could move to mitho's new function since it's basically the same. > If this is, then we should consider doing this for every attribute other than styleAttr. The only thing that is specific to the class attribute here is the hasClass function. I'm not sure I follow. The generator (and most code) already uses fastGetAttr for everything. This bug is about us using fastGetAttribute in one case where it was not OK and hitting an ASSERT in debug builds. > Otherwise this looks pretty good to me. LGTM too. Please move the hasClass to earlier, and consider changing the StyleResolver line. Be aware that that style resolver code is *extremely* performance sensitive.
Tim 'mithro' Ansell
Comment 32 2013-04-01 19:28:52 PDT
Ryosuke Niwa
Comment 33 2013-04-01 19:59:42 PDT
Comment on attachment 196057 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=196057&action=review > Source/WebCore/ChangeLog:3 > + Use fastGetAttribute for className on HTML nodes but not SVG nodes. This line should match the but title. > Source/WebCore/ChangeLog:12 > + Reviewed by NOBODY (OOPS!). This line should appear before the long description but after the bug URL. > LayoutTests/dom/svg/svg-className-lookup-crash.htm:1 > +<body> Missing DOCTYPE. > LayoutTests/dom/svg/svg-className-lookup-crash.htm:13 > + window.testRunner.dumpAsText(); Nit: This should be indented by 4 spaces, not 2.
Ryosuke Niwa
Comment 34 2013-04-01 20:02:20 PDT
Comment on attachment 196057 [details] Patch Oh, oops, I didn't meant to r+ it.
Tim 'mithro' Ansell
Comment 35 2013-04-01 21:13:46 PDT
Tim 'mithro' Ansell
Comment 36 2013-04-01 21:15:36 PDT
Sorry guys, it seems in the confusion I uploaded an old version from my desktop computer rather than the most current version from my laptop. (The two machines are now in sync.) Dangers of coming back from two weeks of holidays :P I'll now get to Ryosuke Niwa's points.
Tim 'mithro' Ansell
Comment 37 2013-04-01 21:21:57 PDT
Tim 'mithro' Ansell
Comment 38 2013-04-01 21:23:13 PDT
Comment on attachment 196057 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=196057&action=review >> Source/WebCore/ChangeLog:3 >> + Use fastGetAttribute for className on HTML nodes but not SVG nodes. > > This line should match the but title. Done. >> Source/WebCore/ChangeLog:12 >> + Reviewed by NOBODY (OOPS!). > > This line should appear before the long description but after the bug URL. Done. >> LayoutTests/dom/svg/svg-className-lookup-crash.htm:1 >> +<body> > > Missing DOCTYPE. Done. >> LayoutTests/dom/svg/svg-className-lookup-crash.htm:13 >> + window.testRunner.dumpAsText(); > > Nit: This should be indented by 4 spaces, not 2. Done.
Darin Adler
Comment 39 2013-04-02 09:53:39 PDT
Comment on attachment 196067 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=196067&action=review > Source/WebCore/dom/Element.h:862 > + return fastGetAttribute(HTMLNames::classAttr); This is a great idea, but I believe the execution is still a little bit incorrect. It’s a programming error to call fastGetAttribute on classAttr from any call site other than this function. Thus the fastAttributeLookupAllowed function should return false for classAttr. Thus, this line of code is wrong, and the fastAttributeLookupAllowed function also is wrong to return "true" for classAttr since it’s not allowed. There are a number of ways to fix this. The simplest is to make a separate private inline function for the “guts” of fastGetAttribute, without the fastAttributeLookupAllowed assertion, and call that here. There are various other suitable refactoring. Even for SVG elements, there is no reason to do the styleAttr check that getAttribute does when fetching a classAttr, so that’s a case we could optimize further if desired. Have we done performance tests on the difference in performance from calling getAttribute vs. "if (isSVG) getAttribute() else fastGetAttribute()"? If it’s not a measurable difference then we should consider that implementation.
Darin Adler
Comment 40 2013-04-02 09:54:12 PDT
Comment on attachment 196067 [details] Patch review- because of my last comment; still a good idea, but we need to do a little better
Andreas Kling
Comment 41 2013-04-02 10:20:36 PDT
(In reply to comment #40) > (From update of attachment 196067 [details]) > review- because of my last comment; still a good idea, but we need to do a little better IIUC this bug is all about generated bindings. We know at compile time if fastGetAttribute(classAttr) is okay or not for a given interface, right? So why not do the branch then instead of at runtime?
Eric Seidel (no email)
Comment 42 2013-04-09 01:47:32 PDT
Comment on attachment 196067 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=196067&action=review >> Source/WebCore/dom/Element.h:862 >> + return fastGetAttribute(HTMLNames::classAttr); > > This is a great idea, but I believe the execution is still a little bit incorrect. > > It’s a programming error to call fastGetAttribute on classAttr from any call site other than this function. Thus the fastAttributeLookupAllowed function should return false for classAttr. Thus, this line of code is wrong, and the fastAttributeLookupAllowed function also is wrong to return "true" for classAttr since it’s not allowed. > > There are a number of ways to fix this. The simplest is to make a separate private inline function for the “guts” of fastGetAttribute, without the fastAttributeLookupAllowed assertion, and call that here. There are various other suitable refactoring. Even for SVG elements, there is no reason to do the styleAttr check that getAttribute does when fetching a classAttr, so that’s a case we could optimize further if desired. > > Have we done performance tests on the difference in performance from calling getAttribute vs. "if (isSVG) getAttribute() else fastGetAttribute()"? If it’s not a measurable difference then we should consider that implementation. It appears that fastAttributeLookupAllowed already returns "false" for "class" in the SVG case: http://trac.webkit.org/browser/trunk/Source/WebCore/dom/Element.cpp#L2609 So I'm not sure that the refactoring you suggest is necessary? fastAttributeLookupAllowed seems to have enough context to tell if class is safe or not.
Eric Seidel (no email)
Comment 43 2013-04-09 01:49:09 PDT
(In reply to comment #42) > (From update of attachment 196067 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=196067&action=review > > Have we done performance tests on the difference in performance from calling getAttribute vs. "if (isSVG) getAttribute() else fastGetAttribute()"? If it’s not a measurable difference then we should consider that implementation. getAttribute() is definitely much slower than fastGetAttribute, but you already know that. :) I'm not sure exactly what you're suggesting as an alternative here. Are you suggesting that we send all SVG attribute accesses down the getAttribute path? That seems overly conservative, if true?
Tim 'mithro' Ansell
Comment 44 2013-04-09 01:51:12 PDT
Comment on attachment 196067 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=196067&action=review >> Source/WebCore/dom/Element.h:862 >> + return fastGetAttribute(HTMLNames::classAttr); > > This is a great idea, but I believe the execution is still a little bit incorrect. > > It’s a programming error to call fastGetAttribute on classAttr from any call site other than this function. Thus the fastAttributeLookupAllowed function should return false for classAttr. Thus, this line of code is wrong, and the fastAttributeLookupAllowed function also is wrong to return "true" for classAttr since it’s not allowed. > > There are a number of ways to fix this. The simplest is to make a separate private inline function for the “guts” of fastGetAttribute, without the fastAttributeLookupAllowed assertion, and call that here. There are various other suitable refactoring. Even for SVG elements, there is no reason to do the styleAttr check that getAttribute does when fetching a classAttr, so that’s a case we could optimize further if desired. > > Have we done performance tests on the difference in performance from calling getAttribute vs. "if (isSVG) getAttribute() else fastGetAttribute()"? If it’s not a measurable difference then we should consider that implementation. This patch doesn't affect fastAttributeLookupAllowed. The fastAttributeLookupAllowed function already returns *false* for classAttr when the object is an SVG object, which is why this patch even started. This patch does precisely; if (isSVG) getAttribute() else fastGetAttribute() As Eric mentioned >Calling fastGetAttribute(classAttr) is measurably more efficient than calling getAttribute(classAttr). We go to great lengths to avoid getAttribute in many places: http://trac.webkit.org/browser/trunk/Source/WebCore/css/StyleResolver.cpp#L985
Brent Fulgham
Comment 45 2022-07-15 16:07:40 PDT
This code has been significantly refactored since this patch was proposed. There doesn't seem to be any action we can take here.
Radar WebKit Bug Importer
Comment 46 2022-07-15 16:08:16 PDT
Note You need to log in before you can comment on or make changes to this bug.