Recently, Lucas Eder became interested in his blog , is it possible for the Java JIT compiler to optimize such code in order to remove unnecessary list traversal from one element:
// ... "",
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/305894/
All Articles