Adopting JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) into Amber

forax at univ-mlv.fr forax at univ-mlv.fr
Mon Apr 24 21:29:20 UTC 2017


----- Mail original -----
> De: "Vicente Romero" <vicente.romero at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "Tagir Valeev" <amaembo at gmail.com>, amber-dev at openjdk.java.net
> Envoyé: Lundi 24 Avril 2017 23:14:11
> Objet: Re: Adopting JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) into Amber

> Hi Remi,
> 
> On 04/24/2017 05:03 PM, Remi Forax wrote:
>> Hi Vicente,
>> The problem of letting intermediary construction is that you keep link to
>> classes that are present at compile time (to represent intermediary states) but
>> may not be present at runtime.
> 
> but in this case we are using a class that is / will be part of a public
> API, and if it's not present at run time there is no point in executing
> the given code. Probably I'm not following you but I believe that in
> this particular case we should be fine.

if i create a class that implement Constable and represent an intermediary state that will be used to create the bootstrap arguments on an invokedynamic,
i see no point to provide that class at runtime.

> 
>>
>> cheers,
>> Rémi
> 
> Vicente

Rémi

> 
>>   
>>
>> ----- Mail original -----
>>> De: "Vicente Romero" <vicente.romero at oracle.com>
>>> À: "Tagir Valeev" <amaembo at gmail.com>, amber-dev at openjdk.java.net
>>> Envoyé: Lundi 24 Avril 2017 15:28:55
>>> Objet: Re: Adopting JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) into Amber
>>> Hi Tagir,
>>>
>>> On 04/24/2017 12:57 AM, Tagir Valeev wrote:
>>>> Hello!
>>>>
>>>>> Does it work if you get rid of the class literals, and use strings?
>>>> Yes, if I change code the following way:
>>>>
>>>> MethodTypeConstant mtc = MethodTypeConstant.of(ClassConstant.of("V"));
>>>> MethodHandleConstant mhc = MethodHandleConstant.ofStatic(
>>>> ClassConstant.of("LTestConst;"), "test", mtc);
>>>> MethodHandle mh = Intrinsics.ldc(mhc);
>>>>
>>>> Then it compiles and runs correctly. Of course, bytecode still contains
>>>> these constants created explicitly:
>>>>
>>>>    0: ldc           #2   // String V
>>>>    2: invokestatic  #3   // Method j/l/i/Constables$ClassConstant.of
>>>>    5: iconst_0
>>>>    6: anewarray     #4   // class j/l/i/Constables$ClassConstant
>>>>    9: invokestatic  #5   // Method j/l/i/Constables$MethodTypeConstant.of
>>>> 12: astore_1
>>>> 13: ldc           #6   // String LTestConst;
>>>> 15: invokestatic  #3   // Method j/l/i/Constables$ClassConstant.of
>>>> 18: ldc           #7   // String test
>>>> 20: aload_1
>>>> 21: invokestatic  #8   // Method j/l/i/Constables$
>>>> MethodHandleConstant.ofStatic
>>>> 24: astore_2
>>>> 25: ldc           #9   // MethodHandle REF_invokeStatic TestConst.test:()V
>>>> 27: astore_3
>>>> 28: aload_3
>>>> 29: invokevirtual #10  // Method j/l/i/MethodHandle.invokeExact:()V
>>>> 32: return
>>>>
>>>> Of these only bytecodes after offset 25 are actually needed. Though
>>>> probably optimizing out intermediate constables is too much...
>>> we decided not to optimize the intermediate constables because we wanted
>>> to be explicit about the fact that the magic would happen only for ldc()
>>> or invokedynamic(). Clearing up all the code and reducing it to an ldc
>>> or indy invocation was considered too magical.
>>>
>>>> With best regards,
>>>> Tagir Valeev.
>>> Thanks,
>>> Vicente
>>>
>>>>
>>>> On Fri, Apr 21, 2017 at 6:37 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
>>>>
>>>>> Does it work if you get rid of the class literals, and use strings?
>>>>>
>>>>> On 4/21/2017 1:03 AM, Tagir Valeev wrote:
>>>>>
>>>>> Seems that it does not work if I use intermediate variable for
>>>>> MethodTypeConstant. Consider the following code:
>>>>>
>>>>> import java.lang.invoke.*;
>>>>> import static java.lang.invoke.Constables.*;
>>>>> import static java.lang.invoke.Intrinsics.*;
>>>>>
>>>>> public class TestConst {
>>>>>       public static void main(String[] args) throws Throwable {
>>>>>           MethodTypeConstant mtc = MethodTypeConstant.of(void.class);
>>>>>           MethodHandleConstant mhc = MethodHandleConstant.ofStatic(TestConst.class,
>>>>> "test", mtc);
>>>>>           MethodHandle mh = Intrinsics.ldc(mhc);
>>>>>           mh.invokeExact();
>>>>>       }
>>>>>
>>>>>       static void test() {
>>>>>           System.out.println("Hello");
>>>>>       }
>>>>> }
>>>>>
>>>>> It's compiled without errors and ldc intrinsic is generated correctly.
>>>>> However for non-intrinsified variables class type is not wrapped into
>>>>> ClassConstant:
>>>>>
>>>>>          0: getstatic     #2                  // Field
>>>>> void.class:Ljava/lang/Class;
>>>>>          3: iconst_0
>>>>>          4: anewarray     #3                  // class
>>>>> java/lang/invoke/Constables$ClassConstant
>>>>>          7: invokestatic  #4                  // Method
>>>>> java/lang/invoke/Constables$MethodTypeConstant.of:(Ljava/lan
>>>>> g/invoke/Constables$ClassConstant;[Ljava/lang/invoke/Constab
>>>>> les$ClassConstant;)Ljava/lang/invoke/Constables$MethodTypeConstant;
>>>>>
>>>>> This, of course, results in verification errors:
>>>>>
>>>>> Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
>>>>> Exception Details:
>>>>>     Location:
>>>>>       TestConst.main([Ljava/lang/String;)V @7: invokestatic
>>>>>     Reason:
>>>>>       Type 'java/lang/Class' (current frame, stack[0]) is not assignable to
>>>>> 'java/lang/invoke/Constables$ClassConstant'
>>>>>     Current Frame:
>>>>>       bci: @7
>>>>>       flags: { }
>>>>>       locals: { '[Ljava/lang/String;' }
>>>>>       stack: { 'java/lang/Class', '[Ljava/lang/invoke/Constables$ClassConstant;'
>>>>> }
>>>>>
>>>>> Probably it would be easier to declare class Class<T> as implements
>>>>> Constable<Class<T>> and replace ClassConstant with Constable<Class<?>> in
>>>>> method signatures where applicable? Or introduce some intermediate
>>>>> interface?
>>>>>
>>>>> With best regards,
>>>>> Tagir Valeev.
>>>>>
>>>>>
>>>>> On Fri, Apr 21, 2017 at 10:47 AM, Tagir Valeev <amaembo at gmail.com> wrote:
>>>>>
>>>>>> Thanks! Works fine for me.
>>>>>>
>>>>>> With best regards,
>>>>>> Tagir Valeev.
>>>>>>
>>>>>> On Thu, Apr 20, 2017 at 8:37 PM, Vicente Romero <
>>>>>> vicente.romero at oracle.com> wrote:
>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I have just pushed a patch that converts class literals into a poly
>>>>>>> expression. Meaning that now you can pass a class literal where a
>>>>>>> ClassConstant is expected. This will simplify the use of the API making the
>>>>>>> user code less verbose. Taking as an example the test case sent by Tagir,
>>>>>>> it could be now rewritten as:
>>>>>>>
>>>>>>> import java.lang.invoke.*;
>>>>>>> import java.lang.invoke.Constables.*;
>>>>>>> import java.lang.reflect.*;
>>>>>>>
>>>>>>> public class MH {
>>>>>>>     private static void test() {
>>>>>>>       System.out.println("Hello");
>>>>>>>     }
>>>>>>>
>>>>>>>     public static void main(String[] args) throws Throwable {
>>>>>>>       final MethodHandle handle = Intrinsics.ldc(
>>>>>>>        MethodHandleConstant.ofStatic(MH.class, "test",
>>>>>>> MethodTypeConstant.of(void.class)));
>>>>>>>       handle.invokeExact();
>>>>>>>     }
>>>>>>> }
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Vicente
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 04/18/2017 11:14 PM, Tagir Valeev wrote:
>>>>>>>
>>>>>>> Thank you for the hint! It also seems that ClassConstant.of(MH.class)
>>>>>>> does not work either and VarHandles are not supported yet. However the
>>>>>>> following sample finally worked for me:
>>>>>>>
>>>>>>>
>>>>>>> import java.lang.invoke.*;
>>>>>>> import java.lang.invoke.Constables.*;
>>>>>>> import java.lang.reflect.*;
>>>>>>>
>>>>>>> public class MH {
>>>>>>>     private static void test() {
>>>>>>>       System.out.println("Hello");
>>>>>>>     }
>>>>>>>
>>>>>>>     public static void main(String[] args) throws Throwable {
>>>>>>>       final MethodHandle handle = Intrinsics.ldc(
>>>>>>>        MethodHandleConstant.ofStatic(ClassConstant.of("LMH;"), "test",
>>>>>>> MethodTypeConstant.of(ClassConstant.of("V"))));
>>>>>>>       handle.invokeExact();
>>>>>>>     }
>>>>>>> }
>>>>>>>
>>>>>>> With best regards,
>>>>>>> Tagir Valeev.
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Apr 18, 2017 at 9:13 PM, Brian Goetz <brian.goetz at oracle.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> The primitive fields (Constables.VOID and friends) are not yet hooked
>>>>>>>> up; for the time being, replace with ClassConstant.of("V").
>>>>>>>>
>>>>>>>>
>>>>>>>> On 4/18/2017 2:17 AM, Tagir Valeev wrote:
>>>>>>>>
>>>>>>>>> Hello!
>>>>>>>>>
>>>>>>>>> I tried to play with this, but still no success. Fresh build from
>>>>>>>>> constant-folding branch. I tried to compile the following files:
>>>>>>>>>
>>>>>>>>> // MH.java
>>>>>>>>>
>>>>>>>>> import java.lang.invoke.*;
>>>>>>>>> import java.lang.invoke.Constables.*;
>>>>>>>>> import java.lang.reflect.*;
>>>>>>>>>
>>>>>>>>> public class MH {
>>>>>>>>>      private static void test() {
>>>>>>>>>        System.out.println("Hello");
>>>>>>>>>      }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>      public static void main(String[] args) throws Throwable {
>>>>>>>>>        final MethodHandle handle = Intrinsics.ldc(
>>>>>>>>>         MethodHandleConstant.ofStatic(ClassConstant.of(MH.class),
>>>>>>>>> "test",
>>>>>>>>> MethodTypeConstant.of(Constables.VOID)));
>>>>>>>>>        handle.invokeExact();
>>>>>>>>>      }
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> // VH.java
>>>>>>>>> import java.lang.invoke.*;
>>>>>>>>> import java.lang.invoke.Constables.*;
>>>>>>>>> import java.lang.reflect.*;
>>>>>>>>>
>>>>>>>>> public class VH {
>>>>>>>>>      private static volatile int counter;
>>>>>>>>>
>>>>>>>>>      private static final VarHandle COUNTER = Intrinsics.ldc(
>>>>>>>>>         VarHandleConstant.ofStaticField(ClassConstant.of(VH.class),
>>>>>>>>> "counter",
>>>>>>>>> Constables.INT));
>>>>>>>>>
>>>>>>>>>      public static void main(String[] args) {
>>>>>>>>>        System.out.println(COUNTER.getAndAdd(1));
>>>>>>>>>        System.out.println(COUNTER.getAndAdd(1));
>>>>>>>>>      }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Building with "javac -XDdoConstantFold=true MH.java" or "javac
>>>>>>>>> -XDdoConstantFold=true VH.java",
>>>>>>>>> javac silently exists without producing .class file or reporting any
>>>>>>>>> error.
>>>>>>>>> Tried with -verbose, the output ends like this:
>>>>>>>>>
>>>>>>>>> [loading /modules/java.base/java/lang/annotation/RetentionPolicy.clas
>>>>>>>>> s]
>>>>>>>>> [loading /modules/java.base/java/lang/annotation/Target.class]
>>>>>>>>> [loading /modules/java.base/java/lang/annotation/ElementType.class]
>>>>>>>>> [checking VH]
>>>>>>>>> [loading /modules/java.base/java/io/Serializable.class]
>>>>>>>>> [loading /modules/java.base/java/lang/AutoCloseable.class]
>>>>>>>>> [loading /modules/java.base/java/lang/Class.class]
>>>>>>>>> [loading /modules/java.base/java/lang/invoke/Constable.class]
>>>>>>>>> [loading /modules/java.base/java/lang/invoke/Intrinsics.class]
>>>>>>>>> [total 1484ms]
>>>>>>>>>
>>>>>>>>> Without  -XDdoConstantFold=true the class file is produced and dies
>>>>>>>>> like
>>>>>>>>>
>>>>>>>>> Exception in thread "main" java.lang.UnsupportedOperationException: no
>>>>>>>>> reflective access
>>>>>>>>> at java.base/java.lang.invoke.Intrinsics.ldc(Intrinsics.java:42)
>>>>>>>>> at MH.main(MH.java:12)
>>>>>>>>>
>>>>>>>>> Which is expected behavior, I guess.
>>>>>>>>>
>>>>>>>>> Am I doing something wrong? Could you compile these files on your side?
>>>>>>>>> Sorry if my tries look lame: I'm very new to this.
>>>>>>>>>
>>>>>>>>> With best regards,
>>>>>>>>> Tagir Valeev.
>>>>>>>>>
>>>>>>>>> On Tue, Apr 18, 2017 at 9:07 AM, Vicente Romero <
>>>>>>>>> vicente.romero at oracle.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>> Support for JEP 303 has been pushed in the amber repo [1, 2] (branch
>>>>>>>>>> name
>>>>>>>>>> is 'constant-folding'). The development is mature although there are
>>>>>>>>>> some
>>>>>>>>>> fresh areas like using reflection for accessing the API methods.
>>>>>>>>>> Reflection
>>>>>>>>>> is needed as the classes defined in the API see [1] are not available
>>>>>>>>>> in
>>>>>>>>>> the boot JDK. There is still some ongoing research so some changes to
>>>>>>>>>> the
>>>>>>>>>> API and the code are to be expected in the near future,
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Vicente
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> [1] http://hg.openjdk.java.net/amber/amber/jdk/rev/2eeb80b82c9c
>>>>>>>>>> [2] http://hg.openjdk.java.net/amber/amber/langtools/rev/7be70b52c760
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 04/17/2017 04:22 PM, Brian Goetz wrote:
>>>>>>>>>>
>>>>>>>>>> JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) is hereby adopted into
>>>>>>>>>>> Project Amber.
>>>>>>>>>>>
>>>>>>>>>>> A first draft of the API can be found at:
>>>>>>>>>>>
>>>>>>>>>>>        http://cr.openjdk.java.net/~briangoetz/JDK-8178320/webrev/
>>>>>>>>>>>
>>>>>>>>>>> Prototype implementation coming soon.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>


More information about the amber-dev mailing list