JITコンパイラーは最適化をクールではなく、非常にクールに

最近、Lucas Eder 、1つの要素からリストの不要なクロールを削除するために、Java JITコンパイラーがそのようなコードを最適化できるかどうかに関するブログに興味を持ちました


// ...    "",      
for (Object object : Collections.singletonList("abc")) {
    doSomethingWith(object);
}

: JIT . HotSpot JVM 64 bit . , :


static int testIterator(List<String> list) {
    int sum = 0;
    for (String s : list) {
        sum += s.length();
    }
    return sum;
}

Java- , :


static int testIterator(List<String> list) {
    int sum = 0;
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        String s = it.next();
        sum += s.length();
    }
    return sum;
}

, list JIT- iterator(), hasNext() next(), , , . , , singletonList? main():


public class Test {
    static int res = 0;

    public static void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            res += testIterator(Collections.singletonList("x"));
        }
        System.out.println(res);
    }
}

testIterator , JIT- C2. , HotSpot JIT-: C1 () C2 (). 64- Java 8 . C1 ( , ). , ( ""). , , , . . JVM , list . , 100% Collections$SingletonList ( singletonList).


, C2, . C2 , SingletonList, . , iterator() singletonIterator(). , , , hasNext, , , NoSuchElementException. C2 ?


, JIT- . hsdis. JITWatch JMH- -perfasm. , :


$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintAssembly Test >output.txt

: . , , testIterator. C2 Intel x64 4 :


,
  # {method} {0x0000000055120518} 'testIterator' '(Ljava/util/List;)I' in 'Test'
  # parm0:    rdx:rdx   = 'java/util/List'
  #           [sp+0x20]  (sp of caller)
  0x00000000028e7560: mov    %eax,-0x6000(%rsp)
  0x00000000028e7567: push   %rbp
  0x00000000028e7568: sub    $0x10,%rsp         ;*synchronization entry
                                                ; - Test::testIterator@-1 (line 15)

  0x00000000028e756c: mov    0x8(%rdx),%r10d    ; implicit exception: dispatches to 0x00000000028e75bd
  0x00000000028e7570: cmp    $0x14d66a20,%r10d  ;   {metadata('java/util/Collections$SingletonList')}
  0x00000000028e7577: jne    0x00000000028e75a0  ;*synchronization entry
                                                ; - java.util.Collections::singletonIterator@-1
                                                ; - java.util.Collections$SingletonList::iterator@4
                                                ; - Test::testIterator@3 (line 16)

  0x00000000028e7579: mov    0x10(%rdx),%ebp    ;*getfield element
                                                ; - java.util.Collections$SingletonList::iterator@1
                                                ; - Test::testIterator@3 (line 16)

  0x00000000028e757c: mov    0x8(%rbp),%r11d    ; implicit exception: dispatches to 0x00000000028e75c9
  0x00000000028e7580: cmp    $0x14d216d0,%r11d  ;   {metadata('java/lang/String')}
  0x00000000028e7587: jne    0x00000000028e75b1
  0x00000000028e7589: mov    %rbp,%r10          ;*checkcast
                                                ; - Test::testIterator@24 (line 16)

  0x00000000028e758c: mov    0xc(%r10),%r10d    ;*getfield value
                                                ; - java.lang.String::length@1
                                                ; - Test::testIterator@30 (line 17)

  0x00000000028e7590: mov    0xc(%r10),%eax     ;*synchronization entry
                                                ; - Test::testIterator@-1 (line 15)
                                                ; implicit exception: dispatches to 0x00000000028e75d5
  0x00000000028e7594: add    $0x10,%rsp
  0x00000000028e7598: pop    %rbp
  0x00000000028e7599: test   %eax,-0x27b759f(%rip)        # 0x0000000000130000
                                                ;   {poll_return}
  0x00000000028e759f: retq   
  ... //   

, — . , :


//    -     JIT- 
mov    %eax,-0x6000(%rsp)
push   %rbp
sub    $0x10,%rsp         
//       list (        rdx).
//        0x8.     list.getClass().
//        null.  ,     null,
//           .
//          NullPointerException
mov    0x8(%rdx),%r10d
//  list.getClass()    Collections$SingletonList.    
//    JVM , , JIT  ,      
cmp    $0x14d66a20,%r10d
//  list -   SingletonList,    
jne    0x00000000028e75a0
//    Collections$SingletonList.element   rbp.   64-,    
//  4   32   ,          32    ebp
mov    0x10(%rdx),%ebp
//           String ( ,  )
mov    0x8(%rbp),%r11d
cmp    $0x14d216d0,%r11d
//    -  ,      (     ClassCastException)
jne    0x00000000028e75b1
//    String.value   r10.   char[],     
mov    %rbp,%r10
mov    0xc(%r10),%r10d
//      eax,        
mov    0xc(%r10),%eax
//   
add    $0x10,%rsp
pop    %rbp
//   safe-point.    JVM      , ,   .
test   %eax,-0x27b759f(%rip)
//   
retq   

- , :


if (list.class != Collections$SingletonList) {
  goto SLOW_PATH;
}
str = ((Collections$SingletonList)list).element;
if (str.class != String) {
  goto EXCEPTIONAL_PATH;
}
return ((String)str).value.length;

? , , . ( , ). JIT- , , , , , hasNext , , ! sum . , . , singletonList, - , (, , ). . null list ( type erasure) — .


, ? , singletonList . . , , JIT- , singletonList . , , , . JIT : , .



Source: https://habr.com/ru/post/J305894/


All Articles