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() SHARED_REQUIRES(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       SHARED_REQUIRES(Locks::mutator_lock_);
61   // Find a RegType, returns null if not found.
62   const RegType* FindClass(mirror::Class* klass, bool precise) const
63       SHARED_REQUIRES(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       SHARED_REQUIRES(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       SHARED_REQUIRES(Locks::mutator_lock_);
70   const ConstantType& FromCat1Const(int32_t value, bool precise)
71       SHARED_REQUIRES(Locks::mutator_lock_);
72   const ConstantType& FromCat2ConstLo(int32_t value, bool precise)
73       SHARED_REQUIRES(Locks::mutator_lock_);
74   const ConstantType& FromCat2ConstHi(int32_t value, bool precise)
75       SHARED_REQUIRES(Locks::mutator_lock_);
76   const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
77       SHARED_REQUIRES(Locks::mutator_lock_);
78   const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right)
79       SHARED_REQUIRES(Locks::mutator_lock_);
80   const RegType& FromUnresolvedSuperClass(const RegType& child)
81       SHARED_REQUIRES(Locks::mutator_lock_);
Zero()82   const ConstantType& Zero() SHARED_REQUIRES(Locks::mutator_lock_) {
83     return FromCat1Const(0, true);
84   }
One()85   const ConstantType& One() SHARED_REQUIRES(Locks::mutator_lock_) {
86     return FromCat1Const(1, true);
87   }
GetCacheSize()88   size_t GetCacheSize() {
89     return entries_.size();
90   }
Boolean()91   const BooleanType& Boolean() SHARED_REQUIRES(Locks::mutator_lock_) {
92     return *BooleanType::GetInstance();
93   }
Byte()94   const ByteType& Byte() SHARED_REQUIRES(Locks::mutator_lock_) {
95     return *ByteType::GetInstance();
96   }
Char()97   const CharType& Char() SHARED_REQUIRES(Locks::mutator_lock_) {
98     return *CharType::GetInstance();
99   }
Short()100   const ShortType& Short() SHARED_REQUIRES(Locks::mutator_lock_) {
101     return *ShortType::GetInstance();
102   }
Integer()103   const IntegerType& Integer() SHARED_REQUIRES(Locks::mutator_lock_) {
104     return *IntegerType::GetInstance();
105   }
Float()106   const FloatType& Float() SHARED_REQUIRES(Locks::mutator_lock_) {
107     return *FloatType::GetInstance();
108   }
LongLo()109   const LongLoType& LongLo() SHARED_REQUIRES(Locks::mutator_lock_) {
110     return *LongLoType::GetInstance();
111   }
LongHi()112   const LongHiType& LongHi() SHARED_REQUIRES(Locks::mutator_lock_) {
113     return *LongHiType::GetInstance();
114   }
DoubleLo()115   const DoubleLoType& DoubleLo() SHARED_REQUIRES(Locks::mutator_lock_) {
116     return *DoubleLoType::GetInstance();
117   }
DoubleHi()118   const DoubleHiType& DoubleHi() SHARED_REQUIRES(Locks::mutator_lock_) {
119     return *DoubleHiType::GetInstance();
120   }
Undefined()121   const UndefinedType& Undefined() SHARED_REQUIRES(Locks::mutator_lock_) {
122     return *UndefinedType::GetInstance();
123   }
Conflict()124   const ConflictType& Conflict() {
125     return *ConflictType::GetInstance();
126   }
127 
128   const PreciseReferenceType& JavaLangClass() SHARED_REQUIRES(Locks::mutator_lock_);
129   const PreciseReferenceType& JavaLangString() SHARED_REQUIRES(Locks::mutator_lock_);
130   const RegType& JavaLangThrowable(bool precise) SHARED_REQUIRES(Locks::mutator_lock_);
131   const RegType& JavaLangObject(bool precise) SHARED_REQUIRES(Locks::mutator_lock_);
132 
133   const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc)
134       SHARED_REQUIRES(Locks::mutator_lock_);
135   // Create an uninitialized 'this' argument for the given type.
136   const UninitializedType& UninitializedThisArgument(const RegType& type)
137       SHARED_REQUIRES(Locks::mutator_lock_);
138   const RegType& FromUninitialized(const RegType& uninit_type)
139       SHARED_REQUIRES(Locks::mutator_lock_);
140   const ImpreciseConstType& ByteConstant() SHARED_REQUIRES(Locks::mutator_lock_);
141   const ImpreciseConstType& CharConstant() SHARED_REQUIRES(Locks::mutator_lock_);
142   const ImpreciseConstType& ShortConstant() SHARED_REQUIRES(Locks::mutator_lock_);
143   const ImpreciseConstType& IntConstant() SHARED_REQUIRES(Locks::mutator_lock_);
144   const ImpreciseConstType& PosByteConstant() SHARED_REQUIRES(Locks::mutator_lock_);
145   const ImpreciseConstType& PosShortConstant() SHARED_REQUIRES(Locks::mutator_lock_);
146   const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader)
147       SHARED_REQUIRES(Locks::mutator_lock_);
148   void Dump(std::ostream& os) SHARED_REQUIRES(Locks::mutator_lock_);
149   const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
150 
151   void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
152       SHARED_REQUIRES(Locks::mutator_lock_);
153   static void VisitStaticRoots(RootVisitor* visitor)
154       SHARED_REQUIRES(Locks::mutator_lock_);
155 
156  private:
157   void FillPrimitiveAndSmallConstantTypes() SHARED_REQUIRES(Locks::mutator_lock_);
158   mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
159       SHARED_REQUIRES(Locks::mutator_lock_);
160   bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
161       SHARED_REQUIRES(Locks::mutator_lock_);
162   const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
163       SHARED_REQUIRES(Locks::mutator_lock_);
164 
165   // Returns the pass in RegType.
166   template <class RegTypeType>
167   RegTypeType& AddEntry(RegTypeType* new_entry) SHARED_REQUIRES(Locks::mutator_lock_);
168 
169   // Add a string piece to the arena allocator so that it stays live for the lifetime of the
170   // verifier.
171   StringPiece AddString(const StringPiece& string_piece);
172 
173   template <class Type>
174   static const Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
175       SHARED_REQUIRES(Locks::mutator_lock_);
176   static void CreatePrimitiveAndSmallConstantTypes() SHARED_REQUIRES(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       12 + (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& arena_;
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