Cache method lowering info in mir graph.

This should enable easy inlining checks. It should also
improve compilation time of methods that call the same
methods over and over - it is exactly such methods that
tend to exceed our 100ms time limit.

Change-Id: If01cd18e039071a74a1444570283c153429c9cd4
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
new file mode 100644
index 0000000..4580e76
--- /dev/null
+++ b/compiler/dex/mir_method_info.cc
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+# include "mir_method_info.h"
+
+#include "driver/compiler_driver.h"
+#include "driver/dex_compilation_unit.h"
+#include "driver/compiler_driver-inl.h"
+#include "mirror/class_loader.h"  // Only to allow casts in SirtRef<ClassLoader>.
+#include "mirror/dex_cache.h"     // Only to allow casts in SirtRef<DexCache>.
+#include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
+
+namespace art {
+
+void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver,
+                                    const DexCompilationUnit* mUnit,
+                                    MirMethodLoweringInfo* method_infos, size_t count) {
+  if (kIsDebugBuild) {
+    DCHECK(method_infos != nullptr);
+    DCHECK_NE(count, 0u);
+    for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
+      MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType());
+      if (it->target_dex_file_ != nullptr) {
+        unresolved.target_dex_file_ = it->target_dex_file_;
+        unresolved.target_method_idx_ = it->target_method_idx_;
+      }
+      DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0);
+    }
+  }
+
+  // We're going to resolve methods and check access in a tight loop. It's better to hold
+  // the lock and needed references once than re-acquiring them again and again.
+  ScopedObjectAccess soa(Thread::Current());
+  SirtRef<mirror::DexCache> dex_cache(soa.Self(), compiler_driver->GetDexCache(mUnit));
+  SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
+      compiler_driver->GetClassLoader(soa, mUnit));
+  SirtRef<mirror::Class> referrer_class(soa.Self(),
+      compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit));
+  // Even if the referrer class is unresolved (i.e. we're compiling a method without class
+  // definition) we still want to resolve methods and record all available info.
+
+  for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
+    // Remember devirtualized invoke target and set the called method to the default.
+    MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
+    MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
+    it->target_dex_file_ = mUnit->GetDexFile();
+    it->target_method_idx_ = it->MethodIndex();
+
+    InvokeType invoke_type = it->GetInvokeType();
+    mirror::ArtMethod* resolved_method =
+        compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(),
+                                       invoke_type);
+    if (UNLIKELY(resolved_method == nullptr)) {
+      continue;
+    }
+    compiler_driver->GetResolvedMethodDexFileLocation(resolved_method,
+        &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_);
+    it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
+
+    MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex());
+    int fast_path_flags = compiler_driver->IsFastInvoke(
+        soa, dex_cache, class_loader, mUnit, referrer_class.get(), resolved_method, &invoke_type,
+        &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
+    uint16_t other_flags = it->flags_ & ~kFlagFastPath & ~(kInvokeTypeMask << kBitSharpTypeBegin);
+    it->flags_ = other_flags |
+        (fast_path_flags != 0 ? kFlagFastPath : 0u) |
+        (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin);
+    it->target_dex_file_ = target_method.dex_file;
+    it->target_method_idx_ = target_method.dex_method_index;
+    it->stats_flags_ = fast_path_flags;
+  }
+}
+
+}  // namespace art