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.h b/compiler/dex/mir_method_info.h
new file mode 100644
index 0000000..a43238c
--- /dev/null
+++ b/compiler/dex/mir_method_info.h
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_COMPILER_DEX_MIR_METHOD_INFO_H_
+#define ART_COMPILER_DEX_MIR_METHOD_INFO_H_
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "invoke_type.h"
+#include "method_reference.h"
+
+namespace art {
+
+class CompilerDriver;
+class DexCompilationUnit;
+class DexFile;
+
+class MirMethodInfo {
+ public:
+  uint16_t MethodIndex() const {
+    return method_idx_;
+  }
+
+  bool IsStatic() const {
+    return (flags_ & kFlagIsStatic) != 0u;
+  }
+
+  bool IsResolved() const {
+    return declaring_dex_file_ != nullptr;
+  }
+
+  const DexFile* DeclaringDexFile() const {
+    return declaring_dex_file_;
+  }
+
+  uint16_t DeclaringClassIndex() const {
+    return declaring_class_idx_;
+  }
+
+  uint16_t DeclaringMethodIndex() const {
+    return declaring_method_idx_;
+  }
+
+ protected:
+  enum {
+    kBitIsStatic = 0,
+    kMethodInfoBitEnd
+  };
+  COMPILE_ASSERT(kMethodInfoBitEnd <= 16, too_many_flags);
+  static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
+
+  MirMethodInfo(uint16_t method_idx, uint16_t flags)
+      : method_idx_(method_idx),
+        flags_(flags),
+        declaring_method_idx_(0u),
+        declaring_class_idx_(0u),
+        declaring_dex_file_(nullptr) {
+  }
+
+  // Make copy-ctor/assign/dtor protected to avoid slicing.
+  MirMethodInfo(const MirMethodInfo& other) = default;
+  MirMethodInfo& operator=(const MirMethodInfo& other) = default;
+  ~MirMethodInfo() = default;
+
+  // The method index in the compiling method's dex file.
+  uint16_t method_idx_;
+  // Flags, for volatility and derived class data.
+  uint16_t flags_;
+  // The method index in the dex file that defines the method, 0 if unresolved.
+  uint16_t declaring_method_idx_;
+  // The type index of the class declaring the method, 0 if unresolved.
+  uint16_t declaring_class_idx_;
+  // The dex file that defines the class containing the method and the method,
+  // nullptr if unresolved.
+  const DexFile* declaring_dex_file_;
+};
+
+class MirMethodLoweringInfo : public MirMethodInfo {
+ public:
+  // For each requested method retrieve the method's declaring location (dex file, class
+  // index and method index) and compute whether we can fast path the method call. For fast
+  // path methods, retrieve the method's vtable index and direct code and method when applicable.
+  static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
+                      MirMethodLoweringInfo* method_infos, size_t count)
+      LOCKS_EXCLUDED(Locks::mutator_lock_);
+
+  MirMethodLoweringInfo(uint16_t method_idx, InvokeType type)
+      : MirMethodInfo(method_idx,
+                      ((type == kStatic) ? kFlagIsStatic : 0u) |
+                      (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
+                      (static_cast<uint16_t>(type) << kBitSharpTypeBegin)),
+        direct_code_(0u),
+        direct_method_(0u),
+        target_dex_file_(nullptr),
+        target_method_idx_(0u),
+        vtable_idx_(0u),
+        stats_flags_(0) {
+  }
+
+  void SetDevirtualizationTarget(const MethodReference& ref) {
+    DCHECK(target_dex_file_ == nullptr);
+    DCHECK_EQ(target_method_idx_, 0u);
+    DCHECK_LE(ref.dex_method_index, 0xffffu);
+    target_dex_file_ = ref.dex_file;
+    target_method_idx_ = ref.dex_method_index;
+  }
+
+  bool FastPath() const {
+    return (flags_ & kFlagFastPath) != 0u;
+  }
+
+  InvokeType GetInvokeType() const {
+    return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
+  }
+
+  art::InvokeType GetSharpType() const {
+    return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
+  }
+
+  MethodReference GetTargetMethod() const {
+    return MethodReference(target_dex_file_, target_method_idx_);
+  }
+
+  uint16_t VTableIndex() const {
+    return vtable_idx_;
+  }
+
+  uintptr_t DirectCode() const {
+    return direct_code_;
+  }
+
+  uintptr_t DirectMethod() const {
+    return direct_method_;
+  }
+
+  int StatsFlags() const {
+    return stats_flags_;
+  }
+
+ private:
+  enum {
+    kBitFastPath = kMethodInfoBitEnd,
+    kBitInvokeTypeBegin,
+    kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3,  // 3 bits for invoke type.
+    kBitSharpTypeBegin,
+    kBitSharpTypeEnd = kBitSharpTypeBegin + 3,  // 3 bits for sharp type.
+    kMethodLoweringInfoEnd = kBitSharpTypeEnd
+  };
+  COMPILE_ASSERT(kMethodLoweringInfoEnd <= 16, too_many_flags);
+  static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
+  static constexpr uint16_t kInvokeTypeMask = 7u;
+  COMPILE_ASSERT((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
+                 assert_invoke_type_bits_ok);
+  COMPILE_ASSERT((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
+                 assert_sharp_type_bits_ok);
+
+  uintptr_t direct_code_;
+  uintptr_t direct_method_;
+  // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
+  // devirtualized invoke target if available, nullptr and 0u otherwise.
+  // After Resolve() they hold the actual target method that will be called; it will be either
+  // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
+  const DexFile* target_dex_file_;
+  uint16_t target_method_idx_;
+  uint16_t vtable_idx_;
+  int stats_flags_;
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_MIR_METHOD_INFO_H_