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

[GenShen] ShenandoahOldEvacRatioPercent=100 fails with divide-by-zero

XMLWordPrintable

    • gc

      I stumbled upon the following issue when working on JDK-8314599.

      SPECjbb run with -XX:ShenandoahOldEvacRatioPercent=100 fails with the following error:

      ```
      #
      # A fatal error has been detected by the Java Runtime Environment:
      #
      # SIGFPE (0x8) at pc=0x00007f8c7cadc130, pid=46666, tid=46720
      #
      # JRE version: OpenJDK Runtime Environment (22.0) (build 22-internal-adhoc.ysr.shenandoah)
      # Java VM: OpenJDK 64-Bit Server VM (22-internal-adhoc.ysr.shenandoah, mixed mode, tiered, compressed oops, compressed class ptrs, shenandoah gc, linux-amd64)
      # Problematic frame:
      # V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130
      #
      # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
      #
      # If you would like to submit a bug report, please visit:
      # https://bugreport.java.com/bugreport/crash.jsp
      #

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

      Command Line: -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-ShenandoahPacing -Xmx30g -Xms30g -XX:+AlwaysPreTouch -Xlog:async -Xlog:gc*=info,gc+age=trace,gc+phases=debug -XX:+DisableExplicitGC -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:ShenandoahOldEvacRatioPercent=100 ../specjbb2015.jar -m COMPOSITE

      Host: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz, 40 cores, 157G, Amazon Linux release 2 (Karoo)
      Time: Tue Dec 12 07:32:43 2023 UTC elapsed time: 6.132387 seconds (0d 0h 0m 6s)

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

      Current thread (0x00007f8c7421fbb0): VMThread "VM Thread" [id=46720, stack(0x00007f8b8797a000,0x00007f8b87a7a000) (1024K)]

      Stack: [0x00007f8b8797a000,0x00007f8b87a7a000], sp=0x00007f8b87a77470, free space=1013k
      Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
      V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130 (shenandoahGeneration.cpp:284)
      V [libjvm.so+0xe0f05c] ShenandoahGeneration::prepare_regions_and_collection_set(bool)+0x18c (shenandoahGeneration.cpp:726)
      V [libjvm.so+0xde979f] ShenandoahConcurrentGC::op_final_mark()+0x8f (shenandoahConcurrentGC.cpp:744)
      V [libjvm.so+0xdec9bf] ShenandoahConcurrentGC::entry_final_mark()+0x9f (shenandoahConcurrentGC.cpp:350)
      V [libjvm.so+0xe93efd] VM_ShenandoahFinalMarkStartEvac::doit()+0x2d (shenandoahVMOperations.cpp:59)
      V [libjvm.so+0x103fa21] VM_Operation::evaluate()+0x101 (vmOperations.cpp:73)
      V [libjvm.so+0x1042cf2] VMThread::evaluate_operation(VM_Operation*)+0xb2 (vmThread.cpp:281)
      V [libjvm.so+0x10439f7] VMThread::inner_execute(VM_Operation*)+0x357 (vmThread.cpp:435)
      V [libjvm.so+0x1043cf7] VMThread::run()+0xb7 (vmThread.cpp:502)
      V [libjvm.so+0xfb1a38] Thread::call_run()+0xa8 (thread.cpp:220)
      V [libjvm.so+0xcef4ea] thread_native_entry(Thread*)+0xda (os_linux.cpp:787)


      ```

      The issue is that although the option's legal range is [0,100], the following code in shenandoahGeneration.cpp::ShenandoahGeneration::compute_evacuation_budgets is problematic when the option value is 100:

      - // maximum_old_evacuation_reserve is an upper bound on memory evacuated from old and evacuated to old (promoted).
      - size_t maximum_old_evacuation_reserve =
      - maximum_young_evacuation_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
      - // Here's the algebra:
      - // TotalEvacuation = OldEvacuation + YoungEvacuation
      - // OldEvacuation = TotalEvacuation * (ShenandoahOldEvacRatioPercent/100)
      - // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
      - // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
      -

      A similar flaw exists also in shenandoahHeap.cpp::ShenandoahHeap::adjust_generation_sizes_for_next_cycle:


      - // We can limit the reserve to the size of anticipated promotions
      - size_t max_old_reserve = young_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
      - // Here's the algebra:
      - // TotalEvacuation = OldEvacuation + YoungEvacuation
      - // OldEvacuation = TotalEvacuation*(ShenandoahOldEvacRatioPercent/100)
      - // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
      - // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
      -


            ysr Y. Ramakrishna
            ysr Y. Ramakrishna
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: