Way 1 seems unnecessarily expensive considering that it requires JVM changes, but doesn't give us anything more than way 2.
Way 2 looks promising because it's inexpensive at the JVM level, and I imagine the cost of the compiler changes is similar to way 1. I like that we can still introduce language level changes with this solution.
Way 3 may be the least intrusive from the JVM's perspective, but it does complicate migration. One disadvantage is that it requires changes to declaration sites and usage sites, while way 2 only requires changes to the declaration site. This may be fine in the empty collection case, but what about cases where the static field is public? We can't control those usage sites.
Way 2 looks promising because it's inexpensive at the JVM level, and I imagine the cost of the compiler changes is similar to way 1. I like that we can still introduce language level changes with this solution.
Way 3 may be the least intrusive from the JVM's perspective, but it does complicate migration. One disadvantage is that it requires changes to declaration sites and usage sites, while way 2 only requires changes to the declaration site. This may be fine in the empty collection case, but what about cases where the static field is public? We can't control those usage sites.
--
Bjørn Vårdal
Bjørn Vårdal
----- Original message -----
From: Remi Forax <[email protected]>
To: Valhalla Expert Group Observers <[email protected]>
Cc: Bjorn B Vardal/Ottawa/IBM@IBMCA
Subject: Re: Classes, specializations, and statics
Date: Thu, Mar 24, 2016 7:01 PM
Hi Brian,
you forget Way 3 :)
Way 3: There's still only two placements, static and instance;
"static" means independent of an instance as before, thus i can not be specialized by a type parameter (which is specific to an instance).
Unlike Way 2, static means static and unlike Way 1, there is no need to a new placement, ACC_SPECIES, because there is a new data-structure let's call it TypeValue that allows to create a map which is indexed by a reified type parameter.
class Collections {
private static final TypeValue<List<*>> EMPTY_LIST = new TypeValue<>() {
public List<*> create(Type type) {
return EmptyList.class.newSpecializedInstance(type);
}
});
public static <any T> List<T> emptyList() {
return (List<T>)TYPE_VALUE.get(T.class);
}
}
regards,
Rémi
----- Mail original -----
> De: "Brian Goetz" <[email protected]>
> À: "Bjorn B Vardal" <[email protected]>, [email protected]
> Envoyé: Jeudi 24 Mars 2016 23:00:26
> Objet: Re: Classes, specializations, and statics
>
> I think there's two ways to think about "specialized statics" at the VM
> level; how you think about it conditions which way you're inclined to go.
>
> Way 1: This is a new thing; we used to have placements for "static" and
> "instance", and now we have three placements: static, instance, and
> specialization. We add a new bit (ACC_SPECIES), and define new bytecode
> behaviors for members with the SPECIES bit set.
>
> Way 2: There's still only two placements, static and instance;
> per-specialization static is just the natural reinterpretation of
> "static" in the face of a many-to-one relationship between source
> classes and runtime classes. What we used to think of static really is
> the weird case, which we can model as "new static, but restricted (using
> "where" restriction) to the all-erased specialization."
>
> Both ways are 100% compatible with existing generic sources and
> classfiles. Way 2 (which seems more natural to me, and also means we
> don't have to invent a new thing at the VM level) exploits the
> requirement that Constant_Class[Foo] and Constant_ParamType[Foo, erased]
> *must* describe the same runtime entity.
>
> With Way 2, we still (probably) have a new concept at the language
> level, which governs whether the so-described member is a member of all
> parameterizations, or only the all-erased one, but this gets compiled
> away. This matches up with our treatment of erasure; it is the choice
> of the language compiler to choose erased generics or reified, and Java
> chooses to erase some parameterizations but not all.
>
> .NET chooses Way 2 in the extreme; static members are not shared across
> specializations at all, since they have no notion of erasure.
> Compatibility wouldn't let us go that far; existing statics are shared
> across all erased parameterizations, so they would need to remain so.
>
> On 3/18/2016 5:01 PM, Bjorn B Vardal wrote:
> > > I wonder if it's not better to have a class like ThreadLocal or
> > ClassValue that
> > > represents a constant that can be different depending on the
> > specialization.
> > That solution seems possible - we could implement
> > specialization-specific statics as a static Map<Class<?>, Foo<?>>,
> > where the type parameter is the key and "specialized static" is the
> > value. However, it would be slower than compiling to static access.
> > Are there other use cases that make specialized statics necessary? So
> > far we have empty collection, which can be implemented using the map.
> > State of the Specialization from Dec 2014 mentioned layers - are
> > specialized statics a step along the path to layers? Will a
> > SpecializedValue map for specialized statics look like an
> > afterthought if we go the rest of the way to layers?
> > --
> > Bjørn Vårdal
> >
> > ----- Original message -----
> > From: Remi Forax <[email protected]>
> > To: Valhalla Expert Group Observers
> > <[email protected]>
> > Cc: Bjorn B Vardal/Ottawa/IBM@IBMCA, Brian Goetz
> > <[email protected]>
> > Subject: Re: Classes, specializations, and statics
> > Date: Tue, Feb 23, 2016 2:57 PM
> > I wonder if it's not better to have a class like ThreadLocal or
> > ClassValue that represents a constant that can be different
> > depending on the specialization.
> >
> > Rémi
> >
> > ----- Mail original -----
> > > De: "Brian Goetz" <[email protected]>
> > > À: "Bjorn B Vardal" <[email protected]>
> > > Cc: [email protected]
> > > Envoyé: Mardi 23 Février 2016 01:23:16
> > > Objet: Re: Classes, specializations, and statics
> > >
> > > It's possible that there could be multiple "ssinit" methods, each
> > > restricted to specific parameterizations (just like any other
> > restricted
> > > method), but in general, the "ssinit" method can be specialized just
> > > like any other method. So what I envision (in the absence of
> > > initialization of conditional members) is possibly two such
> > methods; one
> > > that is specializable (corresponding to _SS members) and one that is
> > > not, restricted to the erased parameterization (corresponding to
> > > traditional statics.)
> > >
> > >
> > >
> > > On 2/22/2016 4:11 PM, Bjorn B Vardal wrote:
> > > > I think we're on the same page regarding specialized <clinit>.
> > > > - The JVM will be handed multiple <clinit> partial methods,
> > and the
> > > > specializer will take care of selecting the appropriate
> > <clinit> for
> > > > each specialization.
> > > > - The erased <clinit> will contain the non-specialized static
> > > > initialization code, which ensures that it only runs once.
> > > > - The erased <clinit> will always run before the first
> > specialization
> > > > <clinit>.
> > > > - The Java syntax is still up for discussion.
> > > > > I think this is mostly a matter of coming up with the right
> > syntax,
> > > > which makes it clear that statics can be per-class or
> > > > per-specialization. There are a whole pile of related
> > > > specialization-related syntax issues, I'll try to get them all
> > in one
> > > > place.
> > > > I don't think the problem will be to make it clear that
> > statics can be
> > > > per-class or per-specialization, but rather why some
> > parameterizations
> > > > (which to the user are synonymous with specializations) don't
> > appear
> > > > to have specialized statics. Do we want to put erasure in the
> > face of
> > > > users like this? It seems better to let the users deal purely with
> > > > parameterizations, and we let specialization and erasure be
> > > > implementation details.
> > > > --
> > > > Bjørn Vårdal
> > > >
> > > > ----- Original message -----
> > > > From: Brian Goetz <[email protected]>
> > > > To: Bjorn B Vardal/Ottawa/IBM@IBMCA,
> > > > [email protected]
> > > > Cc:
> > > > Subject: Re: Classes, specializations, and statics
> > > > Date: Thu, Feb 18, 2016 7:55 PM
> > > >
> > > >
> > > >> Based on the example above, I think we need to be more
> > explicit
> > > >> about how the <clinit> method is handled.
> > > >> There are really two different sets of statics that need
> > to be
> > > >> handled by the class initialization:
> > > >> A) common statics (shared across all instantiations)
> > > >> B) specialized statics
> > > >> In addition to the statics, there is also common (and maybe
> > > >> specialized?) code that is run as part of <clinit>.
> > > >
> > > > There is a reasonable model to collapse these back into one
> > > > concept; treat "common statics" as specialized statics on the
> > > > all-erased parameterization, with a <where> clause that
> > restricts
> > > > them to that parameterization. Not clear whether we
> > actually want
> > > > to represent it that way or not, but its a useful mental model
> > > > that doesn't require the creation of a third thing. (Since
> > > > Class[Foo] and ParamType[Foo,erased*] describe the same class,
> > > > this is also fully binary compatible with existing classes.)
> > > >
> > > > Which means we can do a similar thing with <clinit>, if we
> > want.
> > > > I'll wave my hands because we've not yet talked much about
> > > > conditional members, but it basically looks like this:
> > > >
> > > > <where T*=erased*>
> > > > <init>() { /* common static init code */
> > > > /* specializable init code */ }
> > > >
> > > > <init>() { /* specializable init code */ }
> > > >
> > > > Or not.
> > > >> Where will the initialization code for both kinds of
> > statics be?
> > > >> The existing <clinit> method?
> > > >
> > > > We have two choices:
> > > > - have a new <sclinit> block that gets run once per
> > > > specialization, and keep <clinit>
> > > > - merge the two as above, exploiting planned support for
> > > > conditional members
> > > >
> > > > Either way, as you say, we have to ensure that the common init
> > > > runs exactly once.
> > > >> When using *static, are we only discussing {get,put}? Or
> > is this
> > > >> also proposing invokestatic changes to allow specialized
> > static
> > > >> methods?
> > > >
> > > > Methods too.
> > > >> All of the technical details aside, is this something we
> > really
> > > >> want to expose to the users? They're going to have a
> > hard time
> > > >> understanding why Foo<int> (or Foo<ValueType) gets
> > specialized
> > > >> statics while Foo<String> & Foo<Bar> share the erased
> > version.
> > > >
> > > > I think this is mostly a matter of coming up with the right
> > > > syntax, which makes it clear that statics can be per-class or
> > > > per-specialization. There are a whole pile of related
> > > > specialization-related syntax issues, I'll try to get them
> > all in
> > > > one place.
> > > >
> > > >
> > >
> > >
> >
> >
>
>
