hg: mlvm/mlvm/hotspot: value-obj: first cut
Remi Forax
forax at univ-mlv.fr
Tue Oct 16 02:14:14 PDT 2012
On 10/16/2012 09:48 AM, John Rose wrote:
> On Oct 14, 2012, at 2:25 PM, Remi Forax wrote:
>
>> A value object is a true immutable object so the
>> JIT can constant fold field access or merge redundant access even if
>> there is method call between them but for that the JIT has to insert a
>> check to know if the object is frozen (definitively better than 'locked'
>> IMO) or not. Things are less clear for me when you have operation like
>> ==, does it means that a frozen object has not the same semantics as a
>> not frozen one ?
>
> The reference semantics of a frozen/locked/immutable object are (must
> be) a subset of the full reference semantics of a normal Java object.
>
> The essential feature of a locked object, I think, is that the JVM is
> free to rebox it at any time. (Maybe there is a restricted set of
> "times" that could make sense, but I'm thinking "between any two
> bytecodes".)
>
> Once you grant the JVM the right to rebox at any time, you get
> indeterminate behavior on operations like this:
> Complex x = Complex.valueOf(0, 1);
> synchronized (x) { } // cannot distinguish from synchronized
> (x.clone()) { }
> System.identityHashCode(x); // cannot distinguish from
> System.identityHashCode(x.clone())
> assert(x == x); // cannot distinguish (??) from (x == x.clone())
> Object y = x;
> assert(y == x); // cf. (y == x.clone())
> Object y2 = y;
> assert(y2 == y); // probably true, but how do you tell the view type
> from the bytecodes?
> synchronized (y) { }
> System.identityHashCode(y);
> ArrayList<Complex> xs = ...;
> xs.set(0, x);
> Complex z = xs.get(0);
> assert(z == x);
> ...
>
> This right-to-rebox also means that the JVM can throw away escape
> analysis for such types, since any escaping can be cloned first.
Frozen/locked is a runtime property, not a type property so it's harder
that that.
You have to do a frozen check at the beginning of the method and prey
that people
will only use it with frozen object and not a not frozen one because in
that case, you have to de-optimize.
Maybe, you can have two versions on the same method, one with the frozen
semantics and
one with the boxed one (this is what I have done in JDart). Also, it can
be a type property if no loaded code do a new Complex, like a class
hierarchy analysis but it seems brittle.
> The end result is that nearly all immutable values (of fixed small
> size) can be allocated to registers. This (crucially) includes values
> passed into and returned out of non-inlined methods. This is the basis
> for a number of urgently useful things, beyond Complex.
>
> My goal here is to find a set of design rules under which the
> indeterminacy (a) doesn't matter, (b) can be diagnosed with an
> exception, and/or (c) can be overwritten by an uplevel operation (like
> Object.equals). That's what this is about:
> https://blogs.oracle.com/jrose/entry/value_types_in_the_vm
>
> Mega-extra points for retrofitting to existing bytecodes and behaviors
> in rt.jar etc.
That's the main issue, the java spec mandates that Integer between -128
and 127 must be cached,
so you can't without changing that part of the spec (I'm fine with that,
that rule is a premature optimization)
says that Integer.valueOf will create a frozen/locked object.
>
> — John
Rémi
More information about the mlvm-dev
mailing list