| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ |
| #define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ |
| |
| #include <stdint.h> |
| #include <string_view> |
| #include <vector> |
| |
| #include "base/casts.h" |
| #include "base/macros.h" |
| #include "base/scoped_arena_containers.h" |
| #include "dex/primitive.h" |
| #include "gc_root.h" |
| |
| namespace art { |
| |
| namespace mirror { |
| class Class; |
| class ClassLoader; |
| } // namespace mirror |
| |
| class ClassLinker; |
| class ScopedArenaAllocator; |
| |
| namespace verifier { |
| |
| class BooleanType; |
| class ByteType; |
| class CharType; |
| class ConflictType; |
| class ConstantType; |
| class DoubleHiType; |
| class DoubleLoType; |
| class FloatType; |
| class ImpreciseConstType; |
| class IntegerType; |
| class LongHiType; |
| class LongLoType; |
| class MethodVerifier; |
| class NullType; |
| class PreciseConstType; |
| class PreciseReferenceType; |
| class RegType; |
| class ShortType; |
| class UndefinedType; |
| class UninitializedType; |
| |
| // Use 8 bytes since that is the default arena allocator alignment. |
| static constexpr size_t kDefaultArenaBitVectorBytes = 8; |
| |
| class RegTypeCache { |
| public: |
| RegTypeCache(ClassLinker* class_linker, |
| bool can_load_classes, |
| ScopedArenaAllocator& allocator, |
| bool can_suspend = true); |
| ~RegTypeCache(); |
| static void Init(ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) { |
| if (!RegTypeCache::primitive_initialized_) { |
| CHECK_EQ(RegTypeCache::primitive_count_, 0); |
| CreatePrimitiveAndSmallConstantTypes(class_linker); |
| CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants); |
| RegTypeCache::primitive_initialized_ = true; |
| } |
| } |
| static void ShutDown(); |
| const art::verifier::RegType& GetFromId(uint16_t id) const; |
| const RegType& From(ObjPtr<mirror::ClassLoader> loader, const char* descriptor, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| // Find a RegType, returns null if not found. |
| const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| // Insert a new class with a specified descriptor, must not already be in the cache. |
| const RegType* InsertClass(const std::string_view& descriptor, |
| ObjPtr<mirror::Class> klass, |
| bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| // Get or insert a reg type for a description, klass, and precision. |
| const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const ConstantType& FromCat1Const(int32_t value, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const ConstantType& FromCat2ConstLo(int32_t value, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const ConstantType& FromCat2ConstHi(int32_t value, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& FromDescriptor(ObjPtr<mirror::ClassLoader> loader, |
| const char* descriptor, |
| bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& FromUnresolvedMerge(const RegType& left, |
| const RegType& right, |
| MethodVerifier* verifier) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& FromUnresolvedSuperClass(const RegType& child) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Note: this should not be used outside of RegType::ClassJoin! |
| const RegType& MakeUnresolvedReference() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| const ConstantType& Zero() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return FromCat1Const(0, true); |
| } |
| const ConstantType& One() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return FromCat1Const(1, true); |
| } |
| size_t GetCacheSize() { |
| return entries_.size(); |
| } |
| const BooleanType& Boolean() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ByteType& Byte() REQUIRES_SHARED(Locks::mutator_lock_); |
| const CharType& Char() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ShortType& Short() REQUIRES_SHARED(Locks::mutator_lock_); |
| const IntegerType& Integer() REQUIRES_SHARED(Locks::mutator_lock_); |
| const FloatType& Float() REQUIRES_SHARED(Locks::mutator_lock_); |
| const LongLoType& LongLo() REQUIRES_SHARED(Locks::mutator_lock_); |
| const LongHiType& LongHi() REQUIRES_SHARED(Locks::mutator_lock_); |
| const DoubleLoType& DoubleLo() REQUIRES_SHARED(Locks::mutator_lock_); |
| const DoubleHiType& DoubleHi() REQUIRES_SHARED(Locks::mutator_lock_); |
| const UndefinedType& Undefined() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ConflictType& Conflict(); |
| const NullType& Null(); |
| |
| const PreciseReferenceType& JavaLangClass() REQUIRES_SHARED(Locks::mutator_lock_); |
| const PreciseReferenceType& JavaLangString() REQUIRES_SHARED(Locks::mutator_lock_); |
| const PreciseReferenceType& JavaLangInvokeMethodHandle() REQUIRES_SHARED(Locks::mutator_lock_); |
| const PreciseReferenceType& JavaLangInvokeMethodType() REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& JavaLangThrowable(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& JavaLangObject(bool precise) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| // Create an uninitialized 'this' argument for the given type. |
| const UninitializedType& UninitializedThisArgument(const RegType& type) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& FromUninitialized(const RegType& uninit_type) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& ByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& CharConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& ShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& GetComponentType(const RegType& array, ObjPtr<mirror::ClassLoader> loader) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_); |
| const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; |
| |
| void VisitRoots(RootVisitor* visitor, const RootInfo& root_info) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| static void VisitStaticRoots(RootVisitor* visitor) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| ClassLinker* GetClassLinker() { |
| return class_linker_; |
| } |
| |
| private: |
| void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); |
| ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| bool MatchDescriptor(size_t idx, const std::string_view& descriptor, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Returns the pass in RegType. |
| template <class RegTypeType> |
| RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Add a string to the arena allocator so that it stays live for the lifetime of the |
| // verifier and return a string view. |
| std::string_view AddString(const std::string_view& str); |
| |
| static void CreatePrimitiveAndSmallConstantTypes(ClassLinker* class_linker) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // A quick look up for popular small constants. |
| static constexpr int32_t kMinSmallConstant = -1; |
| static constexpr int32_t kMaxSmallConstant = 4; |
| static const PreciseConstType* small_precise_constants_[kMaxSmallConstant - |
| kMinSmallConstant + 1]; |
| |
| static constexpr size_t kNumPrimitivesAndSmallConstants = |
| 13 + (kMaxSmallConstant - kMinSmallConstant + 1); |
| |
| // Have the well known global primitives been created? |
| static bool primitive_initialized_; |
| |
| // Number of well known primitives that will be copied into a RegTypeCache upon construction. |
| static uint16_t primitive_count_; |
| |
| // The actual storage for the RegTypes. |
| ScopedArenaVector<const RegType*> entries_; |
| |
| // Fast lookup for quickly finding entries that have a matching class. |
| ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_; |
| |
| // Arena allocator. |
| ScopedArenaAllocator& allocator_; |
| |
| ClassLinker* class_linker_; |
| |
| // Whether or not we're allowed to load classes. |
| const bool can_load_classes_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RegTypeCache); |
| }; |
| |
| } // namespace verifier |
| } // namespace art |
| |
| #endif // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ |