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