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