Use compiling class instead of outer class for access checks.

bug:21869678

(cherry picked from commit afd06414598e011693137ba044e38756609b2179)

Change-Id: I982ccdf46e3f4d0cc1901439e0bc2dcfa0fc661f
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 2858c50..1a5f27c 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -682,26 +682,29 @@
       const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
       Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
           outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
-      Handle<mirror::Class> referrer_class(hs.NewHandle(GetOutermostCompilingClass()));
+      Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
 
       // The index at which the method's class is stored in the DexCache's type array.
       uint32_t storage_index = DexFile::kDexNoIndex;
-      bool is_referrer_class = (resolved_method->GetDeclaringClass() == referrer_class.Get());
-      if (is_referrer_class) {
-        storage_index = referrer_class->GetDexTypeIndex();
+      bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
+      if (is_outer_class) {
+        storage_index = outer_class->GetDexTypeIndex();
       } else if (outer_dex_cache.Get() == dex_cache.Get()) {
         // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer.
         compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(),
-                                                                   referrer_class.Get(),
+                                                                   GetCompilingClass(),
                                                                    resolved_method,
                                                                    method_idx,
                                                                    &storage_index);
       }
 
-      if (referrer_class.Get()->IsSubClass(resolved_method->GetDeclaringClass())) {
-        // If the referrer class is the declaring class or a subclass
+      if (outer_class.Get()->IsSubClass(resolved_method->GetDeclaringClass())) {
+        // If the outer class is the declaring class or a subclass
         // of the declaring class, no class initialization is needed
         // before the static method call.
+        // Note that in case of inlining, we do not need to add clinit checks
+        // to calls that satisfy this subclass check with any inlined methods. This
+        // will be detected by the optimization passes.
         clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
       } else if (storage_index != DexFile::kDexNoIndex) {
         // If the method's class type index is available, check
@@ -719,7 +722,7 @@
         } else {
           clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
           HLoadClass* load_class =
-              new (arena_) HLoadClass(storage_index, is_referrer_class, dex_pc);
+              new (arena_) HLoadClass(storage_index, is_outer_class, dex_pc);
           current_block_->AddInstruction(load_class);
           clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
           current_block_->AddInstruction(clinit_check);
@@ -892,9 +895,9 @@
       soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
   Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
       soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
-  Handle<mirror::Class> compiling_class(hs.NewHandle(GetOutermostCompilingClass()));
+  Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
 
-  return compiling_class.Get() == cls.Get();
+  return outer_class.Get() == cls.Get();
 }
 
 bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
diff --git a/test/508-referrer-method/expected.txt b/test/508-referrer-method/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/508-referrer-method/expected.txt
diff --git a/test/508-referrer-method/info.txt b/test/508-referrer-method/info.txt
new file mode 100644
index 0000000..5f533e7
--- /dev/null
+++ b/test/508-referrer-method/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimizing compiler, which used
+to do incorrect access checks on static calls when inlining.
diff --git a/test/508-referrer-method/src/Main.java b/test/508-referrer-method/src/Main.java
new file mode 100644
index 0000000..07b25e4
--- /dev/null
+++ b/test/508-referrer-method/src/Main.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+// Main needs to be a subclass that has access to the
+// protected p1.PackagePrivateA.method.
+public class Main extends p1.PublicC {
+  public static void main(String[] args) {
+    int result = p1.InPackage.$inline$method();
+    if (result != 42) {
+      throw new Error("Expected 42, got " + result);
+    }
+  }
+}
diff --git a/test/508-referrer-method/src/p1/InPackage.java b/test/508-referrer-method/src/p1/InPackage.java
new file mode 100644
index 0000000..84c7d25
--- /dev/null
+++ b/test/508-referrer-method/src/p1/InPackage.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package p1;
+
+public class InPackage {
+  public static int $inline$method() {
+    // Call must be through a public subclass of the holder
+    // of the protected method, so that the Main class also has
+    // access to it.
+    return PublicB.method();
+  }
+}
diff --git a/test/508-referrer-method/src/p1/PackagePrivateA.java b/test/508-referrer-method/src/p1/PackagePrivateA.java
new file mode 100644
index 0000000..af8cfe8
--- /dev/null
+++ b/test/508-referrer-method/src/p1/PackagePrivateA.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+package p1;
+
+class PackagePrivateA {
+  protected static int method() {
+    return 42;
+  }
+}
diff --git a/test/508-referrer-method/src/p1/PublicB.java b/test/508-referrer-method/src/p1/PublicB.java
new file mode 100644
index 0000000..58e9304
--- /dev/null
+++ b/test/508-referrer-method/src/p1/PublicB.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package p1;
+
+public class PublicB extends PackagePrivateA {
+}
diff --git a/test/508-referrer-method/src/p1/PublicC.java b/test/508-referrer-method/src/p1/PublicC.java
new file mode 100644
index 0000000..d68e93b
--- /dev/null
+++ b/test/508-referrer-method/src/p1/PublicC.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package p1;
+
+public class PublicC extends PackagePrivateA {
+}