Moving the _vtable_len into Klass
john.r.rose at oracle.com
Wed Dec 16 20:48:07 UTC 2015
On Dec 16, 2015, at 9:26 AM, Chris Plummer <chris.plummer at oracle.com> wrote:
>> Does anyone know if there is a reason for vtable_length_offset to be a word offset?
> Sorry, I don't have any historical perspective here, other than saying that specifying size, lengths, and offsets for InstanceKlass related stuff seems to all be scaled to HeapWordSize. Just started looking in this area recently for the first time myself. BTW, I think it should be using wordSize instead of HeapWordSize, although they do both evaluate to the same thing.
InstanceKlass and ArrayKlass are the only subclasses of Klass.
Java objects can be instances or arrays, and both have v-tables.
Array v-tables have uninteresting Object methods (only clone is special).
In the A2.0 future, Array v-tables will (probably) have additional methods.
Therefore the property of having a v-table is universal to all Klasses.
Therefore this is a good refactoring.
Here are some bits of ancient history, plus thoughts on scaled sizes:
In the old days (metadata in perm-gen) some Klasses (method-klass,
instance-klass-klass, etc.) did *not* have v-tables.
The necessary alignment of v-table position between InstanceKlass and
ArrayKlass had to be forced by a hack. We have inherited this hack,
but should get rid of it.
The original sizing logic for HotSpot was designed for 32-bit machines.
Using 32-bit integers, sizing logic for some Java data structures is subject
to embarrassing overflows. (Consider `new long[0x7FFFFFFE]`.)
Even size_t (which is unsigned) doesn't quite have enough bits of
dynamic range. And size_t itself was new (not so portable) when
HotSpot was first written. Also, 64-bit integer arithmetic was more
expensive in those days, on some platforms, so the original coders
did not resort to uint64_t for sizing calculations.
By working with ints scaled by wordSize (== sizeof(HeapWord)),
we bought a couple more bits of dynamic range, to avoid overflows
more easily. Having 32-bit ints stored in metadata is also a little
more compact, although this sometimes comes with a risk of
truncation when large values pass through small storage fields.
Nowadays, it would be reasonable to use unscaled sizes almost
everywhere, passed as uint64_t values, and stored smaller
where possible (using scaling or var-ints or whatever, as a
(BTW, I think we should use more UNSIGNED5 var-ints for
metadata sizes, to save footprint and provide safer dynamic range.)
Even from the beginning, the JVM used a mix of scaled
and unscaled size values, although there was an attempt
to make the scaled ones predominate. At some point
we tried to introduce some static typing help to avoid
the obvious sort of bugs; see classes ByteSize and
WordSize. These are helpful but also not universal.
So we have a mix of conventions, not always clearly
sorted out. The complexity and bug-worthiness of
this setup is the biggest down-side to scaled size logic.
An up-side of having scaled sizes is you get 2-3 more bits
of dynamic range. A down-side of having scaled sizes is
you have to decode scaled values by shifting them 2-3 bits.
Sometimes x86 addressing modes help make this decoding
happen "for free" as part of an address formation operation,
but in practice I think this happens unreliably.
(Using a tighter encoding like UNSIGNED5 could decode
about as quickly as an explicit shift, but gain more footprint
benefits. But that's a future conversation.)
I personally don't regard the up-sides for scaled sizes as
sufficient, now that 64-bit math is perfectly cheap.
It will be will be hard to change to unscaled sizes everywhere,
(and I've surely not given the full arguments both ways!)
so we will be living in a mixed world for the foreseeable
future. I do think, however, that it is reasonable to remove
scaled sizes from JVM internal APIs, incrementally over time.
Bottom line: My suggestion is that you make Klass admit
that it always has a v-table, and don't feel bad about using
unscaled sizes appearing in the JVM internal APIs, as long
as you control footprint inside each class.
More information about the hotspot-dev