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/stl_util.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 StringPiece;
36 
37 namespace verifier {
38 
39 class RegType;
40 
41 class RegTypeCache {
42  public:
43   explicit RegTypeCache(bool can_load_classes);
44   ~RegTypeCache();
Init()45   static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
46     if (!RegTypeCache::primitive_initialized_) {
47       CHECK_EQ(RegTypeCache::primitive_count_, 0);
48       CreatePrimitiveAndSmallConstantTypes();
49       CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants);
50       RegTypeCache::primitive_initialized_ = true;
51     }
52   }
53   static void ShutDown();
54   RegType& GetFromId(uint16_t id) const;
55   RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise)
56       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
57   RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
58       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
59   ConstantType& FromCat1Const(int32_t value, bool precise)
60       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
61   ConstantType& FromCat2ConstLo(int32_t value, bool precise)
62       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
63   ConstantType& FromCat2ConstHi(int32_t value, bool precise)
64       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
65   RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
66       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
67   RegType& FromUnresolvedMerge(RegType& left, RegType& right)
68       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
69   RegType& FromUnresolvedSuperClass(RegType& child)
70       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
JavaLangString()71   RegType& JavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
72     // String is final and therefore always precise.
73     return From(NULL, "Ljava/lang/String;", true);
74   }
JavaLangThrowable(bool precise)75   RegType& JavaLangThrowable(bool precise)
76       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
77     return From(NULL, "Ljava/lang/Throwable;", precise);
78   }
Zero()79   ConstantType& Zero() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
80     return FromCat1Const(0, true);
81   }
One()82   ConstantType& One() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
83     return FromCat1Const(1, true);
84   }
GetCacheSize()85   size_t GetCacheSize() {
86     return entries_.size();
87   }
Boolean()88   static RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
89     return *BooleanType::GetInstance();
90   }
Byte()91   static RegType& Byte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
92     return *ByteType::GetInstance();
93   }
Char()94   static RegType& Char() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
95     return *CharType::GetInstance();
96   }
Short()97   static RegType& Short() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
98     return *ShortType::GetInstance();
99   }
Integer()100   static RegType& Integer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
101     return *IntegerType::GetInstance();
102   }
Float()103   static RegType& Float() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
104     return *FloatType::GetInstance();
105   }
LongLo()106   static RegType& LongLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
107     return *LongLoType::GetInstance();
108   }
LongHi()109   static RegType& LongHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
110     return *LongHiType::GetInstance();
111   }
DoubleLo()112   static RegType& DoubleLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
113     return *DoubleLoType::GetInstance();
114   }
DoubleHi()115   static RegType& DoubleHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
116     return *DoubleHiType::GetInstance();
117   }
Undefined()118   static RegType& Undefined() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
119     return *UndefinedType::GetInstance();
120   }
Conflict()121   static RegType& Conflict() {
122     return *ConflictType::GetInstance();
123   }
JavaLangClass(bool precise)124   RegType& JavaLangClass(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
125     return From(NULL, "Ljava/lang/Class;", precise);
126   }
JavaLangObject(bool precise)127   RegType& JavaLangObject(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
128     return From(NULL, "Ljava/lang/Object;", precise);
129   }
130   UninitializedType& Uninitialized(RegType& type, uint32_t allocation_pc)
131       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
132   // Create an uninitialized 'this' argument for the given type.
133   UninitializedType& UninitializedThisArgument(RegType& type)
134       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
135   RegType& FromUninitialized(RegType& uninit_type)
136       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
137   ImpreciseConstType& ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
138   ImpreciseConstType& CharConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
139   ImpreciseConstType& ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
140   ImpreciseConstType& IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
141   ImpreciseConstType& PosByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
142   ImpreciseConstType& PosShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
143   RegType& GetComponentType(RegType& array, mirror::ClassLoader* loader)
144       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
145   void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
146   RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
147 
148   void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
149   static void VisitStaticRoots(RootCallback* callback, void* arg)
150       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
151 
152  private:
153   void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
154   mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
155       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
156   bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
157       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
158   ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
159       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
160 
161   void AddEntry(RegType* new_entry);
162 
163   template <class Type>
164   static Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
165       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
166   static void CreatePrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
167 
168   // The actual storage for the RegTypes.
169   std::vector<RegType*> entries_;
170 
171   // A quick look up for popular small constants.
172   static constexpr int32_t kMinSmallConstant = -1;
173   static constexpr int32_t kMaxSmallConstant = 4;
174   static PreciseConstType* small_precise_constants_[kMaxSmallConstant - kMinSmallConstant + 1];
175 
176   static constexpr size_t kNumPrimitivesAndSmallConstants =
177       12 + (kMaxSmallConstant - kMinSmallConstant + 1);
178 
179   // Have the well known global primitives been created?
180   static bool primitive_initialized_;
181 
182   // Number of well known primitives that will be copied into a RegTypeCache upon construction.
183   static uint16_t primitive_count_;
184 
185   // Whether or not we're allowed to load classes.
186   const bool can_load_classes_;
187 
188   DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
189 };
190 
191 }  // namespace verifier
192 }  // namespace art
193 
194 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
195