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
Change-Id: Ida67993d472b0ba4056d9c21c68f6e5239421f7d
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index c5b44d4..5bd4964 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1103,20 +1103,22 @@
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));
@@ -1124,6 +1126,7 @@
}
} else {
if (!optimizations.GetDestinationIsSource()) {
+ __ cmpl(src, dest);
__ j(kNotEqual, &conditions_on_positions_validated);
}
if (dest_pos.IsConstant()) {