Re: Valhalla EG notes Jan 16, 2019

2019-01-30 Thread Brian Goetz
>  Option 2: RefObject, ValObject - interfaces
>VM at class definition adds RefObject to all existing classes
>value classes required to declare ValObject as superinterface
> 
>ackwardness: VM needs special behaviors for Object.wait, Object.notify - 
> if dynamically a ValObject, throw IMSE
>  instead of having that obvious from the implementation in a superclass.
> 
> Are there other concerns here?
> This seems cleaner to me - especially since I also believe that 
> synchronization on ValObjects will also require
> special handling - which will be vm implementations rather than visible in 
> java sources (exact plan is TBD).

As I said to Remi, let’s be crystal clear that this seems cleaner _only to VM 
implementors_.  To everyone else, it’s less clean, less powerful, less 
educational, and more complicated (“why can’t I implement both RefObject and 
ValObject?”)  

If we bash our heads against the former for a while and give up, that’s OK; we 
can’t solve all the problems all the time.  But let’s be clear what we’re 
doing, and why.  

Theres’s also a middle ground: ValObject is a class, and RefObject is an 
interface.  While this may appear stupid, it reclaims more than half of what we 
lose by making both interfaces — because it gives us a place to put privileged, 
final, value-specific behaviors.  And values are going to need more of them 
than references will.  






Re: Valhalla EG notes Jan 16, 2019

2019-01-30 Thread Karen Kinnear
I see two options proposed:

Option 1: RefObject, ValObject - classes
   VM at class definition time replaces superclass of all existing classes from 
Object -> RefObject
   VM translates:
 new Object -> treated as Object.new() { returns RefObject.new() } // 
assume old code only wants references here
   risk: existing getClass.getSuper() assumptions

Questions:
   How would the VM translate new Object[] ?
 - we might want existing code to be able to handle all subtypes of the top 
type in the existing arrays
 - or erased generics will break

   If I wanted to instantiate a new top type which could hold either RefObject 
or ValObject, how would I do that?
   Object.new()? Object.newObject()

 Option 2: RefObject, ValObject - interfaces
   VM at class definition adds RefObject to all existing classes
   value classes required to declare ValObject as superinterface

   ackwardness: VM needs special behaviors for Object.wait, Object.notify - if 
dynamically a ValObject, throw IMSE
 instead of having that obvious from the implementation in a superclass.

Are there other concerns here?
This seems cleaner to me - especially since I also believe that synchronization 
on ValObjects will also require
special handling - which will be vm implementations rather than visible in java 
sources (exact plan is TBD).


Remi - L/Q signatures are orthogonal to the type hierarchy - they declare 
null-free or null-tolerant
   so Point.val and Point.box are both subclasses of ValObject

thanks,
Karen

> On Jan 30, 2019, at 10:21 AM, fo...@univ-mlv.fr wrote:
> 
> 
> 
> De: "John Rose" 
> À: "Remi Forax" 
> Cc: "Karen Kinnear" , "valhalla-spec-experts" 
> 
> Envoyé: Mercredi 30 Janvier 2019 00:29:01
> Objet: Re: Valhalla EG notes Jan 16, 2019
> On Jan 29, 2019, at 11:10 AM, Remi Forax  > wrote:
> 
> currently the result of the expression "new Object()" is a reference type, so 
> it should be a RefObject, but we have created an Object not a RefObject,
> so it's at best weird.
> 
> I'd like to rationalize this in two steps.
> 
> First, allow `new I(x…)` where `I` is an interface,
> to be treated as shorthand for `I.F(x…)` where
> the method `F` is somehow declared by `I` as
> its canonical factory.  I'm thinking `List.of` is
> a good one.  (Maybe also extend this rule to classes
> with non-public constructors.)
> 
> Second, since `Object` is an honorary interface,
> change the meaning of `new Object()` to be
> `Object.newReference()` (or some such), by
> having `Object` declare `newReference` (of
> no arguments) as its canonical factory.
> 
> Moving `new` statements to factories is coherent,
> also, with changing the translation strategy for Java
> to deprecate the new/init dance outside of the class
> being constructed, and eventually make it illegal in
> bytecode outside of the nest of the class being made.
> In other words, if I could go back in a time machine
> and rewrite the translation strategy, I'd insist that
> each class (or the JVM itself) would define a canonical
> factory for each constructor of that class, and require
> all other classes to allocate via the canonical factory.
> The new/init dance would be legal inside the class
> but nowhere else.  That attack surface has been a
> painful one.  And value types have to use factories
> from the get-go, so we've got to figure it out sooner
> or later.  The name of the canonical factory can be,
> in fact, fixed as ''.
> 
> so new Object() <==> Object.new() and
> class Object {
>   ...
>   public static Object new() { return ReferenceObject.new(); }
> }
> and the translation new Object() to Object.new() has to be done by the VM 
> because there is already a lot of code that do a new Object().
> 
> 
> — John
> 
> 
> I think i still prefer having interfaces Val/Ref instead of classes, these 
> interfaces can be injected by the VM, at least the Ref interface can be 
> injected, for the Val interface, we can requires all value types to implement 
> that interface.
> 
> Another question, we have two representations of a value class, the real 
> value class and the nullable value class, the Q and the L classes, Point.val 
> and Point.box, does Point.box a subtype of Val/ValObject ?
> 
> Rémi



Re: Valhalla EG notes Jan 16, 2019

