Why JVM can not type infer type params but javac can do?

Paul Sandoz paul.sandoz at oracle.com
Thu Jan 8 11:46:51 UTC 2015


On Jan 8, 2015, at 9:54 AM, Ali Ebrahimi <ali.ebrahimi1781 at gmail.com> wrote:

> Hi, maybe this is stupid question, but want to ask and what is requirements
> for this?
> 
> Array instantiation sample:
> public <any T> T[] newArray(int){
>        return new T[0];
> }
> 
> even for non-any T:
> public <T> T[] newArray(int){
>        return new T[0];
> }
> 
> With thousands number of optimization and inlining mechanics equipped in
> jvm, What is the reasoning behind not allowing to jvm to be aware of
> generics info emitted in classfilles?
> 
> Why jvm should not able do following inlining?
> 
> String[] strs =  newArray(int) => String[] strs = new String[0];
> I mean even in jitted code.
> 
> I think some time ago I read some papers in similar area.


Try compiling the following:

public class A {

    static <any T> T[] array(int s) {
       return new T[s];
    }

    static int[] intArray(int s) {
       return array(s);
    }

    public static void main(String[] args) throws Throwable {
        int sum = 0;
        for (int i = 0; i < 1000000; i++) {
            int[] ia = intArray(0);
            sum += ia.length;
        }
        System.out.println(sum);
    }
}

Then run with:

  java -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -Dvalhalla.dumpProxyClasses=. A

You should see an inline trace such as:

                            @ 11   A::intArray (7 bytes)   inline (hot)
                              @ 1   java.lang.invoke.LambdaForm$MH/1389133897::linkToTargetMethod (9 bytes)   force inline by annotation
                                @ 5   java.lang.invoke.LambdaForm$DMH/321001045::invokeStatic_I_L (14 bytes)   force inline by annotation
                                  @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes)   force inline by annotation
                                  @ 10   A$array${0=I}/1922154895::array (4 bytes)   inline (hot)

Look at the specialized class holding the specialized the method:

  javap -p -v A\$array\$\{0\=I\}.1922154895.class 

and you will see:

  static int[] array(int);
    descriptor: (I)[I
    flags: ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: iload_0
         1: newarray       int
         3: areturn

It all inlines rather nicely.


At the moment you will get a ClassCastException if you use a ref, such as String, since javac currently compiles the array method to:

  static <T extends java.lang.Object> T[] array(int);
    descriptor: (I)[Ljava/lang/Object;
    flags: ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: iload_0
         1: anewarray     #2                  // class java/lang/Object
         4: areturn
      LineNumberTable:
        line 4: 0
    BytecodeMapping:
      Code_idx  Signature
          1:    [TT;
    Signature: #18                          // <T:Ljava/lang/Object;>(I)[TT;
    TypeVariablesMap:
      LA;::array(I)[Ljava/lang/Object;:
        Tvar  Flags  Erased bound
        T     [ANY]  Ljava/lang/Object;

That method is not specalized for refs (nor is T reified in such cases). There are some nasty edge cases w.r.t. arrays that need to be solved at some point.

Paul.


More information about the valhalla-dev mailing list