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_