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