Suboptimal C2 code generation
Vitaly Davidovich
vitalyd at gmail.com
Thu Nov 19 22:58:27 UTC 2015
Hi guys,
Consider the following code/setup (8u51 C2 compiler):
private interface I
{
long value();
long value2();
}
private static final class C implements I
{
@Override
public long value() {
return 1;
}
@Override
public long value2() {
return 1;
}
}
private static final class Wrapper
{
private I _i;
public long value() {
return _i != null ? _i.value() : -1;
}
public long value2() {
return _i != null ? _i.value2() : -1;
}
}
// The below is in the outer class now
private final Wrapper _w = new Wrapper();
private long doIt() {
return _w.value() + _w.value2();
}
Simple harness to get code generated:
public void foo() {
int s = 0;
for (int i = 0; i < 15_000; ++i) {
if (i % 1000 == 0) {
_w._i = null;
} else {
_w._i = new C();
}
s += doIt();
}
System.out.println(s);
}
The idea here is to create a profile whereby vast majority of the time
_w._i is not null. Here's the generated code for doIt(), which is the
method I'm interested in:
[Verified Entry Point]
0x00007ff5f82e0080: mov %eax,-0x14000(%rsp)
0x00007ff5f82e0087: push %rbp
0x00007ff5f82e0088: sub $0x20,%rsp ;*synchronization entry
0x00007ff5f82e008c: mov 0x18(%rsi),%r11d ;*getfield _w
0x00007ff5f82e0090: mov 0xc(%r12,%r11,8),%r11d ;*getfield _i
; implicit exception:
dispatches to 0x00007ff5f82e0111
0x00007ff5f82e0095: mov $0x1,%eax
0x00007ff5f82e009a: test %r11d,%r11d
0x00007ff5f82e009d: je 0x00007ff5f82e00d4 ;*ifnull
0x00007ff5f82e009f: mov 0x8(%r12,%r11,8),%r8d
0x00007ff5f82e00a4: cmp $0xf8015a89,%r8d ; {metadata('$C')} //
NOTE: I'm stripping away the nonessential fully qualified name
0x00007ff5f82e00ab: jne 0x00007ff5f82e00f9 ;*invokeinterface value
0x00007ff5f82e00ad: mov $0x1,%ebp ;*lreturn
0x00007ff5f82e00b2: test %r11d,%r11d
0x00007ff5f82e00b5: je 0x00007ff5f82e00dd ;*ifnull
0x00007ff5f82e00b7: mov 0x8(%r12,%r11,8),%r10d
0x00007ff5f82e00bc: cmp $0xf8015a89,%r10d ; {metadata('$C')}
0x00007ff5f82e00c3: jne 0x00007ff5f82e00e6 ;*lreturn
0x00007ff5f82e00c5: add %rbp,%rax ;*ladd
0x00007ff5f82e00c8: add $0x20,%rsp
0x00007ff5f82e00cc: pop %rbp
0x00007ff5f82e00cd: test %eax,0x5e11f2d(%rip) #
0x00007ff5fe0f2000
; {poll_return}
0x00007ff5f82e00d3: retq
Does anyone know why (a) the null check is performed twice and (b) the type
check for $C is performed twice? The simple getters were devirtualized and
constants inlined, which is nice, but I'm wondering why there are redundant
safety checks.
Thanks
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20151119/4af18803/attachment.html>
More information about the hotspot-compiler-dev
mailing list