Ensure inlined static calls perform clinit checks in Optimizing.

Calls to static methods have implicit class initialization
(clinit) checks of the method's declaring class in
Optimizing.  However, when such a static call is inlined,
the implicit clinit check vanishes, possibly leading to an
incorrect behavior.

To ensure that inlining static methods does not change the
behavior of a program, add explicit class initialization
checks (art::HClinitCheck) as well as load class
instructions (art::HLoadClass) as last input of static
calls (art::HInvokeStaticOrDirect) in Optimizing' control
flow graphs, when the declaring class is reachable and not
known to be already initialized.  Then when considering the
inlining of a static method call, proceed only if the method
has no implicit clinit check requirement.

The added explicit clinit checks are already removed by the
art::PrepareForRegisterAllocation visitor.  This CL also
extends this visitor to turn explicit clinit checks from
static invokes into implicit ones after the inlining step,
by removing the added art::HLoadClass nodes mentioned
hereinbefore.

Change-Id: I9ba452b8bd09ae1fdd9a3797ef556e3e7e19c651
diff --git a/test/476-clinit-check-inlining-static-invoke/src/Main.java b/test/476-clinit-check-inlining-static-invoke/src/Main.java
new file mode 100644
index 0000000..a7d3bcd
--- /dev/null
+++ b/test/476-clinit-check-inlining-static-invoke/src/Main.java
@@ -0,0 +1,47 @@
+/*
+ * 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 main(String[] args) {
+    checkClinitCheckBeforeStaticMethodInvoke();
+  }
+
+  static void checkClinitCheckBeforeStaticMethodInvoke() {
+    System.out.println("checkClinitCheckBeforeStaticMethodInvoke START");
+
+    // Call static method to cause implicit class initialization, even
+    // if it is inlined.
+    ClassWithClinit.$opt$inline$StaticMethod();
+    if (!classWithClinitInitialized) {
+      System.out.println("checkClinitCheckBeforeStaticMethodInvoke FAILED");
+      return;
+    }
+
+    System.out.println("checkClinitCheckBeforeStaticMethodInvoke PASSED");
+  }
+
+  static class ClassWithClinit {
+    static {
+      Main.classWithClinitInitialized = true;
+    }
+
+    static void $opt$inline$StaticMethod() {
+    }
+  }
+
+  static boolean classWithClinitInitialized = false;
+}