hg: mlvm/mlvm/hotspot: value-obj: first cut

David Chase david.r.chase at oracle.com
Wed Oct 17 13:41:37 PDT 2012


On 2012-10-17, at 2:12 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> But we can't rely on this, hence it is not a true type property.  But we could make it be as-if.
>> I think I have to assume some sort of a marker class ("implements PermanentlyLockable").
> 
> A bit in the class header (equivalent to implementing 
> PermanentLyLockable) means
> you have now two classses, the one with the old semantics and the one 
> with the new semantics.
> If you can have them both at runtime, you make your inlining cache less 
> efficient,
> it's a problem I've had with PHP.reboot.
> Marking the instance seems a better idea.

I'm not sure I follow this -- if j/l/Integer implements PermanentlyLockable, that's just one class.
You end up with possibly two versions of each entrypoint that handle any Plockable, true, but this seems like a necessary consequence of supporting both legacy (boxed-only) and modern (unboxed) implementations of Plockable types.  The entrypoints are different interfaces at the machine level; I don't see how you can avoid having two.  But many of the entrypoints might be mere stubs/wrappers.

I've been trying to figure out (Bharadwaj Yadavilli stopped by, we talked about this) whether the per-instance Plockable bit needs to exist or not.

Here are some assumptions I'm working from.  If any of these are wrong, that would be useful to know:

- we want "value types" in the future.

- we want value types passed and returned in unboxed form

- we want value types stored in arrays in unboxed form

- we can upcast an array of value-elements to an array of reference-elements

- we will sometimes box value types -- Object o = someInteger

- we must "support" legacy code

- we can use different compilation strategies for code depending on its bytecode version number.


So, a strawman implementation might be the following:

Use of values that implement Plockable in modern bytecodes is guaranteed to conform to the various value-friendly restrictions.
There's no extra bit, no extra call at allocation.
They compile as value types, an occurrence of new-dup-loadargs-init is replaced with running the constructor on the args on local memory.
The only exception is when they are upcast to a reference supertype.

In legacy bytecodes, none of this happens, it's just like today.  Mentions of Plockable types compiled as if they were boxed.

Compilation of any method that mentions a Plockable type in its signature depends on legacy/modern.
In modern, the default implementation is for unboxed, but a boxed stub is provided (perhaps lazily) for references from legacy code.
In legacy, the default implementation is for boxed, but an unboxed stub is provided (perhaps lazily) for references from modern code.

Arrays are nasty.
In both modern and legacy code, arrays themselves are reference types, but arrays of Plockable elements store the elements as value types.
In both modern and legacy code, loads from arrays of a reference type (in legacy code, Plockable is a reference type) with a Plockable subtype call a static factory method of the Plockable type that can create a boxed object given an "array address" and an index.  This can require an element-type check before loads.
Stores work in reverse, same assignment of responsibility to a method of the Plockable type.

Similarly, field loads/stores across the legacy/modern boundary box/unbox as necessary to obtain expected behavior.

Optimizations:
In legacy code, use-def webs of Plockable that are free of identity-uses can be unboxed.  Inlining of unboxing stubs from modern code might help here.
In modern code, identifying use-def webs that connect calls to legacy methods can be boxed, since the value representation will give no savings here.

I assume I am missing something, because I think this is simpler than John's proposal.  Am I skipping ahead straight to value types too quickly?

David



More information about the mlvm-dev mailing list