JDK-8166110 : Inlining through MH invokers/linkers in unreachable code is unsafe
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-09-15
  • Updated: 2018-02-26
  • Resolved: 2017-02-09
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 10 JDK 9
10Fixed 9 b159Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
With the preliminary patch for JDK-8161211 applied in 9-dev, this crash is reproducible:

#  Internal Error (/.../hotspot/src/share/vm/opto/doCall.cpp:719), pid=29519, tid=29587
#  assert(check_call_consistency(jvms, cg)) failed: inconsistent info

Details from fastdebug build:

JVMS depth=1 loc=5 stk=19 arg=19 mon=25 scalar=25 end=25 mondepth=0 sp=0 bci=101 reexecute=false method=static jint java.lang.invoke.LambdaForm$MH022/728637067.loop_002(jobject, jobject)
   bc: JVMS depth=2 loc=5 stk=8 arg=8 mon=13 scalar=13 end=13 mondepth=0 sp=0 bci=123 reexecute=false method=virtual jobject java.lang.invoke.BoundMethodHandle.arg(jint)
   bc: Bytecode info:
<ciMethod name=invokeBasic holder=java/lang/invoke/MethodHandle signature=(Ljava/lang/Object;)D loaded=true arg_size=2 flags=DEFAULT_ACCESS,final,native ident=1114 address=0x00007f44706106e0>

The code to reproduce this is as follows:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class Main {

   public static void main(String[] args) throws Throwable {
       MethodHandle h = makeLoop();
       for (int i = 0; i < 100; ++i) {
           System.err.print(i);
           h.invoke();
           System.err.println();
       }
   }

   static MethodHandle makeLoop() throws Throwable {
       MethodHandle it = MethodHandles.constant(int.class, 10000);
       MethodHandle bo =
               MethodHandles.lookup().findStatic(Main.class, "body", MethodType.methodType(void.class, int.class));
       return MethodHandles.countedLoop(it, null, bo);
   }

   static void body(int x) {
       if (x % 100 == 0) {
           System.err.print('.');
       }
   }

}

[~vlivanov]'s analysis:

The assertion is too strong for the case when C2 processes never-taken branch.

Some details:

jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java:

final Object arg(int i) {
   try {
       switch (speciesData().fieldType(i)) {
       case L_TYPE: return speciesData().getters[i].invokeBasic(this);
       case I_TYPE: return (int) speciesData().getters[i].invokeBasic(this);
       case J_TYPE: return (long) speciesData().getters[i].invokeBasic(this);
       case F_TYPE: return (float) speciesData().getters[i].invokeBasic(this);
       case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this);
       }
   } catch (Throwable ex) {
       throw newInternalError(ex);
   }
   throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i);
}

Even for constant BMH receiver & constant argument, C2 can't constant fold speciesData().fieldType(i), since SpeciesData.typeCodes[] isn't @Stable. Without @Stable, C2 can't contant-fold element loads from arrays.

But it can inline through speciesData().getters[i], since SpeciesData.getters is @Stable. So, the assertion is fired when inlining on never-taken branch happens.

Note by [~mhaupt]: The crash happens with the @Stable annotation on basicTypes. These seems to be nothing that speaks against adding it, though.
Comments
Fix that adds checks of signatures during MH inlining: http://cr.openjdk.java.net/~vlivanov/dchuyko/8166110/webrev.00/
01-02-2017

Removed "blocks" links to JDK-8161210 and JDK-8161211: adopting a different bytecode generation schema in the latter stops triggering this bug.
16-09-2016