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/scoped_arena_containers.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 {
32  class Class;
33  class ClassLoader;
34}  // namespace mirror
35class ScopedArenaAllocator;
36class StringPiece;
37
38namespace verifier {
39
40class RegType;
41
42// Use 8 bytes since that is the default arena allocator alignment.
43static constexpr size_t kDefaultArenaBitVectorBytes = 8;
44
45class RegTypeCache {
46 public:
47  explicit RegTypeCache(bool can_load_classes, ScopedArenaAllocator& arena);
48  ~RegTypeCache();
49  static void Init() SHARED_REQUIRES(Locks::mutator_lock_) {
50    if (!RegTypeCache::primitive_initialized_) {
51      CHECK_EQ(RegTypeCache::primitive_count_, 0);
52      CreatePrimitiveAndSmallConstantTypes();
53      CHECK_EQ(RegTypeCache::primitive_count_, kNumPrimitivesAndSmallConstants);
54      RegTypeCache::primitive_initialized_ = true;
55    }
56  }
57  static void ShutDown();
58  const art::verifier::RegType& GetFromId(uint16_t id) const;
59  const RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise)
60      SHARED_REQUIRES(Locks::mutator_lock_);
61  // Find a RegType, returns null if not found.
62  const RegType* FindClass(mirror::Class* klass, bool precise) const
63      SHARED_REQUIRES(Locks::mutator_lock_);
64  // Insert a new class with a specified descriptor, must not already be in the cache.
65  const RegType* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool precise)
66      SHARED_REQUIRES(Locks::mutator_lock_);
67  // Get or insert a reg type for a description, klass, and precision.
68  const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
69      SHARED_REQUIRES(Locks::mutator_lock_);
70  const ConstantType& FromCat1Const(int32_t value, bool precise)
71      SHARED_REQUIRES(Locks::mutator_lock_);
72  const ConstantType& FromCat2ConstLo(int32_t value, bool precise)
73      SHARED_REQUIRES(Locks::mutator_lock_);
74  const ConstantType& FromCat2ConstHi(int32_t value, bool precise)
75      SHARED_REQUIRES(Locks::mutator_lock_);
76  const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
77      SHARED_REQUIRES(Locks::mutator_lock_);
78  const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right)
79      SHARED_REQUIRES(Locks::mutator_lock_);
80  const RegType& FromUnresolvedSuperClass(const RegType& child)
81      SHARED_REQUIRES(Locks::mutator_lock_);
82  const ConstantType& Zero() SHARED_REQUIRES(Locks::mutator_lock_) {
83    return FromCat1Const(0, true);
84  }
85  const ConstantType& One() SHARED_REQUIRES(Locks::mutator_lock_) {
86    return FromCat1Const(1, true);
87  }
88  size_t GetCacheSize() {
89    return entries_.size();
90  }
91  const BooleanType& Boolean() SHARED_REQUIRES(Locks::mutator_lock_) {
92    return *BooleanType::GetInstance();
93  }
94  const ByteType& Byte() SHARED_REQUIRES(Locks::mutator_lock_) {
95    return *ByteType::GetInstance();
96  }
97  const CharType& Char() SHARED_REQUIRES(Locks::mutator_lock_) {
98    return *CharType::GetInstance();
99  }
100  const ShortType& Short() SHARED_REQUIRES(Locks::mutator_lock_) {
101    return *ShortType::GetInstance();
102  }
103  const IntegerType& Integer() SHARED_REQUIRES(Locks::mutator_lock_) {
104    return *IntegerType::GetInstance();
105  }
106  const FloatType& Float() SHARED_REQUIRES(Locks::mutator_lock_) {
107    return *FloatType::GetInstance();
108  }
109  const LongLoType& LongLo() SHARED_REQUIRES(Locks::mutator_lock_) {
110    return *LongLoType::GetInstance();
111  }
112  const LongHiType& LongHi() SHARED_REQUIRES(Locks::mutator_lock_) {
113    return *LongHiType::GetInstance();
114  }
115  const DoubleLoType& DoubleLo() SHARED_REQUIRES(Locks::mutator_lock_) {
116    return *DoubleLoType::GetInstance();
117  }
118  const DoubleHiType& DoubleHi() SHARED_REQUIRES(Locks::mutator_lock_) {
119    return *DoubleHiType::GetInstance();
120  }
121  const UndefinedType& Undefined() SHARED_REQUIRES(Locks::mutator_lock_) {
122    return *UndefinedType::GetInstance();
123  }
124  const ConflictType& Conflict() {
125    return *ConflictType::GetInstance();
126  }
127
128  const PreciseReferenceType& JavaLangClass() SHARED_REQUIRES(Locks::mutator_lock_);
129  const PreciseReferenceType& JavaLangString() SHARED_REQUIRES(Locks::mutator_lock_);
130  const RegType& JavaLangThrowable(bool precise) SHARED_REQUIRES(Locks::mutator_lock_);
131  const RegType& JavaLangObject(bool precise) SHARED_REQUIRES(Locks::mutator_lock_);
132
133  const UninitializedType& Uninitialized(const RegType& type, uint32_t allocation_pc)
134      SHARED_REQUIRES(Locks::mutator_lock_);
135  // Create an uninitialized 'this' argument for the given type.
136  const UninitializedType& UninitializedThisArgument(const RegType& type)
137      SHARED_REQUIRES(Locks::mutator_lock_);
138  const RegType& FromUninitialized(const RegType& uninit_type)
139      SHARED_REQUIRES(Locks::mutator_lock_);
140  const ImpreciseConstType& ByteConstant() SHARED_REQUIRES(Locks::mutator_lock_);
141  const ImpreciseConstType& CharConstant() SHARED_REQUIRES(Locks::mutator_lock_);
142  const ImpreciseConstType& ShortConstant() SHARED_REQUIRES(Locks::mutator_lock_);
143  const ImpreciseConstType& IntConstant() SHARED_REQUIRES(Locks::mutator_lock_);
144  const ImpreciseConstType& PosByteConstant() SHARED_REQUIRES(Locks::mutator_lock_);
145  const ImpreciseConstType& PosShortConstant() SHARED_REQUIRES(Locks::mutator_lock_);
146  const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader)
147      SHARED_REQUIRES(Locks::mutator_lock_);
148  void Dump(std::ostream& os) SHARED_REQUIRES(Locks::mutator_lock_);
149  const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
150
151  void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
152      SHARED_REQUIRES(Locks::mutator_lock_);
153  static void VisitStaticRoots(RootVisitor* visitor)
154      SHARED_REQUIRES(Locks::mutator_lock_);
155
156 private:
157  void FillPrimitiveAndSmallConstantTypes() SHARED_REQUIRES(Locks::mutator_lock_);
158  mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
159      SHARED_REQUIRES(Locks::mutator_lock_);
160  bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
161      SHARED_REQUIRES(Locks::mutator_lock_);
162  const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)
163      SHARED_REQUIRES(Locks::mutator_lock_);
164
165  // Returns the pass in RegType.
166  template <class RegTypeType>
167  RegTypeType& AddEntry(RegTypeType* new_entry) SHARED_REQUIRES(Locks::mutator_lock_);
168
169  // Add a string piece to the arena allocator so that it stays live for the lifetime of the
170  // verifier.
171  StringPiece AddString(const StringPiece& string_piece);
172
173  template <class Type>
174  static const Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
175      SHARED_REQUIRES(Locks::mutator_lock_);
176  static void CreatePrimitiveAndSmallConstantTypes() SHARED_REQUIRES(Locks::mutator_lock_);
177
178  // A quick look up for popular small constants.
179  static constexpr int32_t kMinSmallConstant = -1;
180  static constexpr int32_t kMaxSmallConstant = 4;
181  static const PreciseConstType* small_precise_constants_[kMaxSmallConstant -
182                                                          kMinSmallConstant + 1];
183
184  static constexpr size_t kNumPrimitivesAndSmallConstants =
185      12 + (kMaxSmallConstant - kMinSmallConstant + 1);
186
187  // Have the well known global primitives been created?
188  static bool primitive_initialized_;
189
190  // Number of well known primitives that will be copied into a RegTypeCache upon construction.
191  static uint16_t primitive_count_;
192
193  // The actual storage for the RegTypes.
194  ScopedArenaVector<const RegType*> entries_;
195
196  // Fast lookup for quickly finding entries that have a matching class.
197  ScopedArenaVector<std::pair<GcRoot<mirror::Class>, const RegType*>> klass_entries_;
198
199  // Whether or not we're allowed to load classes.
200  const bool can_load_classes_;
201
202  // Arena allocator.
203  ScopedArenaAllocator& arena_;
204
205  DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
206};
207
208}  // namespace verifier
209}  // namespace art
210
211#endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_H_
212