RESOLVED FIXED 210138
[Cocoa] Simplify NSArray, NSDictionary, and NSNumber idioms throughout WebKit
https://bugs.webkit.org/show_bug.cgi?id=210138
Summary [Cocoa] Simplify NSArray, NSDictionary, and NSNumber idioms throughout WebKit
Darin Adler
Reported 2020-04-07 11:55:20 PDT
[Cocoa] Simplify NSArray and NSDictionary idioms throughout WebKit
Attachments
Patch (464.75 KB, patch)
2020-04-07 20:19 PDT, Darin Adler
no flags
Patch (467.41 KB, patch)
2020-04-08 13:01 PDT, Darin Adler
no flags
Patch (467.29 KB, patch)
2020-04-08 13:51 PDT, Darin Adler
no flags
Patch (466.52 KB, patch)
2020-04-08 14:57 PDT, Darin Adler
no flags
Patch (465.74 KB, patch)
2020-04-08 18:05 PDT, Darin Adler
no flags
Patch (463.90 KB, patch)
2020-04-08 20:28 PDT, Darin Adler
achristensen: review+
Darin Adler
Comment 1 2020-04-07 20:19:33 PDT Comment hidden (obsolete)
Darin Adler
Comment 2 2020-04-07 20:20:16 PDT
Believe it or not, this started as a live range patch, but I ended up going down a rabbit hole of Cocoa-specific stuff.
Sam Weinig
Comment 3 2020-04-08 07:18:31 PDT
Comment on attachment 395769 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395769&action=review > Source/WTF/wtf/cocoa/VectorCocoa.h:51 > +template<typename VectorType> RetainPtr<NSArray> createNSArray(const VectorType& vector) I really like this. Hated copying this idiom all over. How would you feel about an overload that takes a lambda for one off cases such as the ones in PlatformCAAnimationCocoa? Also, why the discrepency in naming prefixes here? *create*NSArray vs. *make*Vector? > Source/WebCore/platform/graphics/FloatRect.h:283 > +WEBCORE_EXPORT id makeNSArrayElement(const FloatRect&); The makeNSArrayElement() for String (and the description in VectorCocoa.h) return RetainPtr<id>. Should this be consistent? > Source/WebCore/platform/graphics/IntRect.h:254 > +WEBCORE_EXPORT id makeNSArrayElement(const IntRect&); The makeNSArrayElement() for String (and the description in VectorCocoa.h) return RetainPtr<id>. Should this be consistent?
Darin Adler
Comment 4 2020-04-08 09:30:40 PDT
Comment on attachment 395769 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395769&action=review >> Source/WTF/wtf/cocoa/VectorCocoa.h:51 >> +template<typename VectorType> RetainPtr<NSArray> createNSArray(const VectorType& vector) > > I really like this. Hated copying this idiom all over. How would you feel about an overload that takes a lambda for one off cases such as the ones in PlatformCAAnimationCocoa? > > Also, why the discrepency in naming prefixes here? *create*NSArray vs. *make*Vector? The overload with lambda sounds great. I will add it and use it in a future patch. I started with the names makeNSArray and makeVector and would be willing to go back. I renamed makeNSArray to createNSArray because of our tradition of using the word "create" for functions that return a new object in a smart pointer. Happy to do global replace on the name either before landing or after. >> Source/WebCore/platform/graphics/FloatRect.h:283 >> +WEBCORE_EXPORT id makeNSArrayElement(const FloatRect&); > > The makeNSArrayElement() for String (and the description in VectorCocoa.h) return RetainPtr<id>. Should this be consistent? This is my attempt at a possibly-unimportant optimization. The idea is that makeNSArrayElement can either return an autoreleased object in an id or a retained object in a RetainPtr<id>. Always returning RetainPtr<id> would require a little bit more reference count churn in an autoreleased case like this one. The distinction would disappear if we ever move to ARC, of course. I probably should have documented this in the comment in VectorCocoa.h -- by the time I was writing that I had forgotten about it!
Sam Weinig
Comment 5 2020-04-08 12:03:13 PDT
(In reply to Darin Adler from comment #4) > Comment on attachment 395769 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=395769&action=review > > >> Source/WTF/wtf/cocoa/VectorCocoa.h:51 > >> +template<typename VectorType> RetainPtr<NSArray> createNSArray(const VectorType& vector) > > > > I really like this. Hated copying this idiom all over. How would you feel about an overload that takes a lambda for one off cases such as the ones in PlatformCAAnimationCocoa? > > > > Also, why the discrepency in naming prefixes here? *create*NSArray vs. *make*Vector? > > The overload with lambda sounds great. I will add it and use it in a future > patch. > > I started with the names makeNSArray and makeVector and would be willing to > go back. I renamed makeNSArray to createNSArray because of our tradition of > using the word "create" for functions that return a new object in a smart > pointer. Happy to do global replace on the name either before landing or > after. I think that makes sense. No need to change it. > > >> Source/WebCore/platform/graphics/FloatRect.h:283 > >> +WEBCORE_EXPORT id makeNSArrayElement(const FloatRect&); > > > > The makeNSArrayElement() for String (and the description in VectorCocoa.h) return RetainPtr<id>. Should this be consistent? > > This is my attempt at a possibly-unimportant optimization. The idea is that > makeNSArrayElement can either return an autoreleased object in an id or a > retained object in a RetainPtr<id>. Always returning RetainPtr<id> would > require a little bit more reference count churn in an autoreleased case like > this one. The distinction would disappear if we ever move to ARC, of course. > > I probably should have documented this in the comment in VectorCocoa.h -- by > the time I was writing that I had forgotten about it! Yeah, I think just updating the comment in VectorCocoa.h is all that needs to change here.
Darin Adler
Comment 6 2020-04-08 13:01:27 PDT Comment hidden (obsolete)
Darin Adler
Comment 7 2020-04-08 13:02:22 PDT
New patch fixes the NSGeometry problem that was breaking the build and addresses Sam's comment about the VectorCocoa.h comment.
Darin Adler
Comment 8 2020-04-08 13:51:48 PDT Comment hidden (obsolete)
Darin Adler
Comment 9 2020-04-08 14:57:05 PDT Comment hidden (obsolete)
Darin Adler
Comment 10 2020-04-08 18:05:41 PDT Comment hidden (obsolete)
Darin Adler
Comment 11 2020-04-08 20:28:01 PDT
Darin Adler
Comment 12 2020-04-08 21:17:11 PDT
Finally, tests all passing. Sam, would you be willing to review?
Darin Adler
Comment 13 2020-04-08 22:07:52 PDT
Comment on attachment 395905 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395905&action=review > Source/WTF/wtf/cocoa/VectorCocoa.h:77 > +using WTF::makeVector; Note, the reason I don’t need to put a "using WTF::createNSArray" here is that we are calling it with WTF::Vector objects, so argument-dependent lookup will find createNSArray. If we ever wanted to use it on objects of another type that just happened to have both a size function and were compatible with range-based for loops, but were not in the WTF namespace, then we could add "WTF::createNSArray" and it would work just as well with them. Or I could just add the "using" line and not let things be so subtle.
Alex Christensen
Comment 14 2020-04-08 23:39:17 PDT
Comment on attachment 395905 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395905&action=review > Source/WTF/wtf/cocoa/VectorCocoa.h:39 > +// if the value is autoreleased. The makeVectorElement function takes an ignored > +// pointer to the vector element type, making argument-dependent lookup work, and an Doesn't this still require putting a pointer into a certain register? It seems like it would be even faster if we would just use a template type and template overloads instead of an unused null typed pointer.
Darin Adler
Comment 15 2020-04-09 11:23:22 PDT
Comment on attachment 395905 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395905&action=review >> Source/WTF/wtf/cocoa/VectorCocoa.h:39 >> +// pointer to the vector element type, making argument-dependent lookup work, and an > > Doesn't this still require putting a pointer into a certain register? It seems like it would be even faster if we would just use a template type and template overloads instead of an unused null typed pointer. I don’t think it would be measurably faster. - If the function is inlined, then no, no pointer ends up being put into a register. - If the function is not inlined, then putting a zero into a register is super-low-cost. Using a template (the traits pattern) requires messy things like specializing in the namespace that the template is in. And also requires that the functions be in headers rather than .cpp files. I’m not sure it’s the right way to go. We can get the efficiency benefit from just inlining the makeVectorElement function. What do you think?
Alex Christensen
Comment 16 2020-04-09 11:24:38 PDT
If makeVectorElement is always inline, then it will always be super easy for the compiler to optimize out the nullptr entirely.
Darin Adler
Comment 17 2020-04-09 11:43:56 PDT
It’s not required to always be inline, but if we want better performance, I suggest that be the fix. But I’m also willing to consider other designs. The number of makeVectorElement functions is very small compared to the number of makeVector call sites, so changes to makeVectorElement would be easy to do.
Darin Adler
Comment 18 2020-04-09 11:46:53 PDT
Thanks for the comment, by the way. I’m willing to make changes. Still looking for a reviewer, in case you’d like be willing to look over the rest of the patch.
Alex Christensen
Comment 19 2020-04-09 17:01:33 PDT
Comment on attachment 395905 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395905&action=review > Source/WTF/wtf/cocoa/VectorCocoa.h:69 > + constexpr const VectorElementType* typedNull = nullptr; > + if (auto vectorElement = makeVectorElement(typedNull, element)) I think all this is great. It's a wonderful improvement to our code. I think it would be even better if it looked like this: if (auto vectorElement = makeVectorElement<VectorElementType>(element)) I think we could also do that later if we decide that's indeed better. This isn't bad either.
Sam Weinig
Comment 20 2020-04-09 17:43:46 PDT
Comment on attachment 395905 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=395905&action=review r=me as well. >>> Source/WTF/wtf/cocoa/VectorCocoa.h:39 >>> +// pointer to the vector element type, making argument-dependent lookup work, and an >> >> Doesn't this still require putting a pointer into a certain register? It seems like it would be even faster if we would just use a template type and template overloads instead of an unused null typed pointer. > > I don’t think it would be measurably faster. > > - If the function is inlined, then no, no pointer ends up being put into a register. > - If the function is not inlined, then putting a zero into a register is super-low-cost. > > Using a template (the traits pattern) requires messy things like specializing in the namespace that the template is in. And also requires that the functions be in headers rather than .cpp files. I’m not sure it’s the right way to go. > > We can get the efficiency benefit from just inlining the makeVectorElement function. > > What do you think? I think it is very unlikely the function won't be inlined in release code, so the cost should be zero as you say.
Darin Adler
Comment 21 2020-04-09 19:11:40 PDT
Radar WebKit Bug Importer
Comment 22 2020-04-09 19:12:22 PDT
Note You need to log in before you can comment on or make changes to this bug.