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