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

[macOS] : hotspot arm64 bug exposed by latest clang

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b09
    • CPU:
      aarch64
    • OS:
      os_x
    • Verification:
      Verified

      Backports

        Description

        The latest clang compiler (not yet used in OpenJDK tool chains) exposes a bug in the macos aarch64 port which causes a crash on startup (ie just running java -version)

        This was reported by Apple as below :-
        New optimizations in recent versions of clang are exposing undefined behavior in OpenJDK causing the JVM to crash during initialization on Apple Silicon
         

        # A fatal error has been detected by the Java Runtime Environment:
        #
        # Internal Error (assembler_aarch64.hpp:248), pid=33335, tid=7939
        # guarantee(val < (1ULL << nbits)) failed: Field too big for insn
        #
        # JRE version: (17.0.1) (build )
        # Java VM: OpenJDK 64-Bit Server VM (17.0.1-internal+0, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
        # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
        #
        #

        --------------- S U M M A R Y ------------

        Command Line:

        Host: "MacBookAir10,1" arm64 24 MHz, 8 cores, 8G, Darwin 21.3.0, macOS 12.2 (21D33)
        Time: Wed Dec 22 07:42:22 2021 PST elapsed time: 0.021249 seconds (0d 0h 0m 0s)

        --------------- T H R E A D ---------------

        Current thread (0x0000000157014c00): JavaThread "Unknown thread" [_thread_in_vm, id=7939, stack(0x000000016d8b0000,0x000000016dab3000)]

        Stack: [0x000000016d8b0000,0x000000016dab3000], sp=0x000000016dab20c0, free space=2056k
        Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
        V [libjvm.dylib+0xa294b0] _ZN7VMError14report_and_dieEiPKcS1_PcP6ThreadPhPvS6_S1_im+0x4b0
        V [libjvm.dylib+0xa29c4c] _ZN7VMError14report_and_dieEP6ThreadPvPKciS4_S4_Pc+0x40
        V [libjvm.dylib+0x2c83b8] _Z15report_vm_errorPKciS0_S0_z+0x5c
        V [libjvm.dylib+0x879334] _ZN9Assembler4andrEP12RegisterImplS1_y+0x94
        V [libjvm.dylib+0x95d1b0] _ZN13StubGenerator18generate_call_stubERPh+0x9ac
        V [libjvm.dylib+0x92e99c] _ZN13StubGenerator16generate_initialEv+0x34
        V [libjvm.dylib+0x92e2e0] _Z22StubGenerator_generateP10CodeBufferb+0x84
        V [libjvm.dylib+0x95f458] _ZN12StubRoutines11initialize1Ev+0xc8
        V [libjvm.dylib+0x457878] _Z12init_globalsv+0x28
        V [libjvm.dylib+0x9bd9e0] _ZN7Threads9create_vmEP14JavaVMInitArgsPb+0x418
        V [libjvm.dylib+0x4f5514] JNI_CreateJavaVM+0x78
        C [libjli.dylib+0x4608] JavaMain+0x100
        C [libjli.dylib+0x74a0] ThreadJavaMain+0xc
        C [libsystem_pthread.dylib+0x7240] _pthread_start+0x94

        -----
        The problem is undefined behavior in replicate:

          uint64_t replicate(uint64_t bits, int nbits, int count)
          {
            uint64_t result = 0;
            // nbits may be 64 in which case we want mask to be -1
            uint64_t mask = ones(nbits);
            for (int i = 0; i < count ; i++) {
              result <<= nbits;
              result |= (bits & mask);
            }
            return result;
          }

        If nbits is 64, the shift has undefined behavior since the size of the shifted value is 64. Adding a handler for this special case at the start of replicate will address this problem, eg:

        --- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
        +++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
        @@ -129,8 +129,13 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo)

        uint64_t replicate(uint64_t bits, int nbits, int count)
        {
        + // Special case nbits == 64 since the resulting shift below would result in undefined behavior
        + if (nbits == 64) {
        + assert(count <= 1);
        + return bits;
        + }
        +
          uint64_t result = 0;
        - // nbits may be 64 in which case we want mask to be -1
          uint64_t mask = ones(nbits);
          for (int i = 0; i < count ; i++) {
            result <<= nbits;

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                dcubed Daniel Daugherty
                Reporter:
                prr Philip Race
                Votes:
                0 Vote for this issue
                Watchers:
                9 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: