Re: Evolving the wrapper classes

2020-06-19 Thread Dan Smith
> On Jun 19, 2020, at 2:44 PM, fo...@univ-mlv.fr wrote:
> 
> If the VM see I as a subtype of Object, there is no need for a 
> Ljava/lang/Integer$val; at all, it's better to have aload/astore/etc to work 
> on I directly.

That's initially somewhat attractive, but think about the implications for 
things like slot size. Primitives and inline objects are really two very 
different things in the current JVM design.

Re: Evolving the wrapper classes

2020-06-19 Thread Dan Smith
> On Jun 19, 2020, at 1:51 PM, fo...@univ-mlv.fr wrote:
> 
> covariant return type
>  interface I {
> int foo();
>  }
>  interface J {
> Object foo();
>  }
>  class A implements I, J {
>int foo();
>  }
> 
> with I.java compiled a long time ago.

Nothing in this proposal changes how these classes are compiled. The following 
methods will exist:

I.foo()I
J.foo()Ljava/lang/Object;
A.foo()I
A.foo()Ljava/lang/Object; // bridge

I think you may be mixed up thinking that we'll sometimes translate 'int' in a 
descriptor to 'Ljava/lang/Integer$val;', but that's not the case. 'I' is 
preferred wherever possible.



Re: Evolving the wrapper classes

2020-06-19 Thread forax
- Mail original -
> De: "daniel smith" 
> À: "Remi Forax" 
> Cc: "Brian Goetz" , "valhalla-spec-experts" 
> 
> Envoyé: Vendredi 19 Juin 2020 21:27:12
> Objet: Re: Evolving the wrapper classes

