Merge "Fix OOM throwing if it happens in finalizer reference (take 2)"
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 6631009..23c3b39 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -480,38 +480,36 @@
   bool is_instance_call = invoke_type != kStatic;
   const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);
 
-  HInvoke* invoke = nullptr;
-  if (invoke_type == kVirtual || invoke_type == kInterface || invoke_type == kSuper) {
-    MethodReference target_method(dex_file_, method_idx);
-    uintptr_t direct_code;
-    uintptr_t direct_method;
-    int table_index;
-    InvokeType optimized_invoke_type = invoke_type;
-    compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc, true, true,
-                                        &optimized_invoke_type, &target_method, &table_index,
-                                        &direct_code, &direct_method);
-    if (table_index == -1) {
-      return false;
-    }
+  MethodReference target_method(dex_file_, method_idx);
+  uintptr_t direct_code;
+  uintptr_t direct_method;
+  int table_index;
+  InvokeType optimized_invoke_type = invoke_type;
 
-    if (optimized_invoke_type == kVirtual) {
-      invoke = new (arena_) HInvokeVirtual(
-          arena_, number_of_arguments, return_type, dex_pc, table_index);
-    } else if (optimized_invoke_type == kInterface) {
-      invoke = new (arena_) HInvokeInterface(
-          arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
-    } else if (optimized_invoke_type == kDirect) {
-      // For this compiler, sharpening only works if we compile PIC.
-      DCHECK(compiler_driver_->GetCompilerOptions().GetCompilePic());
-      // Treat invoke-direct like static calls for now.
-      invoke = new (arena_) HInvokeStatic(
-          arena_, number_of_arguments, return_type, dex_pc, target_method.dex_method_index);
-    }
+  if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc, true, true,
+                                           &optimized_invoke_type, &target_method, &table_index,
+                                           &direct_code, &direct_method)) {
+    LOG(INFO) << "Did not compile " << PrettyMethod(method_idx, *dex_file_)
+              << " because a method call could not be resolved";
+    return false;
+  }
+  DCHECK(optimized_invoke_type != kSuper);
+
+  HInvoke* invoke = nullptr;
+  if (optimized_invoke_type == kVirtual) {
+    invoke = new (arena_) HInvokeVirtual(
+        arena_, number_of_arguments, return_type, dex_pc, table_index);
+  } else if (optimized_invoke_type == kInterface) {
+    invoke = new (arena_) HInvokeInterface(
+        arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
   } else {
-    DCHECK(invoke_type == kDirect || invoke_type == kStatic);
+    DCHECK(optimized_invoke_type == kDirect || optimized_invoke_type == kStatic);
+    // Sharpening to kDirect only works if we compile PIC.
+    DCHECK((optimized_invoke_type == invoke_type) || (optimized_invoke_type != kDirect)
+           || compiler_driver_->GetCompilerOptions().GetCompilePic());
     // Treat invoke-direct like static calls for now.
     invoke = new (arena_) HInvokeStatic(
-        arena_, number_of_arguments, return_type, dex_pc, method_idx);
+        arena_, number_of_arguments, return_type, dex_pc, target_method.dex_method_index);
   }
 
   size_t start_index = 0;
diff --git a/test/434-invoke-direct/expected.txt b/test/434-invoke-direct/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/434-invoke-direct/expected.txt
diff --git a/test/434-invoke-direct/info.txt b/test/434-invoke-direct/info.txt
new file mode 100644
index 0000000..eae1ef0
--- /dev/null
+++ b/test/434-invoke-direct/info.txt
@@ -0,0 +1,2 @@
+Tests that IllegalAccessError is thrown when a subclass invokes-direct a
+private method from the super class.
diff --git a/test/434-invoke-direct/smali/invoke.smali b/test/434-invoke-direct/smali/invoke.smali
new file mode 100644
index 0000000..b3cdd1e
--- /dev/null
+++ b/test/434-invoke-direct/smali/invoke.smali
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2014 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 LInvokeDirect;
+.super LInvokeDirectSuper;
+
+.method public constructor <init>()V
+      .registers 2
+       invoke-direct {v1}, LInvokeDirectSuper;-><init>()V
+       return-void
+.end method
+
+.method public run()I
+       .registers 3
+       invoke-super {v2}, LInvokeDirectSuper;->privateMethod()I
+       move-result v0
+       return v0
+.end method
diff --git a/test/434-invoke-direct/src/InvokeDirectSuper.java b/test/434-invoke-direct/src/InvokeDirectSuper.java
new file mode 100644
index 0000000..c80a18b
--- /dev/null
+++ b/test/434-invoke-direct/src/InvokeDirectSuper.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 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 InvokeDirectSuper {
+  public int val;
+
+  private int privateMethod() {
+    return val;
+  }
+}
diff --git a/test/434-invoke-direct/src/Main.java b/test/434-invoke-direct/src/Main.java
new file mode 100644
index 0000000..c363e1a
--- /dev/null
+++ b/test/434-invoke-direct/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class Main {
+
+  public static void main(String[] args) throws Throwable {
+    $opt$InvokeDirect();
+  }
+
+  private static void $opt$InvokeDirect() throws Throwable {
+    try {
+      Class<?> c = Class.forName("InvokeDirect");
+      Method m = c.getMethod("run");
+      m.invoke(c.newInstance());
+      throw new RuntimeException("Failed to throw IllegalAccessError");
+    } catch (InvocationTargetException e) {
+      if (!(e.getCause() instanceof IllegalAccessError)) {
+        throw new RuntimeException("Failed to throw IllegalAccessError");
+      }
+    }
+  }
+
+}
+