"Model 2" prototype implementation

Brian Goetz brian.goetz at oracle.com
Fri Aug 7 20:09:14 UTC 2015


Sure, we could have chosen that.  But this is a more straightforward 
translation, and the simpler the translation is, the fewer dark corners 
there are.  For one thing, it means that instanceof/cast (and even more 
importantly, their reflective equivalents) *just work*.  It means that 
the subtyping is scrutable to the JIT and can feed information into 
optimizations.

Most dispatch on Foo<any> receivers can proceed without indy; the 
prototype happens to use it for dispatching all calls on Foo<any> 
receivers, but this is neither necessary nor optimal.



On 8/7/2015 2:01 PM, Rémi Forax wrote:
> Hi Brian,
> why do you need the interface Box$any and not use Object and send Box.class as a bootstrap argument to the indy call ?
>
> Rémi
>
>
> Le 7 août 2015 17:49:31 CEST, Brian Goetz <brian.goetz at oracle.com> a écrit :
>> Great question.  We're working on a writeup of the translation details;
>>
>> we announced the prototype before the writeup was ready, because we
>> didn't want to keep early adopters from trying it out any further, but
>> there's a writeup coming.
>>
>> Here's a very brief taste (but you'll have to wait for the writeup, or
>> use javap on the output of javac, for more).  Imagine the function
>>
>>     R : Type -> Class
>>
>> which maps a compile-time type to a runtime class.  In Java 5 generics,
>>
>> for a class Foo<T>, the R mapping is very simple -- everything is
>> erased:
>>
>> R(Foo<String>) = Foo
>> R(Foo<?>) = Foo
>> R(Foo) = Foo
>>
>> In Valhalla, for a class Foo<any T>, the mapping is more complex:
>>
>> Compatibility demands we adopt the above mappings:
>> R(Foo<String>) = Foo
>> R(Foo<ref>) = Foo
>> R(Foo<raw>) = Foo
>>
>> And we get some new ones:
>> R(Foo<int>) = Foo${0=I} *
>> R(Foo<any>) = Foo$any **
>>
>> *Name mangling is temporary; something better is in the works.
>> **Foo$any is a synthetic *interface* generated by javac, which can be
>> implemented by Foo<int> and Foo<String> alike (using boxing in the API
>> where necessary).
>>
>> Because Foo$any is an interface, it can't have fields.  So we lift the
>> fields of Foo to (possibly boxing) accessors on Foo$any (VM help is
>> needed for nonpublic members here), and we convert field accesses
>> (through receivers of type Foo<any> only!) to invocations of those
>> accessors.  (Field access through concretely-typed receivers
>> (Foo<String> or Foo<int>) are still translated with straight
>> getfield/putfield, so the boxing penalty is only paid by wildcard
>> users.)
>>
>> Here's your example:
>>
>>      public static void main(String[] args) {
>>          Box<int> box = new Box<int>(3);
>>          Box<any> box_any = box;
>>          System.out.println(box_any.get());
>>          System.out.println(box_any.t);
>>      }
>>
>> And the bytecode (which works as expected):
>>
>> public static void main(java.lang.String[]);
>>      Code:
>>         0: new           #2                  // class "Box${0=I}"
>>         3: dup
>>         4: iconst_3
>>         5: invokespecial #3                  // Method
>> "Box${0=I}"."<init>":(I)V
>>         8: astore_1
>>         9: aload_1
>>        10: astore_2
>>        11: getstatic     #4                  // Field
>> java/lang/System.out:Ljava/io/PrintStream;
>>        14: aload_2
>>        15: invokedynamic #5,  0              // InvokeDynamic
>> #0:get:(LBox$$any;)Ljava/lang/Object;
>>        20: invokevirtual #6                  // Method
>> java/io/PrintStream.println:(Ljava/lang/Object;)V
>>        23: getstatic     #4                  // Field
>> java/lang/System.out:Ljava/io/PrintStream;
>>        26: aload_2
>>        27: invokedynamic #7,  0              // InvokeDynamic
>> #1:t$get:(LBox$$any;)Ljava/lang/Object;
>>        32: invokevirtual #6                  // Method
>> java/io/PrintStream.println:(Ljava/lang/Object;)V
>>        35: return
>>
>> BootstrapMethods:
>>    0: #26 invokestatic
>> java/lang/invoke/VirtualAccess.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
>>      Method arguments:
>>        #27 invokeinterface Box$$any.get:()Ljava/lang/Object;
>>    1: #26 invokestatic
>> java/lang/invoke/VirtualAccess.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
>>      Method arguments:
>>        #31 invokeinterface Box$$any.t$get:()Ljava/lang/Object;
>>
>> The invokedynamic at bci=15 and 27 invoke the get() and t$get() methods
>>
>> of the Foo$any interface.  We use invokedynamic instead of
>> invokeinterface because it allows us to do some boxing adaptations more
>>
>> easily than statically generating yet more bridge methods.  (The
>> VirtualAccess bootstrap simply does a MethodHandle.asType adaptation of
>>
>> the provided MH; in the current program, there is no difference in the
>> signatures so it's as if we did an invokeinterface of Box$$any.get() or
>>
>> .t$get() directly.)
>>
>>
>>> I’m wondering how will the implementation work?
>>> Specifically, in this example, which assumes a specialized |Box|
>> class
>>> defined here
>>>
>> <web.archive.org/web/20150801070114/http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html#erasure-example-a-simple-box-class>:
>>>
>>> |Box<int> box = new Box<int>(4); Box<any> box_any = box; // what does
>>> get() return? and how does it return it?
>>> System.out.println(box_any.get()); // even more interesting, how does
>>> this work: System.out.println(box_any.t /* assuming the box value is
>>> visible */); |
>>>
>>> How do you translate the method calls and field accesses? Do they
>> return
>>> boxed values?
>>>
>>> Thanks,
>>> Vlad
>>>
>>> PS: Shameless advertising — I recently worked on a paper describing
>> the
>>> pitfalls I’ve encountered in miniboxing <http://scala-miniboxing.org>
>>> when using erased views (and specialized views) and how to mitigate
>>> them, which has been accepted for PPPJ 2015. In case you’re
>> interested,
>>> an earlier draft is available here
>>> <http://infoscience.epfl.ch/record/208797?ln=en>.
>>>
>>>>


More information about the valhalla-dev mailing list