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 "gc_root.h" 27 #include "primitive.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 PreciseConstType; 52 class PreciseReferenceType; 53 class RegType; 54 class ShortType; 55 class UndefinedType; 56 class UninitializedType; 57 58 // Use 8 bytes since that is the default arena allocator alignment. 59 static constexpr size_t kDefaultArenaBitVectorBytes = 8; 60 61 class RegTypeCache { 62 public: 63 explicit RegTypeCache(bool can_load_classes, ScopedArenaAllocator& arena); 64 ~RegTypeCache(); Init()65 static void Init() REQUIRES_SHARED(Locks::mutator_lock_) { 66 if (!RegTypeCache::primitive_initialized_) { 67 CHECK_EQ(RegTypeCache::primitive_count_, 0); 68 CreatePrimitiveAndSmallConstantTypes(); 69 CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants); 70 RegTypeCache::primitive_initialized_ = true; 71 } 72 } 73 static void ShutDown(); 74 const art::verifier::RegType& GetFromId(uint16_t id) const; 75 const RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise) 76 REQUIRES_SHARED(Locks::mutator_lock_); 77 // Find a RegType, returns null if not found. 78 const RegType* FindClass(mirror::Class* klass, bool precise) const 79 REQUIRES_SHARED(Locks::mutator_lock_); 80 // Insert a new class with a specified descriptor, must not already be in the cache. 81 const RegType* InsertClass(const StringPiece& descriptor, mirror::Class* klass, 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, 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(mirror::ClassLoader* loader, const char* descriptor, bool precise) 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 126 const PreciseReferenceType& JavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_); 127 const PreciseReferenceType& JavaLangString() REQUIRES_SHARED(Locks::mutator_lock_); 128 const RegType& JavaLangThrowable(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); 129 const RegType& JavaLangObject(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); 130 131 const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc) 132 REQUIRES_SHARED(Locks::mutator_lock_); 133 // Create an uninitialized 'this' argument for the given type. 134 const UninitializedType& UninitializedThisArgument(const RegType& type) 135 REQUIRES_SHARED(Locks::mutator_lock_); 136 const RegType& FromUninitialized(const RegType& uninit_type) 137 REQUIRES_SHARED(Locks::mutator_lock_); 138 const ImpreciseConstType& ByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); 139 const ImpreciseConstType& CharConstant() REQUIRES_SHARED(Locks::mutator_lock_); 140 const ImpreciseConstType& ShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); 141 const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_); 142 const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); 143 const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); 144 const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader) 145 REQUIRES_SHARED(Locks::mutator_lock_); 146 void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_); 147 const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; 148 149 void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) 150 REQUIRES_SHARED(Locks::mutator_lock_); 151 static void VisitStaticRoots(RootVisitor* visitor) 152 REQUIRES_SHARED(Locks::mutator_lock_); 153 154 private: 155 void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); 156 mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader) 157 REQUIRES_SHARED(Locks::mutator_lock_); 158 bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise) 159 REQUIRES_SHARED(Locks::mutator_lock_); 160 const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise) 161 REQUIRES_SHARED(Locks::mutator_lock_); 162 163 // Returns the pass in RegType. 164 template <class RegTypeType> 165 RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_); 166 167 // Add a string piece to the arena allocator so that it stays live for the lifetime of the 168 // verifier. 169 StringPiece AddString(const StringPiece& string_piece); 170 171 template <class Type> 172 static const Type* CreatePrimitiveTypeInstance(const std::string& descriptor) 173 REQUIRES_SHARED(Locks::mutator_lock_); 174 static void CreatePrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); 175 176 // A quick look up for popular small constants. 177 static constexpr int32_t kMinSmallConstant = -1; 178 static constexpr int32_t kMaxSmallConstant = 4; 179 static const PreciseConstType* small_precise_constants_[kMaxSmallConstant - 180 kMinSmallConstant + 1]; 181 182 static constexpr size_t kNumPrimitivesAndSmallConstants = 183 12 + (kMaxSmallConstant - kMinSmallConstant + 1); 184 185 // Have the well known global primitives been created? 186 static bool primitive_initialized_; 187 188 // Number of well known primitives that will be copied into a RegTypeCache upon construction. 189 static uint16_t primitive_count_; 190 191 // The actual storage for the RegTypes. 192 ScopedArenaVector<const RegType*> entries_; 193 194 // Fast lookup for quickly finding entries that have a matching class. 195 ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_; 196 197 // Whether or not we're allowed to load classes. 198 const bool can_load_classes_; 199 200 // Arena allocator. 201 ScopedArenaAllocator& arena_; 202 203 DISALLOW_COPY_AND_ASSIGN(RegTypeCache); 204 }; 205 206 } // namespace verifier 207 } // namespace art 208 209 #endif // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ 210