Determining the size of C++ vtables

Ioi Lam ioi.lam at oracle.com
Fri Feb 24 18:50:07 UTC 2017



On 2/23/17 11:17 PM, Thomas Stüfe wrote:
> Hi Ioi,
>
> After reading through the original mailthread referenced in the bug 
> report, the only reason the "just copy enough (200) slots from the 
> vtable in libjvm.so to the vtable in the image" approach does not work 
> for you is that you are afraid of hitting unmapped memory? If I 
> understand it correctly.
>
> If that is the case, why not copy 200 slots with SafeFetch and stop at 
> the first error? That should not incur much additional costs as long 
> as you do not hit an unmapped area, in which case you'd stop anyway.
>
Oh, that's a good simplification.I hadn't thought about using SafeFetch :-(

One issue with it is the 200 slots are too big (ConstantPool needs just 
10 slots), so finding the exact size is a little more efficient and 
saves a few KBs.

Thanks
- Ioi

> That way you make yourself a bit less dependent on compiler internals. 
> I agree that your approach is more elegant, though.
>
> Kind Regards, Thomas
>
> On Fri, Feb 24, 2017 at 4:55 AM, Ioi Lam <ioi.lam at oracle.com 
> <mailto:ioi.lam at oracle.com>> wrote:
>
>
>
>     On 2/23/17 7:47 PM, Ioi Lam wrote:
>
>         Hi,
>
>         I am working on
>         https://bugs.openjdk.java.net/browse/JDK-8005165
>         <https://bugs.openjdk.java.net/browse/JDK-8005165> (Remove
>         CPU-dependent code in self-patching vtables), I need a way
>         find out the size
>         of a C++ vtable. I ended up doing this:
>
>
>         // Objects of the Metadata types (such as Klass and
>         ConstantPool) have C++ vtables.
>         // (In GCC this is the field <Type>::_vptr, i.e., first word
>         in the object.)
>         //
>         // Addresses of the vtables and the methods may be different
>         across JVM runs,
>         // if libjvm.so is dynamically loaded at a different base address.
>         //
>         // To ensure that the Metadata objects in the CDS archive
>         always have the correct vtable:
>         //
>         // + at dump time:  we redirect the _vptr to point to our own
>         vtables inside
>         //                  the CDS image
>         // + at run time:   we clone the actual contents of the
>         vtables from libjvm.so
>         //                  into our own tables.
>         //
>         // To determine the size of the vtable for each type, we use
>         the following
>         // trick by declaring 2 subclasses:
>         //
>         //   class CppVtabTesterA: public InstanceKlass {
>         //          virtual int   last_virtual_method() {return 1;}
>         //   };
>         //   class CppVtabTesterB: public InstanceKlass {
>         //          virtual void* last_virtual_method() {return NULL};
>         //   };
>         //
>         // CppVtabTesterA and CppVtabTesterB's vtables have the
>         following properties:
>         // - Their size (N+1) is exactly one more than the size of
>         InstanceKlass's vtable (N)
>         // - The first N entries have are exactly the same as in
>         InstanceKlass's vtable.
>         // - Their last entry is different.
>         //
>         // So to determine the value of N, we just walk CppVtabTesterA
>         and CppVtabTesterB's tables
>         // and find the first entry that's different
>
>
>         Could anyone comment if this is acceptable? I know it's not
>         100% portable (C++ doesn't
>         specify where to find the vtable, or what's inside), but my
>         assumptions is the same as
>         the existing code. I.e., _vptr is a pointer located at offset
>         0 of the object, and it
>         points to a one-dimensional array.
>
>         So at least it's not any worse than before?
>
>         Thanks
>         - Ioi
>
>     By the way, I first tried having only a single "tester" class and
>     walk the vtable to look for &last_virtual_method, but the C++
>     compiler told me that taking the address of a non-static function
>     is not allowed ..... so I ended up creating two tester classes and
>     checking their differences.
>
>
>
>



More information about the hotspot-dev mailing list