2019-01-30 Thread Brian Goetz

> I think i still prefer having interfaces Val/Ref instead of classes, these 
> interfaces can be injected by the VM, at least the Ref interface can be 
> injected, for the Val interface, we can requires all value types to implement 
> that interface.

I view using interfaces instead of classes here as a fallback; it’s more 
twitchy (VM now has to ensure that nothing implements both), it fails to “paint 
the world as it is” (which I think has tremendous educational value), but most 
importantly, it fails to give us an opportunity to put final methods in 
{Ref,Val}Object.  

For example, suppose we handled wait/notify by making ValObject.wait() be a 
final method which throws.  This lets us manage the constraint using tools we 
already have — inheritance and final methods — rather than inventing yet more 
special rules for what values can and cannot do.  The more we can express in 
the object model users are familiar with, the more users will be able to 
immediately understand what is going on.

Now, maybe injecting superclasses will be so problematic that we give up, and 
go with interfaces instead.  That’s OK, but let’s be clear about what we’re 
doing — that’s the “we gave up because the right thing was too hard” route.  

Re: Valhalla EG notes Jan 16, 2019

2019-01-30 Thread forax
> De: "John Rose" 
> À: "Remi Forax" 
> Cc: "Karen Kinnear" , "valhalla-spec-experts"
> 
> Envoyé: Mercredi 30 Janvier 2019 00:29:01
> Objet: Re: Valhalla EG notes Jan 16, 2019

> On Jan 29, 2019, at 11:10 AM, Remi Forax < [ mailto:fo...@univ-mlv.fr |
> fo...@univ-mlv.fr ] > wrote:

>> currently the result of the expression "new Object()" is a reference type, 
>> so it
>> should be a RefObject, but we have created an Object not a RefObject,
>> so it's at best weird.

> I'd like to rationalize this in two steps.

> First, allow `new I(x…)` where `I` is an interface,
> to be treated as shorthand for `I.F(x…)` where
> the method `F` is somehow declared by `I` as
> its canonical factory. I'm thinking `List.of` is
> a good one. (Maybe also extend this rule to classes
> with non-public constructors.)

> Second, since `Object` is an honorary interface,
> change the meaning of `new Object()` to be
> `Object.newReference()` (or some such), by
> having `Object` declare `newReference` (of
> no arguments) as its canonical factory.

> Moving `new` statements to factories is coherent,
> also, with changing the translation strategy for Java
> to deprecate the new/init dance outside of the class
> being constructed, and eventually make it illegal in
> bytecode outside of the nest of the class being made.
> In other words, if I could go back in a time machine
> and rewrite the translation strategy, I'd insist that
> each class (or the JVM itself) would define a canonical
> factory for each constructor of that class, and require
> all other classes to allocate via the canonical factory.
> The new/init dance would be legal inside the class
> but nowhere else. That attack surface has been a
> painful one. And value types have to use factories
> from the get-go, so we've got to figure it out sooner
> or later. The name of the canonical factory can be,
> in fact, fixed as ''.

so new Object() <==> Object.new() and 
class Object { 
... 
public static Object new() { return ReferenceObject.new(); } 
} 
and the translation new Object() to Object.new() has to be done by the VM 
because there is already a lot of code that do a new Object(). 

> — John

I think i still prefer having interfaces Val/Ref instead of classes, these 
interfaces can be injected by the VM, at least the Ref interface can be 
injected, for the Val interface, we can requires all value types to implement 
that interface. 

Another question, we have two representations of a value class, the real value 
class and the nullable value class, the Q and the L classes, Point.val and 
Point.box, does Point.box a subtype of Val/ValObject ? 

Rémi 


Re: Valhalla EG notes Jan 16, 2019

2019-01-30 Thread Remi Forax
> De: "John Rose" 
> À: "Brian Goetz" 
> Cc: "valhalla-spec-experts" 
> Envoyé: Mercredi 30 Janvier 2019 01:20:50
> Objet: Re: Valhalla EG notes Jan 16, 2019

> On Jan 29, 2019, at 12:27 PM, Brian Goetz < [ mailto:brian.go...@oracle.com |
> brian.go...@oracle.com ] > wrote:

>> But, now we a problem: we have existing code that erases arrays to 
>> `Object[]`,
>> but after the flag day, such code will erase to Array instead.

> Maybe, another way to address this, besides bridging distinct
> descriptors, is to declare that the old descriptors describe
> the new types.

> After all, the old descriptors will be dead (to Java) after the
> translation strategy stops using them. Make all descriptors
> of the form `[T` erase to `Array` or some subtype.

> This isa lossy translation, which means the interpreter will have
> to do extra runtime type checks on xaload/xastore instructions.
> The JIT probably won't care. The scheme might shipwreck
> on reflection, since we need to distinguish all the array classes
> reflectively, but maybe that's where Crasses (runtime class
> mirrors) come in handy, to make that distinction. Put another
> way, int[] and String[] and Object[] are mirrored by Crasses,
> not proper classes.

yes, 
String[].class == Array.class.getSpecialization(String.class) 

Note that even if String is a reference type, here we still want the 
specialization, unlike for generics, so an Array is a special kind of generics 
that requires full reification. 

> Maybe there's a solution along this path. Or maybe the floor
> gives way at some point and you are plunged into the basement
> where the monsters are.

the risk is more a Franckenstein's monster than Cthulhu IMO 

> — John

Rémi