summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Roland Levillain <rpl@google.com> 2016-02-09 12:49:18 +0000
committer Roland Levillain <rpl@google.com> 2016-02-09 12:49:18 +0000
commitca0bf0349f8da35b284df49732e30eeb62591034 (patch)
tree5275be61f01748fc01137147740a19b30f2142a6
parentf637d80872d418fc62ee1d40b19e1f5a676d1399 (diff)
Fix ARM64 Baker's read barrier fast path for ArraySet.
Do not exhaust the pool of scratch (temporary) registers gratuitously when emitting an instrumented array load with a large constant index. Bug: 26817006 Bug: 12687968 Change-Id: I65a4fe676aa3c9e2c8d7e26195d9af6432c83ff9
-rw-r--r--compiler/optimizing/code_generator_arm64.cc14
-rw-r--r--test/572-checker-array-get-regression/expected.txt1
-rw-r--r--test/572-checker-array-get-regression/info.txt3
-rw-r--r--test/572-checker-array-get-regression/src/Main.java60
4 files changed, 70 insertions, 8 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index e20e04400f..cfdf6b18cd 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4880,20 +4880,18 @@ void CodeGeneratorARM64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction*
static_assert(
sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t),
"art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
- temp2 = temps.AcquireW();
// /* HeapReference<Object> */ ref =
// *(obj + offset + index * sizeof(HeapReference<Object>))
- MemOperand source = HeapOperand(obj);
+ const size_t shift_amount = Primitive::ComponentSizeShift(type);
if (index.IsConstant()) {
- uint32_t computed_offset =
- offset + (Int64ConstantFrom(index) << Primitive::ComponentSizeShift(type));
- source = HeapOperand(obj, computed_offset);
+ uint32_t computed_offset = offset + (Int64ConstantFrom(index) << shift_amount);
+ Load(type, ref_reg, HeapOperand(obj, computed_offset));
} else {
+ temp2 = temps.AcquireW();
__ Add(temp2, obj, offset);
- source = HeapOperand(temp2, XRegisterFrom(index), LSL, Primitive::ComponentSizeShift(type));
+ Load(type, ref_reg, HeapOperand(temp2, XRegisterFrom(index), LSL, shift_amount));
+ temps.Release(temp2);
}
- Load(type, ref_reg, source);
- temps.Release(temp2);
} else {
// /* HeapReference<Object> */ ref = *(obj + offset)
MemOperand field = HeapOperand(obj, offset);
diff --git a/test/572-checker-array-get-regression/expected.txt b/test/572-checker-array-get-regression/expected.txt
new file mode 100644
index 0000000000..c08d7831c0
--- /dev/null
+++ b/test/572-checker-array-get-regression/expected.txt
@@ -0,0 +1 @@
+1048575
diff --git a/test/572-checker-array-get-regression/info.txt b/test/572-checker-array-get-regression/info.txt
new file mode 100644
index 0000000000..023d5b0c19
--- /dev/null
+++ b/test/572-checker-array-get-regression/info.txt
@@ -0,0 +1,3 @@
+Regression test for the ARM64 Baker's read barrier fast path compiler
+instrumentatin of array loads with a large constant index, where we
+used to require too many scratch (temporary) registers.
diff --git a/test/572-checker-array-get-regression/src/Main.java b/test/572-checker-array-get-regression/src/Main.java
new file mode 100644
index 0000000000..bc13af9683
--- /dev/null
+++ b/test/572-checker-array-get-regression/src/Main.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+
+ public static void main(String[] args) {
+ System.out.println(test().intValue());
+ }
+
+ /// CHECK-START: java.lang.Integer Main.test() ssa_builder (after)
+ /// CHECK-DAG: <<Method:j\d+>> CurrentMethod
+ /// CHECK-DAG: <<Const2P20:i\d+>> IntConstant 1048576
+ /// CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1
+ /// CHECK-DAG: <<Array:l\d+>> NewArray [<<Const2P20>>,<<Method>>]
+ /// CHECK-DAG: <<NullCheck1:l\d+>> NullCheck [<<Array>>]
+ /// CHECK-DAG: <<Length1:i\d+>> ArrayLength [<<NullCheck1>>]
+ /// CHECK-DAG: <<Index:i\d+>> Add [<<Length1>>,<<ConstM1>>]
+ /// CHECK-DAG: <<NullCheck2:l\d+>> NullCheck [<<Array>>]
+ /// CHECK-DAG: <<Length2:i\d+>> ArrayLength [<<NullCheck2>>]
+ /// CHECK-DAG: <<BoundsCheck:i\d+>> BoundsCheck [<<Index>>,<<Length2>>]
+ /// CHECK-DAG: <<LastElement:l\d+>> ArrayGet [<<NullCheck2>>,<<BoundsCheck>>]
+ /// CHECK-DAG: Return [<<LastElement>>]
+
+ /// CHECK-START: java.lang.Integer Main.test() register (before)
+ /// CHECK-DAG: <<Method:j\d+>> CurrentMethod
+ /// CHECK-DAG: <<Const2P20:i\d+>> IntConstant 1048576
+ /// CHECK-DAG: <<Const2P20M1:i\d+>> IntConstant 1048575
+ /// CHECK-DAG: <<Array:l\d+>> NewArray [<<Const2P20>>,<<Method>>]
+ /// CHECK-DAG: <<LastElement:l\d+>> ArrayGet [<<Array>>,<<Const2P20M1>>]
+ /// CHECK-DAG: Return [<<LastElement>>]
+
+ public static Integer test() {
+ Integer[] integers = new Integer[1024 * 1024];
+ initIntegerArray(integers);
+ // Array load with a large constant index (after constant folding
+ // and bounds check elimination).
+ Integer last_integer = integers[integers.length - 1];
+ return last_integer;
+ }
+
+ public static void initIntegerArray(Integer[] integers) {
+ for (int i = 0; i < integers.length; ++i) {
+ integers[i] = new Integer(i);
+ }
+ }
+
+}