> From: "Brian Goetz" <brian.go...@oracle.com>
> To: "Dan Heidinga" <heidi...@redhat.com>
> Cc: "Remi Forax" <fo...@univ-mlv.fr>, "John Rose" <john.r.r...@oracle.com>,
> "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net>
> Sent: Tuesday, January 25, 2022 3:57:17 PM
> Subject: Re: VM model and aconst_init

> The motivation for this comes from erasure. Even if we specialize, we need to 
> be
> able to use specialized generics in an erased context, because there will be
> erased clients. If we have

> class Foo<T> {
> T m();
> T[] arr();
> }

> we can use also sorts of bridging/casting tricks to make Foo<int> work with 
> the
> erasure of T to Object, but we’ve got much less latitude when we want to treat
> an int[] as an Object[]. Since arrays are mutable / identity objects, we can’t
> copy them even if we wanted to; we need an identity-preserving way to say 
> “this
> int[] array, as if it were an Object[]”. Rejigging array covariance to work
> over the “extends” relation rather than the “subtype” relation seems the least
> damaging way to get there.

Agree for T[], but don't we have the same issue with T.ref, a L-type can be 
specialized by a Q-type ? 

class Foo<T> { 
T.ref field; 
} 

class Bar extends Foo<QComplex;> { 
void m() { 
field = Qcomplex;.new(); 
} 
} 

Rémi 

>> On Jan 25, 2022, at 9:40 AM, Dan Heidinga < [ mailto:heidi...@redhat.com |
>> heidi...@redhat.com ] > wrote:

>>> Can you mix and match both modes in the same method?
>>> Probably, since the interpreter doesn’t care about
>>> multi-bytecode patterns. Dunno if this causes a testing
>>> problem, and if so how to fix it. I think it’s probably
>>> OK, especially if we require the two-way checkcast
>>> (Q-Foo not a subtype of L-Foo in the verifier) so that
>>> each mode stays “in its own lane”.

>>> More explicitly, this is a set of use cases for using
>>> Q-types in C_Class entries in the constant pool to switch
>>> to Q-mode for bytecodes that refer to classes, including
>>> withfield and aconst_init.

>>> Let's talk a bit about having the L world and the Q world completely 
>>> disjoint at
>>> least from the bytecode verifier POV.

>>> It means that we need some checkcasts to move in both direction, from a 
>>> Q-type
>>> to a L-type and vice-versa.
>>> But at the same time, an array of L-type is a subtype of an array of Q-type 
>>> ?
>>> The result to a very uncommon/unconventional type system, and i'm not a big 
>>> fan
>>> of surprises in that area.

>> I've been puzzling over this as well and echo your discomfort with it,
>> mostly on the array side. I haven't been able to identify what the
>> sharp edge here is though other than that it feels surprising.

>> After playing with bytecode sequences, the part I'm not clear on is
>> whether I can store an LFoo; into a [QFoo; directly, or do I need a
>> checkcast QFoo; before the aastore? If I need the checkcast (and I
>> think I do), then I'm starting to come around to the view that the
>> array side isn't actually any different from what we'd do for any
>> other subclass relationship. The checkcast for Q->L is still odd, but
>> less concerning as it deals with new value semantics rather than
>> changing the array covariance?

>> For reference, the bytecodes sequences I've been looking at are the 
>> following:

>> Convert with checkcast:
>> --------------------------------
>> aload_1
>> checkcast QFoo; // or LFoo;

>> and

>> Convert with Q->L array store/load:
>> ---------------------------------------
>> anewarray //LFoo
>> astore_2
>> aload_2
>> iconst_0
>> invokestatic QFoo.<new>QFoo; // or any other way to get a Q
>> aastore
>> aload_2
>> iconst_0
>> aaload // use as an LFoo

>> Convert with L->Q array store/load:
>> ---------------------------------------
>> anewarray //QFoo
>> astore_2
>> aload_2
>> iconst_0
>> invokestatic X.getFoo:()LFoo;
>> // Is a checkcast needed here first to downcast? I think so
>> aastore
>> aload_2
>> iconst_0
>> aaload // use as an QFoo

>> --Dan

>>> Furthermore, i believe that subtyping is a key to avoid multiple bytecode
>>> verification of the generics code.
>>> By example, with the TypeRestriction attribute [1], the restriction has to 
>>> be
>>> subtype of the declared type/descriptor.

>>> Rémi

>>> [1] [
>>> https://cr.openjdk.java.net/~jrose/values/parametric-vm.html#type-restricted-methods-and-fields-and-the-typerestriction-attribute
>>> |
>>> https://cr.openjdk.java.net/~jrose/values/parametric-vm.html#type-restricted-methods-and-fields-and-the-typerestriction-attribute
>>> ]

Reply via email to