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

C2: ZGC fails with 'Incorrect load shift' when invoking Object.clone() reflectively on an array



    • b26



        Executing C2-generated code that for a reflective Object.clone() invocation on an array leads to the following assertion failure (see attached error log file):

        # A fatal error has been detected by the Java Runtime Environment:
        # Internal Error (.../src/hotspot/cpu/x86/gc/z/zAddress_x86.inline.hpp:35), pid=11538, tid=11539
        # assert(index == 0 || is_power_of_2(index)) failed: Incorrect load shift: 11
        # JRE version: Java(TM) SE Runtime Environment (23.0+24) (fastdebug build 23-ea+24-1995)
        # Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 23-ea+24-1995, mixed mode, sharing, tiered, compressed class ptrs, z gc, linux-amd64)
        # Problematic frame:
        # V [libjvm.so+0x1984d24] ZBarrierSet::clone_obj_array(objArrayOop, objArrayOop)+0x874

        Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
        V [libjvm.so+0x1984d24] ZBarrierSet::clone_obj_array(objArrayOop, objArrayOop)+0x874 (zAddress_x86.inline.hpp:35)
        V [libjvm.so+0x1009713] AccessInternal::PostRuntimeDispatch<ZBarrierSet::AccessBarrier<270400ul, ZBarrierSet>, (AccessInternal::BarrierType)9, 270400ul>::access_barrier(oop, oop, unsigned long)+0x3e3
        V [libjvm.so+0x199e8f7] ZBarrierSetRuntime::clone(oopDesc*, oopDesc*, unsigned long)+0x157

        How to reproduce

        Just run the attached test case on a JDK 23 debug build as follows:
        $ java --add-opens java.base/java.lang=ALL-UNNAMED -Xbatch -XX:+UseZGC -XX:-UseTypeProfile Test.java

        Preliminary analysis (thanks to [~aboldtch])

        When C2 compiles a reflective call to Object.clone(), it lacks type information about the receiver (the clone source). To distinguish which clone implementation to use, C2 generates a dynamic check to test if the source is an array [1]. Under this guard, C2 marks the ArrayCopy as is_clone_array(), however the source type is unknown so ZGC implements the ArrayCopy using a runtime call to ZBarrierSetRuntime::clone [2]. This runtime function fails because it expects the source array to be initialized and it is not, due to the ReduceBulkZeroing optimization (enabled by default) applied by C2 at bytecode parsing time [3].

        [1] https://github.com/openjdk/jdk/blob/61db2f5b90cd40ce104cb55bf9fd52d6e141161d/src/hotspot/share/opto/library_call.cpp#L5112
        [2] https://github.com/openjdk/jdk/blob/61db2f5b90cd40ce104cb55bf9fd52d6e141161d/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp#L482-L506
        [3] https://github.com/openjdk/jdk/blob/61db2f5b90cd40ce104cb55bf9fd52d6e141161d/src/hotspot/share/opto/library_call.cpp#L5016-L5026

        This bug affects Generational ZGC only (due to the introduction of store barriers). All JDK versions including Generational ZGC may be affected.


          Issue Links



                rcastanedalo Roberto Castaneda Lozano
                rcastanedalo Roberto Castaneda Lozano
                0 Vote for this issue
                5 Start watching this issue