Adopting JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) into Amber
Vicente Romero
vicente.romero at oracle.com
Mon Apr 24 23:06:00 UTC 2017
On 04/24/2017 05:29 PM, forax at univ-mlv.fr wrote:
> ----- 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.
the problem we are addressing is very specific and narrow, the tree
X.class will be rewritten as ClassConstant.of("descriptorOfX") as
ClassConstant is a final class in the Constables API, I don't see the
problem you are considering
>
>>> cheers,
>>> Rémi
thanks,
Vicente
>> 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