Adopting JEP 303 (Intrinsics for LDC and INVOKEDYNAMIC) into Amber
Tagir Valeev
amaembo at gmail.com
Fri Apr 21 05:31:36 UTC 2017
I also tried to create more sophisticated example, a fancy indy-based
singleton. Seeing that class literals conversion is unstable I don't use
them.
I tried to follow IndyCodeGenerationTest sample. Nevertheless it does not
work for me: it dies the following way:
$ javac -XDdoConstantFold Singleton.java
An exception has occurred in the compiler (10-internal). Please file a bug
against the Java compiler via the Java bug reporting page (
http://bugreport.java.com) after checking the Bug Database (
http://bugs.java.com) for duplicates. Include your program and the
following diagnostic in your report. Thank you.
java.lang.AssertionError: Invalid type of constant pool entry: class
java.lang.invoke.Constables$BootstrapSpecifier
at jdk.compiler/com.sun.tools.javac.jvm.Code.typeForPool(Code.java:928)
at jdk.compiler/com.sun.tools.javac.jvm.Code.emitop1(Code.java:904)
at jdk.compiler/com.sun.tools.javac.jvm.Code.emitLdc(Code.java:391)
at
jdk.compiler/com.sun.tools.javac.jvm.Items$ImmediateItem.ldc(Items.java:575)
at
jdk.compiler/com.sun.tools.javac.jvm.Items$ImmediateItem.load(Items.java:615)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitTypeCast(Gen.java:2190)
at
jdk.compiler/com.sun.tools.javac.tree.JCTree$JCTypeCast.accept(JCTree.java:2012)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:868)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitReturn(Gen.java:1801)
at
jdk.compiler/com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1540)
The full source code follows (Singleton.java):
import java.util.*;
import java.lang.reflect.*;
import java.lang.invoke.*;
import java.lang.invoke.Constables.*;
public class Singleton {
static final MethodHandleConstant FACTORY =
MethodHandleConstant.ofStatic(ClassConstant.of("LSingleton;"),
"singletonFactory",
MethodTypeConstant.of(
ClassConstant.of("Ljava/lang/invoke/CallSite;"),
ClassConstant.of("Ljava/lang/invoke/MethodHandles$Lookup;"),
ClassConstant.of("Ljava/lang/String;"),
ClassConstant.of("Ljava/lang/invoke/MethodType;"),
ClassConstant.of("Ljava/lang/invoke/MethodHandle;")));
public static CallSite singletonFactory(
MethodHandles.Lookup lookup, String name,
MethodType type, MethodHandle ctor) throws Throwable {
Object singleton = ctor.invokeExact();
return new ConstantCallSite(MethodHandles.constant(type.returnType(),
singleton));
}
private Singleton() {
System.out.println("Created!");
}
public static Singleton instance() throws Throwable {
BootstrapSpecifier indyDescr = BootstrapSpecifier.of(
FACTORY, "singletonFactory",
MethodTypeConstant.of(ClassConstant.of("LSingleton;")),
MethodHandleConstant.ofConstructor(ClassConstant.of("LSingleton;"),
MethodTypeConstant.of(ClassConstant.of("V"))));
return (Singleton)Intrinsics.invokedynamic(indyDescr);
}
public static void main(String[] args) throws Throwable {
Set<Singleton> set = new HashSet<>();
for(int i=0; i<100; i++) {
set.add(instance());
}
System.out.println(set.size());
}
}
I'm not 100% sure whether the code is correct, but the error reporting
surely should be improved for further experiments.
By the way seems that indy intrinsification is not fully optioned out by
-XDdoConstantFold. Without this option javac dies with another exception:
An exception has occurred in the compiler (10-internal). Please file a bug
against the Java compiler via the Java bug reporting page (
http://bugreport.java.com) after checking the Bug Database (
http://bugs.java.com) for duplicates. Include your program and the
following diagnostic in your report. Thank you.
java.lang.NullPointerException
at
jdk.compiler/com.sun.tools.javac.jvm.Gen.invokeInstanceMethod(Gen.java:944)
at
jdk.compiler/com.sun.tools.javac.jvm.Gen.invokeInstanceMethod(Gen.java:933)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.generateIndy(Gen.java:959)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:865)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitTypeCast(Gen.java:2190)
at
jdk.compiler/com.sun.tools.javac.tree.JCTree$JCTypeCast.accept(JCTree.java:2012)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:868)
at jdk.compiler/com.sun.tools.javac.jvm.Gen.visitReturn(Gen.java:1801)
With best regards,
Tagir Valeev.
On Fri, Apr 21, 2017 at 12:03 PM, Tagir Valeev <amaembo at gmail.com> 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/
> lang/invoke/Constables$ClassConstant;[Ljava/lang/invoke/Constables$
> 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