diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2016-07-07 12:07:42 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2016-07-08 15:17:56 +0100 |
commit | b198b013ae7bd2da85e007414fc028cd51a13883 (patch) | |
tree | 68e03f732bac2c04305dfac3004fcfc47cd8b223 /compiler | |
parent | 5e99abdef2c9a581d5a3f16b1aeb8b0391e1f91b (diff) | |
download | art-b198b013ae7bd2da85e007414fc028cd51a13883.tar.gz art-b198b013ae7bd2da85e007414fc028cd51a13883.tar.bz2 art-b198b013ae7bd2da85e007414fc028cd51a13883.zip |
Fix System.arraycopy when doing same array copying.
At compile time, if constant source < constant destination, and we don't
know if the arrays are the same, then we must emit code that checks
if the two arrays are the same. If so, we jump to the slow path.
test:610-arraycopy
bug:30030084
(cherry picked from commit 9f65db89353c46f6b189656f7f55a99054e5cfce)
Change-Id:Ida67993d472b0ba4056d9c21c68f6e5239421f7d
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 15 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 17 |
3 files changed, 31 insertions, 15 deletions
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 86b7bc138c..6c253adc2d 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -1397,20 +1397,26 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { Label conditions_on_positions_validated; SystemArrayCopyOptimizations optimizations(invoke); - if (!optimizations.GetDestinationIsSource() && - (!src_pos.IsConstant() || !dest_pos.IsConstant())) { - __ cmp(src, ShifterOperand(dest)); - } // If source and destination are the same, we go to slow path if we need to do // forward copying. if (src_pos.IsConstant()) { int32_t src_pos_constant = src_pos.GetConstant()->AsIntConstant()->GetValue(); if (dest_pos.IsConstant()) { + int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue(); + if (optimizations.GetDestinationIsSource()) { + // Checked when building locations. + DCHECK_GE(src_pos_constant, dest_pos_constant); + } else if (src_pos_constant < dest_pos_constant) { + __ cmp(src, ShifterOperand(dest)); + __ b(slow_path->GetEntryLabel(), EQ); + } + // Checked when building locations. DCHECK(!optimizations.GetDestinationIsSource() || (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue())); } else { if (!optimizations.GetDestinationIsSource()) { + __ cmp(src, ShifterOperand(dest)); __ b(&conditions_on_positions_validated, NE); } __ cmp(dest_pos.AsRegister<Register>(), ShifterOperand(src_pos_constant)); @@ -1418,6 +1424,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { } } else { if (!optimizations.GetDestinationIsSource()) { + __ cmp(src, ShifterOperand(dest)); __ b(&conditions_on_positions_validated, NE); } if (dest_pos.IsConstant()) { diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 04ae3a6732..696fa5254f 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -2017,20 +2017,25 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) { vixl::Label conditions_on_positions_validated; SystemArrayCopyOptimizations optimizations(invoke); - if (!optimizations.GetDestinationIsSource() && - (!src_pos.IsConstant() || !dest_pos.IsConstant())) { - __ Cmp(src, dest); - } // If source and destination are the same, we go to slow path if we need to do // forward copying. if (src_pos.IsConstant()) { int32_t src_pos_constant = src_pos.GetConstant()->AsIntConstant()->GetValue(); if (dest_pos.IsConstant()) { + int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue(); + if (optimizations.GetDestinationIsSource()) { + // Checked when building locations. + DCHECK_GE(src_pos_constant, dest_pos_constant); + } else if (src_pos_constant < dest_pos_constant) { + __ Cmp(src, dest); + __ B(slow_path->GetEntryLabel(), eq); + } // Checked when building locations. DCHECK(!optimizations.GetDestinationIsSource() || (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue())); } else { if (!optimizations.GetDestinationIsSource()) { + __ Cmp(src, dest); __ B(&conditions_on_positions_validated, ne); } __ Cmp(WRegisterFrom(dest_pos), src_pos_constant); @@ -2038,6 +2043,7 @@ void IntrinsicCodeGeneratorARM64::VisitSystemArrayCopy(HInvoke* invoke) { } } else { if (!optimizations.GetDestinationIsSource()) { + __ Cmp(src, dest); __ B(&conditions_on_positions_validated, ne); } __ Cmp(RegisterFrom(src_pos, invoke->InputAt(1)->GetType()), diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 1d32dc7bc5..f726a25fc1 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -1153,20 +1153,22 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { NearLabel conditions_on_positions_validated; SystemArrayCopyOptimizations optimizations(invoke); - if (!optimizations.GetDestinationIsSource() && - (!src_pos.IsConstant() || !dest_pos.IsConstant())) { - __ cmpl(src, dest); - } // If source and destination are the same, we go to slow path if we need to do // forward copying. if (src_pos.IsConstant()) { int32_t src_pos_constant = src_pos.GetConstant()->AsIntConstant()->GetValue(); if (dest_pos.IsConstant()) { - // Checked when building locations. - DCHECK(!optimizations.GetDestinationIsSource() - || (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue())); + int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue(); + if (optimizations.GetDestinationIsSource()) { + // Checked when building locations. + DCHECK_GE(src_pos_constant, dest_pos_constant); + } else if (src_pos_constant < dest_pos_constant) { + __ cmpl(src, dest); + __ j(kEqual, slow_path->GetEntryLabel()); + } } else { if (!optimizations.GetDestinationIsSource()) { + __ cmpl(src, dest); __ j(kNotEqual, &conditions_on_positions_validated); } __ cmpl(dest_pos.AsRegister<CpuRegister>(), Immediate(src_pos_constant)); @@ -1174,6 +1176,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { } } else { if (!optimizations.GetDestinationIsSource()) { + __ cmpl(src, dest); __ j(kNotEqual, &conditions_on_positions_validated); } if (dest_pos.IsConstant()) { |