OSDN Git Service

ART: DCE should know that array-length can throw NPE
authorSerguei Katkov <serguei.i.katkov@intel.com>
Tue, 14 Jul 2015 13:04:48 +0000 (19:04 +0600)
committerVladimir Marko <vmarko@google.com>
Thu, 16 Jul 2015 12:41:44 +0000 (13:41 +0100)
array-length can throw NPE so it should be taking into account.

Bug: 22521944
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
(cherry picked from commit b016c6dd3c30b04104a0a43dc294ce93e5f63874)

Change-Id: I6232430a02f9e6d156ad2aae0eb5a630118c0e79

compiler/dex/gvn_dead_code_elimination.cc
compiler/dex/gvn_dead_code_elimination_test.cc
test/140-dce-regression/expected.txt [new file with mode: 0644]
test/140-dce-regression/info.txt [new file with mode: 0644]
test/140-dce-regression/src/Main.java [new file with mode: 0644]

index b1f5d87..044989e 100644 (file)
@@ -1192,7 +1192,6 @@ bool GvnDeadCodeElimination::RecordMIR(MIR* mir) {
     case Instruction::CONST_WIDE_32:
     case Instruction::CONST_WIDE:
     case Instruction::CONST_WIDE_HIGH16:
-    case Instruction::ARRAY_LENGTH:
     case Instruction::CMPL_FLOAT:
     case Instruction::CMPG_FLOAT:
     case Instruction::CMPL_DOUBLE:
@@ -1316,6 +1315,13 @@ bool GvnDeadCodeElimination::RecordMIR(MIR* mir) {
       }
       break;
 
+    case Instruction::ARRAY_LENGTH:
+      if ((mir->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0) {
+        must_keep = true;
+        uses_all_vregs = true;
+      }
+      break;
+
     case Instruction::AGET_OBJECT:
     case Instruction::AGET:
     case Instruction::AGET_WIDE:
index 461c844..6ba91b6 100644 (file)
@@ -2066,4 +2066,31 @@ TEST_F(GvnDeadCodeEliminationTestSimple, UnusedRegs2) {
   }
 }
 
+TEST_F(GvnDeadCodeEliminationTestSimple, ArrayLengthThrows) {
+  static const MIRDef mirs[] = {
+      DEF_CONST(3, Instruction::CONST, 0u, 0),              // null
+      DEF_UNOP(3, Instruction::ARRAY_LENGTH, 1u, 0u),       // null.length
+      DEF_CONST(3, Instruction::CONST, 2u, 1000u),          // Overwrite the array-length dest.
+  };
+
+  static const int32_t sreg_to_vreg_map[] = { 0, 1, 1 };
+  PrepareSRegToVRegMap(sreg_to_vreg_map);
+
+  PrepareMIRs(mirs);
+  PerformGVN_DCE();
+
+  ASSERT_EQ(arraysize(mirs), value_names_.size());
+  static const size_t diff_indexes[] = { 0, 1, 2 };
+  ExpectValueNamesNE(diff_indexes);
+
+  static const bool eliminated[] = {
+      false, false, false,
+  };
+  static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
+  for (size_t i = 0; i != arraysize(eliminated); ++i) {
+    bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
+    EXPECT_EQ(eliminated[i], actually_eliminated) << i;
+  }
+}
+
 }  // namespace art
diff --git a/test/140-dce-regression/expected.txt b/test/140-dce-regression/expected.txt
new file mode 100644 (file)
index 0000000..863339f
--- /dev/null
@@ -0,0 +1 @@
+Passed
diff --git a/test/140-dce-regression/info.txt b/test/140-dce-regression/info.txt
new file mode 100644 (file)
index 0000000..de6ad34
--- /dev/null
@@ -0,0 +1 @@
+Regression test for quick dead code elimination.
diff --git a/test/140-dce-regression/src/Main.java b/test/140-dce-regression/src/Main.java
new file mode 100644 (file)
index 0000000..f255029
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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 testArrayLength() {
+      int[] arr = null;
+      int len = 0;
+      try {
+        len = arr.length;
+        len = 5;
+      } catch (NullPointerException npe) {
+        System.out.println("Passed");
+      }
+    }
+
+    public static void main(String[] args) {
+      testArrayLength();
+    }
+}