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 <vector> 22 23 #include "base/casts.h" 24 #include "base/macros.h" 25 #include "base/scoped_arena_containers.h" 26 #include "dex/primitive.h" 27 #include "gc_root.h" 28 29 namespace art { 30 namespace mirror { 31 class Class; 32 class ClassLoader; 33 } // namespace mirror 34 class ScopedArenaAllocator; 35 class StringPiece; 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(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(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 StringPiece& descriptor, mirror::Class* klass, bool precise) 84 REQUIRES_SHARED(Locks::mutator_lock_); 85 // Get or insert a reg type for a description, klass, and precision. 86 const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise) 87 REQUIRES_SHARED(Locks::mutator_lock_); 88 const ConstantType& FromCat1Const(int32_t value, bool precise) 89 REQUIRES_SHARED(Locks::mutator_lock_); 90 const ConstantType& FromCat2ConstLo(int32_t value, bool precise) 91 REQUIRES_SHARED(Locks::mutator_lock_); 92 const ConstantType& FromCat2ConstHi(int32_t value, bool precise) 93 REQUIRES_SHARED(Locks::mutator_lock_); 94 const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise) 95 REQUIRES_SHARED(Locks::mutator_lock_); 96 const RegType& FromUnresolvedMerge(const RegType& left, 97 const RegType& right, 98 MethodVerifier* verifier) 99 REQUIRES_SHARED(Locks::mutator_lock_); 100 const RegType& FromUnresolvedSuperClass(const RegType& child) 101 REQUIRES_SHARED(Locks::mutator_lock_); 102 103 // Note: this should not be used outside of RegType::ClassJoin! 104 const RegType& MakeUnresolvedReference() REQUIRES_SHARED(Locks::mutator_lock_); 105 Zero()106 const ConstantType& Zero() REQUIRES_SHARED(Locks::mutator_lock_) { 107 return FromCat1Const(0, true); 108 } One()109 const ConstantType& One() REQUIRES_SHARED(Locks::mutator_lock_) { 110 return FromCat1Const(1, true); 111 } GetCacheSize()112 size_t GetCacheSize() { 113 return entries_.size(); 114 } 115 const BooleanType& Boolean() REQUIRES_SHARED(Locks::mutator_lock_); 116 const ByteType& Byte() REQUIRES_SHARED(Locks::mutator_lock_); 117 const CharType& Char() REQUIRES_SHARED(Locks::mutator_lock_); 118 const ShortType& Short() REQUIRES_SHARED(Locks::mutator_lock_); 119 const IntegerType& Integer() REQUIRES_SHARED(Locks::mutator_lock_); 120 const FloatType& Float() REQUIRES_SHARED(Locks::mutator_lock_); 121 const LongLoType& LongLo() REQUIRES_SHARED(Locks::mutator_lock_); 122 const LongHiType& LongHi() REQUIRES_SHARED(Locks::mutator_lock_); 123 const DoubleLoType& DoubleLo() REQUIRES_SHARED(Locks::mutator_lock_); 124 const DoubleHiType& DoubleHi() REQUIRES_SHARED(Locks::mutator_lock_); 125 const UndefinedType& Undefined() REQUIRES_SHARED(Locks::mutator_lock_); 126 const ConflictType& Conflict(); 127 const NullType& Null(); 128 129 const PreciseReferenceType& JavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_); 130 const PreciseReferenceType& JavaLangString() REQUIRES_SHARED(Locks::mutator_lock_); 131 const PreciseReferenceType& JavaLangInvokeMethodHandle() REQUIRES_SHARED(Locks::mutator_lock_); 132 const PreciseReferenceType& JavaLangInvokeMethodType() REQUIRES_SHARED(Locks::mutator_lock_); 133 const RegType& JavaLangThrowable(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); 134 const RegType& JavaLangObject(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); 135 136 const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc) 137 REQUIRES_SHARED(Locks::mutator_lock_); 138 // Create an uninitialized 'this' argument for the given type. 139 const UninitializedType& UninitializedThisArgument(const RegType& type) 140 REQUIRES_SHARED(Locks::mutator_lock_); 141 const RegType& FromUninitialized(const RegType& uninit_type) 142 REQUIRES_SHARED(Locks::mutator_lock_); 143 const ImpreciseConstType& ByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); 144 const ImpreciseConstType& CharConstant() REQUIRES_SHARED(Locks::mutator_lock_); 145 const ImpreciseConstType& ShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); 146 const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_); 147 const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); 148 const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); 149 const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader) 150 REQUIRES_SHARED(Locks::mutator_lock_); 151 void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_); 152 const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; 153 154 void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) 155 REQUIRES_SHARED(Locks::mutator_lock_); 156 static void VisitStaticRoots(RootVisitor* visitor) 157 REQUIRES_SHARED(Locks::mutator_lock_); 158 159 private: 160 void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); 161 mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader) 162 REQUIRES_SHARED(Locks::mutator_lock_); 163 bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise) 164 REQUIRES_SHARED(Locks::mutator_lock_); 165 const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise) 166 REQUIRES_SHARED(Locks::mutator_lock_); 167 168 // Returns the pass in RegType. 169 template <class RegTypeType> 170 RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_); 171 172 // Add a string piece to the arena allocator so that it stays live for the lifetime of the 173 // verifier. 174 StringPiece AddString(const StringPiece& string_piece); 175 176 static void CreatePrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); 177 178 // A quick look up for popular small constants. 179 static constexpr int32_t kMinSmallConstant = -1; 180 static constexpr int32_t kMaxSmallConstant = 4; 181 static const PreciseConstType* small_precise_constants_[kMaxSmallConstant - 182 kMinSmallConstant + 1]; 183 184 static constexpr size_t kNumPrimitivesAndSmallConstants = 185 13 + (kMaxSmallConstant - kMinSmallConstant + 1); 186 187 // Have the well known global primitives been created? 188 static bool primitive_initialized_; 189 190 // Number of well known primitives that will be copied into a RegTypeCache upon construction. 191 static uint16_t primitive_count_; 192 193 // The actual storage for the RegTypes. 194 ScopedArenaVector<const RegType*> entries_; 195 196 // Fast lookup for quickly finding entries that have a matching class. 197 ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_; 198 199 // Whether or not we're allowed to load classes. 200 const bool can_load_classes_; 201 202 // Arena allocator. 203 ScopedArenaAllocator& allocator_; 204 205 DISALLOW_COPY_AND_ASSIGN(RegTypeCache); 206 }; 207 208 } // namespace verifier 209 } // namespace art 210 211 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ 212