Home | History | Annotate | Download | only in verifier
      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 "base/casts.h"
     21 #include "base/macros.h"
     22 #include "base/stl_util.h"
     23 #include "object_callbacks.h"
     24 #include "reg_type.h"
     25 #include "runtime.h"
     26 
     27 #include <stdint.h>
     28 #include <vector>
     29 
     30 namespace art {
     31 namespace mirror {
     32   class Class;
     33   class ClassLoader;
     34 }  // namespace mirror
     35 class StringPiece;
     36 
     37 namespace verifier {
     38 
     39 class RegType;
     40 
     41 class RegTypeCache {
     42  public:
     43   explicit RegTypeCache(bool can_load_classes);
     44   ~RegTypeCache();
     45   static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     46     if (!RegTypeCache::primitive_initialized_) {
     47       CHECK_EQ(RegTypeCache::primitive_count_, 0);
     48       CreatePrimitiveAndSmallConstantTypes();
     49       CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants);
     50       RegTypeCache::primitive_initialized_ = true;
     51     }
     52   }
     53   static void ShutDown();
     54   RegType& GetFromId(uint16_t id) const;
     55   RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise)
     56       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     57   RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
     58       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     59   ConstantType& FromCat1Const(int32_t value, bool precise)
     60       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     61   ConstantType& FromCat2ConstLo(int32_t value, bool precise)
     62       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     63   ConstantType& FromCat2ConstHi(int32_t value, bool precise)
     64       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     65   RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
     66       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     67   RegType& FromUnresolvedMerge(RegType& left, RegType& right)
     68       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     69   RegType& FromUnresolvedSuperClass(RegType& child)
     70       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     71   RegType& JavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     72     // String is final and therefore always precise.
     73     return From(NULL, "Ljava/lang/String;", true);
     74   }
     75   RegType& JavaLangThrowable(bool precise)
     76       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     77     return From(NULL, "Ljava/lang/Throwable;", precise);
     78   }
     79   ConstantType& Zero() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     80     return FromCat1Const(0, true);
     81   }
     82   ConstantType& One() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     83     return FromCat1Const(1, true);
     84   }
     85   size_t GetCacheSize() {
     86     return entries_.size();
     87   }
     88   static RegType& Boolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     89     return *BooleanType::GetInstance();
     90   }
     91   static RegType& Byte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     92     return *ByteType::GetInstance();
     93   }
     94   static RegType& Char() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     95     return *CharType::GetInstance();
     96   }
     97   static RegType& Short() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     98     return *ShortType::GetInstance();
     99   }
    100   static RegType& Integer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    101     return *IntegerType::GetInstance();
    102   }
    103   static RegType& Float() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    104     return *FloatType::GetInstance();
    105   }
    106   static RegType& LongLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    107     return *LongLoType::GetInstance();
    108   }
    109   static RegType& LongHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    110     return *LongHiType::GetInstance();
    111   }
    112   static RegType& DoubleLo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    113     return *DoubleLoType::GetInstance();
    114   }
    115   static RegType& DoubleHi() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    116     return *DoubleHiType::GetInstance();
    117   }
    118   static RegType& Undefined() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    119     return *UndefinedType::GetInstance();
    120   }
    121   static RegType& Conflict() {
    122     return *ConflictType::GetInstance();
    123   }
    124   RegType& JavaLangClass(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    125     return From(NULL, "Ljava/lang/Class;", precise);
    126   }
    127   RegType& JavaLangObject(bool precise) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    128     return From(NULL, "Ljava/lang/Object;", precise);
    129   }
    130   UninitializedType& Uninitialized(RegType& type, uint32_t allocation_pc)
    131       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    132   // Create an uninitialized 'this' argument for the given type.
    133   UninitializedType& UninitializedThisArgument(RegType& type)
    134       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    135   RegType& FromUninitialized(RegType& uninit_type)
    136       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    137   ImpreciseConstType& ByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    138   ImpreciseConstType& CharConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    139   ImpreciseConstType& ShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    140   ImpreciseConstType& IntConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    141   ImpreciseConstType& PosByteConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    142   ImpreciseConstType& PosShortConstant() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    143   RegType& GetComponentType(RegType& array, mirror::ClassLoader* loader)
    144       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    145   void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    146   RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
    147 
    148   void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    149   static void VisitStaticRoots(RootCallback* callback, void* arg)
    150       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    151 
    152  private:
    153   void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    154   mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
    155       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    156   bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
    157       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    158   ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
    159       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    160 
    161   void AddEntry(RegType* new_entry);
    162 
    163   template <class Type>
    164   static Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
    165       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    166   static void CreatePrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    167 
    168   // The actual storage for the RegTypes.
    169   std::vector<RegType*> entries_;
    170 
    171   // A quick look up for popular small constants.
    172   static constexpr int32_t kMinSmallConstant = -1;
    173   static constexpr int32_t kMaxSmallConstant = 4;
    174   static PreciseConstType* small_precise_constants_[kMaxSmallConstant - kMinSmallConstant + 1];
    175 
    176   static constexpr size_t kNumPrimitivesAndSmallConstants =
    177       12 + (kMaxSmallConstant - kMinSmallConstant + 1);
    178 
    179   // Have the well known global primitives been created?
    180   static bool primitive_initialized_;
    181 
    182   // Number of well known primitives that will be copied into a RegTypeCache upon construction.
    183   static uint16_t primitive_count_;
    184 
    185   // Whether or not we're allowed to load classes.
    186   const bool can_load_classes_;
    187 
    188   DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
    189 };
    190 
    191 }  // namespace verifier
    192 }  // namespace art
    193 
    194 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
    195