s390: MacroAssembler::encode_klass_not_null() may produce wrong results for non-zero values of narrow klass base

XMLWordPrintable

    • Type: Enhancement
    • Resolution: Fixed
    • Priority: P4
    • 17
    • Affects Version/s: 17
    • Component/s: hotspot
    • b12
    • s390x

      This is an old bug in the s390 template interpreter which has been there since the day the s390 port was contributed; it has been dormant however and was activated just recently by JDK-8250989 which changed the way class space reservation happens at CDS dump time.

      It surfaced first as crash in runtime/cds/appcds/cacheObject/DifferentHeapSizes.java .

      -----

      If Compressed class pointer base has a non-zero value it may cause MacroAssembler::encode_klass_not_null() to encode a Klass pointer to a wrong narrow pointer.

      This can be reproduced by starting the VM with
      ```
      -Xshare:dump -XX:HeapBaseMinAddress=2g -Xmx128m
      ```
      but CDS is not involved. It is only relevant insofar as this is the only way to get the following combination:
      - heap is allocated at 0x800_0000. It is small and ends at 0x8800_0000.
      - class space follows at 0x8800_0000
      - the narrow klass pointer base points to the start of the class space at 0x8800_0000.

      It is not possible with an unmodified VM to get the same combination of values with Xshare=on or Xshare=off.

      -----

      In MacroAssembler::encode_klass_not_null(), there is the following section:

      ```
        if (base != NULL) {
          unsigned int base_h = ((unsigned long)base)>>32;
          unsigned int base_l = (unsigned int)((unsigned long)base);
          if ((base_h != 0) && (base_l == 0) && VM_Version::has_HighWordInstr()) {
            lgr_if_needed(dst, current);
            z_aih(dst, -((int)base_h)); // Base has no set bits in lower half.
      A } else if ((base_h == 0) && (base_l != 0)) {
            lgr_if_needed(dst, current);
      B z_agfi(dst, -(int)base_l);
          } else {
            load_const(Z_R0, base);
            lgr_if_needed(dst, current);
            z_sgr(dst, Z_R0);
          }
          current = dst;
        }
      ```

      We enter the condition at (A) if the narrow klass pointer base is non-zero but fits into 32bit. At (B), we want to substract the base from the Klass pointer; we do this by calculating the 32bit twos-complement of the base and add it with AGFI. AGFI adds a 32bit immediate to a 64bit register. In this case, it produces the wrong result if the base is >0x800_0000:

      In the case of the crash, we have:
      base:
       8800_0000
      32bit two's complement of base:
       7800_0000
      klass pointer:
       8804_1040
      klass pointer+7800_0000:
       1_0004_1040

      So the result of the "substraction" is 1_0004_1040, it should be 4_1040, which would be the correct offset of the Klass* pointer within the ccs. This wrong Klass* pointer then gets encoded and written into the Object header. VM crashes the first time the Klass pointer is decoded (which is pretty fast).

            Assignee:
            Thomas Stuefe
            Reporter:
            Thomas Stuefe
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: