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   }
49 
DeclaringClassIndex()50   uint16_t DeclaringClassIndex() const {
51     return declaring_class_idx_;
52   }
53 
DeclaringMethodIndex()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 
MirMethodInfo(uint16_t method_idx,uint16_t flags)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 
92 class 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 
MirMethodLoweringInfo(uint16_t method_idx,InvokeType type)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 
SetDevirtualizationTarget(const MethodReference & ref)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 
FastPath()122   bool FastPath() const {
123     return (flags_ & kFlagFastPath) != 0u;
124   }
125 
NeedsClassInitialization()126   bool NeedsClassInitialization() const {
127     return (flags_ & kFlagNeedsClassInitialization) != 0u;
128   }
129 
GetInvokeType()130   InvokeType GetInvokeType() const {
131     return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
132   }
133 
GetSharpType()134   art::InvokeType GetSharpType() const {
135     return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
136   }
137 
GetTargetMethod()138   MethodReference GetTargetMethod() const {
139     return MethodReference(target_dex_file_, target_method_idx_);
140   }
141 
VTableIndex()142   uint16_t VTableIndex() const {
143     return vtable_idx_;
144   }
145 
DirectCode()146   uintptr_t DirectCode() const {
147     return direct_code_;
148   }
149 
DirectMethod()150   uintptr_t DirectMethod() const {
151     return direct_method_;
152   }
153 
StatsFlags()154   int StatsFlags() const {
155     return stats_flags_;
156   }
157 
158  private:
159   enum {
160     kBitFastPath = kMethodInfoBitEnd,
161     kBitInvokeTypeBegin,
162     kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3,  // 3 bits for invoke type.
163     kBitSharpTypeBegin,
164     kBitSharpTypeEnd = kBitSharpTypeBegin + 3,  // 3 bits for sharp type.
165     kBitNeedsClassInitialization = kBitSharpTypeEnd,
166     kMethodLoweringInfoEnd
167   };
168   COMPILE_ASSERT(kMethodLoweringInfoEnd <= 16, too_many_flags);
169   static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
170   static constexpr uint16_t kFlagNeedsClassInitialization = 1u << kBitNeedsClassInitialization;
171   static constexpr uint16_t kInvokeTypeMask = 7u;
172   COMPILE_ASSERT((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
173                  assert_invoke_type_bits_ok);
174   COMPILE_ASSERT((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
175                  assert_sharp_type_bits_ok);
176 
177   uintptr_t direct_code_;
178   uintptr_t direct_method_;
179   // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
180   // devirtualized invoke target if available, nullptr and 0u otherwise.
181   // After Resolve() they hold the actual target method that will be called; it will be either
182   // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
183   const DexFile* target_dex_file_;
184   uint16_t target_method_idx_;
185   uint16_t vtable_idx_;
186   int stats_flags_;
187 
188   friend class ClassInitCheckEliminationTest;
189 };
190 
191 }  // namespace art
192 
193 #endif  // ART_COMPILER_DEX_MIR_METHOD_INFO_H_
194