vgetfield complete removal
john.r.rose at oracle.com
Wed Aug 9 19:05:56 UTC 2017
On Aug 8, 2017, at 2:12 PM, Frederic Parain <frederic.parain at oracle.com> wrote:
> I intentionally avoid calling the new type utos, because its meaning is different.
> Here’s, we just need a way to factorize some code based on the properties of
> our implementation. U-types (and their associated utos TosState) will have a
> different semantic, allowing a given bytecode to executed on either a L-type
> or a Q-type. Note that at the implementation level, it doesn’t impose that the
> code is shared between L-types and Q-types.
I think eventually we will need only one of [pqu]tos as a new carrier type and
(therefore) interpreter state. The varying semantics will (I think) amount to
differently typed views of the same carrier type. (The typing will be statically
enforced by the verifier, if I'm right about this.) For example, if you push a
Q-Complex on the stack, the verifier will observe "Q-java/math/Complex"
and a U-type carrier, but one which is restricted to (a) no L-types or nulls,
and (b) no class other than java/math/Complex. If you push a U-Object
on the stack, on the other hand, the verifier will observe "U-java/lang/Object"
and (again) a U-type carrier, with no restrictions. Note that there doesn't
have to be any separate Q-mode carrier (in my view) because the U-mode
carrier, plus verifier-enforced restrictions, is enough to carry the data.
I'll say a little more FTR; I've got a proper white paper cooking on this
but it's not ready to post.
For performance, the U-type carrier has to be distinct from the classic L-type
carrier, so there must be at least one bytecode "atou" (or intrinsic method) that
wraps an L-Object into a U-Object (just a mode-tagged union, no unboxing!).
This cannot be an implicit step because of the carrier format difference.
Likewise, control flow merges cannot mix L-mode and U-mode values.
But control flow merges *can* mix Q-typed and U-typed values, because
they both use the U-mode carrier; the verifier must take the union of
both types and assign a type that contains both. In this theory, a verifier
type is a mode/class pair ([LQU], "pkg/class"), and the U and Q modes
can mix, with U overpowering Q at merges, and L not mixing with
either Q or U. (Classes merge the same in all three modes. We could
extend this theory to [IJFD] if we wanted, but that's a separate discussion.)
A "ubox" instruction converts a U-carrier (some Q-Foo or U-Foo) to an L-carrier
(some L-Foo, same Foo), while a "uunbox" converts some L-Foo to Q-Foo.
The current "vbox" and "vunbox" are just aliases for "ubox" and "unbox",
with the verifier observing types restricted to Q and L modes (not U-mode).
Foo may be concrete, an interface, or Object. Note that the U-carrier might
carry a null dynamically after something like "aconst_null;atou", but if the
verifier observes a Q-type, nulls are excluded (but the interpreter must
check for them anyhow, since it doesn't have the verifier types handy).
Anyway, my point is that we are likely to end up with a layered semantics
where there are a very small number of carrier types, and a richer set of
verifier types. Perhaps we will need more than one more carrier type (the
Q/U carrier I'm talking about) but I hope not, since fewer carrier types
means fewer bytecodes.
More information about the valhalla-dev