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