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