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