1 /*
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 
26 namespace art {
27 
28 class CompilerDriver;
29 class DexCompilationUnit;
30 class DexFile;
31 
32 class MirMethodInfo {
33  public:
MethodIndex()34   uint16_t MethodIndex() const {
35     return method_idx_;
36   }
37 
IsStatic()38   bool IsStatic() const {
39     return (flags_ & kFlagIsStatic) != 0u;
40   }
41 
IsResolved()42   bool IsResolved() const {
43     return declaring_dex_file_ != nullptr;
44   }
45 
DeclaringDexFile()46   const DexFile* DeclaringDexFile() const {
47     return declaring_dex_file_;
48   }
SetDeclaringDexFile(const DexFile * dex_file)49   void SetDeclaringDexFile(const DexFile* dex_file) {
50     declaring_dex_file_ = dex_file;
51   }
52 
DeclaringClassIndex()53   uint16_t DeclaringClassIndex() const {
54     return declaring_class_idx_;
55   }
56 
DeclaringMethodIndex()57   uint16_t DeclaringMethodIndex() const {
58     return declaring_method_idx_;
59   }
60 
61  protected:
62   enum {
63     kBitIsStatic = 0,
64     kMethodInfoBitEnd
65   };
66   static_assert(kMethodInfoBitEnd <= 16, "Too many flags");
67   static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
68 
MirMethodInfo(uint16_t method_idx,uint16_t flags)69   MirMethodInfo(uint16_t method_idx, uint16_t flags)
70       : method_idx_(method_idx),
71         flags_(flags),
72         declaring_method_idx_(0u),
73         declaring_class_idx_(0u),
74         declaring_dex_file_(nullptr) {
75   }
76 
77   // Make copy-ctor/assign/dtor protected to avoid slicing.
78   MirMethodInfo(const MirMethodInfo& other) = default;
79   MirMethodInfo& operator=(const MirMethodInfo& other) = default;
80   ~MirMethodInfo() = default;
81 
82   // The method index in the compiling method's dex file.
83   uint16_t method_idx_;
84   // Flags, for volatility and derived class data.
85   uint16_t flags_;
86   // The method index in the dex file that defines the method, 0 if unresolved.
87   uint16_t declaring_method_idx_;
88   // The type index of the class declaring the method, 0 if unresolved.
89   uint16_t declaring_class_idx_;
90   // The dex file that defines the class containing the method and the method,
91   // null if unresolved.
92   const DexFile* declaring_dex_file_;
93 };
94 
95 class MirMethodLoweringInfo : public MirMethodInfo {
96  public:
97   // For each requested method retrieve the method's declaring location (dex file, class
98   // index and method index) and compute whether we can fast path the method call. For fast
99   // path methods, retrieve the method's vtable index and direct code and method when applicable.
100   static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
101                       MirMethodLoweringInfo* method_infos, size_t count)
102       LOCKS_EXCLUDED(Locks::mutator_lock_);
103 
MirMethodLoweringInfo(uint16_t method_idx,InvokeType type,bool is_quickened)104   MirMethodLoweringInfo(uint16_t method_idx, InvokeType type, bool is_quickened)
105       : MirMethodInfo(method_idx,
106                       ((type == kStatic) ? kFlagIsStatic : 0u) |
107                       (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
108                       (static_cast<uint16_t>(type) << kBitSharpTypeBegin) |
109                       (is_quickened ? kFlagQuickened : 0u)),
110         direct_code_(0u),
111         direct_method_(0u),
112         target_dex_file_(nullptr),
113         target_method_idx_(0u),
114         vtable_idx_(0u),
115         stats_flags_(0) {
116   }
117 
SetDevirtualizationTarget(const MethodReference & ref)118   void SetDevirtualizationTarget(const MethodReference& ref) {
119     DCHECK(target_dex_file_ == nullptr);
120     DCHECK_EQ(target_method_idx_, 0u);
121     DCHECK_LE(ref.dex_method_index, 0xffffu);
122     target_dex_file_ = ref.dex_file;
123     target_method_idx_ = ref.dex_method_index;
124   }
125 
FastPath()126   bool FastPath() const {
127     return (flags_ & kFlagFastPath) != 0u;
128   }
129 
IsIntrinsic()130   bool IsIntrinsic() const {
131     return (flags_ & kFlagIsIntrinsic) != 0u;
132   }
133 
IsSpecial()134   bool IsSpecial() const {
135     return (flags_ & kFlagIsSpecial) != 0u;
136   }
137 
IsReferrersClass()138   bool IsReferrersClass() const {
139     return (flags_ & kFlagIsReferrersClass) != 0;
140   }
141 
IsClassInitialized()142   bool IsClassInitialized() const {
143     return (flags_ & kFlagClassIsInitialized) != 0u;
144   }
145 
146   // Returns true iff the method invoke is INVOKE_VIRTUAL_QUICK or INVOKE_VIRTUAL_RANGE_QUICK.
IsQuickened()147   bool IsQuickened() const {
148     return (flags_ & kFlagQuickened) != 0u;
149   }
150 
GetInvokeType()151   InvokeType GetInvokeType() const {
152     return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
153   }
154 
GetSharpType()155   art::InvokeType GetSharpType() const {
156     return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
157   }
158 
GetTargetMethod()159   MethodReference GetTargetMethod() const {
160     return MethodReference(target_dex_file_, target_method_idx_);
161   }
162 
VTableIndex()163   uint16_t VTableIndex() const {
164     return vtable_idx_;
165   }
SetVTableIndex(uint16_t index)166   void SetVTableIndex(uint16_t index) {
167     vtable_idx_ = index;
168   }
169 
DirectCode()170   uintptr_t DirectCode() const {
171     return direct_code_;
172   }
173 
DirectMethod()174   uintptr_t DirectMethod() const {
175     return direct_method_;
176   }
177 
StatsFlags()178   int StatsFlags() const {
179     return stats_flags_;
180   }
181 
CheckEquals(const MirMethodLoweringInfo & info)182   void CheckEquals(const MirMethodLoweringInfo& info) const {
183     CHECK_EQ(method_idx_, info.method_idx_);
184     CHECK_EQ(flags_, info.flags_);
185     CHECK_EQ(declaring_method_idx_, info.declaring_method_idx_);
186     CHECK_EQ(declaring_class_idx_, info.declaring_class_idx_);
187     CHECK_EQ(declaring_dex_file_, info.declaring_dex_file_);
188     CHECK_EQ(direct_code_, info.direct_code_);
189     CHECK_EQ(direct_method_, info.direct_method_);
190     CHECK_EQ(target_dex_file_, info.target_dex_file_);
191     CHECK_EQ(target_method_idx_, info.target_method_idx_);
192     CHECK_EQ(vtable_idx_, info.vtable_idx_);
193     CHECK_EQ(stats_flags_, info.stats_flags_);
194   }
195 
196  private:
197   enum {
198     kBitFastPath = kMethodInfoBitEnd,
199     kBitIsIntrinsic,
200     kBitIsSpecial,
201     kBitInvokeTypeBegin,
202     kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3,  // 3 bits for invoke type.
203     kBitSharpTypeBegin = kBitInvokeTypeEnd,
204     kBitSharpTypeEnd = kBitSharpTypeBegin + 3,  // 3 bits for sharp type.
205     kBitIsReferrersClass = kBitSharpTypeEnd,
206     kBitClassIsInitialized,
207     kBitQuickened,
208     kMethodLoweringInfoBitEnd
209   };
210   static_assert(kMethodLoweringInfoBitEnd <= 16, "Too many flags");
211   static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
212   static constexpr uint16_t kFlagIsIntrinsic = 1u << kBitIsIntrinsic;
213   static constexpr uint16_t kFlagIsSpecial = 1u << kBitIsSpecial;
214   static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
215   static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
216   static constexpr uint16_t kFlagQuickened = 1u << kBitQuickened;
217   static constexpr uint16_t kInvokeTypeMask = 7u;
218   static_assert((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
219                 "assert invoke type bits failed");
220   static_assert((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
221                 "assert sharp type bits failed");
222 
223   uintptr_t direct_code_;
224   uintptr_t direct_method_;
225   // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
226   // devirtualized invoke target if available, null and 0u otherwise.
227   // After Resolve() they hold the actual target method that will be called; it will be either
228   // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
229   const DexFile* target_dex_file_;
230   uint16_t target_method_idx_;
231   uint16_t vtable_idx_;
232   int stats_flags_;
233 
234   friend class MirOptimizationTest;
235   friend class TypeInferenceTest;
236 };
237 
238 }  // namespace art
239 
240 #endif  // ART_COMPILER_DEX_MIR_METHOD_INFO_H_
241