Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8233839

aarch64: missing memory barrier in NewObjectArrayStub and NewTypeArrayStub

XMLWordPrintable

    • b23
    • aarch64
    • generic

        I witnessed random fail of one jcstress test on my 128-core aarch64 server: "org.openjdk.jcstress.tests.defaultValues.arrays.small.plain.StringTest"
        I used the latest aarch64 jdk8u release build.
        Command line: java -jar /home/yangfei/tools/jcstress-tests-all-20191016.jar -jvmArgs "-XX:TieredStopAtLevel=1" -t "org.openjdk.jcstress.tests.defaultValues.arrays.small.plain.StringTest" -time 5000
        Error messages:
           [ERROR] o.o.j.t.defaultValues.arrays.small.plain.StringTest
            Messages:
                Unrecoverable error while running
                java.lang.ArrayIndexOutOfBoundsException: 0
                at org.openjdk.jcstress.tests.defaultValues.arrays.small.plain.StringTest.actor2(StringTest.java:55)
                at org.openjdk.jcstress.tests.defaultValues.arrays.small.plain.StringTest_jcstress.actor2(StringTest_jcstress.java:193)
                at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
                at java.lang.Thread.run(Thread.java:748)

        The jcsress test looks like:

        @JCStressTest
        @Outcome.Outcomes({@Outcome(
           id = {"null, null, null, null"},
           expect = Expect.ACCEPTABLE,
           desc = "Default value for the element."
        ), @Outcome(
           expect = Expect.FORBIDDEN,
           desc = "Non-default values are forbidden."
        )})
        @State
        public class StringTest {
           String[] arr;

           @Actor
           public void actor1() {
              this.arr = new String[4];
           }

           @Actor
           public void actor2(LLLL_Result r) {
              String[] a = this.arr;
              if (a == null) {
                 r.r1 = r.r2 = r.r3 = r.r4 = null;
              } else {
                 r.r1 = a[0]; <==== throws exception here
                 r.r2 = a[1];
                 r.r3 = a[2];
                 r.r4 = a[3];
              }

           }
        }

        From the error message, looks like we are using an array before the initialization of it finished.
        I even reproduced the random failure with a similar case:

        public class ThreadTest {
                public static String[] arr;
                public static String r1, r2, r3, r4;

                static class FirstThread extends Thread {
                        public void actor1() {
                                ThreadTest.arr = new String[4];
                        }

                        public void run() {
                            while (true) {
                                actor1();
                            }
                        }
                }

                static class SecondThread extends Thread {
                        public void actor2() {
                                String[] a = ThreadTest.arr;
                                if (a == null) {
                                        ThreadTest.r1 = null;
                                        ThreadTest.r2 = null;
                                        ThreadTest.r3 = null;
                                        ThreadTest.r4 = null;
                                } else {
                                        ThreadTest.r1 = a[0];
                                        ThreadTest.r2 = a[1];
                                        ThreadTest.r3 = a[2];
                                        ThreadTest.r4 = a[3];
                                }
                        }

                        public void run() {
                                while (true) {
                                        actor2();
                                }
                        }
                }

                public static void main(String args[]) {
                        FirstThread t1 = new FirstThread();
                        SecondThread t2 = new SecondThread();
                        t1.start();
                        t2.start();
                        try {
                                t1.join();
                                t2.join();
                        } catch (InterruptedException e) {
                                System.out.println("INTERRUPTED_MESSAGE");
                        }

                        System.out.println("PASS");
                }

        }

        Command line: java -XX:TieredStopAtLevel=1 ThreadTest
        Error message:
        Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 0
                at ThreadTest$SecondThread.actor2(ThreadTest.java:26)
                at ThreadTest$SecondThread.run(ThreadTest.java:35)

        JIT code for actor1:

        Compiled method (c1) 310 16 1 ThreadTest$FirstThread::actor1 (8 bytes)
         total in heap [0x0000ffff904cbc50,0x0000ffff904cbff8] = 936
         relocation [0x0000ffff904cbd70,0x0000ffff904cbd88] = 24
         main code [0x0000ffff904cbdc0,0x0000ffff904cbf40] = 384
         stub code [0x0000ffff904cbf40,0x0000ffff904cbf50] = 16
         oops [0x0000ffff904cbf50,0x0000ffff904cbf60] = 16
         metadata [0x0000ffff904cbf60,0x0000ffff904cbf70] = 16
         scopes data [0x0000ffff904cbf70,0x0000ffff904cbf90] = 32
         scopes pcs [0x0000ffff904cbf90,0x0000ffff904cbff0] = 96
         dependencies [0x0000ffff904cbff0,0x0000ffff904cbff8] = 8
        Loaded disassembler from /home/yangfei/jdk8u-release/jvm/openjdk-1.8.0-internal/jre/lib/aarch64/server/hsdis-aarch64.so
        Decoding compiled method 0x0000ffff904cbc50:
        Code:
        [Disassembling for mach='aarch64']
        [Entry Point]
        [Constants]
          # {method} {0x0000ffff81b57880} 'actor1' '()V' in 'ThreadTest$FirstThread'
          # [sp+0x40] (sp of caller)
          0x0000ffff904cbdc0: ldr w8, [x1,#8]
          0x0000ffff904cbdc4: cmp w9, w8
          0x0000ffff904cbdc8: b.eq 0x0000ffff904cbe00
          0x0000ffff904cbdcc: b 0x0000ffff900b1ec0 ; {runtime_call}
          0x0000ffff904cbdd0: nop
          0x0000ffff904cbdd4: nop
          0x0000ffff904cbdd8: nop
          0x0000ffff904cbddc: nop
          0x0000ffff904cbde0: nop
          0x0000ffff904cbde4: nop
          0x0000ffff904cbde8: nop
          0x0000ffff904cbdec: nop
          0x0000ffff904cbdf0: nop
          0x0000ffff904cbdf4: nop
          0x0000ffff904cbdf8: nop
          0x0000ffff904cbdfc: nop
        [Verified Entry Point]
          0x0000ffff904cbe00: nop
          0x0000ffff904cbe04: orr x9, xzr, #0xffffffffffffc000
          0x0000ffff904cbe08: str xzr, [sp,x9]
          0x0000ffff904cbe0c: sub sp, sp, #0x40
          0x0000ffff904cbe10: stp x29, x30, [sp,#48] ;*iconst_4
                                                        ; - ThreadTest$FirstThread::actor1@0 (line 7)

          0x0000ffff904cbe14: orr w19, wzr, #0x4
          0x0000ffff904cbe18: mov x3, #0xaf08 // #44808
                                                        ; {metadata('java/lang/String'[])}
          0x0000ffff904cbe1c: movk x3, #0x1, lsl #16
          0x0000ffff904cbe20: movk x3, #0x8, lsl #32
          0x0000ffff904cbe24: ubfx x19, x19, #0, #32
          0x0000ffff904cbe28: mov x5, x19
          0x0000ffff904cbe2c: mov x8, #0xffffff // #16777215
          0x0000ffff904cbe30: cmp x19, x8
          0x0000ffff904cbe34: b.cs 0x0000ffff904cbf0c
          0x0000ffff904cbe38: mov x4, #0x17 // #23
          0x0000ffff904cbe3c: add x4, x4, w19, uxtw #2
          0x0000ffff904cbe40: and x4, x4, #0xfffffffffffffff8
          0x0000ffff904cbe44: ldr x0, [x28,#96]
          0x0000ffff904cbe48: add x4, x0, x4, uxtx
          0x0000ffff904cbe4c: ldr x8, [x28,#112]
          0x0000ffff904cbe50: cmp x4, x8
          0x0000ffff904cbe54: b.hi 0x0000ffff904cbf0c
          0x0000ffff904cbe58: str x4, [x28,#96]
          0x0000ffff904cbe5c: sub x4, x4, x0
          0x0000ffff904cbe60: orr x2, xzr, #0x1
          0x0000ffff904cbe64: str x2, [x0]
          0x0000ffff904cbe68: eor x2, x3, #0x800000000
          0x0000ffff904cbe6c: str w2, [x0,#8]
          0x0000ffff904cbe70: str w19, [x0,#12]
          0x0000ffff904cbe74: subs x4, x4, #0x10
          0x0000ffff904cbe78: b.eq 0x0000ffff904cbecc
          0x0000ffff904cbe7c: add x0, x0, #0x10
          0x0000ffff904cbe80: lsr x4, x4, #3
          0x0000ffff904cbe84: and x8, x4, #0x7
          0x0000ffff904cbe88: sub x4, x4, x8
          0x0000ffff904cbe8c: add x19, x0, x8, lsl #3
          0x0000ffff904cbe90: adr x9, 0x0000ffff904cbec0
          0x0000ffff904cbe94: sub x9, x9, x8, lsl #2
          0x0000ffff904cbe98: br x9
          0x0000ffff904cbe9c: sub x4, x4, #0x8
          0x0000ffff904cbea0: str xzr, [x19,#-64]
          0x0000ffff904cbea4: str xzr, [x19,#-56]
          0x0000ffff904cbea8: str xzr, [x19,#-48]
          0x0000ffff904cbeac: str xzr, [x19,#-40]
          0x0000ffff904cbeb0: str xzr, [x19,#-32]
          0x0000ffff904cbeb4: str xzr, [x19,#-24]
          0x0000ffff904cbeb8: str xzr, [x19,#-16]
          0x0000ffff904cbebc: str xzr, [x19,#-8]
          0x0000ffff904cbec0: add x19, x19, #0x40
          0x0000ffff904cbec4: cbnz x4, 0x0000ffff904cbe9c
          0x0000ffff904cbec8: sub x0, x0, #0x10
          0x0000ffff904cbecc: dmb ishst ;*anewarray
                                                        ; - ThreadTest$FirstThread::actor1@1 (line 7)

          0x0000ffff904cbed0: mov x1, #0x22c0 // #8896
                                                        ; {oop(a 'java/lang/Class' = 'ThreadTest')}
          0x0000ffff904cbed4: movk x1, #0x8016, lsl #16
          0x0000ffff904cbed8: movk x1, #0x5, lsl #32
          0x0000ffff904cbedc: lsr x8, x0, #3
          0x0000ffff904cbee0: str w8, [x1,#104]
          0x0000ffff904cbee4: lsr x0, x1, #9
          0x0000ffff904cbee8: mov x1, #0xf000 // #61440
          0x0000ffff904cbeec: movk x1, #0x8bff, lsl #16
          0x0000ffff904cbef0: movk x1, #0xffff, lsl #32
          0x0000ffff904cbef4: strb wzr, [x0,x1,lsl #0] ;*putstatic arr
                                                        ; - ThreadTest$FirstThread::actor1@4 (line 7)

          0x0000ffff904cbef8: ldp x29, x30, [sp,#48]
          0x0000ffff904cbefc: add sp, sp, #0x40
          0x0000ffff904cbf00: adrp x8, 0x0000ffffa02e3000
                                                        ; {poll_return}
          0x0000ffff904cbf04: ldr wzr, [x8] ; {poll_return}
          0x0000ffff904cbf08: ret
          0x0000ffff904cbf0c: bl 0x0000ffff900dcf80 ; OopMap{off=336} < =================== slow path
                                                        ;*anewarray
                                                        ; - ThreadTest$FirstThread::actor1@1 (line 7)
                                                        ; {runtime_call}
          0x0000ffff904cbf10: b 0x0000ffff904cbed0
          0x0000ffff904cbf14: nop
          0x0000ffff904cbf18: nop
          0x0000ffff904cbf1c: ldr x0, [x28,#784]
          0x0000ffff904cbf20: str xzr, [x28,#784]
          0x0000ffff904cbf24: str xzr, [x28,#792]
          0x0000ffff904cbf28: ldp x29, x30, [sp,#48]
          0x0000ffff904cbf2c: add sp, sp, #0x40
          0x0000ffff904cbf30: b 0x0000ffff900defc0 ; {runtime_call}
          0x0000ffff904cbf34: .inst 0x00000000 ; undefined
          0x0000ffff904cbf38: .inst 0x00000000 ; undefined
          0x0000ffff904cbf3c: .inst 0x00000000 ; undefined
        [Exception Handler]
        [Stub Code]
          0x0000ffff904cbf40: bl 0x0000ffff900dc8c0 ; {no_reloc}
        [Deopt Handler Code]
          0x0000ffff904cbf44: adr x30, 0x0000ffff904cbf44
          0x0000ffff904cbf48: b 0x0000ffff900b35c0 ; {runtime_call}
          0x0000ffff904cbf4c: .inst 0x00000000 ; undefined
        OopMapSet contains 1 OopMaps

        #0
        OopMap{off=336}

        As there is a StoreStore memory barrier for the fast path, I looks into the slow path here.
        Obviously, the StoreStore memory barrier is missing for the slow path.


        Patch for aarch64 8u:
        diff -r 02145a45eff6 src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp
        --- a/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Mon Nov 05 12:53:55 2018 +0100
        +++ b/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Fri Nov 08 11:05:48 2019 +0800
        @@ -877,6 +877,7 @@
                   __ sub(arr_size, arr_size, t1); // body length
                   __ add(t1, t1, obj); // body start
                   __ initialize_body(t1, arr_size, 0, t2);
        + __ membar(Assembler::StoreStore);
                   __ verify_oop(obj);

                   __ ret(lr);
        @@ -905,6 +906,7 @@
                   __ sub(arr_size, arr_size, t1); // body length
                   __ add(t1, t1, obj); // body start
                   __ initialize_body(t1, arr_size, 0, t2);
        + __ membar(Assembler::StoreStore);
                   __ verify_oop(obj);

                   __ ret(lr);


        Patch for 14 and 11u:
        diff -r ad157fab6bf5 src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
        --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp Thu Nov 07 16:26:57 2019 -0800
        +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp Fri Nov 08 16:10:08 2019 +0800
        @@ -840,6 +840,7 @@
                   __ sub(arr_size, arr_size, t1); // body length
                   __ add(t1, t1, obj); // body start
                   __ initialize_body(t1, arr_size, 0, t2);
        + __ membar(Assembler::StoreStore);
                   __ verify_oop(obj);

                   __ ret(lr);

              fyang Fei Yang
              fyang Fei Yang
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: