This failure is observable with the preliminary patch for JDK-8161211 applied in 9-dev:
# Internal Error (/home/michael/dev/hotspot/src/share/vm/opto/doCall.cpp:719), pid=29519, tid=29587
# assert(check_call_consistency(jvms, cg)) failed: inconsistent info
Details:
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 the crash is this:
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 from [~mhaupt]: the crash happens even with BMH.SpeciesData.basicTypes annotated as @Stable. There seems to be nothing that speaks against adding this annotation, though.
# Internal Error (/home/michael/dev/hotspot/src/share/vm/opto/doCall.cpp:719), pid=29519, tid=29587
# assert(check_call_consistency(jvms, cg)) failed: inconsistent info
Details:
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 the crash is this:
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 from [~mhaupt]: the crash happens even with BMH.SpeciesData.basicTypes annotated as @Stable. There seems to be nothing that speaks against adding this annotation, though.
- blocks
-
JDK-8161210 slowdown in MHs.iteratedLoop handles
-
- Open
-
-
JDK-8161211 better inlining support for loop bytecode intrinsics
-
- Closed
-
- duplicates
-
JDK-8166110 Inlining through MH invokers/linkers in unreachable code is unsafe
-
- Resolved
-