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