>> On Jun 19, 2020, at 12:54 PM, Remi Forax  wrote:
>> 
>>> Note that [I and [QInteger$val have the exact same layout, so it is really a
>>> matter of treating the two type names as referring to the same underlying
>>> runtime type.
>> 
>> yes, but at the same time descriptor are matched by name and you need to have
>> the proper descriptor when overriding/implementing a method,
>> so the strategy of blindly replacing every I by QInteger$val; doesn't really
>> work.
>> 
>> Usually the solution is to use bridges but bridges only work with subtyping
>> relationship not equivalence relationship (because you can travel in both
>> direction).
>> I believe we need to bring the forward/bridge-o-matic at the same time we
>> retrofit primitive to inline.
> 
> In the VM this is mostly a verification problem: have a
> '[Qjava/lang/Integer$val;', need a '[I'? You're good! ("Mostly", because there
> is still the matter of ensuring there's a single encoding for both kinds of
> objects, or that the instructions are capable of handling two different
> encodings.)
> 
> I'm not sure we'd get into any situations where a '([I)V' descriptor needs to
> override a '([Qjava/lang/Integer$val)V' descriptor, or vice versa, until we 
> get
> to specialization,

covariant return type
  interface I {
 int foo();
  }
  interface J {
 Object foo();
  }
  class A implements I, J {
int foo();
  }

with I.java compiled a long time ago.

> and then I'm not sure this is any different than other forms
> of bridging. All existing code will continue to use 'I' in its compiled
> descriptors.

if everything is compiled at the same time, there is no issue, otherwise you 
can create a loop.

Rémi


Re: Evolving the wrapper classes

2020-06-19 Thread Dan Smith


> On Jun 19, 2020, at 12:54 PM, Remi Forax  wrote:
> 
>> Note that [I and [QInteger$val have the exact same layout, so it is really a 
>> matter of treating the two type names as referring to the same underlying 
>> runtime type.
> 
> yes, but at the same time descriptor are matched by name and you need to have 
> the proper descriptor when overriding/implementing a method,
> so the strategy of blindly replacing every I by QInteger$val; doesn't really 
> work.
> 
> Usually the solution is to use bridges but bridges only work with subtyping 
> relationship not equivalence relationship (because you can travel in both 
> direction).
> I believe we need to bring the forward/bridge-o-matic at the same time we 
> retrofit primitive to inline.

In the VM this is mostly a verification problem: have a 
'[Qjava/lang/Integer$val;', need a '[I'? You're good! ("Mostly", because there 
is still the matter of ensuring there's a single encoding for both kinds of 
objects, or that the instructions are capable of handling two different 
encodings.)

I'm not sure we'd get into any situations where a '([I)V' descriptor needs to 
override a '([Qjava/lang/Integer$val)V' descriptor, or vice versa, until we get 
to specialization, and then I'm not sure this is any different than other forms 
of bridging. All existing code will continue to use 'I' in its compiled 
descriptors.



Re: Evolving the wrapper classes

2020-06-19 Thread forax
Blindly is perhaps a word too strong, let say we have to come with a plan, a 
good plan, 
and i fail to see how it can work with only the current bridge mechanism we 
have. 

Rémi 

> De: "Brian Goetz" 
> À: "Remi Forax" 
> Cc: "Tobi Ajila" , "valhalla-spec-experts"
> , "valhalla-spec-experts"
> 
> Envoyé: Vendredi 19 Juin 2020 20:59:35
> Objet: Re: Evolving the wrapper classes

>> yes, but at the same time descriptor are matched by name and you need to have
>> the proper descriptor when overriding/implementing a method,
>> so the strategy of blindly replacing every I by QInteger$val; doesn't really
>> work.

> Who said blindly?


Re: Evolving the wrapper classes

2020-06-19 Thread Brian Goetz

I hope to surprise you positively!

On 6/19/2020 3:09 PM, fo...@univ-mlv.fr wrote:
Blindly is perhaps a word too strong, let say we have to come with a 
plan, a good plan,
and i fail to see how it can work with only the current bridge 
mechanism we have.






Re: Evolving the wrapper classes

2020-06-19 Thread Brian Goetz




yes, but at the same time descriptor are matched by name and you need 
to have the proper descriptor when overriding/implementing a method,
so the strategy of blindly replacing every I by QInteger$val; doesn't 
really work.


Who said blindly?



Re: Evolving the wrapper classes

2020-06-19 Thread Remi Forax
> De: "Brian Goetz" 
> À: "Tobi Ajila" 
> Cc: "valhalla-spec-experts" ,
> "valhalla-spec-experts" 
> Envoyé: Vendredi 19 Juin 2020 20:18:09
> Objet: Re: Evolving the wrapper classes

> Zooming out, what we've been trying to do is shake out the places where the 
> JVM
> treats primitives and references differently, and aligning them, so that we 
> are
> able to broaden the approach of "generics erase T to Object" to include 
> inlines
> and primitives. The war cry might be:

> Object is the new Any

> L-World does much of this for inlines, but we don't want to leave primitives 
> out
> in in the cold in the programming model; being able to get good behavior for
> Foo but not the same for Foo would be a missed opportunity to
> provide a uniform programming model. Much of this is either handled by 
> existing
> L-World behavior (e.g., behavior of ==), but this seam is one that needs to be
> covered. We can cover some in the static compiler (conversions between I and
> Qint) but when it comes to arrays, the invariance of arrays would expose our
> tricks, and we'd have to have awful restrictions like "you can't use arrays in
> generics."

> Note that [I and [QInteger$val have the exact same layout, so it is really a
> matter of treating the two type names as referring to the same underlying
> runtime type.
yes, but at the same time descriptor are matched by name and you need to have 
the proper descriptor when overriding/implementing a method, 
so the strategy of blindly replacing every I by QInteger$val; doesn't really 
work. 

Usually the solution is to use bridges but bridges only work with subtyping 
relationship not equivalence relationship (because you can travel in both 
direction). 
I believe we need to bring the forward/bridge-o-matic at the same time we 
retrofit primitive to inline. 

Rémi 

> On 6/19/2020 1:07 PM, Tobi Ajila wrote:

>>> Because arrays have identity (not to mention potentially large copying 
>>> costs),
>>> there is simply no reasonable conversion we can define; any "conversion" 
>>> would
>>> involve copying all the data, changing identity, or both. Just as with the
>>> array subtyping requirements (Point[] <: Point.ref[] <: Object[]), these are
>> > things only the VM can do for us.

>> I suspected that this was likely due to the large cost of converting between
>> `[I` and `[java/lang/Integer$val`. However, I am still a little unclear as to
>> what the motivation is for this. Is this solely for specialized generics?

>> In Dan's examples with `I` and `java/lang/Integer$val`, the only places where
>> conversions are needed are when primitives are used as type parameters or to
>> call instance methods on them, both of which can already be done with 
>> primitive
>> arrays. So in the LW3 - LW20 timeframe would we have any need for these
>> conversions? If so, could you provide some examples?

>> In the case of specialized generics, is the intention that `[I` (and I 
>> suppose
>> `I` as well) will appear in generic code?


Re: Evolving the wrapper classes

2020-06-19 Thread Brian Goetz
Zooming out, what we've been trying to do is shake out the places where 
the JVM treats primitives and references differently, and aligning them, 
so that we are able to broaden the approach of "generics erase T to 
Object" to include inlines and primitives.  The war cry might be:


    Object is the new Any

L-World does much of this for inlines, but we don't want to leave 
primitives out in in the cold in the programming model; being able to 
get good behavior for Foo but not the same for Foo would be 
a missed opportunity to provide a uniform programming model.  Much of 
this is either handled by existing L-World behavior (e.g., behavior of 
==), but this seam is one that needs to be covered.  We can cover some 
in the static compiler (conversions between I and Qint) but when it 
comes to arrays, the invariance of arrays would expose our tricks, and 
we'd have to have awful restrictions like "you can't use arrays in 
generics."


Note that [I and [QInteger$val have the exact same layout, so it is 
really a matter of treating the two type names as referring to the same 
underlying runtime type.


On 6/19/2020 1:07 PM, Tobi Ajila wrote:


> Because arrays have identity (not to mention potentially large 
copying costs), there is simply no reasonable conversion we can 
define; any "conversion" would involve copying all the data, changing 
identity, or both.  Just as with the array subtyping requirements 
(Point[] <: Point.ref[] <: Object[]), these are things only the VM can 
do for us.


I suspected that this was likely due to the large cost of converting 
between `[I` and `[java/lang/Integer$val`. However, I am still a 
little unclear as to what the motivation is for this. Is this solely 
for specialized generics?


In Dan's examples with `I` and `java/lang/Integer$val`, the only 
places where conversions are needed are when primitives are used as 
type parameters or to call instance methods on them, both of which can 
already be done with primitive arrays. So in the LW3 - LW20 timeframe 
would we have any need for these conversions? If so, could you provide 
some examples?


In the case of specialized generics, is the intention that `[I` (and I 
suppose `I` as well) will appear in generic code?






RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila
Thanks for the example Dan, this "Object[] objs = arr; // just like Point[]
<: Object[]" makes it very clear. Brian's response makes more sense to me
now.


> From: Dan Smith 
> To: Tobi Ajila 
> Cc: Brian Goetz , valhalla-spec-experts
> , valhalla-spec-experts
> 
> Date: 2020/06/19 01:32 PM
> Subject: [EXTERNAL] Re: Evolving the wrapper classes
>
>
> > On Jun 19, 2020, at 11:07 AM, Tobi Ajila  wrote:
> >
> > I am still a little unclear as to what the motivation is for this.
> Is this solely for specialized generics?
> >
> > In Dan's examples with `I` and `java/lang/Integer$val`, the only
> places where conversions are needed are when primitives are used as
> type parameters or to call instance methods on them, both of which
> can already be done with primitive arrays. So in the LW3 - LW20
> timeframe would we have any need for these conversions? If so, could
> you provide some examples?
>
> I think it comes down to specialization and subtyping.
>
> Pre-specialization, here's one example that uses subtyping:
>
> int[] arr = { 1 };
> Object[] objs = arr; // just like Point[] <: Object[]
> Object obj = objs[0];
> Integer i = (Integer) obj;
>
> This would compile to something like:
>
> iconst_1
> newarray T_INT
> dup
> iconst_0
> iconst_1
> iastore
> astore_0
>
> aload_0
> astore_1
>
> aload_1
> iconst_0
> aaload
> astore_2
>
> aload_2
> checkcast java/lang/Integer
> astore_3
>
> Going in the other direction—allocating a [Qjava/lang/Integer; and
> then using iaload/iastore on it—may not be necessary unless/until
> the language supports "new T[]" in specialized code, but it
> tentatively makes sense to support now anyway, rather than having to
> come back and fix it up later.
>
> > In the case of specialized generics, is the intention that `[I`
> (and I suppose `I` as well) will appear in generic code?
>
> If you mean "can '[' be specialized to '[I'?", the answer is no.
> The primitive types cannot act as type arguments.


Re: Evolving the wrapper classes

2020-06-19 Thread Dan Smith
PSA: this thread has been polluted with the address:

valhalla-spec-experts 

Which just generates admin notifications. Please delete that address from any 
replies. :-)

Re: Evolving the wrapper classes

2020-06-19 Thread Dan Smith


> On Jun 19, 2020, at 11:07 AM, Tobi Ajila  wrote:
> 
> I am still a little unclear as to what the motivation is for this. Is this 
> solely for specialized generics?
> 
> In Dan's examples with `I` and `java/lang/Integer$val`, the only places where 
> conversions are needed are when primitives are used as type parameters or to 
> call instance methods on them, both of which can already be done with 
> primitive arrays. So in the LW3 - LW20 timeframe would we have any need for 
> these conversions? If so, could you provide some examples?

I think it comes down to specialization and subtyping.

Pre-specialization, here's one example that uses subtyping:

int[] arr = { 1 };
Object[] objs = arr; // just like Point[] <: Object[]
Object obj = objs[0];
Integer i = (Integer) obj;

This would compile to something like:

iconst_1
newarray T_INT
dup
iconst_0
iconst_1
iastore
astore_0

aload_0
astore_1

aload_1
iconst_0
aaload
astore_2

aload_2
checkcast java/lang/Integer
astore_3

Going in the other direction—allocating a [Qjava/lang/Integer; and then using 
iaload/iastore on it—may not be necessary unless/until the language supports 
"new T[]" in specialized code, but it tentatively makes sense to support now 
anyway, rather than having to come back and fix it up later.

> In the case of specialized generics, is the intention that `[I` (and I 
> suppose `I` as well) will appear in generic code?

If you mean "can '[' be specialized to '[I'?", the answer is no. The 
primitive types cannot act as type arguments.

RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila


> Because arrays have identity (not to mention potentially large copying
costs), there is simply no reasonable conversion we can define; any
"conversion" would involve copying all the data, changing identity, or
both.  Just as with the array subtyping requirements (Point[] <: Point.ref
[] <: Object[]), these are things only the VM can do for us.

I suspected that this was likely due to the large cost of converting
between `[I` and `[java/lang/Integer$val`. However, I am still a little
unclear as to what the motivation is for this. Is this solely for
specialized generics?

In Dan's examples with `I` and `java/lang/Integer$val`, the only places
where conversions are needed are when primitives are used as type
parameters or to call instance methods on them, both of which can already
be done with primitive arrays. So in the LW3 - LW20 timeframe would we have
any need for these conversions? If so, could you provide some examples?

In the case of specialized generics, is the intention that `[I` (and I
suppose `I` as well) will appear in generic code?



Re: Evolving the wrapper classes

2020-06-19 Thread Brian Goetz
> Given your examples can we assume that the JVM will never need to do an 
> implicit `Qjava/lang/Integer$val;` to `I` conversion? And these will always 
> be explicit conversions performed by javac?
> 

Correct.

> > - The type [I is considered by the verifier to be equivalent to 
> > [java/lang/Integer$val. Array operations (aaload, iaload, etc.) support 
> > this.
> 
> Could you please explain the motivation behind this? Specifically, in which 
> cases are iaload and aaload operations both performed on `[I` ? 
> 
> If `I` and `Qjava/lang/Integer$val;` will require explicit javac conversions, 
> shouldn't `[I` and `[java/lang/Integer$val` also?
> 

Because arrays have identity (not to mention potentially large copying costs), 
there is simply no reasonable conversion we can define; any “conversion” would 
involve copying all the data, changing identity, or both.  Just as with the 
array subtyping requirements (Point[] <: Point.ref[] <: Object[]), these are 
things only the VM can do for us.  




RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila
Hi Dan S.

>>> - Where necessary (depending on the operations being performed), the
compiler generates conversions between 'I' and 'java/lang/Integer$val'. 'I'
is preferred wherever possible.
>>
>> We have to use QInteger$val whenever we use int as a type parameter, the
rest of the time, we can use I.
...
> (Note that none of these conversions are "boxing" or "unboxing". They're
strictly compilation artifacts. It may be useful to come up with a new word
for them.)

Given your examples can we assume that the JVM will never need to do an
implicit `Qjava/lang/Integer$val;` to `I` conversion? And these will always
be explicit conversions performed by javac?

> - The type [I is considered by the verifier to be equivalent to
[java/lang/Integer$val. Array operations (aaload, iaload, etc.) support
this.

Could you please explain the motivation behind this? Specifically, in which
cases are iaload and aaload operations both performed on `[I` ?

If `I` and `Qjava/lang/Integer$val;` will require explicit javac
conversions, shouldn't `[I` and `[java/lang/Integer$val` also?


Regards,
--Tobi


Re: Evolving the wrapper classes

2020-06-17 Thread Dan Smith
> On Jun 17, 2020, at 4:30 PM, Kevin Bourrillion  wrote:
> 
>> - The type 'Integer.val' is equivalent to 'int'. Primitive types are inline 
>> types—they have members, support method invocation, etc.
>> 
> This at least suggests that `42L.hashCode()` would begin to work just as 
> `"foo".hashCode()` does?

Yep, that's what I mean. Member accesses are now allowed (assuming the member 
you're looking for exists) for all types.

> Users can write `Integer.val` in their code, but would there ever be a good 
> reason to? I assume we would always prefer `int`. And this actually makes me 
> wonder if it's worth considering also allowing `int.ref` to be an alias for 
> `Integer` because it would allow users to drop the word `Integer` from their 
> code more completely, and therefore `int` would look more and more like it 
> was just an inline type like any other. It reminds you that the old 
> boxing/unboxing isn't in play anymore. And `int.ref` is more self-evidently 
> something you can't synchronize on, etc. But, what would remain weird is that 
> you don't actually find a val-default class called `int` sitting in an 
> `int.java` file.

Agreed, I think it would be reasonable to consider both i) supporting 'int.ref' 
as type syntax, and ii) prohibiting 'Integer.val'.

Although, redundancies aside, if you have some discomfort with bare 'Integer' 
being a reference type for an inline class, you may have similar discomfort 
with our "reference default" story in general (e.g., 'LocalDateTime' will have 
the same properties).

Re: Evolving the wrapper classes

2020-06-17 Thread Brian Goetz


Hmm, just maybe this will be less confusing than I was fearing. I'm 
seeing now that "Integer is the real class, int is alias for 
Integer.val" is a whole lot cleaner than "int becomes a val-default 
class and Integer is demoted to alias for int.ref", which for some 
reason was the way I was thinking of it.


I'm sure that, sometime during the evolution, I probably said it the way 
you remember.  Then Dan came along and cleaned it up :)






Java language/compiler changes (when --enable-preview is set):
- The class file reader knows how to find the special
Integer.class and Integer$val.class.
- The type 'Integer.val' is equivalent to 'int'. Primitive types
are inline types—they have members, support method invocation, etc.


This at least /suggests /that `42L.hashCode()` would begin to work 
just as `"foo".hashCode()` does?


We certainly have that option.  We could decide to not take it, on the 
theory that it scares the neighbors, but it does seem sensible to just 
say "0L is a long-valued expression" and "long implements XYZ 
interfaces", and let the neighbors be scared for a few minutes.


Users /can/ write `Integer.val` in their code, but would there ever be 
a good reason to? I assume we would always prefer `int`. And this 
actually makes me wonder if it's worth considering also allowing 
`int.ref` to be an alias for `Integer` because it would allow users to 
drop the word `Integer` from their code more completely, and therefore 
`int` would look more and more like it was just an inline type like 
any other. It reminds you that the old boxing/unboxing isn't in play 
anymore. And `int.ref` is more self-evidently something you can't 
synchronize on, etc. But, what would remain weird is that you don't 
/actually /find a val-default class called `int` sitting in an 
`int.java` file.


Right, there's a set of pros and cons here, none of which are 
technical.  Being able to say `int.ref` makes it more clear that `int` 
and `Point` are the same thing, but on the other hand, it raises issues 
of "there are two ways to say the same thing, so let's have an endless 
debate about it."





Re: Evolving the wrapper classes

2020-06-17 Thread Dan Smith



> On Jun 17, 2020, at 4:13 PM, Brian Goetz  wrote:
> 
>> - Where necessary (depending on the operations being performed), the 
>> compiler generates conversions between 'I' and 'java/lang/Integer$val'. 'I' 
>> is preferred wherever possible.
> 
> We have to use QInteger$val whenever we use int as a type parameter, the rest 
> of the time, we can use I.  

Right. Specifically, if we support inline types as type arguments before we get 
to specialization, we'll use erasure, which looks like:

new java/util/ArrayList;
// dup, init
astore 1

aload 1
iconst_0
invokestatic Qjava/lang/Integer$val;.(I)Qjava/lang/Integer$val; // <-- 
conversion
invokevirtual java/util/ArrayList.add:(Ljava/lang/Object;)Z
pop

aload1
iconst_0
invokevirtual java/util/ArrayList.get(I)Ljava/lang/Object;
checkcast Qjava/lang/Integer$val;
invokevirtual Qjava/lang/Integer$val;.intValue()I  // <-- conversion

And then there's also instance method invocations:

iconst_0
invokestatic Qjava/lang/Integer$val;.(I)Qjava/lang/Integer$val; // <-- 
conversion
invokevirtual Qjava/lang/Integer$val;.floatValue()F

(Note that none of these conversions are "boxing" or "unboxing". They're 
strictly compilation artifacts. It may be useful to come up with a new word for 
them.)

Re: Evolving the wrapper classes

2020-06-17 Thread Brian Goetz

This is pretty much what I was expecting.  A few comments:


Step 1: Warnings


A dynamic warning, initially only activated by opt-in, when someone 
attempts to synchronize on an instance of a wrapper class.  There's a 
changeset in review now for 16.



- Where necessary (depending on the operations being performed), the compiler 
generates conversions between 'I' and 'java/lang/Integer$val'. 'I' is preferred 
wherever possible.


We have to use QInteger$val whenever we use int as a type parameter, the 
rest of the time, we can use I.



Library changes:
- The constructors are removed, replaced with private constructors.


This can happen earlier if we want; we can just remove them (after 
suitable DFR.)  There are factories.





Evolving the wrapper classes

2020-06-17 Thread Dan Smith
Here's a concrete proposal for how we'll evolve the wrapper classes (Byte, 
Short, Integer, Long, Float, Double, Character, and Boolean) to be inline 
classes whose ".val" representations are (in the Java language) the primitive 
types.

This has the effect of replacing boxing conversions in the Java language with 
lighter-weight reference conversions (no identity is imposed), and will 
facilitate specialization in the JVM by wrapping primitive values in 
lightweight inline class instances.

Important concepts in this approach:

- The wrapper classes are reference-default classes—'Integer' is a '.ref' type.
- In the language, 'int' is an alias for 'Integer.val'. These are the same type.
- In the JVM, there are three distinct types: 'Ljava/lang/Integer;', 
'Qjava/lang/Integer$val;', and 'I'

The below outline feels pretty complete to me, as far as the core 
library/JVM/compiler components are concerned, and quite achievable. Please 
raise anything I'm overlooking (I'm sure there's something...).

---

Step 1: Warnings

In the near future, we implement a variety of warnings for clients of the 
wrapper classes who rely on features that will break when the wrapper classes 
are inline classes:

Library changes:
- The constructors, currently marked deprecated, are deprecated for removal. 
This should amplify warnings about their use.

Java compiler changes:
- Attempts to synchronize on or invoke wait/notify methods of expressions with 
wrapper class static types produce a new warning.
- Possibly, uses of '==', 'identityHashCode', or 'clone' on these expressions 
produce a warning.
- Possibly, any uses of 'getClass' that compare with '==' to wrapper class 
literals produce a warning.

JVM changes:
- Possibly, runtime warnings occur mimicking some of the compiler warnings, but 
using runtime types.

(Note that all of these warnings may also apply to Value-based Classes. The 
wrapper classes happen to fall short of the value-based class requirements in 
their factories' guarantees about identity; these rules about factories and 
equality are probably unnecessary limitations, given the current deterministic 
behavior of acmp.)

---

Step 2: Preview Feature

When, or sometime after, we ship inline classes as a preview feature, we 
support treating the wrapper classes as inline.

JVM changes (when --enable-preview is set):
- References to java/lang/Integer and java/lang/Integer$val are hacked to load 
special class files corresponding to the .ref and .val types of inline class 
Integer.
- The type [I is considered by the verifier to be equivalent to 
[java/lang/Integer$val. Array operations (aaload, iaload, etc.) support this.

Java language/compiler changes (when --enable-preview is set):
- The class file reader knows how to find the special Integer.class and 
Integer$val.class.
- The type 'Integer.val' is equivalent to 'int'. Primitive types are inline 
types—they have members, support method invocation, etc.
- Where necessary (depending on the operations being performed), the compiler 
generates conversions between 'I' and 'java/lang/Integer$val'. 'I' is preferred 
wherever possible.
- Boxing can be specified with stronger guarantees about '=='.

---

Step 3: Standard Feature

When we're ready to leave preview, we'll need to raise the profile of "those 
things we warned about are going to blow up now!".

Library changes:
- The wrapper classes are declared in source as reference-default inline 
classes.
- The constructors are removed, replaced with private constructors.

JVM changes:
- Wrapper classes are loaded using standard processes.

Java language/compiler changes:
- The wrapper classes have special permission to declare fields of their own 
type.
- Wrapper classes are read using standard processes.