Determining the size of C++ vtables

Thomas Stüfe thomas.stuefe at gmail.com
Fri Feb 24 07:17:28 UTC 2017


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.

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> wrote:

>
>
> On 2/23/17 7:47 PM, Ioi Lam wrote:
>
>> Hi,
>>
>> I am working on 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