[webkit-dev] Accidental binary bloating via C/C++ class/struct + Objective-C
Yusuke Suzuki
ysuzuki at apple.com
Mon Jan 13 17:52:52 PST 2020
Hello WebKittens,
I recently striped 830KB binary size in WebKit just by using a work-around.
This email describes what happened so far, to prevent from happening again.
## Problem
When C/C++ struct/class is included in field types and method types in Objective-C, Objective-C compiler puts type-enconding-string which gathers type information one-leve deep for C/C++ struct/class if
1. The type is a pointer to C/C++ struct/class
2. The type is a value of C/C++ struct/class
3. The type is a reference to C/C++ struct/class
However, our WebKit C/C++ struct/class is typically very complex type using a lot of templates. Unfortunately, Objective-C compiler includes expanded template definition as a string and adds it as a type-enconding-string into the release binary!
For example, https://trac.webkit.org/changeset/254152/webkit <https://trac.webkit.org/changeset/254152/webkit> is removing JSC::VM& from Objective-C signature, and it reduces 200KB binary size!
Another example is https://trac.webkit.org/changeset/254241/webkit <https://trac.webkit.org/changeset/254241/webkit>, which removes a lot of WebCore::WebView* etc. from Objective-C method signature, and reduces 630KB binary.
## Solution for now
We can purge type-encoding-string if we use Objective-C NS_DIRECT feature (which makes Objective-C function as C function calling convention, removing metadata).
However, this does not work universally: with NS_DIRECT, Objective-C override does not work. This means we need to be extra-careful when using it.
So, as a simple, but effective work-around, in the above patch, we introduced NakedRef<T> / NakedPtr<T>. This is basically raw pointer / raw reference to T, with a wrapper class.
This leverages the behavior of Objective-C compiler’s mechanism “one-level deep type information collection”. Since NakedRef<T> / NakedPtr<T> introduces one-level deep field,
Objective-C compiler does not collect the type information of T if NakedPtr<T> is included in the fields / signatures, while the compiler collects information when T* is used.
So, if you are using T& / T* C/C++ struct/class in Objective-C, let’s convert it to NakedRef<T> / NakedPtr<T>. Then you could save much binary size immediately without causing any performance problem.
## Future work
We would like to avoid including such types accidentally in Objective-C. We should introduce build-time hook script which detects such a thing.
I uploaded the PoC script in https://bugs.webkit.org/show_bug.cgi?id=205968 <https://bugs.webkit.org/show_bug.cgi?id=205968>, and I’m personally planning to introduce such a hook into a part of build process.
-Yusuke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-dev/attachments/20200113/2517aa8b/attachment.htm>
More information about the webkit-dev
mailing list