xref: /aosp_15_r20/art/runtime/verifier/reg_type_cache.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2012 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_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
18 #define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
19 
20 #include <stdint.h>
21 #include <string_view>
22 #include <vector>
23 
24 #include "base/arena_containers.h"
25 #include "base/casts.h"
26 #include "base/macros.h"
27 #include "dex/primitive.h"
28 #include "gc_root.h"
29 #include "handle_scope.h"
30 #include "reg_type.h"
31 
32 namespace art HIDDEN {
33 
34 namespace mirror {
35 class Class;
36 class ClassLoader;
37 }  // namespace mirror
38 
39 class ClassLinker;
40 class DexFile;
41 
42 namespace verifier {
43 
44 class MethodVerifier;
45 
46 // Use 8 bytes since that is the default arena allocator alignment.
47 static constexpr size_t kDefaultArenaBitVectorBytes = 8;
48 
49 class RegTypeCache {
50  public:
51   EXPORT RegTypeCache(Thread* self,
52                       ClassLinker* class_linker,
53                       ArenaPool* arena_pool,
54                       Handle<mirror::ClassLoader> class_loader,
55                       const DexFile* dex_file,
56                       bool can_load_classes = true,
57                       bool can_suspend = true);
58 
GetClassLoader()59   Handle<mirror::ClassLoader> GetClassLoader() const {
60     return class_loader_;
61   }
62 
GetDexFile()63   const DexFile* GetDexFile() const {
64     return dex_file_;
65   }
66 
CanLoadClasses()67   bool CanLoadClasses() const {
68     return can_load_classes_;
69   }
70 
CanSuspend()71   bool CanSuspend() const {
72     return can_suspend_;
73   }
74 
NumberOfRegKindCacheIds()75   static constexpr uint32_t NumberOfRegKindCacheIds() { return kNumberOfRegKindCacheIds; }
76 
77   // Translate `RegType::Kind` to id for a pre-initialized register type.
78   // Cannot be used for non-zero reference kinds other than `JavaLangObject()`; all other
79   // kinds (undefined, conflict, primitive and constant kinds) have pre-initialized types.
80   static constexpr uint16_t IdForRegKind(RegType::Kind kind);
81 
82   // Translate `id` to `RegType::Kind`.
83   // The `id` must be lower than `NumberOfRegKindCacheIds()`.
84   static constexpr RegType::Kind RegKindForId(uint16_t id);
85 
86   // Get register type for a `RegType::Kind` with the same restrictions as `IdForRegKind()`.
87   const RegType& GetFromRegKind(RegType::Kind kind) const;
88 
89   const RegType& GetFromId(uint16_t id) const;
90   // Get or insert a reg type for a klass.
91   const RegType& FromClass(ObjPtr<mirror::Class> klass)
92       REQUIRES_SHARED(Locks::mutator_lock_);
93   const RegType& FromDescriptor(const char* descriptor)
94       REQUIRES_SHARED(Locks::mutator_lock_);
95   const RegType& FromUnresolvedMerge(const RegType& left,
96                                      const RegType& right,
97                                      MethodVerifier* verifier)
98       REQUIRES_SHARED(Locks::mutator_lock_);
99 
100   const RegType& FromTypeIndex(dex::TypeIndex type_index) REQUIRES_SHARED(Locks::mutator_lock_);
101 
102   // Note: this should not be used outside of RegType::ClassJoin!
103   const RegType& MakeUnresolvedReference() REQUIRES_SHARED(Locks::mutator_lock_);
104 
GetCacheSize()105   size_t GetCacheSize() {
106     return entries_.size();
107   }
108 
109   const UndefinedType& Undefined() const REQUIRES_SHARED(Locks::mutator_lock_);
110   const ConflictType& Conflict() const;
111   const NullType& Null() const;
112 
113   const BooleanType& Boolean() const REQUIRES_SHARED(Locks::mutator_lock_);
114   const ByteType& Byte() const REQUIRES_SHARED(Locks::mutator_lock_);
115   const CharType& Char() const REQUIRES_SHARED(Locks::mutator_lock_);
116   const ShortType& Short() const REQUIRES_SHARED(Locks::mutator_lock_);
117   const IntegerType& Integer() const REQUIRES_SHARED(Locks::mutator_lock_);
118   const FloatType& Float() const REQUIRES_SHARED(Locks::mutator_lock_);
119   const LongLoType& LongLo() const REQUIRES_SHARED(Locks::mutator_lock_);
120   const LongHiType& LongHi() const REQUIRES_SHARED(Locks::mutator_lock_);
121   const DoubleLoType& DoubleLo() const REQUIRES_SHARED(Locks::mutator_lock_);
122   const DoubleHiType& DoubleHi() const REQUIRES_SHARED(Locks::mutator_lock_);
123 
124   const ZeroType& Zero() const REQUIRES_SHARED(Locks::mutator_lock_);
125   const BooleanConstantType& BooleanConstant() const REQUIRES_SHARED(Locks::mutator_lock_);
126   const ByteConstantType& ByteConstant() const REQUIRES_SHARED(Locks::mutator_lock_);
127   const CharConstantType& CharConstant() const REQUIRES_SHARED(Locks::mutator_lock_);
128   const ShortConstantType& ShortConstant() const REQUIRES_SHARED(Locks::mutator_lock_);
129   const IntegerConstantType& IntegerConstant() const REQUIRES_SHARED(Locks::mutator_lock_);
130   const PositiveByteConstantType& PositiveByteConstant() const
131       REQUIRES_SHARED(Locks::mutator_lock_);
132   const PositiveShortConstantType& PositiveShortConstant() const
133       REQUIRES_SHARED(Locks::mutator_lock_);
134   const ConstantLoType& ConstantLo() const REQUIRES_SHARED(Locks::mutator_lock_);
135   const ConstantHiType& ConstantHi() const REQUIRES_SHARED(Locks::mutator_lock_);
136 
137   const ReferenceType& JavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_);
138   const ReferenceType& JavaLangString() REQUIRES_SHARED(Locks::mutator_lock_);
139   const ReferenceType& JavaLangInvokeMethodHandle() REQUIRES_SHARED(Locks::mutator_lock_);
140   const ReferenceType& JavaLangInvokeMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
141   const ReferenceType& JavaLangThrowable() REQUIRES_SHARED(Locks::mutator_lock_);
142   const JavaLangObjectType& JavaLangObject() REQUIRES_SHARED(Locks::mutator_lock_);
143 
144   const UninitializedType& Uninitialized(const RegType& type)
145       REQUIRES_SHARED(Locks::mutator_lock_);
146   // Create an uninitialized 'this' argument for the given type.
147   const UninitializedType& UninitializedThisArgument(const RegType& type)
148       REQUIRES_SHARED(Locks::mutator_lock_);
149   const RegType& FromUninitialized(const RegType& uninit_type)
150       REQUIRES_SHARED(Locks::mutator_lock_);
151 
152   const RegType& GetComponentType(const RegType& array) REQUIRES_SHARED(Locks::mutator_lock_);
153   void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_);
154   const RegType& RegTypeFromPrimitiveType(Primitive::Type) const
155       REQUIRES_SHARED(Locks::mutator_lock_);
156 
GetClassLinker()157   ClassLinker* GetClassLinker() const {
158     return class_linker_;
159   }
160 
161   static constexpr uint32_t kUndefinedCacheId = 0;
162   static constexpr uint32_t kConflictCacheId = kUndefinedCacheId + 1u;
163   static constexpr uint32_t kBooleanCacheId = kConflictCacheId + 1u;
164   static constexpr uint32_t kByteCacheId = kBooleanCacheId + 1u;
165   static constexpr uint32_t kCharCacheId = kByteCacheId + 1u;
166   static constexpr uint32_t kShortCacheId = kCharCacheId + 1u;
167   static constexpr uint32_t kIntegerCacheId = kShortCacheId + 1u;
168   static constexpr uint32_t kLongLoCacheId = kIntegerCacheId + 1u;
169   static constexpr uint32_t kLongHiCacheId = kLongLoCacheId + 1u;
170   static constexpr uint32_t kFloatCacheId = kLongHiCacheId + 1u;
171   static constexpr uint32_t kDoubleLoCacheId = kFloatCacheId + 1u;
172   static constexpr uint32_t kDoubleHiCacheId = kDoubleLoCacheId + 1u;
173   static constexpr uint32_t kZeroCacheId = kDoubleHiCacheId + 1u;
174   static constexpr uint32_t kBooleanConstantCacheId = kZeroCacheId + 1u;
175   static constexpr uint32_t kPositiveByteConstantCacheId = kBooleanConstantCacheId + 1u;
176   static constexpr uint32_t kPositiveShortConstantCacheId = kPositiveByteConstantCacheId + 1u;
177   static constexpr uint32_t kCharConstantCacheId = kPositiveShortConstantCacheId + 1u;
178   static constexpr uint32_t kByteConstantCacheId = kCharConstantCacheId + 1u;
179   static constexpr uint32_t kShortConstantCacheId = kByteConstantCacheId + 1u;
180   static constexpr uint32_t kIntegerConstantCacheId = kShortConstantCacheId + 1u;
181   static constexpr uint32_t kConstantLoCacheId = kIntegerConstantCacheId + 1u;
182   static constexpr uint32_t kConstantHiCacheId = kConstantLoCacheId + 1u;
183   static constexpr uint32_t kNullCacheId = kConstantHiCacheId + 1u;
184   static constexpr uint32_t kJavaLangObjectCacheId = kNullCacheId + 1u;
185   static constexpr uint32_t kNumberOfRegKindCacheIds = kJavaLangObjectCacheId + 1u;
186 
187   static constexpr uint32_t kUninitializedJavaLangObjectCacheId = kNumberOfRegKindCacheIds;
188   static constexpr uint32_t kNumberOfFixedCacheIds = kUninitializedJavaLangObjectCacheId + 1u;
189 
190  private:
191   // We want 0 to mean an empty slot in `ids_for_type_index_`, so that we do not need to fill
192   // the array after allocaing zero-initialized storage. This needs to correspond to a fixed
193   // cache id that cannot be returned for a type index, such as `kUndefinedCacheId`.
194   static constexpr uint32_t kNoIdForTypeIndex = 0u;
195   static_assert(kNoIdForTypeIndex == kUndefinedCacheId);
196 
197   void FillPrimitiveAndConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
198   ObjPtr<mirror::Class> ResolveClass(const char* descriptor, size_t descriptor_length)
199       REQUIRES_SHARED(Locks::mutator_lock_);
200   bool MatchDescriptor(size_t idx, const std::string_view& descriptor)
201       REQUIRES_SHARED(Locks::mutator_lock_);
202 
203   const RegType& From(const char* descriptor)
204       REQUIRES_SHARED(Locks::mutator_lock_);
205 
206   const RegType& FromTypeIndexUncached(dex::TypeIndex type_index)
207       REQUIRES_SHARED(Locks::mutator_lock_);
208 
209   // Returns the pass in RegType.
210   template <class RegTypeType>
211   RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_);
212 
213   // Add a string to the arena allocator so that it stays live for the lifetime of the
214   // verifier and return a string view.
215   std::string_view AddString(const std::string_view& str);
216 
217   // Arena allocator.
218   ArenaAllocator allocator_;
219 
220   // The actual storage for the RegTypes.
221   ArenaVector<const RegType*> entries_;
222 
223   // Fast lookup for quickly finding entries that have a matching class.
224   ArenaVector<std::pair<Handle<mirror::Class>, const RegType*>> klass_entries_;
225 
226   // Handle scope containing classes.
227   VariableSizedHandleScope handles_;
228 
229   ClassLinker* class_linker_;
230   Handle<mirror::ClassLoader> class_loader_;
231   const DexFile* const dex_file_;
232 
233   // Fast lookup by type index.
234   uint16_t* const ids_for_type_index_;
235 
236   // Cache last uninitialized "this" type used for constructors.
237   const UninitializedType* last_uninitialized_this_type_;
238 
239   // Whether or not we're allowed to load classes.
240   const bool can_load_classes_;
241 
242   // Whether or not we're allowed to suspend.
243   const bool can_suspend_;
244 
245   DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
246 };
247 
248 }  // namespace verifier
249 }  // namespace art
250 
251 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
252