| /* |
| * 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 "base/casts.h" |
| #include "base/macros.h" |
| #include "base/stl_util.h" |
| #include "reg_type.h" |
| #include "runtime.h" |
| |
| #include <stdint.h> |
| #include <vector> |
| |
| namespace art { |
| namespace mirror { |
| class Class; |
| class ClassLoader; |
| } // namespace mirror |
| namespace verifier { |
| |
| class RegType; |
| |
| const size_t kNumPrimitives = 12; |
| class RegTypeCache { |
| public: |
| explicit RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) { |
| entries_.reserve(64); |
| FillPrimitiveTypes(); |
| } |
| ~RegTypeCache(); |
| static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| if(!RegTypeCache::primitive_initialized_) { |
| CHECK_EQ(RegTypeCache::primitive_count_, 0); |
| CreatePrimitiveTypes(); |
| CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitives); |
| RegTypeCache::primitive_initialized_ = true; |
| } |
| } |
| static void ShutDown(); |
| const art::verifier::RegType& GetFromId(uint16_t id) const; |
| const RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| template <class Type> |
| static Type* CreatePrimitiveTypeInstance(const std::string& descriptor) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| void FillPrimitiveTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromCat1Const(int32_t value, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromCat2ConstLo(int32_t value, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromCat2ConstHi(int32_t value, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromUnresolvedSuperClass(const RegType& child) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& JavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| // String is final and therefore always precise. |
| return From(NULL, "Ljava/lang/String;", true); |
| } |
| const RegType& JavaLangThrowable(bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| return From(NULL, "Ljava/lang/Throwable;", precise); |
| } |
| const RegType& Zero() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| return FromCat1Const(0, true); |
| } |
| size_t GetCacheSize() { |
| return entries_.size(); |
| } |
| const RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| return *BooleanType::GetInstance(); |
| } |
| const RegType& Byte() { |
| return *ByteType::GetInstance(); |
| } |
| const RegType& Char() { |
| return *CharType::GetInstance(); |
| } |
| const RegType& Short() { |
| return *ShortType::GetInstance(); |
| } |
| const RegType& Integer() { |
| return *IntegerType::GetInstance(); |
| } |
| const RegType& Float() { |
| return *FloatType::GetInstance(); |
| } |
| const RegType& LongLo() { |
| return *LongLoType::GetInstance(); |
| } |
| const RegType& LongHi() { |
| return *LongHiType::GetInstance(); |
| } |
| const RegType& DoubleLo() { |
| return *DoubleLoType::GetInstance(); |
| } |
| const RegType& DoubleHi() { |
| return *DoubleHiType::GetInstance(); |
| } |
| const RegType& Undefined() { |
| return *UndefinedType::GetInstance(); |
| } |
| const RegType& Conflict() { |
| return *ConflictType::GetInstance(); |
| } |
| const RegType& JavaLangClass(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| return From(NULL, "Ljava/lang/Class;", precise); |
| } |
| const RegType& JavaLangObject(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { |
| return From(NULL, "Ljava/lang/Object;", precise); |
| } |
| const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| // Create an uninitialized 'this' argument for the given type. |
| const RegType& UninitializedThisArgument(const RegType& type) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& FromUninitialized(const RegType& uninit_type) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; |
| |
| private: |
| std::vector<RegType*> entries_; |
| static bool primitive_initialized_; |
| static uint16_t primitive_start_; |
| static uint16_t primitive_count_; |
| static void CreatePrimitiveTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| // Whether or not we're allowed to load classes. |
| const bool can_load_classes_; |
| DISALLOW_COPY_AND_ASSIGN(RegTypeCache); |
| mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| void ClearException(); |
| bool MatchDescriptor(size_t idx, const char* descriptor, bool precise) |
| SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |
| }; |
| |
| } // namespace verifier |
| } // namespace art |
| |
| #endif // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_ |