blob: e64b028a9ec182ab98f3dc83f5109c54f14c1c94 [file] [log] [blame]
Vladimir Markof096aad2014-01-23 15:51:58 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_DEX_MIR_METHOD_INFO_H_
18#define ART_COMPILER_DEX_MIR_METHOD_INFO_H_
19
20#include "base/logging.h"
21#include "base/macros.h"
22#include "base/mutex.h"
23#include "invoke_type.h"
24#include "method_reference.h"
25
26namespace art {
27
28class CompilerDriver;
29class DexCompilationUnit;
30class DexFile;
31
32class MirMethodInfo {
33 public:
34 uint16_t MethodIndex() const {
35 return method_idx_;
36 }
37
38 bool IsStatic() const {
39 return (flags_ & kFlagIsStatic) != 0u;
40 }
41
42 bool IsResolved() const {
43 return declaring_dex_file_ != nullptr;
44 }
45
46 const DexFile* DeclaringDexFile() const {
47 return declaring_dex_file_;
48 }
49
50 uint16_t DeclaringClassIndex() const {
51 return declaring_class_idx_;
52 }
53
54 uint16_t DeclaringMethodIndex() const {
55 return declaring_method_idx_;
56 }
57
58 protected:
59 enum {
60 kBitIsStatic = 0,
61 kMethodInfoBitEnd
62 };
63 COMPILE_ASSERT(kMethodInfoBitEnd <= 16, too_many_flags);
64 static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
65
66 MirMethodInfo(uint16_t method_idx, uint16_t flags)
67 : method_idx_(method_idx),
68 flags_(flags),
69 declaring_method_idx_(0u),
70 declaring_class_idx_(0u),
71 declaring_dex_file_(nullptr) {
72 }
73
74 // Make copy-ctor/assign/dtor protected to avoid slicing.
75 MirMethodInfo(const MirMethodInfo& other) = default;
76 MirMethodInfo& operator=(const MirMethodInfo& other) = default;
77 ~MirMethodInfo() = default;
78
79 // The method index in the compiling method's dex file.
80 uint16_t method_idx_;
81 // Flags, for volatility and derived class data.
82 uint16_t flags_;
83 // The method index in the dex file that defines the method, 0 if unresolved.
84 uint16_t declaring_method_idx_;
85 // The type index of the class declaring the method, 0 if unresolved.
86 uint16_t declaring_class_idx_;
87 // The dex file that defines the class containing the method and the method,
88 // nullptr if unresolved.
89 const DexFile* declaring_dex_file_;
90};
91
92class MirMethodLoweringInfo : public MirMethodInfo {
93 public:
94 // For each requested method retrieve the method's declaring location (dex file, class
95 // index and method index) and compute whether we can fast path the method call. For fast
96 // path methods, retrieve the method's vtable index and direct code and method when applicable.
97 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
98 MirMethodLoweringInfo* method_infos, size_t count)
99 LOCKS_EXCLUDED(Locks::mutator_lock_);
100
101 MirMethodLoweringInfo(uint16_t method_idx, InvokeType type)
102 : MirMethodInfo(method_idx,
103 ((type == kStatic) ? kFlagIsStatic : 0u) |
104 (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
105 (static_cast<uint16_t>(type) << kBitSharpTypeBegin)),
106 direct_code_(0u),
107 direct_method_(0u),
108 target_dex_file_(nullptr),
109 target_method_idx_(0u),
110 vtable_idx_(0u),
111 stats_flags_(0) {
112 }
113
114 void SetDevirtualizationTarget(const MethodReference& ref) {
115 DCHECK(target_dex_file_ == nullptr);
116 DCHECK_EQ(target_method_idx_, 0u);
117 DCHECK_LE(ref.dex_method_index, 0xffffu);
118 target_dex_file_ = ref.dex_file;
119 target_method_idx_ = ref.dex_method_index;
120 }
121
122 bool FastPath() const {
123 return (flags_ & kFlagFastPath) != 0u;
124 }
125
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100126 bool IsReferrersClass() const {
127 return (flags_ & kFlagIsReferrersClass) != 0;
128 }
129
130 bool IsClassInitialized() const {
131 return (flags_ & kFlagClassIsInitialized) != 0u;
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000132 }
133
Vladimir Markof096aad2014-01-23 15:51:58 +0000134 InvokeType GetInvokeType() const {
135 return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
136 }
137
138 art::InvokeType GetSharpType() const {
139 return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
140 }
141
142 MethodReference GetTargetMethod() const {
143 return MethodReference(target_dex_file_, target_method_idx_);
144 }
145
146 uint16_t VTableIndex() const {
147 return vtable_idx_;
148 }
149
150 uintptr_t DirectCode() const {
151 return direct_code_;
152 }
153
154 uintptr_t DirectMethod() const {
155 return direct_method_;
156 }
157
158 int StatsFlags() const {
159 return stats_flags_;
160 }
161
162 private:
163 enum {
164 kBitFastPath = kMethodInfoBitEnd,
165 kBitInvokeTypeBegin,
166 kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3, // 3 bits for invoke type.
167 kBitSharpTypeBegin,
168 kBitSharpTypeEnd = kBitSharpTypeBegin + 3, // 3 bits for sharp type.
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100169 kBitIsReferrersClass = kBitSharpTypeEnd,
170 kBitClassIsInitialized,
171 kMethodLoweringInfoBitEnd
Vladimir Markof096aad2014-01-23 15:51:58 +0000172 };
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100173 COMPILE_ASSERT(kMethodLoweringInfoBitEnd <= 16, too_many_flags);
Vladimir Markof096aad2014-01-23 15:51:58 +0000174 static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100175 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
176 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
Vladimir Markof096aad2014-01-23 15:51:58 +0000177 static constexpr uint16_t kInvokeTypeMask = 7u;
178 COMPILE_ASSERT((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
179 assert_invoke_type_bits_ok);
180 COMPILE_ASSERT((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
181 assert_sharp_type_bits_ok);
182
183 uintptr_t direct_code_;
184 uintptr_t direct_method_;
185 // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
186 // devirtualized invoke target if available, nullptr and 0u otherwise.
187 // After Resolve() they hold the actual target method that will be called; it will be either
188 // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
189 const DexFile* target_dex_file_;
190 uint16_t target_method_idx_;
191 uint16_t vtable_idx_;
192 int stats_flags_;
Vladimir Markobfea9c22014-01-17 17:49:33 +0000193
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100194 friend class MirOptimizationTest;
Vladimir Markof096aad2014-01-23 15:51:58 +0000195};
196
197} // namespace art
198
199#endif // ART_COMPILER_DEX_MIR_METHOD_INFO_H_