xref: /aosp_15_r20/art/runtime/verifier/reg_type-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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_INL_H_
18 #define ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
19 
20 #include "reg_type.h"
21 
22 #include "base/arena_allocator.h"
23 #include "base/casts.h"
24 #include "method_verifier.h"
25 #include "mirror/class.h"
26 #include "verifier_deps.h"
27 
28 namespace art HIDDEN {
29 namespace verifier {
30 
GetClass()31 inline ObjPtr<mirror::Class> RegType::GetClass() const {
32   DCHECK(IsReference()) << Dump();
33   return down_cast<const ReferenceType&>(*this).GetClassImpl();
34 }
35 
GetClassHandle()36 inline Handle<mirror::Class> RegType::GetClassHandle() const {
37   DCHECK(IsReference()) << Dump();
38   return down_cast<const ReferenceType&>(*this).GetClassHandleImpl();
39 }
40 
41 namespace detail {
42 
43 class RegTypeAssignabilityImpl final : RegType {
44  public:
RegTypeAssignabilityImpl(RegType::Kind kind)45   explicit constexpr RegTypeAssignabilityImpl(RegType::Kind kind)
46       : RegType("", /* unused cache id */ 0, kind) {}
47 
48   static constexpr Assignability AssignabilityFrom(RegType::Kind lhs_kind, RegType::Kind rhs_kind);
49 };
50 
AssignabilityFrom(RegType::Kind lhs_kind,RegType::Kind rhs_kind)51 constexpr RegType::Assignability RegTypeAssignabilityImpl::AssignabilityFrom(
52     RegType::Kind lhs_kind, RegType::Kind rhs_kind) {
53   RegTypeAssignabilityImpl lhs(lhs_kind);
54   RegTypeAssignabilityImpl rhs(rhs_kind);
55   auto maybe_narrowing_conversion = [&rhs]() constexpr {
56     return rhs.IsIntegralTypes() ? Assignability::kNarrowingConversion
57                                  : Assignability::kNotAssignable;
58   };
59   if (lhs.IsBoolean()) {
60     return rhs.IsBooleanTypes() ? Assignability::kAssignable : maybe_narrowing_conversion();
61   } else if (lhs.IsByte()) {
62     return rhs.IsByteTypes() ? Assignability::kAssignable : maybe_narrowing_conversion();
63   } else if (lhs.IsShort()) {
64     return rhs.IsShortTypes() ? Assignability::kAssignable : maybe_narrowing_conversion();
65   } else if (lhs.IsChar()) {
66     return rhs.IsCharTypes() ? Assignability::kAssignable : maybe_narrowing_conversion();
67   } else if (lhs.IsInteger()) {
68     return rhs.IsIntegralTypes() ? Assignability::kAssignable : Assignability::kNotAssignable;
69   } else if (lhs.IsFloat()) {
70     return rhs.IsFloatTypes() ? Assignability::kAssignable : Assignability::kNotAssignable;
71   } else if (lhs.IsLongLo()) {
72     return rhs.IsLongTypes() ? Assignability::kAssignable : Assignability::kNotAssignable;
73   } else if (lhs.IsDoubleLo()) {
74     return rhs.IsDoubleTypes() ? Assignability::kAssignable : Assignability::kNotAssignable;
75   } else if (lhs.IsConflict()) {
76     // TODO: The `MethodVerifier` is doing a `lhs` category check for `return{,-wide,-object}`
77     // before the assignability check, so a `Conflict` (`void`) is not a valid `lhs`. We could
78     // speed up the verification by removing the category check and relying on the assignability
79     // check. Then we would need to return `NotAssignable` here as the result would be used
80     // if a value is returned from a `void` method.
81     return Assignability::kInvalid;
82   } else if (lhs.IsUninitializedTypes() || lhs.IsUnresolvedMergedReference()) {
83     // These reference kinds are not valid `lhs`.
84     return Assignability::kInvalid;
85   } else if (lhs.IsNonZeroReferenceTypes()) {
86     if (rhs.IsZeroOrNull()) {
87       return Assignability::kAssignable;  // All reference types can be assigned null.
88     } else if (!rhs.IsNonZeroReferenceTypes()) {
89       return Assignability::kNotAssignable;  // Expect rhs to be a reference type.
90     } else if (rhs.IsUninitializedTypes()) {
91       // References of uninitialized types can be copied but not assigned.
92       return Assignability::kNotAssignable;
93     } else if (lhs.IsJavaLangObject()) {
94       return Assignability::kAssignable;  // All reference types can be assigned to Object.
95     } else {
96       // Use `Reference` to tell the caller to process a reference assignability check.
97       // This check requires more information than the kinds available here.
98       return Assignability::kReference;
99     }
100   } else {
101     DCHECK(lhs.IsUndefined() || lhs.IsHighHalf() || lhs.IsConstantTypes());
102     return Assignability::kInvalid;
103   }
104 }
105 
106 }  // namespace detail
107 
AssignabilityFrom(Kind lhs,Kind rhs)108 inline RegType::Assignability RegType::AssignabilityFrom(Kind lhs, Kind rhs) {
109   static constexpr size_t kNumKinds = NumberOfKinds();
110   using AssignabilityTable = std::array<std::array<Assignability, kNumKinds>, kNumKinds>;
111   static constexpr AssignabilityTable kAssignabilityTable = []() constexpr {
112     AssignabilityTable result;
113     for (size_t lhs = 0u; lhs != kNumKinds; ++lhs) {
114       for (size_t rhs = 0u; rhs != kNumKinds; ++rhs) {
115         result[lhs][rhs] = detail::RegTypeAssignabilityImpl::AssignabilityFrom(
116             enum_cast<RegType::Kind>(lhs), enum_cast<RegType::Kind>(rhs));
117       }
118     }
119     return result;
120   }();
121 
122   return kAssignabilityTable[lhs][rhs];
123 }
124 
new(size_t size,ArenaAllocator * allocator)125 inline void* RegType::operator new(size_t size, ArenaAllocator* allocator) {
126   return allocator->Alloc(size, kArenaAllocMisc);
127 }
128 
129 }  // namespace verifier
130 }  // namespace art
131 
132 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
133