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