summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2016-07-07 12:07:42 +0100
committerNicolas Geoffray <ngeoffray@google.com>2016-07-08 15:17:56 +0100
commitb198b013ae7bd2da85e007414fc028cd51a13883 (patch)
tree68e03f732bac2c04305dfac3004fcfc47cd8b223 /compiler
parent5e99abdef2c9a581d5a3f16b1aeb8b0391e1f91b (diff)
downloadart-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.cc15
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc14
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc17
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()) {