[aarch64-port-dev ] RFR (trivial) : fix aarch64-8u type profile bug
Yangfei (Felix)
felix.yang at huawei.com
Thu Sep 19 03:17:30 UTC 2019
Hi,
When I play with a simple test case (InstanceOfExample.java), I witnessed strange C2 JIT code generated by aarch64-8u:
000 B1: # B9 B2 <- BLOCK HEAD IS JUNK Freq: 1
000 # stack bang size=48
sub sp, sp, #48
stp rfp, lr, [sp, #32]
014 ldr R10, [R1, #8] # class
018 NullCheck R1
018
018 B2: # B8 B3 <- B1 Freq: 0.999999
018 + mov R4, precise klass MotorCycle: 0x0000ffff7c069030:Constant:exact * # ptr < ==============
024 + cmp R10, R4 // ptr < ==============
028 bne B8 # unsigned P=0.000000 C=-1.000000 < ==============
028
02c B3: # B6 B4 <- B2 Freq: 0.999999
02c + ldr R10, [R4, #32] # class
030 + mov R0, precise klass DriveCar: 0x0000ffff7c06a750:Constant:exact * # ptr
03c + cmp R10, R0 // ptr
040 bne B6 # unsigned P=0.170000 C=-1.000000
……
0b0 B8: # N1 <- B2 Freq: 1e-35
0b0 + spill R1 -> [sp, #0] # spill size = 64
0b4 + mov R1, #-34 # int
0b8 call,static 0x0000ffff8979efc0 // ==> wrapper for: uncommon_trap(reason='class_check' action='maybe_recompile')
# InstanceOfExample::instanceOfDriverCar @ bci:1 L[0]=_ STK[0]=sp + #0
# OopMap{[0]=Oop off=188}
0bc ShouldNotReachHere
Here, C2 inserts an uncommon trap in B2 if the incoming parameter ‘o’ of instanceOfDriverCar method is not an instance of MotorCycle.
As we send three different types of objects to instanceOfDriverCar method, this JIT code is not expected.
The uncommon trap happens after Thread.sleep in main when instanceOfDriverCar got a Car object.
GDB shows that profile_has_unique_klass gives a wrong result: profile.morphism() equals 1, but it should be 2 here, and this misleads the C2 compiler.
I found this bug is fixed in: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/22fd02fad88b
Fix for aarch64-8u is trivial:
diff -r a1986eb5d5fd src/cpu/aarch64/vm/interp_masm_aarch64.cpp
--- a/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Mon Sep 09 18:54:16 2019 +0200
+++ b/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Fri Sep 20 11:09:10 2019 +0800
@@ -1163,12 +1163,12 @@
b(done);
bind(found_null);
} else {
- cbz(reg2, done);
+ cbnz(reg2, done);
}
break;
}
// Since null is rare, make it be the branch-taken case.
- cbz(reg2,found_null);
+ cbz(reg2, found_null);
// Put all the "Case 3" tests here.
record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
Is it OK to go? Thanks.
Command line:
java -XX:+UseSerialGC -Xms128M -Xmx128M -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:CICompilerCount=2 -XX:+PrintCompilation -XX:-TieredCompilation -XX:LoopMaxUnroll=0
-XX:CompileOnly=InstanceOfExample::instanceOfDriverCar -XX:-Inline -XX:+UnlockDiagnosticVMOptions -XX:+PrintOptoAssembly InstanceOfExample
InstanceOfExample.java:
public class InstanceOfExample {
public static int count = 0;
public static void main(String[] args) throws Exception {
Vehicle vehicle = new Vehicle();
Car car = new Car();
MotorCycle moto = new MotorCycle();
Object[] tools = new Object[]{vehicle, car, moto};
for (int i = 0; i < 20000; i++) {
if (instanceOfDriverCar(tools[i % 3])) {
count++;
}
}
Thread.sleep(2000);
if (instanceOfDriverCar(car)) {
count++;
}
}
public static boolean instanceOfDriverCar(Object o) {
if (o instanceof DriveCar) {
return true;
}
return false;
}
}
class Vehicle {
}
class Car extends Vehicle implements DriveCar {
}
class MotorCycle extends Vehicle {
}
interface DriveCar {
}
More information about the aarch64-port-dev
mailing list