Skip to content

Commit e2803ed

Browse files
committed
8231055: C2: arraycopy with same non escaping src and dest but different positions causes wrong execution
Reviewed-by: thartmann, vlivanov
1 parent 12c278c commit e2803ed

File tree

2 files changed

+62
-17
lines changed

2 files changed

+62
-17
lines changed

src/hotspot/share/opto/macro.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -357,19 +357,38 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
357357
if (ac->modifies(offset, offset, &_igvn, true)) {
358358
assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result");
359359
uint shift = exact_log2(type2aelembytes(bt));
360-
Node* diff = _igvn.transform(new SubINode(ac->in(ArrayCopyNode::SrcPos), ac->in(ArrayCopyNode::DestPos)));
360+
Node* src_pos = ac->in(ArrayCopyNode::SrcPos);
361+
Node* dest_pos = ac->in(ArrayCopyNode::DestPos);
362+
const TypeInt* src_pos_t = _igvn.type(src_pos)->is_int();
363+
const TypeInt* dest_pos_t = _igvn.type(dest_pos)->is_int();
364+
365+
Node* adr = NULL;
366+
const TypePtr* adr_type = NULL;
367+
if (src_pos_t->is_con() && dest_pos_t->is_con()) {
368+
intptr_t off = ((src_pos_t->get_con() - dest_pos_t->get_con()) << shift) + offset;
369+
Node* base = ac->in(ArrayCopyNode::Src);
370+
adr = _igvn.transform(new AddPNode(base, base, MakeConX(off)));
371+
adr_type = _igvn.type(base)->is_ptr()->add_offset(off);
372+
if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) {
373+
// Don't emit a new load from src if src == dst but try to get the value from memory instead
374+
return value_from_mem(ac->in(TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr(), alloc);
375+
}
376+
} else {
377+
Node* diff = _igvn.transform(new SubINode(ac->in(ArrayCopyNode::SrcPos), ac->in(ArrayCopyNode::DestPos)));
361378
#ifdef _LP64
362-
diff = _igvn.transform(new ConvI2LNode(diff));
379+
diff = _igvn.transform(new ConvI2LNode(diff));
363380
#endif
364-
diff = _igvn.transform(new LShiftXNode(diff, intcon(shift)));
365-
366-
Node* off = _igvn.transform(new AddXNode(MakeConX(offset), diff));
367-
Node* base = ac->in(ArrayCopyNode::Src);
368-
Node* adr = _igvn.transform(new AddPNode(base, base, off));
369-
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
370-
if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) {
371-
// Don't emit a new load from src if src == dst but try to get the value from memory instead
372-
return value_from_mem(ac->in(TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr(), alloc);
381+
diff = _igvn.transform(new LShiftXNode(diff, intcon(shift)));
382+
383+
Node* off = _igvn.transform(new AddXNode(MakeConX(offset), diff));
384+
Node* base = ac->in(ArrayCopyNode::Src);
385+
adr = _igvn.transform(new AddPNode(base, base, off));
386+
adr_type = _igvn.type(base)->is_ptr()->add_offset(Type::OffsetBot);
387+
if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) {
388+
// Non constant offset in the array: we can't statically
389+
// determine the value
390+
return NULL;
391+
}
373392
}
374393
res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl);
375394
}

test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8229016
26+
* @bug 8229016 8231055
2727
* @summary Test correct elimination of array allocation with arraycopy to itself.
2828
* @library /test/lib
2929
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test
@@ -39,7 +39,7 @@ public class TestSelfArrayCopy {
3939
private static final int rI1 = Utils.getRandomInstance().nextInt();
4040
private static final int rI2 = Utils.getRandomInstance().nextInt();
4141

42-
private static int test() {
42+
private static int test1() {
4343
// Non-escaping allocation
4444
Integer[] array = {rI1, rI2};
4545
// Arraycopy with src == dst
@@ -51,14 +51,40 @@ private static int test() {
5151
return array[0] + array[1];
5252
}
5353

54+
private static int test2() {
55+
// Non-escaping allocation
56+
Integer[] array = {rI1, rI2};
57+
// Arraycopy with src == dst
58+
System.arraycopy(array, 0, array, 1, 1);
59+
if (b) {
60+
// Uncommon trap
61+
System.out.println(array[0]);
62+
}
63+
return array[0] + array[1];
64+
}
65+
5466
public static void main(String[] args) {
55-
int expected = rI1 + rI2;
67+
int expected1 = rI1 + rI2;
68+
int expected2 = rI1 + rI1;
5669
// Trigger compilation
5770
for (int i = 0; i < 20_000; ++i) {
58-
int result = test();
59-
if (result != expected) {
60-
throw new RuntimeException("Incorrect result: " + result + " != " + expected);
71+
int result = test1();
72+
if (result != expected1) {
73+
throw new RuntimeException("Incorrect result: " + result + " != " + expected1);
6174
}
75+
result = test2();
76+
if (result != expected2) {
77+
throw new RuntimeException("Incorrect result: " + result + " != " + expected2);
78+
}
79+
}
80+
b = true;
81+
int result = test1();
82+
if (result != expected1) {
83+
throw new RuntimeException("Incorrect result: " + result + " != " + expected1);
84+
}
85+
result = test2();
86+
if (result != expected2) {
87+
throw new RuntimeException("Incorrect result: " + result + " != " + expected2);
6288
}
6389
}
6490
}

0 commit comments

Comments
 (0)