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