Consider this program:
public class Sample {
static final String[] ARRAY = new String[1000];
static final ArrayList<String> LIST = new ArrayList<>(Arrays.asList(ARRAY));
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public static void test(Object o) {}
@Benchmark
public void run(Blackhole bh) {
for (int i = 0; Integer.compareUnsigned(i, LIST.size()) < 0; i++) {
test(LIST.get(i));
}
}
}
The loop is compiled to:
0x00007fbe5c6b6280: mov %ebp,%r8d
0x00007fbe5c6b6283: test %r10d,%r10d
0x00007fbe5c6b6286: jl 0x00007fbe5c6b6328
0x00007fbe5c6b628c: cmp %r10d,%r8d
0x00007fbe5c6b628f: jae 0x00007fbe5c6b62fa
0x00007fbe5c6b6295: movabs $0x751589d30,%r10 ; {oop(a 'java/util/ArrayList'{0x0000000751589d30})}
0x00007fbe5c6b629f: mov 0x14(%r10),%r11d
0x00007fbe5c6b62a3: mov %r8d,%ebp
0x00007fbe5c6b62a6: mov 0xc(%r12,%r11,8),%r10d ; implicit exception: dispatches to 0x00007fbe5c6b634d
0x00007fbe5c6b62ab: cmp %r10d,%ebp
0x00007fbe5c6b62ae: jae 0x00007fbe5c6b6314
0x00007fbe5c6b62b0: lea (%r12,%r11,8),%r10
0x00007fbe5c6b62b4: mov 0x10(%r10,%rbp,4),%r11d
0x00007fbe5c6b62b9: mov %r11,%rsi
0x00007fbe5c6b62bc: shl $0x3,%rsi
0x00007fbe5c6b62c0: data16 xchg %ax,%ax
0x00007fbe5c6b62c3: call 0x00007fbe5c6b9700 ; ImmutableOopMap {}
;*invokestatic test {reexecute=0 rethrow=0 return_oop=0}
; - org.openjdk.bench.vm.compiler.Sample::run@22 (line 51)
; {static_call}
0x00007fbe5c6b62c8: mov 0x380(%r15),%r11
0x00007fbe5c6b62cf: movabs $0x751589d30,%r10 ; {oop(a 'java/util/ArrayList'{0x0000000751589d30})}
0x00007fbe5c6b62d9: mov 0x10(%r10),%r10d
0x00007fbe5c6b62dd: inc %ebp ; ImmutableOopMap {}
;*goto {reexecute=1 rethrow=0 return_oop=0}
; - (reexecute) org.openjdk.bench.vm.compiler.Sample::run@28 (line 50)
0x00007fbe5c6b62df: test %eax,(%r11) ; {poll}
0x00007fbe5c6b62e2: cmp %r10d,%ebp
0x00007fbe5c6b62e5: jb 0x00007fbe5c6b6280
Obviously, the bound check at 0x00007fbe5c6b628c is the same as the loop condition, it should be elided.