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