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
216
217
218
/*
 * 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_INL_H_
#define ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
 
#include "reg_type.h"
 
#include "base/casts.h"
#include "base/scoped_arena_allocator.h"
#include "method_verifier.h"
#include "mirror/class.h"
#include "verifier_deps.h"
 
namespace art {
namespace verifier {
 
inline bool RegType::CanAccess(const RegType& other) const {
  DCHECK(IsReferenceTypes());
  DCHECK(!IsNull());
  if (Equals(other)) {
    return true;  // Trivial accessibility.
  } else {
    bool this_unresolved = IsUnresolvedTypes();
    bool other_unresolved = other.IsUnresolvedTypes();
    if (!this_unresolved && !other_unresolved) {
      return GetClass()->CanAccess(other.GetClass());
    } else if (!other_unresolved) {
      return other.GetClass()->IsPublic();  // Be conservative, only allow if other is public.
    } else {
      return false;  // More complicated test not possible on unresolved types, be conservative.
    }
  }
}
 
inline bool RegType::CanAccessMember(ObjPtr<mirror::Class> klass, uint32_t access_flags) const {
  DCHECK(IsReferenceTypes());
  if (IsNull()) {
    return true;
  }
  if (!IsUnresolvedTypes()) {
    return GetClass()->CanAccessMember(klass, access_flags);
  } else {
    return false;  // More complicated test not possible on unresolved types, be conservative.
  }
}
 
inline bool RegType::IsConstantBoolean() const {
  if (!IsConstant()) {
    return false;
  } else {
    const ConstantType* const_val = down_cast<const ConstantType*>(this);
    return const_val->ConstantValue() >= 0 && const_val->ConstantValue() <= 1;
  }
}
 
inline bool RegType::AssignableFrom(const RegType& lhs,
                                    const RegType& rhs,
                                    bool strict,
                                    MethodVerifier* verifier) {
  if (lhs.Equals(rhs)) {
    return true;
  } else {
    switch (lhs.GetAssignmentType()) {
      case AssignmentType::kBoolean:
        return rhs.IsBooleanTypes();
      case AssignmentType::kByte:
        return rhs.IsByteTypes();
      case AssignmentType::kShort:
        return rhs.IsShortTypes();
      case AssignmentType::kChar:
        return rhs.IsCharTypes();
      case AssignmentType::kInteger:
        return rhs.IsIntegralTypes();
      case AssignmentType::kFloat:
        return rhs.IsFloatTypes();
      case AssignmentType::kLongLo:
        return rhs.IsLongTypes();
      case AssignmentType::kDoubleLo:
        return rhs.IsDoubleTypes();
      case AssignmentType::kConflict:
        LOG(WARNING) << "RegType::AssignableFrom lhs is Conflict!";
        return false;
      case AssignmentType::kReference:
        if (rhs.IsZeroOrNull()) {
          return true;  // All reference types can be assigned null.
        } else if (!rhs.IsReferenceTypes()) {
          return false;  // Expect rhs to be a reference type.
        } else if (lhs.IsUninitializedTypes() || rhs.IsUninitializedTypes()) {
          // Uninitialized types are only allowed to be assigned to themselves.
          // TODO: Once we have a proper "reference" super type, this needs to be extended.
          return false;
        } else if (lhs.IsJavaLangObject()) {
          return true;  // All reference types can be assigned to Object.
        } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
          // If we're not strict allow assignment to any interface, see comment in ClassJoin.
          return true;
        } else if (lhs.IsJavaLangObjectArray()) {
          return rhs.IsObjectArrayTypes();  // All reference arrays may be assigned to Object[]
        } else if (lhs.HasClass() && rhs.HasClass()) {
          // Test assignability from the Class point-of-view.
          bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass());
          // Record assignability dependency. The `verifier` is null during unit tests and
          // VerifiedMethod::GenerateSafeCastSet.
          if (verifier != nullptr) {
            VerifierDeps::MaybeRecordAssignability(
                verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result);
          }
          return result;
        } else {
          // Unresolved types are only assignable for null and equality.
          // Null cannot be the left-hand side.
          return false;
        }
      case AssignmentType::kNotAssignable:
        break;
    }
    LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '"
               << lhs << "' := '" << rhs << "'";
    UNREACHABLE();
  }
}
 
inline bool RegType::IsAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
  return AssignableFrom(*this, src, false, verifier);
}
 
inline bool RegType::IsStrictlyAssignableFrom(const RegType& src, MethodVerifier* verifier) const {
  return AssignableFrom(*this, src, true, verifier);
}
 
inline const DoubleHiType* DoubleHiType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const DoubleLoType* DoubleLoType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const LongHiType* LongHiType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const LongLoType* LongLoType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const FloatType* FloatType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const CharType* CharType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const ShortType* ShortType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const ByteType* ByteType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
 
inline const IntegerType* IntegerType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const BooleanType* BooleanType::GetInstance() {
  DCHECK(BooleanType::instance_ != nullptr);
  return BooleanType::instance_;
}
 
inline const ConflictType* ConflictType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const UndefinedType* UndefinedType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline const NullType* NullType::GetInstance() {
  DCHECK(instance_ != nullptr);
  return instance_;
}
 
inline void* RegType::operator new(size_t size, ScopedArenaAllocator* allocator) {
  return allocator->Alloc(size, kArenaAllocMisc);
}
 
}  // namespace verifier
}  // namespace art
 
#endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_