[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