> On Jul 21, 2016, at 6:42 PM, Peter Collingbourne <[email protected]> wrote:
> 
> Hi all,
> 
> The ABI currently requires that virtual tables for a class appear 
> consecutively in a virtual table group. I would like to propose a restriction 
> that would require that compilers may only access the virtual table 
> associated with the address point stored in an object's virtual table 
> pointer, and may not rely on any knowledge that the compiler may have about 
> the relative layout of other virtual tables in the virtual table group.
> 
> The purpose of this restriction is to allow an implementation to split a 
> virtual table group along virtual table boundaries.
> 
> Motivation
> 
> There are at least two scenarios which would benefit from vtable splitting: 
> clients which want to place data either before or after the ABI-required part 
> of a virtual table, and clients which want to control the layout of virtual 
> tables for performance or security reasons.
> 
> As an example of the first scenario, when performing whole-program virtual 
> call optimization, Clang will apply an optimization known as virtual constant 
> propagation [0], which causes data to be laid out at a specific offset from 
> the address point of each virtual table in a hierarchy. If that virtual table 
> appears in a virtual table group, padding is required to place the data at an 
> appropriate offset for each class. Because of the current restriction that 
> vtables must appear consecutively, the optimizer may need to add more padding 
> than necessary, or inhibit the optimization entirely if it would require too 
> much padding.
> 
> As an example of the second scenario, an implementation may wish to lay out 
> virtual tables hierarchically either in order to increase the likelihood of a 
> cache hit when repeatedly making the same virtual call over a set of 
> heterogeneous objects, or to efficiently implement a security mitigation 
> (specifically control flow integrity [1]) based on checking virtual table 
> addresses for set membership. Placing only virtual tables (rather than 
> virtual table groups) consecutively would likely increase the cache hit 
> likelihood further and reduces the amount of metadata required to implement 
> set membership checks.
> 
> In an experiment involving the Chromium web browser, I have measured a binary 
> size decrease of 1.5%, and a median performance improvement of about 1% on 
> Chromium's layout benchmarks when comparing a binary compiled with control 
> flow integrity and whole-program virtual call optimization against a binary 
> compiled with control flow integrity, whole-program virtual call optimization 
> and a prototype implementation of vtable splitting.
> 
> Commentary
> 
> Although the ABI specifies [2] the calling convention for virtual calls, 
> which requires the call to be made using the this-adjustment appropriate for 
> the object from which the virtual table pointer was loaded, the as-if rule 
> could in principle allow a program to make a call using a different virtual 
> table if the virtual table group contains multiple secondary virtual tables, 
> as the distance between these virtual tables would be fixed (the same would 
> be possible for all virtual tables if the dynamic type were known, but in 
> that case the program could just call the appropriate virtual function 
> directly).

In what situation would the distance between secondary virtual tables in a VTT 
be fixed where you don't know the dynamic type?  Derived classes can always 
introduce or re-introduce virtual bases in ways that re-order the secondary 
virtual tables.

John.

> 
> The purported benefit would be to avoid an additional virtual pointer load 
> from the object in cases where consecutive calls are made to virtual 
> functions introduced in different bases. However, it seems to me that cases 
> where this is beneficial would be rare: not only would you need at least 
> three bases and a derived class which does not override any of the called 
> virtual functions, but when performing two consecutive calls it seems likely 
> that the vtable would need to be reloaded anyway, either from the object or 
> from the stack, especially with majority caller-save ABIs such as x86-64, or 
> in any event because the first virtual call may have changed the object's 
> dynamic type. It seems (according to experiments [3] carried out at 
> godbolt.org <http://godbolt.org/>) that all major compilers (gcc, clang, icc) 
> do already use the appropriate vtable group and therefore are compliant with 
> the proposed restriction.
> 
> (There would also seem to be nothing preventing an implementation from 
> choosing to load the RTTI pointer or offset-to-top from another virtual table 
> group. However I would consider this even less likely to be beneficial than a 
> virtual call via another virtual table.)
> 
> The ABI specifies that the vtables in a group shall be laid out consecutively 
> when referenced via a vtable group symbol, and I'm not proposing to change 
> this. The effect of this proposal would be to allow a vtable to be split if 
> the vtable group symbol is not referenced directly by name outside of the 
> translation unit(s) participating in the optimization. This may be the case 
> when a class has internal linkage, or if the program is linked with LTO, 
> which allows the compiler to know which symbols are referenced outside of the 
> LTO'd part of the program.
> 
> Wording
> 
> I propose to add two paragraphs to the section of the ABI describing virtual 
> table groups, as follows:
> 
> diff --git a/abi.html b/abi.html
> index 79cda2c..fce0c60 100644
> --- a/abi.html
> +++ b/abi.html
> @@ -1193,6 +1193,18 @@ and again excluding primary bases
>  (which share virtual tables with the classes for which they are primary).
>  </ul>
>  
> +<p>
> +When performing a virtual call or loading any other data from an address
> +derived from the address point stored in an object's virtual table pointer,
> +a program may only load from the virtual table associated with that address
> +point, and not from any other virtual table in the same virtual table group
> +which might be presumed to be located at a fixed offset from the address
> +point as a result of the above layout algorithm.
> +
> +<p>
> +The purpose of this restriction is to allow an implementation to split a
> +virtual table group along virtual table boundaries if its symbol is not
> +visible to other translation units.
>  
>  <p>
>  <a name="vtable-construction">
> 
> 
> Thanks,
> Peter
> 
> [0] http://lists.llvm.org/pipermail/llvm-dev/2016-January/094600.html 
> <http://lists.llvm.org/pipermail/llvm-dev/2016-January/094600.html>
> [1] http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html 
> <http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html>
> [2] https://mentorembedded.github.io/cxx-abi/abi.html#vcall.caller 
> <https://mentorembedded.github.io/cxx-abi/abi.html#vcall.caller>
> [3] https://godbolt.org/g/wX7Ay6 <https://godbolt.org/g/wX7Ay6> is a 
> three-bases test case by Richard Smith, https://godbolt.org/g/7eG8A1 
> <https://godbolt.org/g/7eG8A1> is a dynamic-type-known test case by me
> _______________________________________________
> cxx-abi-dev mailing list
> [email protected]
> http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev

_______________________________________________
cxx-abi-dev mailing list
[email protected]
http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev

Reply via email to