8268125: ZGC: Clone oop array gets wrong acopy stub
Reviewed-by: kvn, vlivanov
This commit is contained in:
parent
9f3c7e74ff
commit
d384093289
@ -852,3 +852,5 @@ void BarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac
|
||||
|
||||
phase->igvn().replace_node(ac, call);
|
||||
}
|
||||
|
||||
#undef XTOP
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/regalloc.hpp"
|
||||
#include "opto/rootnode.hpp"
|
||||
#include "opto/runtime.hpp"
|
||||
#include "opto/type.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
@ -253,11 +254,51 @@ static const TypeFunc* clone_type() {
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
#define XTOP LP64_ONLY(COMMA phase->top())
|
||||
|
||||
void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
|
||||
Node* const src = ac->in(ArrayCopyNode::Src);
|
||||
|
||||
if (ac->is_clone_array()) {
|
||||
// Clone primitive array
|
||||
BarrierSetC2::clone_at_expansion(phase, ac);
|
||||
const TypeAryPtr* ary_ptr = src->get_ptr_type()->isa_aryptr();
|
||||
BasicType bt;
|
||||
if (ary_ptr == NULL) {
|
||||
// ary_ptr can be null iff we are running with StressReflectiveCode
|
||||
// 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)) {
|
||||
// Clone object array
|
||||
bt = T_OBJECT;
|
||||
} else {
|
||||
// Clone primitive array
|
||||
bt = T_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
Node* ctrl = ac->in(TypeFunc::Control);
|
||||
Node* mem = ac->in(TypeFunc::Memory);
|
||||
Node* src = ac->in(ArrayCopyNode::Src);
|
||||
Node* src_offset = ac->in(ArrayCopyNode::SrcPos);
|
||||
Node* dest = ac->in(ArrayCopyNode::Dest);
|
||||
Node* dest_offset = ac->in(ArrayCopyNode::DestPos);
|
||||
Node* length = ac->in(ArrayCopyNode::Length);
|
||||
|
||||
Node* payload_src = phase->basic_plus_adr(src, src_offset);
|
||||
Node* payload_dst = phase->basic_plus_adr(dest, dest_offset);
|
||||
|
||||
const char* copyfunc_name = "arraycopy";
|
||||
address copyfunc_addr = phase->basictype2arraycopy(bt, NULL, NULL, true, copyfunc_name, true);
|
||||
|
||||
const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
|
||||
const TypeFunc* call_type = OptoRuntime::fast_arraycopy_Type();
|
||||
|
||||
Node* call = phase->make_leaf_call(ctrl, mem, call_type, copyfunc_addr, copyfunc_name, raw_adr_type, payload_src, payload_dst, length XTOP);
|
||||
phase->transform_later(call);
|
||||
|
||||
phase->igvn().replace_node(ac, call);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -289,6 +330,8 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a
|
||||
phase->igvn().replace_node(ac, call);
|
||||
}
|
||||
|
||||
#undef XTOP
|
||||
|
||||
// == Dominating barrier elision ==
|
||||
|
||||
static bool block_has_safepoint(const Block* block, uint from, uint to) {
|
||||
|
@ -4117,6 +4117,8 @@ bool LibraryCallKit::inline_unsafe_copyMemory() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef XTOP
|
||||
|
||||
//------------------------clone_coping-----------------------------------
|
||||
// Helper function for inline_native_clone.
|
||||
void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array) {
|
||||
|
@ -1224,6 +1224,8 @@ bool PhaseMacroExpand::generate_unchecked_arraycopy(Node** ctrl, MergeMemNode**
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef XTOP
|
||||
|
||||
void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||
Node* ctrl = ac->in(TypeFunc::Control);
|
||||
Node* io = ac->in(TypeFunc::I_O);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2021, 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
|
||||
@ -26,21 +26,304 @@
|
||||
* @bug 8155643
|
||||
* @summary Test Object.clone() intrinsic if ReduceInitialCardMarks is disabled.
|
||||
*
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-ReduceInitialCardMarks
|
||||
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::test
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-ReduceInitialCardMarks
|
||||
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||
* compiler.arraycopy.TestObjectArrayClone
|
||||
*
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions
|
||||
* -XX:CompileCommand=compileonly,compiler.arraycopy.TestObjectArrayClone::testClone*
|
||||
* compiler.arraycopy.TestObjectArrayClone
|
||||
*/
|
||||
|
||||
package compiler.arraycopy;
|
||||
|
||||
public class TestObjectArrayClone {
|
||||
class Payload implements Cloneable {
|
||||
boolean b;
|
||||
int i;
|
||||
char c;
|
||||
String str;
|
||||
short s;
|
||||
int i2;
|
||||
|
||||
public static TestObjectArrayClone[] test(TestObjectArrayClone[] arr) {
|
||||
return arr.clone();
|
||||
public Payload(boolean b, int i, char c, String str, short s, int i2) {
|
||||
super();
|
||||
this.b = b;
|
||||
this.i = i;
|
||||
this.c = c;
|
||||
this.str = str;
|
||||
this.s = s;
|
||||
this.i2 = i2;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(new TestObjectArrayClone[42]);
|
||||
public Payload clonep() {
|
||||
try {
|
||||
return (Payload) super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Payload2 implements Cloneable {
|
||||
boolean b;
|
||||
int i;
|
||||
char c;
|
||||
String str;
|
||||
short s;
|
||||
int i2;
|
||||
boolean b2;
|
||||
int i3;
|
||||
char c2;
|
||||
String str2;
|
||||
short s2;
|
||||
int i4;
|
||||
|
||||
public Payload2(boolean b, int i, char c, String str, short s, int i2, boolean b2, int i3, char c2, String str2,
|
||||
short s2, int i4) {
|
||||
super();
|
||||
this.b = b;
|
||||
this.i = i;
|
||||
this.c = c;
|
||||
this.str = str;
|
||||
this.s = s;
|
||||
this.i2 = i2;
|
||||
this.b2 = b2;
|
||||
this.i3 = i3;
|
||||
this.c2 = c2;
|
||||
this.str2 = str2;
|
||||
this.s2 = s2;
|
||||
this.i4 = i4;
|
||||
}
|
||||
|
||||
public Payload2 clonep() {
|
||||
try {
|
||||
return (Payload2) super.clone();
|
||||
} catch(CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestObjectArrayClone {
|
||||
|
||||
public static String[] escape_arr;
|
||||
|
||||
public static String str1 = new String("1");
|
||||
public static String str2 = new String("2");
|
||||
public static String str3 = new String("3");
|
||||
public static String str4 = new String("4");
|
||||
public static String str5 = new String("5");
|
||||
|
||||
public static String[] testCloneObjectArray(String[] arr) {
|
||||
return arr.clone();
|
||||
}
|
||||
|
||||
public static String[] testCloneObjectArrayCopy(String[] arr) {
|
||||
String[] arr2 = new String[arr.length];
|
||||
System.arraycopy(arr, 0, arr2, 0, arr.length);
|
||||
return arr2;
|
||||
}
|
||||
|
||||
public static String[] testCloneShortObjectArray() {
|
||||
String[] arr = new String[5];
|
||||
arr[0] = str1;
|
||||
arr[1] = str2;
|
||||
arr[2] = str3;
|
||||
arr[3] = str4;
|
||||
arr[4] = str5;
|
||||
escape_arr = arr;
|
||||
return arr.clone();
|
||||
}
|
||||
|
||||
public static String[] testCloneShortObjectArrayCopy() {
|
||||
String[] arr = new String[5];
|
||||
arr[0] = str1;
|
||||
arr[1] = str2;
|
||||
arr[2] = str3;
|
||||
arr[3] = str4;
|
||||
arr[4] = str5;
|
||||
escape_arr = arr;
|
||||
String[] arr2 = new String[arr.length];
|
||||
System.arraycopy(arr, 0, arr2, 0, arr.length);
|
||||
return arr2;
|
||||
}
|
||||
|
||||
public static int[] testClonePrimitiveArray(int[] arr) {
|
||||
return arr.clone();
|
||||
}
|
||||
|
||||
public static Object testCloneOop(Payload p) {
|
||||
return p.clonep();
|
||||
}
|
||||
|
||||
public static Object testCloneOop2(Payload2 p) {
|
||||
return p.clonep();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String[] arr1 = new String[42];
|
||||
for (int j = 0; j < arr1.length; j++) {
|
||||
arr1[j] = new String(Integer.toString(j));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
String[] arr2 = testCloneObjectArray(arr1);
|
||||
verifyStr(arr1, arr2);
|
||||
String[] arr3 = testCloneObjectArray(arr1);
|
||||
verifyStr(arr1, arr3);
|
||||
String[] arr4 = testCloneObjectArray(arr1);
|
||||
verifyStr(arr1, arr4);
|
||||
verifyStr(arr1, arr3);
|
||||
verifyStr(arr1, arr2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
String[] value = testCloneShortObjectArray();
|
||||
verifyStr(value, escape_arr);
|
||||
String[] value2 = testCloneShortObjectArray();
|
||||
verifyStr(value2, escape_arr);
|
||||
String[] value3 = testCloneShortObjectArray();
|
||||
verifyStr(value3, escape_arr);
|
||||
verifyStr(value, value3);
|
||||
verifyStr(value, value2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
String[] arr2 = testCloneObjectArrayCopy(arr1);
|
||||
verifyStr(arr1, arr2);
|
||||
String[] arr3 = testCloneObjectArrayCopy(arr1);
|
||||
verifyStr(arr1, arr3);
|
||||
String[] arr4 = testCloneObjectArrayCopy(arr1);
|
||||
verifyStr(arr1, arr4);
|
||||
verifyStr(arr1, arr3);
|
||||
verifyStr(arr1, arr2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
String[] value = testCloneShortObjectArrayCopy();
|
||||
verifyStr(value, escape_arr);
|
||||
String[] value2 = testCloneShortObjectArrayCopy();
|
||||
verifyStr(value2, escape_arr);
|
||||
String[] value3 = testCloneShortObjectArrayCopy();
|
||||
verifyStr(value3, escape_arr);
|
||||
verifyStr(value, value3);
|
||||
verifyStr(value, value2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
testClonePrimitiveArray(new int[42]);
|
||||
}
|
||||
|
||||
Payload ref = new Payload(false, -1, 'c', str1, (short) 5, -1);
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
Payload p1 = (Payload) testCloneOop(ref);
|
||||
verifyPayload(ref, p1);
|
||||
Payload p2 = (Payload) testCloneOop(ref);
|
||||
verifyPayload(ref, p2);
|
||||
Payload p3 = (Payload) testCloneOop(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);
|
||||
for (int i = 0; i < 50_000; i++) {
|
||||
Payload2 p1 = (Payload2) testCloneOop2(ref2);
|
||||
verifyPayload2(ref2, p1);
|
||||
Payload2 p2 = (Payload2) testCloneOop2(ref2);
|
||||
verifyPayload2(ref2, p2);
|
||||
Payload2 p3 = (Payload2) testCloneOop2(ref2);
|
||||
verifyPayload2(ref2, p3);
|
||||
verifyPayload2(p2, p3);
|
||||
verifyPayload2(p1, p3);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyPayload(Payload p1, Payload p2) {
|
||||
if (p1.b != p2.b) {
|
||||
throw new RuntimeException("b is wrong");
|
||||
}
|
||||
if (p1.c != p2.c) {
|
||||
throw new RuntimeException("c is wrong");
|
||||
}
|
||||
if (p1.i != p2.i) {
|
||||
throw new RuntimeException("i is wrong");
|
||||
}
|
||||
if (p1.s != p2.s) {
|
||||
throw new RuntimeException("s is wrong");
|
||||
}
|
||||
if (p1.i2 != p2.i2) {
|
||||
throw new RuntimeException("i2 is wrong");
|
||||
}
|
||||
if (p1.str != p2.str) {
|
||||
throw new RuntimeException("str is wrong");
|
||||
}
|
||||
if (!p1.str.equals(p2.str)) {
|
||||
throw new RuntimeException("str content is wrong");
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyPayload2(Payload2 p1, Payload2 p2) {
|
||||
if (p1.b != p2.b) {
|
||||
throw new RuntimeException("b is wrong");
|
||||
}
|
||||
if (p1.c != p2.c) {
|
||||
throw new RuntimeException("c is wrong");
|
||||
}
|
||||
if (p1.i != p2.i) {
|
||||
throw new RuntimeException("i is wrong");
|
||||
}
|
||||
if (p1.s != p2.s) {
|
||||
throw new RuntimeException("s is wrong");
|
||||
}
|
||||
if (p1.i2 != p2.i2) {
|
||||
throw new RuntimeException("i2 is wrong");
|
||||
}
|
||||
if (p1.str != p2.str) {
|
||||
throw new RuntimeException("str is wrong");
|
||||
}
|
||||
if (!p1.str.equals(p2.str)) {
|
||||
throw new RuntimeException("str content is wrong");
|
||||
}
|
||||
if (p1.b2 != p2.b2) {
|
||||
throw new RuntimeException("b is wrong");
|
||||
}
|
||||
if (p1.c2 != p2.c2) {
|
||||
throw new RuntimeException("c is wrong");
|
||||
}
|
||||
if (p1.i3 != p2.i3) {
|
||||
throw new RuntimeException("i is wrong");
|
||||
}
|
||||
if (p1.s2 != p2.s2) {
|
||||
throw new RuntimeException("s is wrong");
|
||||
}
|
||||
if (p1.i4 != p2.i4) {
|
||||
throw new RuntimeException("i2 is wrong");
|
||||
}
|
||||
if (p1.str2 != p2.str2) {
|
||||
throw new RuntimeException("str is wrong");
|
||||
}
|
||||
if (!p1.str2.equals(p2.str2)) {
|
||||
throw new RuntimeException("str content is wrong");
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyStr(String[] arr1, String[] arr2) {
|
||||
if (arr1 == arr2) {
|
||||
throw new RuntimeException("Must not be the same");
|
||||
}
|
||||
if (arr1.length != arr2.length) {
|
||||
throw new RuntimeException("Must have the same length");
|
||||
}
|
||||
for (int i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] != arr2[i]) {
|
||||
throw new RuntimeException("Fail cloned element not the same: " + i);
|
||||
}
|
||||
if (!arr1[i].equals(arr2[i])) {
|
||||
throw new RuntimeException("Fail cloned element content not the same");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user