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/casts.h"
25 #include "base/macros.h"
26 #include "base/scoped_arena_containers.h"
27 #include "dex/primitive.h"
28 #include "gc_root.h"
29 #include "handle_scope.h"
30 
31 namespace art HIDDEN {
32 
33 namespace mirror {
34 class Class;
35 class ClassLoader;
36 }  // namespace mirror
37 
38 class ClassLinker;
39 class ScopedArenaAllocator;
40 
41 namespace verifier {
42 
43 class BooleanType;
44 class ByteType;
45 class CharType;
46 class ConflictType;
47 class ConstantType;
48 class DoubleHiType;
49 class DoubleLoType;
50 class FloatType;
51 class ImpreciseConstType;
52 class IntegerType;
53 class LongHiType;
54 class LongLoType;
55 class MethodVerifier;
56 class NullType;
57 class PreciseConstType;
58 class PreciseReferenceType;
59 class RegType;
60 class ShortType;
61 class UndefinedType;
62 class UninitializedType;
63 
64 // Use 8 bytes since that is the default arena allocator alignment.
65 static constexpr size_t kDefaultArenaBitVectorBytes = 8;
66 
67 class RegTypeCache {
68  public:
69   RegTypeCache(Thread* self,
70                ClassLinker* class_linker,
71                bool can_load_classes,
72                ScopedArenaAllocator& allocator,
73                bool can_suspend = true);
74   const art::verifier::RegType& GetFromId(uint16_t id) const;
75   // Find a RegType, returns null if not found.
76   const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const
77       REQUIRES_SHARED(Locks::mutator_lock_);
78   // Insert a new class with a specified descriptor, must not already be in the cache.
79   const RegType* InsertClass(const std::string_view& descriptor,
80                              ObjPtr<mirror::Class> klass,
81                              bool precise)
82       REQUIRES_SHARED(Locks::mutator_lock_);
83   // Get or insert a reg type for a description, klass, and precision.
84   const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise)
85       REQUIRES_SHARED(Locks::mutator_lock_);
86   const ConstantType& FromCat1Const(int32_t value, bool precise)
87       REQUIRES_SHARED(Locks::mutator_lock_);
88   const ConstantType& FromCat2ConstLo(int32_t value, bool precise)
89       REQUIRES_SHARED(Locks::mutator_lock_);
90   const ConstantType& FromCat2ConstHi(int32_t value, bool precise)
91       REQUIRES_SHARED(Locks::mutator_lock_);
92   const RegType& FromDescriptor(Handle<mirror::ClassLoader> loader, const char* descriptor)
93       REQUIRES_SHARED(Locks::mutator_lock_);
94   const RegType& FromUnresolvedMerge(const RegType& left,
95                                      const RegType& right,
96                                      MethodVerifier* verifier)
97       REQUIRES_SHARED(Locks::mutator_lock_);
98   const RegType& FromUnresolvedSuperClass(const RegType& child)
99       REQUIRES_SHARED(Locks::mutator_lock_);
100 
101   // Note: this should not be used outside of RegType::ClassJoin!
102   const RegType& MakeUnresolvedReference() REQUIRES_SHARED(Locks::mutator_lock_);
103 
Zero()104   const ConstantType& Zero() REQUIRES_SHARED(Locks::mutator_lock_) {
105     return FromCat1Const(0, true);
106   }
One()107   const ConstantType& One() REQUIRES_SHARED(Locks::mutator_lock_) {
108     return FromCat1Const(1, true);
109   }
GetCacheSize()110   size_t GetCacheSize() {
111     return entries_.size();
112   }
113   const BooleanType& Boolean() REQUIRES_SHARED(Locks::mutator_lock_);
114   const ByteType& Byte() REQUIRES_SHARED(Locks::mutator_lock_);
115   const CharType& Char() REQUIRES_SHARED(Locks::mutator_lock_);
116   const ShortType& Short() REQUIRES_SHARED(Locks::mutator_lock_);
117   const IntegerType& Integer() REQUIRES_SHARED(Locks::mutator_lock_);
118   const FloatType& Float() REQUIRES_SHARED(Locks::mutator_lock_);
119   const LongLoType& LongLo() REQUIRES_SHARED(Locks::mutator_lock_);
120   const LongHiType& LongHi() REQUIRES_SHARED(Locks::mutator_lock_);
121   const DoubleLoType& DoubleLo() REQUIRES_SHARED(Locks::mutator_lock_);
122   const DoubleHiType& DoubleHi() REQUIRES_SHARED(Locks::mutator_lock_);
123   const UndefinedType& Undefined() REQUIRES_SHARED(Locks::mutator_lock_);
124   const ConflictType& Conflict();
125   const NullType& Null();
126 
127   const PreciseReferenceType& JavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_);
128   const PreciseReferenceType& JavaLangString() REQUIRES_SHARED(Locks::mutator_lock_);
129   const PreciseReferenceType& JavaLangInvokeMethodHandle() REQUIRES_SHARED(Locks::mutator_lock_);
130   const PreciseReferenceType& JavaLangInvokeMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
131   const RegType& JavaLangThrowable() REQUIRES_SHARED(Locks::mutator_lock_);
132   const RegType& JavaLangObject(bool precise) REQUIRES_SHARED(Locks::mutator_lock_);
133 
134   const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc)
135       REQUIRES_SHARED(Locks::mutator_lock_);
136   // Create an uninitialized 'this' argument for the given type.
137   const UninitializedType& UninitializedThisArgument(const RegType& type)
138       REQUIRES_SHARED(Locks::mutator_lock_);
139   const RegType& FromUninitialized(const RegType& uninit_type)
140       REQUIRES_SHARED(Locks::mutator_lock_);
141   const ImpreciseConstType& ByteConstant() REQUIRES_SHARED(Locks::mutator_lock_);
142   const ImpreciseConstType& CharConstant() REQUIRES_SHARED(Locks::mutator_lock_);
143   const ImpreciseConstType& ShortConstant() REQUIRES_SHARED(Locks::mutator_lock_);
144   const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_);
145   const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_);
146   const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_);
147   const RegType& GetComponentType(const RegType& array, Handle<mirror::ClassLoader> loader)
148       REQUIRES_SHARED(Locks::mutator_lock_);
149   void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_);
150   const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
151 
GetClassLinker()152   ClassLinker* GetClassLinker() const {
153     return class_linker_;
154   }
155 
GetNullHandle()156   Handle<mirror::Class> GetNullHandle() const {
157     return null_handle_;
158   }
159 
160   static constexpr int32_t kMinSmallConstant = -1;
161   static constexpr int32_t kMaxSmallConstant = 4;
162   static constexpr int32_t kNumSmallConstants = kMaxSmallConstant - kMinSmallConstant + 1;
163   static constexpr size_t kNumPrimitivesAndSmallConstants = 13 + kNumSmallConstants;
164   static constexpr int32_t kBooleanCacheId = kNumSmallConstants;
165   static constexpr int32_t kByteCacheId = kNumSmallConstants + 1;
166   static constexpr int32_t kShortCacheId = kNumSmallConstants + 2;
167   static constexpr int32_t kCharCacheId = kNumSmallConstants + 3;
168   static constexpr int32_t kIntCacheId = kNumSmallConstants + 4;
169   static constexpr int32_t kLongLoCacheId = kNumSmallConstants + 5;
170   static constexpr int32_t kLongHiCacheId = kNumSmallConstants + 6;
171   static constexpr int32_t kFloatCacheId = kNumSmallConstants + 7;
172   static constexpr int32_t kDoubleLoCacheId = kNumSmallConstants + 8;
173   static constexpr int32_t kDoubleHiCacheId = kNumSmallConstants + 9;
174   static constexpr int32_t kUndefinedCacheId = kNumSmallConstants + 10;
175   static constexpr int32_t kConflictCacheId = kNumSmallConstants + 11;
176   static constexpr int32_t kNullCacheId = kNumSmallConstants + 12;
177 
178  private:
179   void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
180   ObjPtr<mirror::Class> ResolveClass(const char* descriptor, Handle<mirror::ClassLoader> loader)
181       REQUIRES_SHARED(Locks::mutator_lock_);
182   bool MatchDescriptor(size_t idx, const std::string_view& descriptor, bool precise)
183       REQUIRES_SHARED(Locks::mutator_lock_);
184   const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
185       REQUIRES_SHARED(Locks::mutator_lock_);
186 
187   const RegType& From(Handle<mirror::ClassLoader> loader, const char* descriptor)
188       REQUIRES_SHARED(Locks::mutator_lock_);
189 
190   // Returns the pass in RegType.
191   template <class RegTypeType>
192   RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_);
193 
194   // Add a string to the arena allocator so that it stays live for the lifetime of the
195   // verifier and return a string view.
196   std::string_view AddString(const std::string_view& str);
197 
198   // The actual storage for the RegTypes.
199   ScopedArenaVector<const RegType*> entries_;
200 
201   // Fast lookup for quickly finding entries that have a matching class.
202   ScopedArenaVector<std::pair<Handle<mirror::Class>, const RegType*>> klass_entries_;
203 
204   // Arena allocator.
205   ScopedArenaAllocator& allocator_;
206 
207   // Handle scope containing classes.
208   VariableSizedHandleScope handles_;
209   ScopedNullHandle<mirror::Class> null_handle_;
210 
211   ClassLinker* class_linker_;
212 
213   // Whether or not we're allowed to load classes.
214   const bool can_load_classes_;
215 
216   DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
217 };
218 
219 }  // namespace verifier
220 }  // namespace art
221 
222 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
223