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

Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org>
Reviewed-by: kvn, thartmann, aboldtch
This commit is contained in:
Roberto Castañeda Lozano 2024-06-03 07:37:17 +00:00
parent d2d78ad18e
commit e0ac8249f5
2 changed files with 41 additions and 4 deletions

View File

@ -5013,7 +5013,13 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b
assert(alloc_obj->is_CheckCastPP() && raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), "");
AllocateNode* alloc = nullptr;
if (ReduceBulkZeroing) {
if (ReduceBulkZeroing &&
// If we are implementing an array clone without knowing its source type
// (can happen when compiling the array-guarded branch of a reflective
// Object.clone() invocation), initialize the array within the allocation.
// This is needed because some GCs (e.g. ZGC) might fall back in this case
// to a runtime clone call that assumes fully initialized source arrays.
(!is_array || obj->get_ptr_type()->isa_aryptr() != nullptr)) {
// We will be completely responsible for initializing this object -
// mark Initialize node as complete.
alloc = AllocateNode::Ideal_allocation(alloc_obj);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/*
* @test
* @bug 8155643 8268125 8270461 8270098
* @bug 8155643 8268125 8270461 8270098 8332959
* @summary Test Object.clone() intrinsic.
* @modules java.base/java.lang:+open
*
@ -41,6 +41,7 @@
* @run main/othervm -Xbatch -XX:-UseTypeProfile
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
* -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
* -XX:CompileCommand=compileonly,*::invokeVirtual
* compiler.arraycopy.TestObjectArrayClone
*/
@ -188,10 +189,18 @@ public class TestObjectArrayClone {
return clone.invoke(obj);
}
public static void main(String[] args) throws Exception {
public static Object testCloneObjectWithMethodHandle(MethodHandle clone, Object obj) throws Throwable {
return clone.invokeExact(obj);
}
public static void main(String[] args) throws Throwable {
Method clone = Object.class.getDeclaredMethod("clone");
clone.setAccessible(true);
MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(Object.class, MethodHandles.lookup());
MethodType mt = MethodType.methodType(Object.class);
MethodHandle mh = privateLookup.findVirtual(Object.class, "clone", mt);
String[] arr1 = new String[42];
for (int j = 0; j < arr1.length; j++) {
arr1[j] = new String(Integer.toString(j));
@ -258,6 +267,17 @@ public class TestObjectArrayClone {
verifyStr(value, value2);
}
for (int i = 0; i < 50_000; i++) {
String[] arr2 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
verifyStr(arr1, arr2);
String[] arr3 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
verifyStr(arr1, arr3);
String[] arr4 = (String[]) testCloneObjectWithMethodHandle(mh, (Object)arr1);
verifyStr(arr1, arr4);
verifyStr(arr1, arr3);
verifyStr(arr1, arr2);
}
int[] arr2 = new int[42];
for (int i = 0; i < arr2.length; i++) {
arr2[i] = i;
@ -320,6 +340,17 @@ public class TestObjectArrayClone {
verifyPayload2(p2, p3);
verifyPayload2(p1, p3);
}
for (int i = 0; i < 50_000; i++) {
Payload2 p1 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
verifyPayload2(ref2, p1);
Payload2 p2 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
verifyPayload2(ref2, p2);
Payload2 p3 = (Payload2) testCloneObjectWithMethodHandle(mh, ref2);
verifyPayload2(ref2, p3);
verifyPayload2(p2, p3);
verifyPayload2(p1, p3);
}
}
public static void verifyPayload(Payload p1, Payload p2) {