JDK-8162384 : Performance regression: bimorphic inlining may be bypassed by type speculation
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8u20,9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-07-22
  • Updated: 2017-11-29
  • Resolved: 2016-07-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u152Fixed 9 b131Fixed
Related Reports
Relates :  
Description
Here is an example of that problem:

private static int iterateIndirect(ByteBuffer buffer) {
	int n = buffer.remaining();
	while (n > 0 && buffer.get(n - 1) == 0) {
		n--;
	}
	return n;
}

Profiling is:

static ByteBufferTest::iterateIndirect(Ljava/nio/ByteBuffer;)I
  interpreter_invocation_count:        2 
  invocation_counter:                  2 
  backedge_counter:               156672 
  mdo size: 600 bytes

0 fast_aload_0
1 invokevirtual 49 <java/nio/ByteBuffer.remaining()I> 
  0   bci: 1    VirtualCallData     count(0) nonprofiled_count(0) entries(1)
                                    'java/nio/DirectByteBuffer'(1 1.00)
                                    method_entries(0)
4 istore_1
5 iload_1
6 ifle 25
  56  bci: 6    BranchData          taken(0) displacement(144)
                                    not taken(96249)
9 fast_aload_0
10 iload_1
11 iconst_1
12 isub
13 invokevirtual 50 <java/nio/ByteBuffer.get(I)B> 
  88  bci: 13   VirtualCallData     trap/ ByteBufferTest::iterateIndirect(class_check recompiled) count(0) nonprofiled_count(0) entries(2)
                                    'java/nio/HeapByteBuffer'(47103 0.49)
                                    'java/nio/DirectByteBuffer'(49151 0.51)
                                    method_entries(0)
16 ifne 25
  144 bci: 16   BranchData          trap(intrinsic_or_type_checked_inlining recompiled) flags(224) taken(1) displacement(56)
                                    not taken(96254)
19 iinc #1 -1
22 goto 5
  176 bci: 22   JumpData            taken(96254) displacement(-120)
25 iload_1
26 ireturn

The method is called with either a HeapByteBuffer or a DirectByteBuffer but profiling didn't run long enough to collect both at bci 1. The profiling at bci 1 DirectByteBuffer) is fed to type speculation. Call at bci 13 uses the speculation, inlines DirectByteBuffer::get(). When a HeapByteBuffer is passed to the compiled method, an uncommon trap occurs, the method is recompiled, speculation is used again to inline DirectByteBuffer::get() but because of the trap a virtual call is compiled to cover cases where the speculation fails. Given the profile data at the call, it would be much better to use bimorphic inlining and ignore speculation.
Comments
regarding lack of test case: This bug affects quality of code generation/performance and not correctness. It's hard to observe with a simple regression test.
18-08-2016