mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 17:44:40 +02:00
8270098: ZGC: ZBarrierSetC2::clone_at_expansion fails with "Guard against surprises" assert
Reviewed-by: neliasso, kvn
This commit is contained in:
parent
d53d94b14d
commit
2384e12888
2 changed files with 95 additions and 23 deletions
|
@ -268,17 +268,10 @@ static const TypeFunc* clone_type() {
|
||||||
|
|
||||||
void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
|
void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
|
||||||
Node* const src = ac->in(ArrayCopyNode::Src);
|
Node* const src = ac->in(ArrayCopyNode::Src);
|
||||||
|
|
||||||
if (ac->is_clone_array()) {
|
|
||||||
const TypeAryPtr* ary_ptr = src->get_ptr_type()->isa_aryptr();
|
const TypeAryPtr* ary_ptr = src->get_ptr_type()->isa_aryptr();
|
||||||
BasicType bt;
|
|
||||||
if (ary_ptr == NULL) {
|
if (ac->is_clone_array() && ary_ptr != NULL) {
|
||||||
// ary_ptr can be null iff we are running with StressReflectiveCode
|
BasicType bt = ary_ptr->elem()->array_element_basic_type();
|
||||||
// This code will be unreachable
|
|
||||||
assert(StressReflectiveCode, "Guard against surprises");
|
|
||||||
bt = T_LONG;
|
|
||||||
} else {
|
|
||||||
bt = ary_ptr->elem()->array_element_basic_type();
|
|
||||||
if (is_reference_type(bt)) {
|
if (is_reference_type(bt)) {
|
||||||
// Clone object array
|
// Clone object array
|
||||||
bt = T_OBJECT;
|
bt = T_OBJECT;
|
||||||
|
@ -286,7 +279,6 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a
|
||||||
// Clone primitive array
|
// Clone primitive array
|
||||||
bt = T_LONG;
|
bt = T_LONG;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Node* ctrl = ac->in(TypeFunc::Control);
|
Node* ctrl = ac->in(TypeFunc::Control);
|
||||||
Node* mem = ac->in(TypeFunc::Memory);
|
Node* mem = ac->in(TypeFunc::Memory);
|
||||||
|
@ -333,12 +325,11 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a
|
||||||
Node* const dst = ac->in(ArrayCopyNode::Dest);
|
Node* const dst = ac->in(ArrayCopyNode::Dest);
|
||||||
Node* const size = ac->in(ArrayCopyNode::Length);
|
Node* const size = ac->in(ArrayCopyNode::Length);
|
||||||
|
|
||||||
assert(ac->is_clone_inst(), "Sanity check");
|
|
||||||
assert(size->bottom_type()->is_long(), "Should be long");
|
assert(size->bottom_type()->is_long(), "Should be long");
|
||||||
|
|
||||||
// The native clone we are calling here expects the instance size in words
|
// The native clone we are calling here expects the instance size in words
|
||||||
// Add header/offset size to payload size to get instance size.
|
// Add header/offset size to payload size to get instance size.
|
||||||
Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(false) >> LogBytesPerLong);
|
Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(ac->is_clone_array()) >> LogBytesPerLong);
|
||||||
Node* const full_size = phase->transform_later(new AddLNode(size, base_offset));
|
Node* const full_size = phase->transform_later(new AddLNode(size, base_offset));
|
||||||
|
|
||||||
Node* const call = phase->make_leaf_call(ctrl,
|
Node* const call = phase->make_leaf_call(ctrl,
|
||||||
|
|
|
@ -23,21 +23,33 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8155643 8268125 8270461
|
* @bug 8155643 8268125 8270461 8270098
|
||||||
* @summary Test Object.clone() intrinsic.
|
* @summary Test Object.clone() intrinsic.
|
||||||
|
* @modules java.base/java.lang:+open
|
||||||
*
|
*
|
||||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
|
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
|
||||||
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||||
|
* -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
|
||||||
* compiler.arraycopy.TestObjectArrayClone
|
* compiler.arraycopy.TestObjectArrayClone
|
||||||
* @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
* @run main/othervm -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||||
|
* -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
|
||||||
* compiler.arraycopy.TestObjectArrayClone
|
* compiler.arraycopy.TestObjectArrayClone
|
||||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedClassPointers -Xmx128m
|
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedClassPointers -Xmx128m
|
||||||
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||||
|
* -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
|
||||||
|
* compiler.arraycopy.TestObjectArrayClone
|
||||||
|
* @run main/othervm -Xbatch -XX:-UseTypeProfile
|
||||||
|
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||||
|
* -XX:CompileCommand=compileonly,jdk.internal.reflect.GeneratedMethodAccessor*::invoke
|
||||||
* compiler.arraycopy.TestObjectArrayClone
|
* compiler.arraycopy.TestObjectArrayClone
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package compiler.arraycopy;
|
package compiler.arraycopy;
|
||||||
|
|
||||||
|
import java.lang.invoke.*;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
class Payload implements Cloneable {
|
class Payload implements Cloneable {
|
||||||
boolean b;
|
boolean b;
|
||||||
int i;
|
int i;
|
||||||
|
@ -136,6 +148,17 @@ public class TestObjectArrayClone {
|
||||||
return arr.clone();
|
return arr.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] testCloneShortObjectArray2(Method clone) throws Exception {
|
||||||
|
String[] arr = new String[5];
|
||||||
|
arr[0] = str1;
|
||||||
|
arr[1] = str2;
|
||||||
|
arr[2] = str3;
|
||||||
|
arr[3] = str4;
|
||||||
|
arr[4] = str5;
|
||||||
|
escape_arr = arr;
|
||||||
|
return (String[]) testCloneObject(clone, arr);
|
||||||
|
}
|
||||||
|
|
||||||
public static String[] testCloneShortObjectArrayCopy() {
|
public static String[] testCloneShortObjectArrayCopy() {
|
||||||
String[] arr = new String[5];
|
String[] arr = new String[5];
|
||||||
arr[0] = str1;
|
arr[0] = str1;
|
||||||
|
@ -161,7 +184,14 @@ public class TestObjectArrayClone {
|
||||||
return p.clonep();
|
return p.clonep();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static Object testCloneObject(Method clone, Object obj) throws Exception {
|
||||||
|
return clone.invoke(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Method clone = Object.class.getDeclaredMethod("clone");
|
||||||
|
clone.setAccessible(true);
|
||||||
|
|
||||||
String[] arr1 = new String[42];
|
String[] arr1 = new String[42];
|
||||||
for (int j = 0; j < arr1.length; j++) {
|
for (int j = 0; j < arr1.length; j++) {
|
||||||
arr1[j] = new String(Integer.toString(j));
|
arr1[j] = new String(Integer.toString(j));
|
||||||
|
@ -178,6 +208,20 @@ public class TestObjectArrayClone {
|
||||||
verifyStr(arr1, arr2);
|
verifyStr(arr1, arr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 50_000; i++) {
|
||||||
|
for (int j = 0; j < arr1.length; j++) {
|
||||||
|
arr1[j] = new String(Integer.toString(j));
|
||||||
|
}
|
||||||
|
String[] arr2 = (String[]) testCloneObject(clone, arr1);
|
||||||
|
verifyStr(arr1, arr2);
|
||||||
|
String[] arr3 = (String[]) testCloneObject(clone, arr1);
|
||||||
|
verifyStr(arr1, arr3);
|
||||||
|
String[] arr4 = (String[]) testCloneObject(clone, arr1);
|
||||||
|
verifyStr(arr1, arr4);
|
||||||
|
verifyStr(arr1, arr3);
|
||||||
|
verifyStr(arr1, arr2);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 50_000; i++) {
|
for (int i = 0; i < 50_000; i++) {
|
||||||
String[] value = testCloneShortObjectArray();
|
String[] value = testCloneShortObjectArray();
|
||||||
verifyStr(value, escape_arr);
|
verifyStr(value, escape_arr);
|
||||||
|
@ -185,6 +229,9 @@ public class TestObjectArrayClone {
|
||||||
verifyStr(value2, escape_arr);
|
verifyStr(value2, escape_arr);
|
||||||
String[] value3 = testCloneShortObjectArray();
|
String[] value3 = testCloneShortObjectArray();
|
||||||
verifyStr(value3, escape_arr);
|
verifyStr(value3, escape_arr);
|
||||||
|
String[] value4 = testCloneShortObjectArray2(clone);
|
||||||
|
verifyStr(value4, escape_arr);
|
||||||
|
verifyStr(value, value4);
|
||||||
verifyStr(value, value3);
|
verifyStr(value, value3);
|
||||||
verifyStr(value, value2);
|
verifyStr(value, value2);
|
||||||
}
|
}
|
||||||
|
@ -211,8 +258,21 @@ public class TestObjectArrayClone {
|
||||||
verifyStr(value, value2);
|
verifyStr(value, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int[] arr2 = new int[42];
|
||||||
|
for (int i = 0; i < arr2.length; i++) {
|
||||||
|
arr2[i] = i;
|
||||||
|
}
|
||||||
for (int i = 0; i < 50_000; i++) {
|
for (int i = 0; i < 50_000; i++) {
|
||||||
testClonePrimitiveArray(new int[42]);
|
int[] res1 = testClonePrimitiveArray(arr2);
|
||||||
|
int[] res2 = (int[])testCloneObject(clone, arr2);
|
||||||
|
for (int j = 0; j < arr2.length; j++) {
|
||||||
|
if (res1[j] != j) {
|
||||||
|
throw new RuntimeException("Unexpected result: " + res1[j] + " != " + j);
|
||||||
|
}
|
||||||
|
if (res2[j] != j) {
|
||||||
|
throw new RuntimeException("Unexpected result: " + res2[j] + " != " + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1);
|
Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1);
|
||||||
|
@ -227,6 +287,17 @@ public class TestObjectArrayClone {
|
||||||
verifyPayload(p1, p3);
|
verifyPayload(p1, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 50_000; i++) {
|
||||||
|
Payload p1 = (Payload) testCloneObject(clone, ref);
|
||||||
|
verifyPayload(ref, p1);
|
||||||
|
Payload p2 = (Payload) testCloneObject(clone, ref);
|
||||||
|
verifyPayload(ref, p2);
|
||||||
|
Payload p3 = (Payload) testCloneObject(clone, ref);
|
||||||
|
verifyPayload(ref, p3);
|
||||||
|
verifyPayload(p2, p3);
|
||||||
|
verifyPayload(p1, p3);
|
||||||
|
}
|
||||||
|
|
||||||
Payload2 ref2 = new Payload2(false, -1, 'c', str1, (short) 5, -1, false, 0, 'k', str2, (short)-1, 0);
|
Payload2 ref2 = new Payload2(false, -1, 'c', str1, (short) 5, -1, false, 0, 'k', str2, (short)-1, 0);
|
||||||
for (int i = 0; i < 50_000; i++) {
|
for (int i = 0; i < 50_000; i++) {
|
||||||
Payload2 p1 = (Payload2) testCloneOop2(ref2);
|
Payload2 p1 = (Payload2) testCloneOop2(ref2);
|
||||||
|
@ -238,6 +309,17 @@ public class TestObjectArrayClone {
|
||||||
verifyPayload2(p2, p3);
|
verifyPayload2(p2, p3);
|
||||||
verifyPayload2(p1, p3);
|
verifyPayload2(p1, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 50_000; i++) {
|
||||||
|
Payload2 p1 = (Payload2) testCloneObject(clone, ref2);
|
||||||
|
verifyPayload2(ref2, p1);
|
||||||
|
Payload2 p2 = (Payload2) testCloneObject(clone, ref2);
|
||||||
|
verifyPayload2(ref2, p2);
|
||||||
|
Payload2 p3 = (Payload2) testCloneObject(clone, ref2);
|
||||||
|
verifyPayload2(ref2, p3);
|
||||||
|
verifyPayload2(p2, p3);
|
||||||
|
verifyPayload2(p1, p3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void verifyPayload(Payload p1, Payload p2) {
|
public static void verifyPayload(Payload p1, Payload p2) {
|
||||||
|
@ -323,7 +405,6 @@ public class TestObjectArrayClone {
|
||||||
if (!arr1[i].equals(arr2[i])) {
|
if (!arr1[i].equals(arr2[i])) {
|
||||||
throw new RuntimeException("Fail cloned element content not the same");
|
throw new RuntimeException("Fail cloned element content not the same");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue