Bug 222518 - Reduce compile time and binary size cost of enabling proper CSSStyleDeclaration property access behavior
Summary: Reduce compile time and binary size cost of enabling proper CSSStyleDeclarati...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Bindings (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Sam Weinig
URL:
Keywords: InRadar
Depends on: 223542 223613
Blocks: 217623
  Show dependency treegraph
 
Reported: 2021-02-27 14:15 PST by Sam Weinig
Modified: 2021-04-11 10:06 PDT (History)
16 users (show)

See Also:


Attachments
JSCSSStyleDeclaration.cpp (if you disable the legacy flag) (3.04 MB, text/x-csrc)
2021-03-03 10:25 PST, Sam Weinig
no flags Details
Patch (116.27 KB, patch)
2021-04-02 21:48 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (113.81 KB, patch)
2021-04-03 12:06 PDT, Sam Weinig
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (111.83 KB, patch)
2021-04-03 12:20 PDT, Sam Weinig
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (112.72 KB, patch)
2021-04-03 12:39 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Test overloading of non-type template parameters (539 bytes, text/x-csrc)
2021-04-05 09:31 PDT, Sam Weinig
no flags Details
Patch (117.83 KB, patch)
2021-04-05 12:27 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Test Case (532 bytes, text/html)
2021-04-10 10:20 PDT, Sam Weinig
no flags Details
Patch (120.81 KB, patch)
2021-04-10 19:59 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff
Patch (126.03 KB, patch)
2021-04-11 08:57 PDT, Sam Weinig
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sam Weinig 2021-02-27 14:15:28 PST
Once the change for https://bugs.webkit.org/show_bug.cgi?id=222517 is landed in it's disabled form, we need to work to remove the compile time and binary size regression that would come with enabling it.
Comment 1 Sam Weinig 2021-02-27 14:38:55 PST
A very simple idea, but with a runtime cost (though unlikely a runtime regression from the legacy code currently in the build, we should test) would be to replace all the getter / setters implementations with a single pair that re-lookup the name. Unfortunately, it seems only getters are passed their name in the callback, so at best (without making changes to JSC) we only be able to replace half the functions.
Comment 2 Sam Weinig 2021-02-27 14:51:45 PST
An alternative is that we could try to make the namedGetter/nameSetter approach work for this case by better emulating what a real property get/set would do for these properties.
Comment 3 Sam Weinig 2021-02-27 15:05:54 PST
If we don't go the "make it work like named getter/setter in getPropertySlot/putPropertySlot" route, I think the ideal would be a single function for all the gets, a single function for all the sets, and somehow encoding the CSSPropertyID in the static HashTableValues and passing that value to the shared functions. Been a long while since I looked at that part of JSC, so not sure how feasible that would be.

I'm a little confused about what role the static HashTables play these days. It seems like we mostly just use a const array of HashTableValues and call reifyStaticProperty on each one as soon as we create the prototype.
Comment 4 Sam Sneddon [:gsnedders] 2021-03-02 07:17:13 PST
(In reply to Sam Weinig from comment #1)
> A very simple idea, but with a runtime cost (though unlikely a runtime
> regression from the legacy code currently in the build, we should test)
> would be to replace all the getter / setters implementations with a single
> pair that re-lookup the name. Unfortunately, it seems only getters are
> passed their name in the callback, so at best (without making changes to
> JSC) we only be able to replace half the functions.

I'd be curious about why JSC has that asymmetry? At the spec level, neither getters nor setters are passed their names, so presumably there's some reason for this in JSC?

Also: how big is the binary size regression at this point? Is it just the generated getter/setter functions that dominate the regression?
Comment 5 Sam Weinig 2021-03-03 10:25:54 PST
Created attachment 422110 [details]
JSCSSStyleDeclaration.cpp (if you disable the legacy flag)
Comment 6 Radar WebKit Bug Importer 2021-03-06 14:16:18 PST
<rdar://problem/75136887>
Comment 7 Sam Weinig 2021-03-16 09:31:36 PDT
(In reply to Sam Sneddon [:gsnedders] from comment #4)
> (In reply to Sam Weinig from comment #1)
> > A very simple idea, but with a runtime cost (though unlikely a runtime
> > regression from the legacy code currently in the build, we should test)
> > would be to replace all the getter / setters implementations with a single
> > pair that re-lookup the name. Unfortunately, it seems only getters are
> > passed their name in the callback, so at best (without making changes to
> > JSC) we only be able to replace half the functions.
> 
> I'd be curious about why JSC has that asymmetry? At the spec level, neither
> getters nor setters are passed their names, so presumably there's some
> reason for this in JSC?

I kind of doubt there is a good reason, probably just driven by needs since this is all internals stuff.

> 
> Also: how big is the binary size regression at this point? Is it just the
> generated getter/setter functions that dominate the regression?

Not sure at this point. It would be good to measure.


I have two ideas about to proceed here:

1) Add a PropertyName parameter to the custom setters, and implement a single set of getter/setters based on the property name parameter.

2) Add a mechanism to smuggle a parameter to the custom getter/setters stored that we store in the DOMAttributeGetterSetter at re-ification time during the prototype's creation. We could avoid making DOMAttributeGetterSetter bigger by utilizing the DOMAttributeAnnotation's domJIT pointer, which is always null in this case (and in most cases).


After sleeping on it, I'm somewhat leaning towards doing #1 first, just to see what if there is performance cost and if it fixes the compile time regression, as either solution is going to grow the number of parameters passed to custom setters by 1, and that scares me a bit.
Comment 8 Sam Weinig 2021-03-18 09:08:16 PDT
I prototyped / implemented adding PropertyName to custom setters in https://bugs.webkit.org/show_bug.cgi?id=223413.
Comment 9 Sam Weinig 2021-03-22 17:06:39 PDT
Now that setters have a property name, the next step is allowing multiple attributes to use the same function pointers for the getter/setter implementation. To do that, we need to fix bug 223542.
Comment 10 Sam Weinig 2021-03-22 17:07:01 PDT
Or rather, we need to fix bug 223613.
Comment 11 Sam Weinig 2021-04-02 21:48:21 PDT Comment hidden (obsolete)
Comment 12 Sam Weinig 2021-04-03 12:06:35 PDT Comment hidden (obsolete)
Comment 13 Sam Weinig 2021-04-03 12:20:25 PDT Comment hidden (obsolete)
Comment 14 Sam Weinig 2021-04-03 12:37:16 PDT Comment hidden (obsolete)
Comment 15 Sam Weinig 2021-04-03 12:39:00 PDT
Created attachment 425108 [details]
Patch
Comment 16 Darin Adler 2021-04-04 14:57:25 PDT
Comment on attachment 425108 [details]
Patch

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

r=me assuming tests pass (seeing EWS api-gtk failing right now?), there are not other scaling issues other than compile time and binary size, and this does resolve both of those issues as claimed

> Source/WebCore/bindings/js/JSDOMAttribute.h:61
> +    static bool setPassingPropertyName(JSC::JSGlobalObject& lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName attributeName)

Given overloading, can’t this be named set? Or do template arguments not do the overloading thing?

> LayoutTests/ChangeLog:14
> +        Remove tests for iteration order, which is not standardized, and not consistent among
> +        browsers.

But stability still seems desirable, so I’d kind of still wish for a test.
Comment 17 Sam Weinig 2021-04-05 09:31:42 PDT
Created attachment 425158 [details]
Test overloading of non-type template parameters
Comment 18 Sam Weinig 2021-04-05 09:39:30 PDT
(In reply to Darin Adler from comment #16)
> Comment on attachment 425108 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=425108&action=review
> 
> r=me assuming tests pass (seeing EWS api-gtk failing right now?), there are
> not other scaling issues other than compile time and binary size, and this
> does resolve both of those issues as claimed
> 
> > Source/WebCore/bindings/js/JSDOMAttribute.h:61
> > +    static bool setPassingPropertyName(JSC::JSGlobalObject& lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName attributeName)
> 
> Given overloading, can’t this be named set? Or do template arguments not do
> the overloading thing?

I didn't think you could overload using only non-type template parameters, but it seems you totally can. Will fix! (I uploaded my test for this since I thought it was interesting enough).

> 
> > LayoutTests/ChangeLog:14
> > +        Remove tests for iteration order, which is not standardized, and not consistent among
> > +        browsers.
> 
> But stability still seems desirable, so I’d kind of still wish for a test.

Yeah, I agree. Will make it a test that ensure the order by checking that we maintain the following invariants when iterating:

- 4 groupings
  - 1st grouping, camel case, alphabetical, includes properties with "Webkit" and "Epub" prefix with initial uppercase letter, no dashes anywhere in the name
  - 2nd grouping, webkit case, alphabetical, all properties prefixed with "webkit" with initial lowercase letter.
  - 3rd grouping, dashed case, alphabetical, all properties have a dash in them.
  - 4th grouping, epub case, alphabetical, all properties prefixed with "epub" with initial lowercase letter


Thanks for the review.
Comment 19 Sam Weinig 2021-04-05 12:27:48 PDT
Created attachment 425187 [details]
Patch
Comment 20 Sam Sneddon [:gsnedders] 2021-04-06 08:35:07 PDT
(In reply to Sam Weinig from comment #18)
> (In reply to Darin Adler from comment #16)
> > > LayoutTests/ChangeLog:14
> > > +        Remove tests for iteration order, which is not standardized, and not consistent among
> > > +        browsers.
> > 
> > But stability still seems desirable, so I’d kind of still wish for a test.
> 
> Yeah, I agree. Will make it a test that ensure the order by checking that we
> maintain the following invariants when iterating:
> 
> - 4 groupings
>   - 1st grouping, camel case, alphabetical, includes properties with
> "Webkit" and "Epub" prefix with initial uppercase letter, no dashes anywhere
> in the name
>   - 2nd grouping, webkit case, alphabetical, all properties prefixed with
> "webkit" with initial lowercase letter.
>   - 3rd grouping, dashed case, alphabetical, all properties have a dash in
> them.
>   - 4th grouping, epub case, alphabetical, all properties prefixed with
> "epub" with initial lowercase letter

Looking quickly, it seems that Firefox just iterates in the order they appear in the WebIDL file, which appears to be not really that well-defined (filesystem enumeration order defined!), but groups longhands, shorthands, and aliases together.

Not sure if I have any strong preference; I wonder if we could just get away with a single alphabetical ordering?
Comment 21 Sam Weinig 2021-04-10 10:20:14 PDT
Created attachment 425687 [details]
Test Case
Comment 22 Sam Weinig 2021-04-10 19:59:42 PDT
Created attachment 425697 [details]
Patch
Comment 23 Darin Adler 2021-04-11 07:57:53 PDT
Now I feel bad suggesting you do the overloading, because it looks like it works fine on GCC and clang, but not the Microsoft compiler!
Comment 24 Sam Weinig 2021-04-11 08:28:32 PDT
(In reply to Darin Adler from comment #23)
> Now I feel bad suggesting you do the overloading, because it looks like it
> works fine on GCC and clang, but not the Microsoft compiler!

Heh. But we both learned things! So win win!
Comment 25 Sam Weinig 2021-04-11 08:57:14 PDT
Created attachment 425709 [details]
Patch
Comment 26 EWS 2021-04-11 10:06:55 PDT
Committed r275808 (236379@main): <https://commits.webkit.org/236379@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 425709 [details].