Merge "Revert^2: Deopt does not throw"
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index f784f8f..79bb70b 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -1916,15 +1916,6 @@
   }
 }
 
-bool HBasicBlock::HasThrowingInstructions() const {
-  for (HInstructionIterator it(GetInstructions()); !it.Done(); it.Advance()) {
-    if (it.Current()->CanThrow()) {
-      return true;
-    }
-  }
-  return false;
-}
-
 static bool HasOnlyOneInstruction(const HBasicBlock& block) {
   return block.GetPhis().IsEmpty()
       && !block.GetInstructions().IsEmpty()
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 79d7330..b315c81 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1272,8 +1272,6 @@
   // the appropriate try entry will be returned.
   const HTryBoundary* ComputeTryEntryOfSuccessors() const;
 
-  bool HasThrowingInstructions() const;
-
   // Returns whether this block dominates the blocked passed as parameter.
   bool Dominates(HBasicBlock* block) const;
 
@@ -2132,6 +2130,7 @@
         !CanThrow() &&
         !IsSuspendCheck() &&
         !IsControlFlow() &&
+        !IsDeoptimize() &&
         !IsNativeDebugInfo() &&
         !IsParameterValue() &&
         // If we added an explicit barrier then we should keep it.
@@ -3238,7 +3237,9 @@
 
   bool NeedsEnvironment() const OVERRIDE { return true; }
 
-  bool CanThrow() const OVERRIDE { return true; }
+  // Even though deoptimize is often used for "exceptional cases" to go back to
+  // the interpreter, it never throws an exception.
+  bool CanThrow() const OVERRIDE { return false; }
 
   DeoptimizationKind GetDeoptimizationKind() const { return GetPackedField<DeoptimizeKindField>(); }
 
diff --git a/test/683-deopt-regression/expected.txt b/test/683-deopt-regression/expected.txt
new file mode 100644
index 0000000..b0aad4d
--- /dev/null
+++ b/test/683-deopt-regression/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/683-deopt-regression/info.txt b/test/683-deopt-regression/info.txt
new file mode 100644
index 0000000..0c2cb81
--- /dev/null
+++ b/test/683-deopt-regression/info.txt
@@ -0,0 +1 @@
+Regression test on deopt from BCE
diff --git a/test/683-deopt-regression/smali/Deopt.smali b/test/683-deopt-regression/smali/Deopt.smali
new file mode 100644
index 0000000..3bd9f6c
--- /dev/null
+++ b/test/683-deopt-regression/smali/Deopt.smali
@@ -0,0 +1,60 @@
+# Copyright (C) 2018 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.
+
+.class public LDeopt;
+
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+.registers 1
+    invoke-direct {v0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static testCase([I)I
+    .registers 8
+
+    const v0, 0x0          # counter
+    const v1, 0xF          # loop max
+    const v2, 0x0          # result
+
+    :try_start
+    # Something throwing to start the try block. v6 contains a reference.
+    move-object v6, p0
+    aget v3, p0, v0
+
+    # Invalidate v6 before entering the loop.
+    const-wide v5, 0x0
+
+    :loop_start
+    # Set v6 to a different reference (creates a catch phi).
+    const v6, 0x0
+
+    aget v3, p0, v0
+    add-int/2addr v2, v3
+    add-int/lit8 v0, v0, 0x1
+    if-lt v0, v1, :loop_start
+
+    :try_end
+    .catchall {:try_start .. :try_end} :catch
+
+    :exit
+    return v2
+
+    :catch
+    invoke-virtual {v6}, Ljava/lang/Object;->hashCode()I   # use v6 as a reference
+    goto :exit
+
+.end method
+
diff --git a/test/683-deopt-regression/src/Main.java b/test/683-deopt-regression/src/Main.java
new file mode 100644
index 0000000..326fe47
--- /dev/null
+++ b/test/683-deopt-regression/src/Main.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    if (System.getProperty("java.vm.name").equals("Dalvik")) {
+      Class<?> c = Class.forName("Deopt");
+      Method m = c.getMethod("testCase", int[].class);
+      int[] p = null;
+      try {
+        m.invoke(null, p);
+        System.out.println("should not reach");
+      } catch (Exception e) {
+        // Tried to invoke hashCode on incoming null.
+      }
+      int result;
+      int[] q = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+      result = ((Integer) m.invoke(null, q));
+      expectEquals(120, result);
+      int[] r = { };
+      result = ((Integer) m.invoke(null, r));
+      expectEquals(0, result);
+      int[] s = { 1 };
+      try {
+        m.invoke(null, s);
+        System.out.println("should not reach");
+      } catch (Exception e) {
+        // Tried to invoke hashCode on generated null.
+      }
+    }
+    System.out.println("passed");
+  }
+
+  private static void expectEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+}